interval-3.2.0/DESCRIPTION0000644000000000000000000000170313316017127013176 0ustar 00000000000000Name: interval Version: 3.2.0 Date: 2018-07-01 Author: Oliver Heimlich Maintainer: Oliver Heimlich Title: Real-valued interval arithmetic Description: The interval package for real-valued interval arithmetic allows one to evaluate functions over subsets of their domain. All results are verified, because interval computations automatically keep track of any errors. These concepts can be used to handle uncertainties, estimate arithmetic errors and produce reliable results. Also it can be applied to computer-assisted proofs, constraint programming, and verified computing. The implementation is based on interval boundaries represented by binary64 numbers and is conforming to IEEE Std 1788-2015, IEEE standard for interval arithmetic. Depends: octave (>= 3.8.0) SystemRequirements: mpfr (>= 3.1.0) [Debian] libmpfr4 (>= 3.1.0) BuildRequires: mpfr (>= 3.1.0) [Debian] libmpfr-dev (>= 3.1.0) License: GPL-3.0+ interval-3.2.0/INDEX0000644000000000000000000000705013316017127012263 0ustar 00000000000000interval >> Real-valued interval arithmetic Interval constant empty entire nai Interval constructor hull midrad @infsup/infsup @infsup/newdec @infsupdec/infsupdec Interval function (most with tightest accuracy) @infsup/abs @infsup/acos @infsup/acosh @infsup/asin @infsup/asinh @infsup/atan @infsup/atan2 @infsup/atanh @infsup/cancelminus @infsup/cancelplus @infsup/cbrt @infsup/ceil @infsup/cos @infsup/cosh @infsup/cot @infsup/coth @infsup/csc @infsup/csch @infsup/dilog @infsup/ei @infsup/erf @infsup/erfc @infsup/exp @infsup/expm1 @infsup/factorial @infsup/fix @infsup/floor @infsup/fma @infsup/gamma @infsup/gammaln @infsup/hypot @infsup/ldivide @infsup/linspace @infsup/log @infsup/log10 @infsup/log1p @infsup/log2 @infsup/max @infsup/min @infsup/minus @infsup/mod @infsup/nthroot @infsup/plus @infsup/pow @infsup/pow10 @infsup/pow2 @infsup/power @infsup/pown @infsup/psi @infsup/rdivide @infsup/realsqrt @infsup/rem @infsup/round @infsup/roundb @infsup/rsqrt @infsup/sec @infsup/sech @infsup/sign @infsup/sin @infsup/sinh @infsup/sqrt @infsup/tan @infsup/tanh @infsup/times @infsup/uminus @infsup/uplus Interval matrix operation @infsup/chol @infsup/det @infsup/dot @infsup/expm @infsup/inv @infsup/lu @infsup/mldivide @infsup/mpower @infsup/mrdivide @infsup/mtimes @infsup/norm @infsup/prod @infsup/qr @infsup/sum @infsup/sumabs @infsup/sumsq Interval comparison @infsup/disjoint @infsup/eq @infsup/ge @infsup/gt @infsup/interior @infsup/iscommoninterval @infsup/isempty @infsup/isentire @infsup/ismember @infsup/issingleton @infsup/le @infsup/lt @infsup/ne @infsup/overlap @infsup/precedes @infsup/strictprecedes @infsup/strictsubset @infsup/subset @infsupdec/isnai Set operation @infsup/bisect @infsup/intersect @infsup/mince @infsup/nextout @infsup/setdiff @infsup/setxor @infsup/union Interval reverse operation @infsup/absrev @infsup/atan2rev1 @infsup/atan2rev2 @infsup/coshrev @infsup/cosrev @infsup/mulrev @infsup/pownrev @infsup/powrev1 @infsup/powrev2 @infsup/sinrev @infsup/sqrrev @infsup/tanrev Interval numeric function @infsup/hdist @infsup/idist @infsup/inf @infsup/mag @infsup/mid @infsup/mig @infsup/rad @infsup/sdist @infsup/smig @infsup/sup @infsup/wid Interval input and output interval_bitpack intervaltotext exacttointerval @infsup/bitunpack @infsup/disp @infsup/display @infsup/fprintf @infsup/intervaltoexact @infsup/plot @infsup/plot3 @infsup/printf @infsup/sprintf Interval solver or optimizer @infsup/fminsearch @infsup/fsolve @infsup/fzero @infsup/gauss @infsup/polyval Interval contractor arithmetic ctc_intersect ctc_union Verified solver or optimizer vereigback vereigvec verintlinineqs verinvnonneg verlinineqnn verlinprog Utility function @infsup/cat @infsup/columns @infsup/ctranspose @infsup/diag @infsup/end @infsup/horzcat @infsup/iscolumn @infsup/ismatrix @infsup/isrow @infsup/isscalar @infsup/issquare @infsup/isvector @infsup/length @infsup/ndims @infsup/numel @infsup/postpad @infsup/prepad @infsup/reshape @infsup/resize @infsup/rows @infsup/size @infsup/subsasgn @infsup/subsref @infsup/transpose @infsup/tril @infsup/triu @infsup/vertcat @infsupdec/decorationpart @infsupdec/intervalpart API function to low-level libraries crlibm_function mpfr_function_d mpfr_linspace_d mpfr_matrix_mul_d mpfr_matrix_sqr_d mpfr_to_string_d mpfr_vector_sum_d mpfr_vector_dot_d Internal utility function (use at one's own risk) __setround__ __check_crlibm__ __split_interval_literals__ interval-3.2.0/doc/CITATION.texinfo0000644000000000000000000000141113316017127015041 0ustar 00000000000000\input texinfo @setfilename CITATION @settitle CITATION file @documentencoding UTF-8 @c This is part of the GNU Octave Interval Package. @c Copyright 2015-2017 Oliver Heimlich. @c See the file COPYING for copying conditions. The interval package is a collection of functions for interval arithmetic. It is developed at Octave Forge, a sibling of the GNU Octave project. To cite this particular version of the interval package in publications use: @display @@software@{octave-interval, author = @{Oliver Heimlich@}, title = @{GNU Octave Interval Package@}, url = @{https://octave.sourceforge.io/interval/@}, version = @{@value{version}@}, date = @{@value{date}@}, @} @end display @noindent See also @command{citation} for citing Octave as a whole. @bye interval-3.2.0/doc/COPYING.texinfo0000644000000000000000000000217213316017127014744 0ustar 00000000000000\input texinfo @setfilename COPYING @settitle COPYING file @documentencoding UTF-8 @c This is part of the GNU Octave Interval Package. @c Copyright 2015-2017 Oliver Heimlich. The interval package is free software and can be used under the terms of the GNU General Public License Version 3 (or at your option any later version). The wording of the license can be found below. The interval package contains derivative work, which is based on other free software released under various licenses. Original authors are properly attributed in the manual and copyright statements have been retained in the particular source files or in separate .license files. For simplicity, most derivative work has been relicensed in this package. Thus, the GPLv3+ is the main license for the software and documentation in this package. This package bundles the library crlibm in @code{src/crlibm/}, which is licensed under the GNU Lesser General Public License Version 2.1 (or at your option any later version). The license can be found in @code{src/crlibm/COPYING.LIB}. @sp 5 @center The GNU General Public License. @include license/gpl-3.0.texi @bye interval-3.2.0/doc/Makefile0000644000000000000000000000314213316017127013674 0ustar 00000000000000## This is part of the GNU Octave Interval Package. ## Copyright 2015-2017 Oliver Heimlich. ## See the file COPYING for copying conditions. SHELL = /bin/sh M_IMAGE = $(wildcard image/*.m) $(patsubst %.m.texinfo,%.m,$(wildcard image/*.m.texinfo)) IMAGE_OBJ = $(patsubst %,%.png,$(M_IMAGE)) OBJ = manual.html manual.pdf $(IMAGE_OBJ) MAKEINFO ?= makeinfo VERSION ?= $(shell grep "^Version: " ../packinfo/DESCRIPTION ../DESCRIPTION | head -1 | cut -f2 -d" ") OCTAVE ?= octave .PHONY: all clean images all: $(OBJ) images: $(IMAGE_OBJ) manual.html: manual.texinfo $(wildcard chapter/*) license/gpl-3.0.texi $(wildcard image/*.texinfo) $(IMAGE_OBJ) @echo " [MAKEINFO --html] $<" @$(MAKEINFO) -D 'version $(VERSION)' --html --no-split --css-include manual.css "$<" manual.pdf: manual.texinfo $(wildcard chapter/*) license/gpl-3.0.texi $(wildcard image/*.texinfo) $(wildcard image/*.pdf) $(IMAGE_OBJ) @echo " [MAKEINFO --pdf] $<" @$(MAKEINFO) --Xopt=--texinfo='@set version $(VERSION)' --pdf "$<" image/%.m.png: image/%.m @echo " [OCTAVE] $<" @$(OCTAVE) --no-history \ --eval "pkg load interval;" \ --eval "set (0, 'defaultfigurevisible', 'off');" \ --eval "source ('$<');" \ --eval "print (gcf, '$@');" @# The image size is too large for inclusion in the pdf, @# thus we increase the resolution from 150 to 250 dpi. @echo " [IMAGEMAGICK] $@" @convert -density 98.425 -units PixelsPerCentimeter "$@" "$@" image/%.m: image/%.m.texinfo @echo " [MAKEINFO --plaintext] $<" @$(MAKEINFO) -D m-file --plaintext "$<" > "$@" clean: $(RM) $(OBJ) $(RM) *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr interval-3.2.0/doc/NEWS.texinfo0000644000000000000000000006343313316017127014417 0ustar 00000000000000\input texinfo @setfilename NEWS @settitle NEWS file @documentencoding UTF-8 @c This is part of the GNU Octave Interval Package. @c Copyright 2015-2018 Oliver Heimlich @c Copyright 2017 Joel Dahne @c See the file COPYING for copying conditions. @macro release{version, date} @heading Version \version\ \date\ @end macro @center GNU Octave Interval Package @center Summary of important user-visible changes @release{3.2.0, 2018-07-01} @itemize @item Fixed a regression where decorated intervals could no longer be used in Octave 4.4 (bug #53331). @item intervaltotext: A change in Octave 4.4 has removed the possibility to increase Octave's output precision beyond 16 decimal digits (bug #53456), which has made it impossible to output intervals with a higher accuracy. The function @command{intervaltotext} has been reimplemented with several new format options to customize the format and accuracy of the interval literal. All recommended conversion specifiers from IEEE Std 1788-2015 are now supported, e. g., intervals can be printed in uncertain form. @item printf, fprintf, sprintf: New functions to produce formatted output with interval literals. @item numel: Added support for additional arguments to compute the number of elements after indexing an interval array. This allows combined indexing expressions of the form @code{x(1:2).inf}. @item Fixed several warnings during package installation. @end itemize @release{3.1.0, 2017-12-21} This minor release introduces two new functions and fixes severe bugs. @itemize @item mod, rem: Two new interval arithmetic functions to compute the remainder of a floored division or truncated division respectively. @item plot: Fixed a regression with plotting 2D rectangles in the upcoming Octave 4.4. @item The internal function @command{__print_mesa__} for off-screen mesa rendering has been removed, because the upstream mesa project no longer supports off-screen and on-screen rendering in a single executable (Debian bug #877149). It is recommended to use Octave's @command{print} function instead, which has greatly been improved in Octave 4.2 regarding the output of rectangles and boxes. @item A package installation error on 32-bit systems could be fixed (bug #51857). @item During package installation, FPU control has not be activated on x86-32 platforms. Thus, the crlibm library could not disable 80-bit floating-point arithmetic and produced wrong results. This has been detected by the interval package, which fell back on the slower mpfr library instead (Debian bug #874135). After fixing compiler options, x86-32 platforms can now use crlibm correctly—even without 64-bit SSE registers. @item Source code for interval arithmetic tests from the ITF1788 project have been removed from this package, since the loadable test data @code{itl.mat} can be edited and processed with Octave easily. If unit test code for other interval arithmetic libraries shall be generated, find the project at @url{https://github.com/oheim/ITF1788}. @item Thanks to Olaf Till, this package obtains a configure script (patch #9518). It checks for available libraries during package installation and can help to identify missing dependencies. @end itemize @release{3.0.0, 2017-08-19} This major release introduces support for N-dimensional arrays of intervals. With previous versions, interval objects have been limited to two dimensions. Only scalar values, vectors, and matrices could be created. Now, interval objects can be used with three or more dimensions as well. Binary and ternary operations support broadcasting of singleton dimensions, which can be expanded to produce higher dimensional results. Most work for this version has been accomplished by Joel Dahne during his Google Summer of Code project. The project involved thorough maintenance of all interval functions, which led to improvements and bugfixes beyond the original goal. @itemize @item Support for N-dimensional arrays of intervals. @item Removed interval implementation of @command{meshgrid}, it now falls back on the standard implementation which can output a 3-d grid properly. This no longer automatically converts all input to intervals. For example, it is possible to create a grid for interval X values and non-interval Y values. @item dot, prod, sum: Altered how empty input is handled. They are more consistent with the standard sum and prod functions (return zero/one for 0×0 input along the first dimension). For the dot function it is slightly different from how the Octave core function handles it at the moment (bug #51333). @item Output of interval matrices may be customized with @command{format compact} to display more data per page. @item nthroot, pownrev: Now supports vectorization of @var{n} (for nthroot) and @var{p} (for pownrev), broadcasting is fully supported. @item Indexing expressions on intervals can now use the @command{end} keyword and the special operator @samp{:} to select all entries. This affects selection of entries and assignment of entries (bug #49592, bug #50626). @item Adjustments to ITF1788 test suite: @itemize @item Several further unit tests have been derived from libieeep1788 together with the latest version of the interval testing framework. That is, tests with NaN values, NaI values, IEEE 1788 exceptions, and tests for the following functions: numsToInterval, textToInterval, intervalPart, newDev, setDec, decorationPart, and reduction operations. @item Unit tests have been reorganized: The source code of test cases has been moved to /src/test/. @item The test suite is no longer compiled as separate Octave test files (*.tst). Instead, any interval test library files (*.itl) are stored as loadable test data (itl.mat). The test data is then used by built-in self-tests of the functions. This simplifies testing of functions and saves storage space after package installation. For example, @command{test @@infsup/plus} will run any arithmetic tests on the interval plus function. @end itemize @item Adjustments to the package documentation: @itemize @item Information about how to create N-dimensional arrays of intervals. @item To improve privacy and page loading times, the package manual no longer uses external references for CSS and web fonts. @item The package URL has been updated (after Octave Forge has switched to HTTPS). @item HTML fonts have been changed and fallback fonts for Windows have been introduced. @item Adjustments to code examples to support the latest versions of the doctest package and symbolic package. @end itemize @end itemize Bugfixes @itemize @item Processor support for SSE2 is automatically detected during package installation. This fixes installation problems on devices without SSE2, for example the usual Android phones and tablets (bug #51758). @item wid, mig, mag: Fixed wrong return value for NaI (not an interval) values. The functions failed to return NaN (not a number). @item diag: With more than one argument the function no longer fails with an error. @item dot: Fixed error in identification of dimensions when broadcasting: When the optional dimension argument is missing, the first non-singleton dimension of both arguments is used (before broadcasting applies). @item infsupdec: Now creates a warning if the @code{[NaI]} literal is combined with decoration, e. g. @samp{[NaI]_ill}. @item infsupdec: No longer produces warnings for mixed parameters with strings and numerics. @item verlinineqnn: No longer produces warnings for unverified solutions. @item pow: Fixed error when called with vector arguments. The result was only guaranteed to be sharp in the first entry, e. g. @samp{pow ([0 0], infsup (0, 1))} produced the interval [0, 1] for the second entry. @item pow2rev: Fixed errors when called with non-scalar arguments in two cases, which could produce wrong results. @item ctc_intersect, ctc_union: Fixed runtime errors when the combined contractor function is called with less than two output arguments. @item sin: Fixed possible interval representation error, where the upper boundary of the result could become a signed zero (bug #51283). @item factorial: Improved result decoration for integer input, since the function is continuous (bug #51783). @end itemize @release{2.1.0, 2016-12-28} @itemize @item The speed of some arithmetic operations has been greatly improved. They have previously been computed by multi-precision arithmetic which simulates binary64 floating-point arithmetic (MPFR library). Now, a specialized correctly rounded mathematical library (crlibm) computes identical results 30–100 times faster. There is no accuracy drawback, arithmetic operations will compute tight interval enclosures as before. The following functions benefit from this: acos, asin, atan, cos, cosh, exp, expm1, log, log10, log1p, log2, sin, sinh, tan. @end itemize Bugfixes @itemize @item Fixed indexing expression in interval constructor for illegal intervals of the form @code{[-inf, -inf]} or @code{[inf, inf]} @item polyval: Fixed unnecessary warnings when evaluated on empty intervals @item Fixed compilation errors on FreeBSD 9.3 @end itemize @release{2.0.0, 2016-11-20} This major release contains fundamental changes to the interval constructors. After a discussion on the P1788 mailing list, it has been revealed that this interval package didn't implement exceptions from the standard for interval arithmetic correctly: Operations from IEEE Std 1788-2015 which trigger an “exception” shall return a value nonetheless. Conformance has been improved in this new version, but may break compatibility with previous versions. A second big news is that the interval package comprises functions from VERSOFT, a verification software package by Jiří Rohn, who has generously published his work as free software this year. Unfortunately, some of VERSOFT's functions are encrypted and could not be included yet. @itemize @item nai: With additional arguments, matrices of NaI (not an interval) values can be constructed. Previously, NaI has been restricted to be of scalar value. @item infsup: The bare interval constructor merely triggers a warning instead of an error on illegal input, which creates empty intervals. If input contains legitimate as well as illegal input, only entries with illegal input will carry empty intervals. @item infsupdec: The decorated interval constructor may create interval matrices which have NaI (not an interval) as entries. If input contains legitimate as well as illegal input, only entries with illegal input will carry NaI values. @item Warning and error identifiers of the constructors have been revised. The warning identifier @code{interval:NaI} has been removed. Illegal input signals an @code{interval:UndefinedOperation} warning. If the input is of an illegal data type or of illegal size, the constructors signal an @code{interval:InvalidOperand} warning. The warning identifier @code{interval:PossiblyUndefinedOperation} has been renamed to @code{interval:PossiblyUndefined} to better match the wording in the standard document. Also, previous versions failed to trigger this warning in cases where there is a floating point number between boundaries @var{u} < @var{l}, which has been fixed. @item It is no longer valid to call @code{infsup (+inf, -inf)} to create an empty interval and the constructor will signal a warning in these cases. This change has been made to better conform to the @command{numsToInterval} function from the interval standard. You may create empty intervals with either @code{infsup ()} or @code{infsupdec ()} or @code{empty ()}. @item inf, sup: If the input is NaI (not an interval), these functions return NaN (not a number) values instead of an error. @item Output of intervals in hexadecimal form discriminates between subnormal boundaries and normal boundaries. Subnormal numbers start with “0x0.” whereas normal numbers start with “0x1.”. Also, hexadecimal form has been changed to lower case. @item resize: New interval elements are initialized with zero instead of empty intervals to better match the corresponding Octave function. @item Interval constructors may broadcast column and row vectors. @item Performance improvements: factorial on large arguments; plot and plot3 on input that is plotted as a line. @item New interval functions: tril, triu, qr @item New functions which have been ported from Jiří Rohn's VERSOFT: chol, vereigback, vereigvec, verintlinineqs, verinvnonneg, verlinineqnn, verlinprog @item recip, sqr: The functions have been removed, after they have been deprecated in version 1.4.0. @item plot3: Fixed plotting with gnuplot and fixed an issue where the figure did not switch from 2D to 3D after plotting. @item expm1: Fixed documentation, the function computes exp (X) - 1 instead of exp (X - 1). @item norm: Fixed an error where the Hamming norm of empty intervals was non-empty. @end itemize @release{1.5.0, 2016-05-31} @itemize @item norm: Added subordinate matrix norms and the max norm @item strictsubset: New interval comparison function @item Package documentation: Added new example (Cameleon problem), and the growing list of examples has been split into several web pages. @item Package documentation: Updated recommendations to install and load the package. The autoload feature will be removed in Octave 4.2.0. (patch #8981, thanks to juanpi) @item Support package installation in Octave 4.1.0+ (bug #47288) @end itemize @release{1.4.1, 2016-02-13} @itemize @item Fixed a compile error for 32-bit systems during package installation (bug #47100) @end itemize @release{1.4.0, 2016-02-09} @itemize @item mpower: Improved accuracy and speed. The interval matrix square can now be computed without dependency errors and with tightest accuracy. @item factorial: New interval arithmetic operation @item expm, norm: New interval matrix operations @item The functions recip and sqr have been deprecated and will be removed in a future release. Please use @code{1 ./ @var{x}} and @code{@var{x} .^ 2} instead. @end itemize @noindent Bugfixes @itemize @item bitunpack, interval_bitpack: The order of inf/sup/dec parts has been fixed. The function documentation describes how the functions behave on little-endian and big-endian systems. @end itemize @release{1.3.0, 2015-12-22} @itemize @item postpad, prepad, subsasgn: Implicit new elements during subscript assignment and padding have been initialized with empty intervals before this release. This behavior has changed. Now, the implicit new element are initialized with zero to make a correct interval extension of the corresponding built-in function. @item fsolve: New function to solve (systems of) equations and compute the inverse of a set under a function @item ctc_intersect, ctc_union: Utility functions for contractors and the fsolve function @item det, prod, recip: New interval arithmetic functions @item diag: New utility function to create diagonal matrices or extract vectors from diagonals of matrices @item decorationpart: Choose between different return types with a second parameter @item For several functions it is now possible to broadcast row vectors against column vectors or vectors against matrices. @item The user manual has been restructured for better accessibility by new users. A bunch of usage examples demonstrates the package's capabilities. @end itemize @noindent Bugfixes @itemize @item sum, sumabs, sumsq: Fixed result for matrices of size zero @item powrev1, powrev2: Fixed indexing for vectors @end itemize @release{1.2.0, 2015-10-01} @itemize @item The output format for intervals has been changed. The number of decimal places now respects what has been set by the user with the @command{format short} or @command{format long} command, and is much shorter by default. Also it is possible to use @command{format hex}. The old format can be accessed with the @command{intervaltotext} function. @item fminsearch: New optimizer function for finding the minimum value of a function over interval constraints using the Skelboe-Moore algorithm @item fzero: Changed function parameters to support optimset options @item power: Improved speed of the general interval power function and monomials with the notation x .^ n @item plot, plot3: Added support for colormaps @end itemize @noindent Bugfixes @itemize @item mldivide: Fixed algorithm to handle more matrices without error @item bisect: Fixed an error during bisection of singleton intervals (thanks to Helmut for finding this during OctConf 2015) @end itemize @release{1.1.0, 2015-08-03} @itemize @item meshgrid, mince: New utility functions to help plotting of interval functions @item linspace: New interval arithmetic function @item intersect, max, min, union: Allow evaluation as aggregate functions within an interval matrix along a common dimension @item Improvements to the documentation @itemize @item Added cross-references between package documentation and function reference @item Extended information about interval arithmetic in general @item Extended information about implemented IEEE Std 1788-2015 functions and fixed references to the standard document @item Added information about plotting intervals @item Simplified package description @item Graphics with higher resolutions, demo of interval sombrero function plot on first page, and minor style fixes @end itemize @end itemize @noindent Bugfixes @itemize @item plot3: Fixed plotting of interval edges when plotting several intervals at once using matrices @end itemize @release{1.0.0, 2015-06-13} @itemize @item IEEE Std 1788-2015, IEEE standard for interval arithmetic, was approved on June 11. To mark the occasion, the major version number has been raised. @item All interval constructors have been extended to create interval matrices from a single string. Commas or spaces may be used as a column separator (consecutive separators are trimmed). Semicolon and new line characters can be used as a row separator. @item hdist, idist, sdist, smig: New interval numeric functions @item User manual: Relicensed under GPL, added examples from the former Octave SIMP package, and various minor improvements. @end itemize @noindent Bugfixes @itemize @item mtimes: Fixed matrix-vector multiplication of decorated intervals @item Fixed a linking error in mkoctfile that could prevent package installation (bug #45280) @end itemize @release{0.2.1, 2015-05-30} @itemize @item plot, plot3: New interval plotting functions. Pay attention to the included examples, which can be executed with @code{demo @@infsup/plot} and @code{demo @@infsup/plot3} respectively. @item polyval: New interval arithmetic algorithm @item bisect: New set operation for bisecting algorithms @item sinrev, cosrev, tanrev, atan2rev1, atan2rev2: Now allow non-scalar arguments @item Simplified licensing: Relicensed parts of the software that were not under GPL @item Updated information for citation of the package @end itemize @noindent Bugfixes @itemize @item Fixed generation of the manual in PDF format @item subsasgn: Fixed cases where decoration could be lost (bug #42735) @end itemize @release{0.2.0, 2015-05-03} @itemize @item User manual included in the package, see doc/manual.texinfo @item New utility functions: cat, postpad, prepad, reshape, resize @item and, or: Removed deprecated functions @item Improved display output for cell arrays and new function: disp @item Minor performance improvements (all decorated interval functions, horzcat, vertcat) @end itemize @noindent Bugfixes @itemize @item issquare, isrow, iscolumn: Fixed compatibility issues with GNU Octave 4.0 @item cbrt: Allow negative values as parameter @item cot: Fixed accuracy for x = 0 @item cos, csc, sec, sin: Fixed correctness in certain cases @item Prevent multibyte characters in Microsoft Windows console @end itemize @release{0.1.5, 2015-04-06} @itemize @item Implicit decoration of bare intervals triggers a warning now and can be allowed or forbidden by the user. Implicit decoration of bare interval literals is not affected. @item newdec: New operation for explicit promotion of bare intervals into decorated intervals (without warning). @item Decorated interval literals with illegal decoration are no longer allowed and produce NaIs. @item hull: In contrast to the union function, the interval constructor is no longer considered a set operation and can create intervals with a non-trivial decoration. @item setdiff, setxor: New set operations @item intersect, union: Renamed set operations; the old function names (and, or) are hereby deprecated and are going to be removed in the next release. @item intervaltotext, intervaltoexact: Decimal fractions no longer omit zero before the point, and unnecessary trailing decimal places can be omitted more consistently and in more cases than before (also affects console output). Improved accuracy and performance with support for interval matrices. @end itemize @noindent Bugfixes @itemize @item mtimes, mldivide: Support for broadcasting of scalar parameters @item nextout: Support for decorated intervals @item An error in GNU Octave core, which could lead to lost or wrong interval decorations, no longer affects decorated intervals (bug #42735) @item Some errors in the function documentation have been fixed (thanks to doctest-for-matlab and Colin's texinfo compatibility patches) @item Fixed interval field access on Windows @end itemize @release{0.1.4, 2015-03-15} @itemize @item New interval constructors: hull, midrad @item New interval arithmetic functions: cbrt, cot, coth, csc, csch, dilog, ei, erf, erfc, gamma, gammaln, psi, rsqrt, sec, sech @item mtimes: Support for fast, less accurate evaluation using BLAS routines @item mldivide, mrdivide, inv: Improved performance by using faster mtimes @item infsup, infsupdec: Enabled broadcasting of scalar boundaries @item rad: May compute mid and rad simultaneously @item subsref: Access to interval properties using field syntax: x.inf and x.sup @end itemize @release{0.1.3, 2015-02-24} @itemize @item Fixed a compile error that could possibly occur during package installation @end itemize @release{0.1.2, 2015-02-22} @itemize @item New interval arithmetic functions: nthroot, hypot, log1p, expm1 @item lu: New operation for LU(P) decomposition of interval matrices @item nai: New decorated interval constant @item mldivide, mrdivide, inv: Greatly improved accuracy and performance of the linear solver @item Improved accuracy of vector sums, dot products, pownrev, and powrev2 @item powrev1, powrev2, pownrev, mulrev: Now allow non-scalar arguments @item overlap: Renamed one overlapping state from equal to equals @item mulrevtopair: No longer available, use mulrev with two output parameters for two-output division @item setdec: No longer available, use infsupdec instead @item Small performance improvements @end itemize @noindent Bugfixes @itemize @item Compatibility with GNU Octave 4.0 (bug #43925) @item Build problems during package installation with environment variables @item iscommoninterval: The decorated variant must return true for common intervals without com decoration @item eq: The decorated variant must not consider the decoration value @item Several decorated functions: When evaluated on a subset of the function's domain, the result's decoration must be dac if the function's restriction to that subset is continuous @item Decorated boolean functions: Must return false when evaluated on NaI input @item Interval constructors: A PossibleUndefined warning must be issued if an interval is created from two very close decimal numbers (which can not be separated in the floating-point context) where the lower boundary is greater than the upper boundary when compared with infinite precision @item Interval constructors: NaNs must produce empty intervals @item Decorated interval constructor: Illegal decorations for empty intervals must be adjusted to trv, and illegal decoration com for unbounded intervals must be adjusted to dac. @item cancelminus/cancelplus: The functions returned wrong results if the interval widths could not be compared in double-precision @item cos: Accuracy for x = [0] improved @item pow, powrev1, powrev2: The function must be defined for x = 0 and y > 0 @item All reverse operations: Must return a trivial decoration information at best (the only exception is mulrev) @end itemize @release{0.1.1, 2015-02-01} @itemize @item Increased speed of computation for large matrices @item Improved performance for fma and dot @item mpfr_vector_dot_d: Changed syntax for faster computation on intervals @item Decorated versions of mtimes, mldivide, mpower, inv and reduction operations sum, dot, subabs, subsquare @item Renamed function sumsquare to sumsq in accordance with GNU Octave function names @item New function: fzero for finding all roots of an interval arithmetic function @end itemize @noindent Bugfixes @itemize @item nextout: Function returned wrong results @item exacttointerval: Now produces bare intervals instead of decorated intervals in conformance with IEEE P1788 @item atanh: Function returned wrong results for ±1 @item dot: Function returned wrong results for some inputs @item fma: Function returned wrong results for some inputs @item infsup: Function returned wrong interval boundaries for decimal numbers, function failed on mixed numerical and string boundaries in single cell array parameter @item mulrevtopair: Fixed order of operands in conformance with IEEE P1788 and wrong results when evaluated on intervals that contain zero @end itemize @release{0.1.0, 2015-01-21} @itemize @item Initial release version, which already contains all required operations of the preliminary standard document IEEE P1788. @end itemize @bye interval-3.2.0/doc/chapter/advanced-topics.texinfo0000644000000000000000000002651613316017127020336 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2016 Oliver Heimlich. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @include macros.texinfo @chapter Advanced Topics @section Error Handling Due to the nature of set-based interval arithmetic, one should not observe errors (in the sense of raised GNU Octave error messages) during computation unless operations are evaluated for incompatible data types. Arithmetic operations which are not defined for (parts of) their input, simply ignore anything that is outside of their domain. However, the interval constructors can produce warnings depending on the input. The @funref{@@infsup/infsup} constructor will warn if the interval boundaries are invalid and returns empty intervals in these cases. Contrariwise, the (preferred) @funref{@@infsupdec/infsupdec}, @funref{midrad} and @funref{hull} constructors will only issue a warning and return [NaI] objects, which will propagate and survive through computations. NaI stands for “not an interval”. Effects of set-based interval arithmetic on partial functions and the NaI object @example @group ## Evaluation of a function outside of its domain ## returns an empty interval infsupdec (2) / 0 @result{} ans = [Empty]_trv infsupdec (0) ^ infsupdec (0) @result{} ans = [Empty]_trv @end group @end example @example @group ## Illegal interval construction creates a NaI infsupdec (3, 2) @print{} warning: illegal interval boundaries: @print{} infimum greater than supremum @result{} ans = [NaI] @end group @end example @example @group ## NaI even survives through computations ans + 1 @result{} ans = [NaI] @end group @end example There are some situations where the interval package cannot decide whether an error occurred or not and issues a warning. The user may choose to ignore these warnings or handle them as errors, see @command{help warning} for instructions. @float Table,tab:warnings @caption{Warning IDs} @table @option @item interval:PossiblyUndefined @table @asis @item Reason Interval construction with boundaries in decimal format, and the constructor can't decide whether the lower boundary is smaller than the upper boundary. Both boundaries are very close and lie between subsequent binary64 numbers. @item Possible consequences The constructed interval is a valid and tight enclosure of both numbers. If the lower boundary was actually greater than the upper boundary, this illegal interval is not considered an error. @end table @item interval:ImplicitPromote @table @asis @item Reason An interval operation has been evaluated on both, a bare and a decorated interval. The bare interval has been converted into a decorated interval in order to produce a decorated result. Note: This warning does not occur if a bare interval literal string gets promoted into a decorated interval, e. g., @code{infsupdec (1, 2) + "[3, 4]"} does not produce this warning whereas @code{infsupdec (1, 2) + infsup (3, 4)} does. A bare interval can be explicitly promoted with the @funref{@@infsup/newdec} function. @item Possible consequences The implicit conversion applies the best possible decoration for the bare interval. If the bare interval has been produced from an interval arithmetic computation, this branch of computation is not covered by the decoration information and the final decoration could be considered wrong. For example, @code{infsupdec (1, 2) + infsup (0, 1) ^ 0} would ignore that 0^0 is undefined. @end table @item interval:UndefinedOperation @table @asis @item Reason An error has occurred during interval construction and the NaI object has been produced (an empty interval in case of the bare interval constructor). The warning text contains further details. A NaI can be explicitly created with the @funref{nai} function. @item Possible consequences Nothing bad is going to happen, because the semantics of NaI and empty intervals are well defined by IEEE Std 1788-2015. However, the user might choose to cancel the algorithm immediately when the NaI is encountered for the first time. @end table @end table @end float @section Decorations The interval package provides a powerful decoration system for intervals, as specified by IEEE Std 1788-2015, IEEE standard for interval arithmetic. By default any interval carries a decoration, which collects additional information about the course of function evaluation on the interval data. Only the (unfavored) @funref{@@infsup/infsup} constructor creates bare, undecorated intervals and the @funref{@@infsupdec/intervalpart} operation may be used to demote decorated intervals into bare, undecorated ones. It is highly recommended to always use the decorated interval arithmetic, which gives additional information about an interval result in exchange for a tiny overhead. The following decorations are available: @float @multitable {Decoration ABC} {Bounded} {Continuous} {Defined} {Definition Definition Definition} @headitem Decoration @tab Bounded @tab Continuous @tab Defined @tab Definition @item com (common) @tab ✓ @tab ✓ @tab ✓ @tab x is a bounded, nonempty subset of Dom(f); f is continuous at each point of x; and the computed interval f(x) is bounded @item dac (defined and continuous) @tab @tab ✓ @tab ✓ @tab x is a nonempty subset of Dom(f); and the restriction of f to x is continuous @item def (defined) @tab @tab @tab ✓ @tab x is a nonempty subset of Dom(f) @item trv (trivial) @tab @tab @tab @tab always true@*(so gives no information) @item ill (ill-formed) @tab @tab @tab @tab Not an interval, at least one interval constructor failed during the course of computation @end multitable @end float The decoration information is especially useful after a very long and complicated function evaluation. For example, when the “def” decoration survives until the final result, it is proven that the overall function is actually defined for all values covered by the input intervals. Examples of using the decoration system @example @group x = infsupdec (3, 4) @result{} x = [3, 4]_com y = x - 3.5 @result{} y = [-0.5, +0.5]_com @end group @end example @example @group ## The square root function ignores any negative part of the input, ## but the decoration indicates whether this has or has not happened. sqrt (x) @result{} ans ⊂ [1.732, 2]_com sqrt (y) @result{} ans ⊂ [0, 0.70711]_trv @end group @end example Please note that decoration information will not survive through reverse operations (see below) and set operations. @section Specialized interval constructors Above mentioned interval construction with decimal numbers or numeric data is straightforward. Beyond that, there are more ways to define intervals or interval boundaries. @itemize @item Hexadecimal-floating-constant form: Each interval boundary may be defined by a hexadecimal number (optionally containing a point) and an exponent field with an integral power of two as defined by the C99 standard @uref{http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf,@asis{ISO/IEC9899, N1256, §6.4.4.2}}. This can be used as a convenient way to define interval boundaries in binary64 precision, because the hexadecimal form is much shorter than the decimal representation of many numbers. @item Rational literals: Each interval boundary may be defined as a fraction of two decimal numbers. This is especially useful if interval boundaries shall be tightest enclosures of fractions, that would be hard to write down as a decimal number. @item Uncertain form: The interval as a whole can be defined by a midpoint or upper/lower boundary and an integral number of @uref{http://en.wikipedia.org/wiki/Unit_in_the_last_place,“units in last place” (ULPs)} as an uncertainty. The format is @code{m?ruE}, where @table @code @item m is a mantissa in decimal, @item r is either empty (which means ½ ULP) or is a non-negative decimal integral ULP count or is the @option{?} character (for unbounded intervals), @item u is either empty (symmetrical uncertainty of r ULPs in both directions) or is either @option{u} (up) or @option{d} (down), @item E is either empty or an exponent field comprising the character @code{e} followed by a decimal integer exponent (base 10). @end table @end itemize Examples of different formats during interval construction @example @group infsupdec ("0x1.999999999999Ap-4") # hex-form @result{} ans ⊂ [0.1, 0.10001]_com @end group @end example @example @group infsupdec ("1/3", "7/9") # rational form @result{} ans ⊂ [0.33333, 0.77778]_com @end group @end example @example @group infsupdec ("121.2?") # uncertain form @result{} ans ⊂ [121.14, 121.25]_com @end group @end example @example @group infsupdec ("5?32e2") # uncertain form with ulp count @result{} ans = [-2700, +3700]_com @end group @end example @example @group infsupdec ("-42??u") # unbound uncertain form @result{} ans = [-42, +Inf]_dac @end group @end example The hex-form can be set for output with the @command{format hex} command. @section Reverse Arithmetic Operations Some arithmetic functions also provide reverse mode operations. That is inverse functions with interval constraints. For example the @funref{@@infsup/sqrrev} function can compute the inverse of the @code{@var{x} .^ 2} function on intervals. The syntax is @code{sqrrev (@var{C}, @var{X})} and will compute the enclosure of all numbers x ∈ @var{X} that fulfill the constraint x² ∈ @var{C}. In the following example, we compute the constraints for base and exponent of the power function pow as shown in the figure. @float Figure,reverse @caption{Reverse power operations. A relevant subset of the function's domain is outlined and hatched. In this example we use x^y ∈ [2, 3].} @shortcaption{Reverse power operations} @myimage{image/inverse-power.svg,Reverse Power Functions} @end float @example @group x = powrev1 (infsupdec ("[1.1, 1.45]"), infsupdec (2, 3)) @result{} x ⊂ [1.6128, 2.7149]_trv y = powrev2 (infsupdec ("[2.14, 2.5]"), infsupdec (2, 3)) @result{} y ⊂ [0.75647, 1.4441]_trv @end group @end example @section Tips and Tricks For convenience it is possible to implicitly call the interval constructor during all interval operations if at least one input already is an interval object. @example @group infsupdec ("17.7") + 1 @result{} ans ⊂ [18.699, 18.701]_com ans + "[0, 2]" @result{} ans ⊂ [18.699, 20.701]_com @end group @end example Interval functions with only one argument can be called by using property syntax, e. g. @code{x.inf}, @code{x.sup} or even @code{x.sqrt}. Whilst most functions (@funref{@@infsup/size}, @funref{@@infsup/isvector}, @funref{@@infsup/ismatrix}, …) work as expected on interval data types, the function @funref{@@infsup/isempty} is evaluated element-wise and checks if an interval equals the empty set. @example @group builtin ("isempty", empty ()) @result{} ans = 0 isempty (empty ()) @result{} ans = 1 @end group @end example @section Validation The interval package contains an extensive test suite, which can be run with the command @command{__run_test_suite__ (@{pkg("list", "interval")@{@}.dir@}, @{@})} to verify correct functionality for a particular system. In addition, examples from the package documentation can be verified using the doctest package: @example @c doctest: +SKIP @group pkg load doctest doctest (pkg ("list", "interval")@{@}.dir) @end group @end example interval-3.2.0/doc/chapter/examples.texinfo0000644000000000000000000003704513316017127017107 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2017 Oliver Heimlich. @c Copyright 2017 Joel Dahne @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @include macros.texinfo @chapter Examples This chapter presents some more or less exotic use cases for the interval package. @section Arithmetic with System-independent Accuracy According to IEEE Std 754 only the most basic floating-point operations must be provided with high accuracy. This is also true for the arithmetic functions in Octave. It is no surprise that many arithmetic functions fail to provide perfect results and their output may be system dependent. We compute the cosecant for 100 different values. @example @group x = vec (1 ./ magic (10)); sum (subset (csc (x), csc (infsupdec (x)))) @result{} ans = 98 @end group @end example Due to the general containment rule of interval arithmetic @code{x ∈ X ⇒ f (x) ∈ f (X)} one would expect the @code{csc (x)} to always be contained in the interval version of the cosecant for the same input. However, the classic cosecant is not very accurate whereas the interval version is. In 2 out 100 cases the built-in cosecant is less accurate than 1 ULP. @section Prove the Existence of a Fixed Point A weaker formulation of Brower's fixed-point theorem goes: If @var{x} is a bounded interval and function @var{f} is continuous and @var{f} (@var{x}) ⊂ @var{x}, then there exists a point @var{x}₀ ∈ @var{x} such that @var{f} (@var{x}₀) = @var{x}₀. These properties can be tested automatically. Decorated intervals can even prove that the function is continuous. @example @group x = infsupdec ("[-1, +1]"); f = @@cos; subset (f (x), x) @result{} ans = 1 iscommoninterval (x) @result{} ans = 1 continuous = strcmp (decorationpart (f (x)), "com") @result{} continuous = 1 @end group @end example Furthermore it is sometimes possible to approximate the fixed-point by repetitive evaluation of the function, although there are better methods to do so in general. @example @group for i = 1 : 20 x = f (x); endfor display (x) @result{} x ⊂ [0.73893, 0.73919]_com @end group @end example @menu Further Examples * Floating-point Numbers:: Analyze properties of binary64 numbers with intervals * Root Finding:: Find guaranteed enclosures for roots of a function * Parameter Estimation:: Examples of set inversion via interval analysis * Path Planning:: Find a feasible path between two points @end menu @node Floating-point Numbers @section Floating-point Numbers Floating-point numbers are most commonly used in binary64 format, a.k.a. double precision. Internally they are stored in the form @code{± @var{m} * 2 ^ @var{e}} with some integral mantissa @var{m} and exponent @var{e}. Most decimal fractions can only be stored approximately in this format. The @funref{intervaltotext} function can be used to output the approximate value up to the last decimal digit. @example @group intervaltotext (infsup (0.1), "[.55g]") @result{} ans = [0.1000000000000000055511151231257827021181583404541015625] @end group @end example It can be seen that 0.1 is converted into the most accurate floating-point number. In this case that value is greater than 0.1. The next lower value can be seen after producing an interval enclosure around 0.1 with the nearest floating-point numbers in each direction. @example @group intervaltotext (infsup ("0.1"), "[.55g]") @result{} ans = [0.09999999999999999167332731531132594682276248931884765625, 0.1000000000000000055511151231257827021181583404541015625] @end group @end example The error of this approximation can be examined with the @funref{@@infsup/wid} function. @example @group wid (infsup ("0.1")) @result{} ans = 1.3878e-17 @end group @end example With the @funref{@@infsup/nextout} function an interval can be enlarged in each direction up to the next floating-point number. Around zero the distance towards the next floating point number is very small, but gets bigger for numbers of higher magnitude. @example @group wid (nextout (infsup ([0, 1, 1e10, 1e100]))) @result{} ans = 9.8813e-324 3.3307e-16 3.8147e-06 3.8853e+84 @end group @end example @node Root Finding @section Root Finding @subsection Interval Newton Method In numerical analysis, @uref{https://en.wikipedia.org/wiki/Newton%27s_method,Newton's method} can find an approximation to a root of a function. Starting at a location @var{x}₀ the algorithms executes the following step to produce a better approximation: @display @var{x}₁ = @var{x}₀ @minus{} @var{f} (@var{x}₀) / @var{f}' (@var{x}₀) @end display The step can be interpreted geometrically as an intersection of the graph's tangent with the x-axis. Eventually, this may converge to a single root. In interval analysis, we start with an interval @var{x}₀ and utilize the following interval Newton step: @display @var{x}₁ = (mid (@var{x}₀) @minus{} @var{f} (mid (@var{x}₀)) / @var{f}' (@var{x}₀)) ∩ @var{x}₀ @end display Here we use the pivot element @code{mid (@var{x}₀)} and produce an enclosure of all possible tangents with the x-axis. In special cases the division with @code{@var{f}' (@var{x}₀)} yields two intervals and the algorithm bisects the search range. Eventually this algorithm produces enclosures for all possible roots of the function @var{f} in the interval @var{x}₀. The interval newton method is implemented by the function @funref{@@infsup/fzero}. To produce the derivative of function @var{f}, the automatic differentiation from the symbolic package bears a helping hand. However, be careful since this may introduce numeric errors with coefficients. @example @group @c doctest: +SKIP_IF(compare_versions (ver ("symbolic").Version, "2.5.0", "<")) f = @@(x) sqrt (x) + (x + 1) .* cos (x); @end group @group pkg load symbolic df = function_handle (diff (formula (f (sym ("x"))))) @result{} df = @@(x) -(x + 1) .* sin (x) + cos (x) + 1 ./ (2 * sqrt (x)) @end group @group @c doctest: +SKIP_IF(compare_versions (ver ("symbolic").Version, "2.5.0", "<")) fzero (f, infsup ("[0, 6]"), df) @result{} ans ⊂ 2×1 interval vector [2.059, 2.0591] [4.3107, 4.3108] @end group @end example We could find two roots in the interval [0, 6]. @subsection Bisection Consider the function @code{f (@var{x}, @var{y}) = -(5*@var{y} - 20*@var{y}^3 + 16*@var{y}^5)^6 + (-(5*@var{x} - 20*@var{x}^3 + 16*@var{x}^5)^3 + 5*@var{y} - 20*@var{y}^3 + 16*@var{y}^5)^2}, which has several roots in the area @var{x}, @var{y} ∈ [-1, 1]. @myimage{image/poly-example-surf.m,Surface plot of @code{f (@var{x}, @var{y})} which shows a lot of roots for the function} The function is particular difficult to compute with intervals, because its variables appear several times in the expression, which benefits overestimation from the dependency problem. Computing root enclosures with the @funref{@@infsup/fsolve} function is unfeasible, because many bisections would be necessary until the algorithm terminates with a useful result. It is possible to reduce the overestimation with the @funref{@@infsup/polyval} function to some degree, but since this function is quite costly to compute, it does not speed up the bisecting algorithm. @include image/poly-example-roots-simple.m.texinfo @myimage{image/poly-example-roots-simple.m,Enclosures of roots for the function @code{f (@var{x}, @var{y})}} Now we use the same algorithm with the same number of iterations, but also utilize the @emph{mean value theorem} to produce better enclosures of the function value with first order approximation of the function. The function is evaluated at the interval's midpoint and a range evaluation of the derivative can be used to produce an enclosure of possible function values. @include image/poly-example-roots-with-deriv.m.texinfo By using the derivative, it is possible to reduce overestimation errors and achieve a much better convergence behavior. @myimage{image/poly-example-roots-with-deriv.m,Enclosures of roots for the function @code{f (@var{x}, @var{y})}} @node Parameter Estimation @section Parameter Estimation @subsection Small Search Space Consider the model @code{y (@var{t}) = @var{p1} * exp (@var{p2} * t)}. The parameters @var{p1} and @var{p2} are unknown, but it is known that the model fulfills the following constraints, which have been obtained using measurements with known error bounds. @display @verbatim p1, p2 ∈ [-3, 3] y (0.2) ∈ [1.5, 2] y (1) ∈ [0.7, 0.8] y (2) ∈ [0.1, 0.3] y (4) ∈ [-0.1, 0.03] @end verbatim @end display A better enclosure of the parameters @var{p1} and @var{p2} can be estimated with the @funref{@@infsup/fsolve} function. @example @group ## Model y = @@(p1, p2, t) p1 .* exp (p2 .* t); ## Observations / Constraints t = [0.2; 1; 2; 4]; y_t = infsup ("[1.5, 2]; [0.7, 0.8]; [0.1, 0.3]; [-0.1, 0.03]"); ## Estimate parameters f = @@(p1, p2) y (p1, p2, t); p = fsolve (f, infsup ("[-3, 3]; [-3, 3]"), y_t) @result{} p ⊂ 2×1 interval vector [1.9863, 2.6075] [-1.3243, -1.0429] @end group @end example The resulting @code{p} guarantees to contain all parameters @code{[@var{p1}; @var{p2}]} which satisfy all constraints on @var{y}. It is no surprise that @code{f (p)} intersects the constraints for @var{y}. @example @group f (p(1), p(2)) @result{} ans ⊂ 4×1 interval vector [1.5241, 2.1166] [0.52838, 0.91888] [0.14055, 0.32382] [0.0099459, 0.040216] @end group @end example @subsection Larger Search Space Consider the function @code{f (x) = @var{p1} ^ x * (@var{p2} + @var{p3} * x + @var{p4} * x^2)}. Let's say we have some known function values (measurements) and want to find matching parameters @var{p1} through @var{p4}. The data sets (@var{x}, @var{y}) can be simulated. The parameters shall be reconstructed from the observed values on the search range @var{p}. Using plain @funref{@@infsup/fsolve} would take considerably longer, because the search range has 4 dimensions. Bisecting intervals requires an exponential number of steps and can easily become inefficient. Thus we use a contractor for function @var{f}, which in addition to the function value can produce a refinement for its parameter constraints. Contractors can easily be build using interval reverse operations like @funref{@@infsup/mulrev}, @funref{@@infsup/sqrrev}, @funref{@@infsup/powrev1}, etc. @example @c doctest: -TEXINFO_SKIP_BLOCKS_WO_OUTPUT @group ## Simulate some data sets and add uncertainty x = -6 : 3 : 18; f = @@(p1, p2, p3, p4) ... p1 .^ x .* (p2 + p3 .* x + p4 .* x .^ 2); y = f (1.5, 1, -3, 0.5) .* infsup ("[0.999, 1.001]"); @end group @group function [fval, p1, p2, p3, p4] = ... contractor (y, p1, p2, p3, p4) x = -6 : 3 : 18; ## Forward evaluation a = p1 .^ x; b = p3 .* x; c = p2 + b; d = p4 .* x .^ 2; e = c + d; fval = a .* e; ## Reverse evaluation and ## undo broadcasting of x y = intersect (y, fval); a = mulrev (e, y, a); e = mulrev (a, y, e); p1 = powrev1 (x, a, p1); p1 = intersect (p1, [], 2); c = intersect (c, e - d); d = intersect (d, e - c); p2 = intersect (p2, c - b); p2 = intersect (p2, [], 2); b = intersect (b, c - p2); p3 = mulrev (x, b, p3); p3 = intersect (p3, [], 2); p4 = mulrev (x .^ 2, d, p4); p4 = intersect (p4, [], 2); endfunction @end group @end example Now, search for solutions in the range of @code{p} and try to restore the function parameters. @example @group p = infsup ("[1.1, 2] [1, 5] [-5, -1] [0.1, 5]"); p = fsolve (@@contractor, ... p, y, ... struct ("Contract", true))' @result{} p ⊂ 4×1 interval vector [1.4991, 1.5009] [1, 1.0011] [-3.0117, -2.9915] [0.49772, 0.50578] @end group @end example The function parameters 1.5, 1, @minus{}3, and 0.5 from above could be restored. The contractor function could significantly improve the convergence speed of the algorithm. @subsection Combination of Functions Sometimes it is hard to express the search range in terms of a single function and its constraints, when the preimage of the function consists of a union or intersection of different parts. Several contractor functions can be combined using @funref{ctc_union} or @funref{ctc_intersect} to make a contractor function for more complicated sets. The combined contractor function allows one to solve for more complicated sets in a single step. @include image/contractor-rings-union.m.texinfo @myimage{image/contractor-rings-union.m,Set inversion for two rings} Intersections of contractor functions are especially useful to apply several constraints at once. For example, when it is known that a particular location has a distance of @var{a} ∈ [3, 4] from object A, located at coordinates (1, 3), and a distance of @var{b} ∈ [5, 6] from object B, located at coordinates (2, -1), the intersection of both rings yields all possible locations in the search range. The combined contractor function enables fast convergence of the search algorithm. @include image/contractor-rings-intersect.m.texinfo @myimage{image/contractor-rings-intersect.m,Set inversion for intersection of two rings} @node Path Planning @section Path Planning @float Figure,cameleon-problem @caption{Cameleon Problem: The polygon has to be moved from the left to the right without touching any obstacles along the path.} @shortcaption{Cameleon Problem Description} @myimage{image/cameleon-start-end.svg,Cameleon Problem: Start and End Position} @end float The problem presented here is a simplified version from the paper L. Jaulin (2001). @uref{https://www.ensta-bretagne.fr/jaulin/cameleon.html,Path planning using intervals and graphs.} Reliable Computing, issue 1, volume 7, 1–15. There is an object, a simple polygon in this case, which shall be moved from a starting position to a specified target position. Along the way there are obstacles which may not be touched by the polygon. The polygon can be moved in one direction (left to right or right to left) and may be rotated around its lower left corner. This makes a two dimensional parameter space and any feasible positions can be determined using interval arithmetic like in the examples above. Then we use a simple path planning algorithm: We move along the centers of adjacent and feasible boxes in the parameter space until we have a closed path from the start position to the end position. The path is guaranteed to be feasible, that is, there will be no collisions if we follow the path. @include image/cameleon.m.texinfo The script visualizes the solution in the parameter space. Unfeasible parameters are white, and uncertain combinations of parameters are red. The algorithm's accuracy is just good enough to find a closed path, which is drawn in green color. The uncertain red area is quite big because we have used a very simple check for verification whether the polygon overlaps the obstacles. This could be improved. @myimage{image/cameleon.m,Computed feasible path in parameter space} The solution is not optimal, please refer to Luc Jaulin's paper for more sophisticated approaches. However, we could find a valid solution that moves the polygon as desired without touching any obstacles. @float Figure,cameleon-solution @caption{Cameleon Problem: A possible solution which moves the polygon from the left to the right without touching obstacles.} @shortcaption{Cameleon Problem Solution} @html @end html @myimage{image/cameleon-transition.svg,Cameleon Problem: Transition from Start to End Position} @html @end html @end float interval-3.2.0/doc/chapter/getting-started.texinfo0000644000000000000000000004773413316017127020404 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2017 Oliver Heimlich. @c Copyright 2017 Joel Dahne @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @include macros.texinfo @chapter Getting Started This chapter takes you by the hand and gives a quick overview on the interval packages basic capabilities. More detailed information can usually be found in the functions' documentation. @section Installation It is recommended to install the package from specialized distributors for the particular platform, e. g., @uref{https://tracker.debian.org/pkg/octave-interval,Debian GNU/Linux}, @uref{https://trac.macports.org/browser/trunk/dports/math/octave-interval,MacPorts (for Mac OS X)}, @uref{http://www.freshports.org/math/octave-forge-interval/,FreshPorts (for FreeBSD)}, and so on. Since Octave version 4.0.1 the package is included in the @uref{https://ftp.gnu.org/gnu/octave/windows/,official installer for Microsoft Windows} and is installed automatically on that platform. In any case, the interval package can alternatively be installed with the @command{pkg} command from within Octave. Latest release versions are published at Octave Forge and can be automatically downloaded with the @option{-forge} option. @example @c doctest: +SKIP @group pkg install -forge interval   @print{} For information about changes from previous versions   @print{} of the interval package, run 'news interval'. @end group @end example During this kind of installation parts of the interval package are compiled for the target system, which requires development libraries for GNU Octave (version ≥ 3.8.0) and GNU MPFR (version ≥ 3.1.0) to be installed. It might be necessary to install packages “liboctave-dev” and “libmpfr-dev”, which are provided by most GNU distributions (names may vary). In order to use the interval package during an Octave session, it must have been @emph{loaded}, i. e., added to the path. In the following parts of the manual it is assumed that the package has been loaded, which can be accomplished with the @command{pkg load interval} command. It is recommended to add this command at the beginning of script files, especially if script files are published or shared. Automatic loading of the interval package can be activated by adding the line @command{pkg load interval} to your @file{.octaverc} file located in your user folder, for more information @pxref{Startup Files,,, octave, GNU Octave manual}. That's it. The package is ready to be used within Octave. @section Set-based Interval Arithmetic The most important and fundamental concepts in the context of the interval package are: @itemize @item Intervals are closed, connected subsets of the real numbers. Intervals may be unbound (in either or both directions) or empty. In special cases @code{+inf} and @code{-inf} are used to denote boundaries of unbound intervals, but any member of the interval is a @emph{finite} real number. @item Classical functions are extended to interval functions as follows: The result of function @var{f} evaluated on interval @var{x} is an interval enclosure of all possible values of @var{f} over @var{x} where the function is defined. Most interval arithmetic functions in this package manage to produce a very accurate such enclosure. @item The result of an interval arithmetic function is an interval in general. It might happen, that the mathematical range of a function consist of several intervals, but their union will be returned, e. g., 1 / [-1, 1] = [Entire]. @end itemize More details can be found in @ref{Introduction to Interval Arithmetic}. @section Input and Output Before exercising interval arithmetic, interval objects must be created from non-interval data. There are interval constants @funref{empty} and @funref{entire} and the interval constructors @funref{@@infsupdec/infsupdec} (create an interval from boundaries), @funref{midrad} (create an interval from midpoint and radius) and @funref{hull} (create an interval enclosure for a list of mixed arguments: numbers, intervals or interval literals). The constructors are very sophisticated and can be used with several kinds of parameters: Interval boundaries can be given by numeric values or string values with decimal numbers. Create intervals for performing interval arithmetic @example @group ## Interval with a single number infsupdec (1) @result{} ans = [1]_com @end group @end example @example @group ## Interval defined by lower and upper bound infsupdec (1, 2) @result{} ans = [1, 2]_com @end group @end example @example @group ## Boundaries are converted from strings infsupdec ("3", "4") @result{} ans = [3, 4]_com @end group @end example @example @group ## Decimal number infsupdec ("1.1") @result{} ans ⊂ [1.0999, 1.1001]_com @end group @end example @example @group ## Decimal number with scientific notation infsupdec ("5.8e-17") @result{} ans ⊂ [5.7999e-17, 5.8001e-17]_com @end group @end example @example @group ## Interval around 12 with uncertainty of 3 midrad (12, 3) @result{} ans = [9, 15]_com @end group @end example @example @group ## Again with decimal numbers midrad ("4.2", "1e-3") @result{} ans ⊂ [4.1989, 4.2011]_com @end group @end example @example @group ## Interval members with arbitrary order hull (3, 42, "19.3", "-2.3") @result{} ans ⊂ [-2.3001, +42]_com @end group @end example @example @group ## Symbolic numbers hull ("pi", "e") @result{} ans ⊂ [2.7182, 3.1416]_com @end group @end example @strong{Warning:} In above examples decimal fractions are passed as a string to the constructor. Otherwise it is possible, that GNU Octave introduces conversion errors when the numeric literal is converted into a floating-point number @emph{before} it is passed to the constructor. The interval construction is a critical process, but after this the interval package takes care of any further conversion errors, representational errors, round-off errors and inaccurate numeric functions. Beware of the conversion pitfall @example @group ## The numeric constant 0.3 is an approximation of the ## decimal number 0.3. An interval around this approximation ## will not contain the decimal number 0.3. output_precision (17) infsupdec (0.3) @result{} ans ⊂ [0.29999999999999998, 0.29999999999999999]_com @end group @end example @example @group ## However, passing the decimal number 0.3 as a string ## to the interval constructor will create an interval which ## actually encloses the decimal number. format short infsupdec ("0.3") @result{} ans ⊂ [0.29999, 0.30001]_com @end group @end example For maximum portability it is recommended to use interval literals, which are standardized by IEEE Std 1788-2015. Both interval boundaries are then given as a string in the form @code{[@var{l}, @var{u}]}. The output in the examples above gives examples of several interval literals. @example @group ## Interval literal infsupdec ("[20, 4.2e10]") @result{} ans = [20, 4.2e+10]_com @end group @end example The default text representation of intervals is not guaranteed to be exact, because this would massively spam console output. For example, the exact text representation of @code{realmin} would be over 700 decimal places long! However, the output is correct as it guarantees to contain the actual boundaries: a displayed lower (upper) boundary is always less (greater) than or equal to the actual boundary. @subsection Interval Vectors, Matrices and Arrays Vectors, matrices and arrays of intervals can be created by passing numerical arrays, string or cell arrays to the interval constructors. With cell arrays it is also possible to mix several types of boundaries. Interval arrays behave like normal arrays in GNU Octave and can be used for broadcasting and vectorized function evaluation. Vectorized function evaluation usually is the key to create very fast programs. Create interval arrays @example @group M = infsupdec (magic (3)) @result{} M = 3×3 interval matrix [8]_com [1]_com [6]_com [3]_com [5]_com [7]_com [4]_com [9]_com [2]_com @end group @end example @example @group infsupdec (magic (3), magic (3) + 1) @result{} ans = 3×3 interval matrix [8, 9]_com [1, 2]_com [6, 7]_com [3, 4]_com [5, 6]_com [7, 8]_com [4, 5]_com [9, 10]_com [2, 3]_com @end group @end example @example @group infsupdec ("0.1; 0.2; 0.3; 0.4; 0.5") @result{} ans ⊂ 5×1 interval vector [0.099999, 0.10001]_com [0.19999, 0.20001]_com [0.29999, 0.30001]_com [0.39999, 0.40001]_com [0.5]_com @end group @end example @example @group infsupdec ("1 [2, 3]; 4, 5, 6") @result{} ans = 2×3 interval matrix [1]_com [2, 3]_com [Empty]_trv [4]_com [5]_com [6]_com @end group @end example @example @group infsupdec (@{1; eps; "4/7"; "pi"@}, @{2; 1; "e"; "0xff"@}) @result{} ans ⊂ 4×1 interval vector [1, 2]_com [2.2204e-16, 1]_com [0.57142, 2.7183]_com [3.1415, 255]_com @end group @end example @example @group infsupdec (ones (2, 2, 2)) @result{} ans = 2×2×2 interval array ans(:,:,1) = [1]_com [1]_com [1]_com [1]_com ans(:,:,2) = [1]_com [1]_com [1]_com [1]_com @end group @end example Strings can easily be used to create vectors and matrices of intervals, @code{,} and @code{;} are used to denote the next element in the row or a new row. Octave does however not have way of representing arrays with three or more dimensions using strings in the same way. Therefore you can only create such arrays by passing numerical matrices or cells to the constructor. Alternatively you can build it up in steps. @example @group A = infsupdec ("1 [2, 3]; 4, 5; 6, 7") @result{} A = 3×2 interval matrix [1]_com [2, 3]_com [4]_com [5]_com [6]_com [7]_com A(:,:,2) = infsupdec ("0.1, 0.2; 0.3, 0.4; 0.5, 0.6") @result{} A ⊂ 3×2×2 interval array ans(:,:,1) = [1]_com [2, 3]_com [4]_com [5]_com [6]_com [7]_com ans(:,:,2) = [0.099999, 0.10001]_com [0.19999, 0.20001]_com [0.29999, 0.30001]_com [0.39999, 0.40001]_com [0.5]_com [0.59999, 0.60001]_com @end group @end example @section Arithmetic Operations The interval package comprises many interval arithmetic operations. A complete list can be found in its function reference. Function names match GNU Octave standard functions where applicable and follow recommendations by IEEE Std 1788-2015 otherwise, @pxref{Function Names}. The interval arithmetic flavor used by this package is the “set-based” interval arithmetic and follows these rules: Intervals are sets. They are subsets of the set of real numbers. The interval version of an elementary function such as sin(x) is essentially the natural extension to sets of the corresponding point-wise function on real numbers. That is, the function is evaluated for each number in the interval where the function is defined and the result must be an enclosure of all possible values that may occur. By default arithmetic functions are computed with best possible accuracy (which is more than what is guaranteed by GNU Octave core functions). The result will therefore be a tight and very accurate enclosure of the true mathematical value in most cases. Details on each function's accuracy can be found in its documentation, which is accessible with GNU Octave's @command{help} command. Examples of using interval arithmetic functions @example @group sin (infsupdec (0.5)) @result{} ans ⊂ [0.47942, 0.47943]_com @end group @end example @example @group power (infsupdec (2), infsupdec (3, 4)) @result{} ans = [8, 16]_com @end group @end example @example @group atan2 (infsupdec (1), infsupdec (1)) @result{} ans ⊂ [0.78539, 0.7854]_com @end group @end example @example @group midrad (magic (3), 0.5) * pascal (3) @result{} ans = 3×3 interval matrix [13.5, 16.5]_com [25, 31]_com [42, 52]_com [13.5, 16.5]_com [31, 37]_com [55, 65]_com [13.5, 16.5]_com [25, 31]_com [38, 48]_com @end group @end example @section Numerical Operations Some interval functions do not return an interval enclosure, but a single number (in binary64 precision). Most important are @funref{@@infsup/inf} and @funref{@@infsup/sup}, which return the lower and upper interval boundaries. More such operations are @funref{@@infsup/mid} (approximation of the interval's midpoint), @funref{@@infsup/wid} (approximation of the interval's width), @funref{@@infsup/rad} (approximation of the interval's radius), @funref{@@infsup/mag} (interval's magnitude) and @funref{@@infsup/mig} (interval's mignitude). @example @group ## Enclosure of the decimal number 0.1 is not exact ## and results in an interval with a small uncertainty. wid (infsupdec ("0.1")) @result{} ans = 1.3878e-17 @end group @end example @section Boolean Operations Interval comparison operations produce boolean results. While some comparisons are especially for intervals (@funref{@@infsup/subset}, @funref{@@infsup/interior}, @funref{@@infsup/ismember}, @funref{@@infsup/isempty}, @funref{@@infsup/disjoint}, …) others are interval extensions of simple numerical comparison. For example, the less-or-equal comparison is mathematically defined as ∀a ∃b a ≤ b ∧ ∀b ∃a a ≤ b. @example @group infsup (1, 3) <= infsup (2, 4) @result{} ans = 1 @end group @end example @section Matrix and Array Operations Above mentioned operations can also be applied element-wise to interval vectors, matrices or arrays. Many operations use vectorization techniques. In addition, there are operations on interval matrices and arrays. These operations comprise: dot product, matrix multiplication, vector sums (all with tightest accuracy), matrix inversion, matrix powers, and solving linear systems (the latter are less accurate). As a result of missing hardware / low-level library support and missing optimizations, these operations are relatively slow compared to familiar operations in floating-point arithmetic. Examples of using interval matrix functions @example @group A = infsupdec ([1, 2, 3; 4, 0, 0; 0, 0, 1]); A (2, 3) = "[0, 6]" @result{} A = 3×3 interval matrix [1]_com [2]_com [3]_com [4]_com [0]_com [0, 6]_com [0]_com [0]_com [1]_com @end group @end example @example @group B = inv (A) @result{} B = 3×3 interval matrix [0]_trv [0.25]_trv [-1.5, 0]_trv [0.5]_trv [-0.125]_trv [-1.5, -0.75]_trv [0]_trv [0]_trv [1]_trv @end group @end example @example @group A * B @result{} ans = 3×3 interval matrix [1]_trv [0]_trv [-1.5, +1.5]_trv [0]_trv [1]_trv [-6, +6]_trv [0]_trv [0]_trv [1]_trv @end group @end example @example @group A = infsupdec (magic (3)) @result{} A = 3×3 interval matrix [8]_com [1]_com [6]_com [3]_com [5]_com [7]_com [4]_com [9]_com [2]_com @end group @end example @example @group c = A \ [3; 4; 5] @result{} c ⊂ 3×1 interval vector [0.18333, 0.18334]_trv [0.43333, 0.43334]_trv [0.18333, 0.18334]_trv @end group @end example @example @group A * c @result{} ans ⊂ 3×1 interval vector [2.9999, 3.0001]_trv [3.9999, 4.0001]_trv [4.9999, 5.0001]_trv @end group @end example @subsection Notes on Linear Systems A system of linear equations in the form A@var{x} = b with intervals can be seen as a range of classical linear systems, which can be solved simultaneously. Whereas classical algorithms compute an approximation for a single solution of a single linear system, interval algorithms compute an enclosure for all possible solutions of (possibly several) linear systems. Some characteristics should definitely be known when linear interval systems are solved: @itemize @item If the linear system is underdetermined and has infinitely many solutions, the interval solution will be unbound in at least one of its coordinates. Contrariwise, from an unbound result it can not be concluded whether the linear system is underdetermined or has solutions. @item If the interval result is empty in at least one of its coordinates, the linear system is guaranteed to be overdetermined and has no solutions. Contrariwise, from a non-empty result it can not be concluded whether all or some of the systems have solutions or not. @item Wide intervals within the matrix A can easily lead to a superposition of cases, where the rank of A is no longer unique. If the linear interval system contains cases of linear independent equations as well as linear dependent equations, the resulting enclosure of solutions will inevitably be very broad. @end itemize However, solving linear systems with interval arithmetic can produce useful results in many cases and automatically carries a guarantee for error boundaries. Additionally, it can give better information than the floating-point variants for some cases. Standard floating point arithmetic versus interval arithmetic on ill-conditioned linear systems @example @group A = [1, 0; 2, 0]; ## This linear system has no solutions A \ [3; 0] @print{} warning: ...matrix singular to machine precision... @result{} ans = 0.60000 0.00000 @end group @end example @example @group ## This linear system has many solutions A \ [4; 8] @result{} ans = 4 0 @end group @end example @example @group ## The empty interval vector proves that there is no solution infsup (A) \ [3; 0] @result{} ans = 2×1 interval vector [Empty] [Empty] @end group @end example @example @group ## The unbound interval vector indicates ## that there may be many solutions infsup (A) \ [4; 8] @result{} ans = 2×1 interval vector [4] [Entire] @end group @end example @section Plotting Plotting of intervals in 2D and 3D can be achieved with the functions @funref{@@infsup/plot} and @funref{@@infsup/plot3} respectively. However, some differences in comparison with classical plotting in Octave shall be noted. When plotting classical (non-interval) functions in Octave, one normally uses a vector and evaluates a function on that vector element-wise. The resulting X and Y (and possibly Z) coordinates are then drawn against each other, whilst coordinates can be connected using interpolated lines. The plot shows an approximation of the function's graph and the accuracy (and smoothness of the graph) primarily depends on the number of coordinates where the function has been evaluated. Evaluating the same function on a single interval (e. g. the part of the function's domain that is of interest) yields a single interval result which covers the actual range of the function. Plotting just two intervals, input and output, against each other is boring, because the plot would only show a single rectangle. Contrariwise, evaluating the function for many individual points (e. g. using @funref{@@infsup/linspace}) would hardly fit in the philosophy of interval arithmetic. Individual points of evaluation are not interconnected by the interval plotting functions, because that would introduce errors. The solution for plotting functions with interval arithmetic is called: “mincing”. The @funref{@@infsup/mince} function divides an interval into many smaller adjacent subsets, which can be used for range evaluations of the function. As a result, one gets vectors of intervals, which produce a coverage of the function's graph using rectangles. Please note, how the rectangles cover the sine function's true range from @minus{}1 to 1 in the following example, whilst the interpolated lines make a poor approximation. @include image/interval-vs-normal-plot.m.texinfo @myimage{image/interval-vs-normal-plot.m,Plotting an interval function and a classic function} For 3D plotting the Octave meshgrid function, as usual, becomes handy. The following example shows how two different ranges for X and Y coordinates are used to construct a grid, where the function @funref{@@infsup/atan2} is evaluated. In this particular case the interval grid has gaps, because X and Y coordinates have been constructed such that intervals do not intersect. @include image/interval-plot3.m.texinfo @myimage{image/interval-plot3.m,Plotting 3D interval grid points} interval-3.2.0/doc/chapter/ieee-1788.texinfo0000644000000000000000000004662013316017127016604 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2016 Oliver Heimlich. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @include macros.texinfo @appendix IEEE Std 1788-2015 The IEEE standard for interval arithmetic is an important asset for the general use of interval arithmetic. Several interval arithmetic libraries have been created (most popular for the language C++), which vary greatly in their philosophy, completeness and—most important—mathematical definition of certain functions and arithmetic evaluation. The standard grants support for several interval arithmetic flavors, but fights incompatibilities on many layers: Interval arithmetic applications shall be portable, predictable, and reproducible. This is especially important since interval arithmetic shall lead to reliable results. Also a common standard is necessary to catalyze the availability of (fast) interval operations in hardware. For all conforming implementations certain accuracy constraints must be satisfied and a good amount of interval functions must be implemented. It is defined how to handle functions that are not globally defined or have limiting values. Also such basic things like interval representation, many useful constructors, and interchange encoding are addressed. The interval package for GNU Octave is the first complete implementation that claims to be standard conforming. @menu * Function Names:: List of functions defined by IEEE Std 1788-2015@*and how they have been implemented in GNU Octave * Conformance Claim:: Official statement and some@*implementation specific details regarding the standard @end menu @node Function Names @appendixsec Function Names In terms of a better integration into the GNU Octave language, several operations use a function name which is different from the name proposed in the standard document. The following table translates and lists the implemented function names of the IEEE standard for interval arithmetic. The implementation provides several additional functions, but this section lists only functions that are mentioned in IEEE Std 1788-2015. @appendixsubsec Interval constants See @funref{empty} and @funref{entire}. @appendixsubsec Constructors The operations textToInterval (@var{S}), numsToInterval (@var{l}, @var{u}), and setDec (@var{x}) are implemented by the class constructors @funref{@@infsup/infsup} for bare intervals and @funref{@@infsupdec/infsupdec} for decorated intervals. @appendixsubsec Required functions @float Table,tab:required-forward-functions @caption{Required forward elementary functions} @shortcaption{Required forward elementary functions} @multitable {roundTiesToAway (x)} {@@infsupdec/iscommoninterval} {Tightness (and comments...)} @headitem Operation @tab Implementation @tab Tightness @ifnottex @headitem @tab @r{@emph{Basic operations}} @tab @end ifnottex @item neg (@var{x}) @tab@funref{@@infsup/uminus} @tab tightest @item add (@var{x}, @var{y}) @tab@funref{@@infsup/plus} @tab tightest @item sub (@var{x}, @var{y}) @tab@funref{@@infsup/minus} @tab tightest @item mul (@var{x}, @var{y}) @tab@funref{@@infsup/times} @tab tightest @item div (@var{x}, @var{y}) @tab@funref{@@infsup/rdivide} @tab tightest @item recip (@var{x}) @tab@code{1 ./ @var{x}} @tab tightest @item sqr (@var{x}) @tab@code{@var{x} .^ 2} @tab tightest @item sqrt (@var{x}) @tab@funref{@@infsup/realsqrt} @tab tightest @item fma (@var{x}, @var{y}, @var{z}) @tab@funref{@@infsup/fma} @tab tightest @ifnottex @headitem @tab @r{@emph{Power functions}} @tab @end ifnottex @item pown (@var{x}, @var{p}) @tab@funref{@@infsup/pown} @tab tightest @item pow (@var{x}, @var{y}) @tab@funref{@@infsup/pow} @tab tightest @item exp (@var{x}) @tab@funref{@@infsup/exp} @tab tightest @item exp2 (@var{x}) @tab@funref{@@infsup/pow2} @tab tightest @item exp10 (@var{x}) @tab@funref{@@infsup/pow10} @tab tightest @item log (@var{x}) @tab@funref{@@infsup/log} @tab tightest @item log2 (@var{x}) @tab@funref{@@infsup/log2} @tab tightest @item log10 (@var{x}) @tab@funref{@@infsup/log10} @tab tightest @ifnottex @headitem @tab @r{@emph{Trigonometric / hyperbolic}} @tab @end ifnottex @item sin (@var{x}) @tab@funref{@@infsup/sin} @tab tightest @item cos (@var{x}) @tab@funref{@@infsup/cos} @tab tightest @item tan (@var{x}) @tab@funref{@@infsup/tan} @tab tightest @item asin (@var{x}) @tab@funref{@@infsup/asin} @tab tightest @item acos (@var{x}) @tab@funref{@@infsup/acos} @tab tightest @item atan (@var{x}) @tab@funref{@@infsup/atan} @tab tightest @item atan2 (@var{y}, @var{x}) @tab@funref{@@infsup/atan2} @tab tightest @item sinh (@var{x}) @tab@funref{@@infsup/sinh} @tab tightest @item cosh (@var{x}) @tab@funref{@@infsup/cosh} @tab tightest @item tanh (@var{x}) @tab@funref{@@infsup/tanh} @tab tightest @item asinh (@var{x}) @tab@funref{@@infsup/asinh} @tab tightest @item acosh (@var{x}) @tab@funref{@@infsup/acosh} @tab tightest @item atanh (@var{x}) @tab@funref{@@infsup/atanh} @tab tightest @ifnottex @headitem @tab @r{@emph{Integer functions}} @tab @end ifnottex @item sign (@var{x}) @tab@funref{@@infsup/sign} @tab tightest @item ceil (@var{x}) @tab@funref{@@infsup/ceil} @tab tightest @item floor (@var{x}) @tab@funref{@@infsup/floor} @tab tightest @item trunc (@var{x}) @tab@funref{@@infsup/fix} @tab tightest @item roundTiesToEven (@var{x}) @tab@funref{@@infsup/roundb} @tab tightest @item roundTiesToAway (@var{x}) @tab@funref{@@infsup/round} @tab tightest @ifnottex @headitem @tab @r{@emph{Absmax functions}} @tab @end ifnottex @item abs (@var{x}) @tab@funref{@@infsup/abs} @tab tightest @item min (@var{x}, @var{y}) @tab@funref{@@infsup/min} @tab tightest @item max (@var{x}, @var{y}) @tab@funref{@@infsup/max} @tab tightest @end multitable @end float @float Table,tab:required-reverse-functions @caption{Required reverse functions} @shortcaption{Required reverse functions} @multitable {roundTiesToAway (x)} {@@infsupdec/iscommoninterval} {Tightness (and comments...)} @headitem Operation @tab Implementation @tab Tightness @ifnottex @headitem @tab @r{@emph{From unary functions}} @tab @end ifnottex @item sqrRev (@var{c}, @var{x}) @tab@funref{@@infsup/sqrrev} @tab tightest @item absRev (@var{c}, @var{x}) @tab@funref{@@infsup/absrev} @tab tightest @item pownRev (@var{c}, @var{x}, @var{p}) @tab@funref{@@infsup/pownrev} @tab valid (tightest for @var{p} ≥ @minus{}2) @item sinRev (@var{c}, @var{x}) @tab@funref{@@infsup/sinrev} @tab valid @item cosRev (@var{c}, @var{x}) @tab@funref{@@infsup/cosrev} @tab valid @item tanRev (@var{c}, @var{x}) @tab@funref{@@infsup/tanrev} @tab valid @item coshRev (@var{c}, @var{x}) @tab@funref{@@infsup/coshrev} @tab tightest @ifnottex @headitem @tab @r{@emph{From binary functions}} @tab @end ifnottex @item mulRev (@var{b}, @var{c}, @var{x}) @tab@funref{@@infsup/mulrev} @tab tightest @item powRev1 (@var{b}, @var{c}, @var{x}) @tab@funref{@@infsup/powrev1} @tab valid @item powRev2 (@var{a}, @var{c}, @var{x}) @tab@funref{@@infsup/powrev2} @tab valid @item atan2Rev1 (@var{b}, @var{c}, @var{x}) @tab@funref{@@infsup/atan2rev1} @tab valid @item atan2Rev2 (@var{a}, @var{c}, @var{x}) @tab@funref{@@infsup/atan2rev2} @tab valid @ifnottex @headitem @tab @r{@emph{Two-output division}} @tab @end ifnottex @item mulRevToPair (@var{b}, @var{c}) @tab@funref{@@infsup/mulrev} @tab tightest @ifnottex @headitem @tab @r{@emph{Cancellative addition@*and subtraction}} @tab @end ifnottex @item cancelMinus (@var{x}, @var{y}) @tab@funref{@@infsup/cancelminus} @tab tightest @item cancelPlus (@var{x}, @var{y}) @tab@funref{@@infsup/cancelplus} @tab tightest @end multitable @end float @float Table,tab:required-set-operations @caption{Required set operations} @shortcaption{Required set operations} @multitable {roundTiesToAway (x)} {@@infsupdec/iscommoninterval} {Tightness (and comments...)} @headitem Operation @tab Implementation @tab Tightness @item intersection (@var{x}, @var{y}) @tab@funref{@@infsup/intersect} @tab tightest @item convexHull (@var{x}, @var{y}) @tab@funref{@@infsup/union} @tab tightest @end multitable @end float @float Table,tab:required-numeric-functions @caption{Required numeric functions of intervals} @shortcaption{Required numeric functions of intervals} @multitable {roundTiesToAway (x)} {@@infsupdec/iscommoninterval} {Tightness (and comments...)} @headitem Operation @tab Implementation @tab Rounding mode @item inf (@var{x}) @tab@funref{@@infsup/inf} @tab @item sup (@var{x}) @tab@funref{@@infsup/sup} @tab @item mid (@var{x}) @tab@funref{@@infsup/mid} @tab to nearest, ties to even @item wid (@var{x}) @tab@funref{@@infsup/wid} @tab toward +∞ @item rad (@var{x}) @tab@funref{@@infsup/rad} @tab toward +∞ @item mag (@var{x}) @tab@funref{@@infsup/mag} @tab @item mig (@var{x}) @tab@funref{@@infsup/mig} @tab @end multitable @end float @float Table,tab:required-boolean-functions @caption{Required boolean functions of intervals} @shortcaption{Required boolean functions of intervals} @multitable {roundTiesToAway (x)} {@@infsupdec/iscommoninterval} {Tightness (and comments...)} @headitem Operation @tab Implementation @tab Description @item isEmpty (@var{x}) @tab@funref{@@infsup/isempty} @tab @var{x} is the empty set @item isEntire (@var{x}) @tab@funref{@@infsup/isentire} @tab @var{x} is the whole line @item equal (@var{a}, @var{b}) @tab@funref{@@infsup/eq} @tab @var{a} equals @var{b} @item subset (@var{a}, @var{b}) @tab@funref{@@infsup/subset} @tab @var{a} is a subset of @var{b} @item less (@var{a}, @var{b}) @tab@funref{@@infsup/le} @tab @var{a} is weakly less than @var{b} @item precedes (@var{a}, @var{b}) @tab@funref{@@infsup/precedes} @tab @var{a} is left of but may touch @var{b} @item interior (@var{a}, @var{b}) @tab@funref{@@infsup/interior} @tab @var{a} is interior to @var{b} @item strictLess (@var{a}, @var{b}) @tab@funref{@@infsup/lt} @tab @var{a} is strictly less than @var{b} @item strictPrecedes (@var{a}, @var{b}) @tab@funref{@@infsup/strictprecedes} @tab @var{a} is strictly left of @var{b} @item disjoint (@var{a}, @var{b}) @tab@funref{@@infsup/disjoint} @tab @var{a} and @var{b} are disjoint @end multitable @end float @appendixsubsec Recommended functions @float Table,tab:recommended-functions @caption{Recommended functions} @shortcaption{Recommended functions} @multitable {roundTiesToAway (x)} {@@infsupdec/iscommoninterval} {Tightness (and comments...)} @headitem Operation @tab Implementation @tab Tightness / Comments @ifnottex @headitem @tab @r{@emph{Elementary functions}} @tab @end ifnottex @item rootn (@var{x}, @var{q}) @tab@funref{@@infsup/nthroot} @tab valid (tightest for @var{q} ≥ @minus{}2) @item expm1 (@var{x}) @tab@funref{@@infsup/expm1} @tab tightest @item logp1 (@var{x}) @tab@funref{@@infsup/log1p} @tab tightest @item hypot (@var{x}, @var{y}) @tab@funref{@@infsup/hypot} @tab tightest @item rSqrt (@var{x}) @tab@funref{@@infsup/rsqrt} @tab tightest @ifnottex @headitem @tab @r{@emph{Boolean functions}} @tab @end ifnottex @item isCommonInterval (@var{x}) @tab@funref{@@infsup/iscommoninterval} @tab (=bound and non-empty) @item isSingleton (@var{x}) @tab@funref{@@infsup/issingleton} @tab (=single real) @item isMember (@var{m}, @var{x}) @tab@funref{@@infsup/ismember} @tab @ifnottex @headitem @tab @r{@emph{Extended comparison}} @tab @end ifnottex @item overlap (@var{a}, @var{b}) @tab@funref{@@infsup/overlap} @tab @end multitable @end float @appendixsubsec Operations on/with decorations See @funref{@@infsup/newdec}, @funref{@@infsupdec/intervalpart}, and @funref{@@infsupdec/decorationpart}. The operation setDec is implemented by @funref{@@infsupdec/infsupdec}. For comparison of decorations with respect to the propagation order @code{com > dac > def > trv > ill} use the numeric value returned by @code{decorationpart (@var{x}, "uint8")}. @appendixsubsec Reduction operations See @funref{mpfr_vector_sum_d} and @funref{mpfr_vector_dot_d}. The operations @code{sumAbs} and @code{sumSquare} can be computed with @code{mpfr_vector_sum_d (@var{rounding mode}, abs (@var{x}))} and @code{mpfr_vector_dot_d (@var{rounding mode}, @var{x}, @var{x})} respectively. @appendixsubsec Input The operation @code{textToInterval} is implemented by the class constructors @funref{@@infsup/infsup} for bare intervals and @funref{@@infsupdec/infsupdec} for decorated intervals. Both are able to operate on interval literals provided as strings. @appendixsubsec Output See @funref{intervaltotext}. @appendixsubsec Exact text representation See @funref{exacttointerval} and @funref{@@infsup/intervaltoexact}. @appendixsubsec Interchange representation and encoding See @funref{interval_bitpack} and @funref{@@infsup/bitunpack}. @node Conformance Claim @appendixsec Conformance Claim The inverval package version @value{version} for GNU Octave is conforming to IEEE Std 1788-2015, IEEE Standard for Interval Arithmetic. It is conforming to the set-based flavor with IEEE 754 conformance for the infsup binary64 interval type and without compressed arithmetic. Additionally it provides no further flavors. @appendixsec Conformance Questionnaire @html
@end html @enumerate a @item Implementation-defined behavior @enumerate 1 @item What status flags or other means to signal the occurrence of certain decoration values in computations does the implementation provide if any? The implementation does not signal the occurrence of decoration values. @end enumerate @item Documentation of behavior @enumerate 1 @item If the implementation supports implicit interval types, how is the interval hull operation realized? The implementation supports explicit interval types only. @item What accuracy is achieved (i.e., tightest, accurate, or valid) for each of the implementation’s interval operations? The accuracy requirements of IEEE Std 1788-2015 are fulfilled. Most operations achieve tightest accuracy, some operations (especially reverse operations) do not. The tightness of each operation is documented in the function's documentation string and can be displayed with the @command{help} command. @item Under what conditions is a constructor unable to determine whether a Level 1 value exists that corresponds to the supplied inputs? When two different string boundaries for an interval both lie between the same two subsequent binary64 numbers, a PossiblyUndefined warning is created. @item How are ties broken in rounding numbers if multiple numbers qualify as the rounded result? Tie-breaking uses the IEEE Std 754 default: round ties to even. @item How are interval datums converted to their exact text representations? The binary64 boundaries are converted into hexadecimal-significand form as required by the standard. It is also possible to convert interval datums to exact interval literals in decimal form, see optional arguments of function @funref{intervaltotext} for that purpose. @end enumerate @item Implementation-defined behavior @enumerate 1 Does the implementation include the interval overlapping function? If so, how is it made available to the user? Yes, the interval overlapping function is implemented under the name @funref{@@infsup/overlap}. @item Does the implementation store additional information in a NaI? What functions are provided for the user to set and read this information? No additional information is stored in a NaI. @item What means if any does the implementation provide for an exception to be signaled when a NaI is produced? The creation of a NaI is signaled with GNU Octave's warning mechanism. @item What interval types are supported besides the required ones? None. @item What mechanisms of exception handling are used in exception handlers provided by the implementation? What additional exception handling is provided by the implementation? The exceptions described by IEEE Std 1788-2015 raise a warning, which can be handled with GNU Octave's warning mechanism. The warning may be customized to produce an error instead and interrupt computation. The implementation provides no additional exception handling. @item [Question does not apply to IEEE 754 conforming types.] @item Does the implementation include different versions of the same operation for a given type and how are these provided to the user? The interval matrix multiplication (see @funref{@@infsup/mtimes}) offers two implementations, with either @option{tightest} or @option{valid} accuracy. The user may chose the desired version with an optional argument during the function call. @item What combinations of formats are supported in interval constructors? Any reasonable combination of the formats described in the standard document is supported. @item [Question does not apply to IEEE 754 conforming types.] @item What methods are used to read or write strings from or to character streams? Does the implementation employ variations in locales (such as specific character case matching)? This includes the syntax used in the strings for reading and writing. Input and output is implemented with GNU Octave string variables in UTF-8 encoding. There is no discrimination between different locales. Character case is ignored during input. The syntax for interval literals is used as described by the standard document. @item What is the tightness for the interval to string conversion for all interval types? The general-purpose interval to string conversion produces the tightest decimal infsup form which has no more digits than are necessary to separate two binary64 numbers. @item What is the result of Level 3 operations for invalid inputs? Interval constructors prevent the creation of invalid Level 3 interval datums. Any non-interval input to Level 3 operations is implicitly converted into an interval and the operation silently continues on interval inputs. If at least one input is a decorated interval, bare interval inputs are implicitly decorated as described by @command{newDec} in the standard document. Implicit promotion from a bare interval to a decorated interval is signaled with GNU Octave's warning mechanism. If implicit conversion fails (e.g., illegal interval literals), bare interval operations produce empty intervals, whereas the decorated interval operations continue on NaI inputs. @item [Question does not apply to IEEE 754 conforming types.] @item What decorations does the implementation provide and what is their mathematical definition? How are these decorations mapped when converting an interval to the interchange format? The implementation provides the decorations com, dac, def, trv, and ill as described by the standard document. @item [Question does not apply to IEEE 754 conforming types.] @end enumerate @item [Question applies to compressed arithmetic only, which is not supported.] @item [Questions apply to non-standard flavors only, which are not supported.] @end enumerate interval-3.2.0/doc/chapter/introduction-to-interval-arithmetic.texinfo0000644000000000000000000003261213316017127024376 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2016 Oliver Heimlich. @c Copyright 2008-2009 Simone Pernice. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @include macros.texinfo @chapter Introduction to Interval Arithmetic @quotation Give a digital computer a problem in arithmetic, and it will grind away methodically, tirelessly, at gigahertz speed, until ultimately it produces the wrong answer. … An interval computation yields a pair of numbers, an upper and a lower bound, which are guaranteed to enclose the exact answer. Maybe you still don’t know the truth, but at least you know how much you don’t know. @author Brian Hayes, @uref{http://dx.doi.org/10.1511/2003.6.484,DOI: 10.1511/2003.6.484} @end quotation Interval arithmetic adds two unique features to ordinary computer arithmetic: (1) Functions can be evaluated over (connected) subsets of their domain, and (2) any computational errors are automatically considered and are accumulated in the final outcome. In conjunction they yield a @emph{verified result enclosure} over a range of input values. These possibilities of interval arithmetic enable great new possibilities, but what is wrong with the well-known computer arithmetic in the first place? @section Motivation Floating-point arithmetic, as specified by @uref{http://en.wikipedia.org/wiki/IEEE_floating_point,IEEE Std 754}, is available in almost every computer system today. It is wide-spread, implemented in common hardware and integral part in programming languages. For example, the binary64 format (a.k.a. double-precision) is the default numeric data type in GNU Octave. Benefits are obvious: The results of arithmetic operations are (mostly) well-defined and comparable between different systems and computation is highly efficient. However, there are some downsides of floating-point arithmetic in practice, which will eventually produce errors in computations. Generally speaking, most of these problems occur in any arithmetic with finite precision. @itemize @item Floating-point arithmetic is often used mindlessly by developers. @url{http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html} @url{http://www.cs.berkeley.edu/~wkahan/Mindless.pdf} @url{http://www.ima.umn.edu/~arnold/disasters/} @item The binary (base-2) data types categorically are not suitable for doing financial computations. Very often representational errors are introduced when using “real world” decimal numbers. @url{http://en.wikipedia.org/wiki/Decimal_computer} @item Even if the developer would be proficient, most developing environments / technologies limit floating-point arithmetic capabilities to a very limited subset of IEEE Std 754: Only one or two data types, no rounding modes, missing functions, … @url{http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf} @item Results are @uref{https://hal.archives-ouvertes.fr/hal-00128124/en/,hardly predictable}. All operations produce the best possible accuracy at runtime, this is how a floating point works. Contrariwise, financial computer systems typically use a @uref{http://en.wikipedia.org/wiki/Fixed-point_arithmetic,fixed-point arithmetic} (COBOL, PL/I, …), where overflow and rounding can be precisely predicted at @emph{compile-time}. @item Results are system dependent. All but the most basic floating-point operations are @uref{http://www.gnu.org/software/libc/manual/html_node/Errors-in-Math-Functions.html#Errors-in-Math-Functions,not guaranteed to be accurate} and produce different results depending on low level libraries and @uref{http://developer.amd.com/tools-and-sdks/cpu-development/libm/,hardware}. @item If you do not know the technical details (cf. first bullet) you ignore the fact that the computer lies to you in many situations. For example, when looking at numerical output and the computer says “@code{ans = 0.1},” this is not absolutely correct. In fact, the value is only close enough to the value 0.1. Additionally, many functions produce limit values (∞ × −∞ = −∞, ∞ ÷ 0 = ∞, ∞ ÷ −0 = −∞, log (0) = −∞), which is sometimes (but not always!) useful when overflow and underflow occur. @end itemize Interval arithmetic addresses above problems in its very special way. It accepts the fact that numbers cannot be stored or computed with infinite precision and introduces enclosures of exact values, which can be computed on any machine with finite precision. This introduces new possibilities for algorithms. Any errors are covered by the range of an interval during the course of computation. All members of intervals are by definition finite real numbers, which results in an exception free and mathematically well-defined arithmetic. The possibility to actually evaluate a function on a connected range of values and compute a guaranteed enclosure of all possible values is a unique selling point. For example, the @uref{http://en.wikipedia.org/wiki/Interval_arithmetic#Interval_Newton_method,interval newton method} (see @funref{@@infsup/fzero}) is able to find @emph{all} zeros of a particular function. More precisely, the algorithm is able to reliably eliminate ranges of values where the function cannot have a root by a simple interval evaluation of either the function itself or its derivative. Global convergence can be achieved by bisecting the intermediate ranges. @section Error bounds in real life @c This section is largely based on the documentation for the Octave SIMP package by Simone Pernice. Intervals can be used instead of simple numbers to automatically take into account the tolerance (or uncertainty) of the values used in calculation. Every day we need to compute the result of a lot of simple mathematical equations. For example the cost of the apples bought at the farmer's market is given by: @display apple price = apple cost per kilo · kilos of apple bought @end display When we need the result of those mathematical expressions, we put the values on the right hand side of the equation and we compute its result for the left hand side. We usually put wrong (erroneous) numbers into the equation and therefore where is no doubt we get wrong results. There are a lot of reasons why we use incorrect values, for example @enumerate @item Most of the values are measured, therefore they are known within a given tolerance. @uref{http://en.wikipedia.org/wiki/Accuracy_and_precision,Wikipedia sv. accuracy and precision} @item Some values have an infinite number of digits after the (decimal) point, e.g. π. @item Some values change with time or samples (or whatever), like the weight of a person, which can change of 5 percent during the day, or the current gain of a bipolar junction transistor (BJP), which can change of 50 percent on the samples of the same series. @item Some values are estimation or guess—something like between a minimum and a maximum. @end enumerate @noindent For example, if a pipe breaks and you want to buy a new one you need its diameter. If you do not have a caliber, you may measure its circumference and divide it by π. @display diameter = circumference / π @end display Here are two errors: the circumference is known within the tolerance given by your meter, moreover π has an infinite number of digits while only few of them can be used in the operation. You may think the error is negligible, the result is enough accurate to buy a new pipe in a hardware shop. However, the not infinite precision of those operations avoid the use of computers as automatic theorem demonstration tools and so on. This kind of issue is quite common in engineer design. What engineers do is to make sure their design will work in the worst case or in most of the cases (usually more than 99.9 percent). A simple example follows. Let us say you want to repaint the walls of your living room completely messed up by your children. You need to compute how many paint cans you need to buy. The equation is quite simple: @display paint cans = 2 · (room width + room length) · room height / (paint per can · paint efficiency), @end display @noindent where “paint efficiency” is how many square meters of surface can be painted with a liter of paint. The problem here is that usually we do not have a long enough meter to measure the room width and length. It is much simpler to count the number of steps to go through it (1 step is about a meter, let us say from 0.9 to 1.1 meters). Moreover, the paint provider usually declares a paint efficiency range. Here is the data: @itemize @item room width = 6 steps (5.4m to 6.6m) @item room length = 4 steps (3.6m to 4.4m) @item room height = 3m (it is assumed to be correct) @item paint efficiency = from 0.7 to 1.3 square meters per liter @item paint liters per can = 40 (it is assumed to be correct) @end itemize @noindent To compute the average result just put average values in. We get: paint cans = 2 · (6 + 4) · 3 / (40 · 1) = 1.5, which means two paint cans unless you are able to buy just half of the second can. What happens in the worst case? Just put pessimistic values in the equation. We get: paint cans = 2 · (6.6 + 4.4) · 3 / (40 · 0.7) = 2.36. That is, in the worst case we would be short 0.36 cans of paint. It makes sense to buy 3 cans. Last, consider the best case. Is it enough to only buy a single can of paint? Just put optimistic values in the equation. We get: paint cans = 2 · (5.4 + 3.6) · 3 / (40 · 1.3) = 1.04, which means one can of paint would not be enough. You have to buy at least two cans, but probably need one more. For this result we had to go through the equation multiple times (at least twice) and carefully consider for each variable, which would be the most optimistic / pessimistic value assignment, which is not trivial. For example consider the room size versus the paint efficiency: It depends whether the highest or the lowest value takes an optimistic or pessimistic role—and this was a simple example with basic arithmetic operations. Using interval arithmetic it is possible to compute the result in a single run with ranges as inputs. The following example demonstrates this and further below is explained how it works. @example @group step = midrad (1, "0.1"); w = 6 * step; l = 4 * step; h = 3; eff = infsupdec ("[0.7, 1.3]"); cansize = 40; cans = 2 * (w + l) * h / (eff * cansize) @result{} cans ⊂ [1.0384, 2.3572]_com @end group @end example @example @group ## Since we can only buy whole cans ceil (cans) @result{} ans = [2, 3]_def @end group @end example @section Pros and Cons Interval arithmetic, introduced in the 1960s, is a young and powerful technique. Its first application has been to control errors in computations and simplify error analysis for engineers (rounding errors, truncation errors, and conversion errors). The range evaluation of functions has soon been exploited for reliably checking for certain function values and for self-verifying algorithms. Latest usage scenarios comprise root finding, function approximation, and robust pattern recognition. More useful applications are certainly left to be detected. The major problem in interval arithmetic is that errors can easily build up, such that the final result is too wide to be useful. This is especially true when the @emph{dependency problem} applies, that is, a single variable occurs several times within a computation and is represented by an interval in each occurrence. Then, the variable virtually may take different values independently, which introduces a systematic error. For example, computing @code{x .^ 2} will always yield a subset of @code{times (x, x)}, the latter considers two intervals independent of each other. @example @group x = infsupdec ("[-1, 3]"); x .^ 2 @result{} ans = [0, 9]_com times (x, x) @result{} ans = [-3, +9]_com @end group @end example After all, it is possible to reduce overestimation errors by subdividing the function's domain into smaller intervals, e. g., with bisection. This technique is called “mincing”. The computational errors are proportional to the interval width and a linear convergence can be achieved. @example @group x1 = infsupdec ("[-1, 1]"); x2 = infsupdec ("[1, 3]"); hull (x1 .^ 2, x2 .^ 2) @result{} ans = [0, 9]_com hull (times (x1, x1), times (x2, x2)) @result{} ans = [-1, +9]_com @end group @end example However, this does not help when ranges of input values are too big. For certain applications it is better to use statistical models, where infinite domains are supported. @section Theory There are good introductions to interval arithmetic available and should be consulted for a deeper understanding of the topic. The following recommendations can make a starting point. @itemize @item @uref{http://en.wikipedia.org/wiki/Interval_arithmetic,Wikipedia sv. interval arithmetic} @item Introduction to Interval Analysis (2009), by Ramon E. Moore, R. Baker Kearfott, and Michael J. Cloud. Cambridge University Press. ISBN 978-0898716696. @item @uref{http://www-sop.inria.fr/coprin/logiciels/ALIAS/Examples/COURS/index.html,Introduction to the methods used in interval arithmetic (French)}. @item @uref{http://www.maths.manchester.ac.uk/~higham/narep/narep416.pdf,Interval analysis in MATLAB} Note: The INTLAB toolbox for Matlab is not entirely compatible with this interval package for GNU Octave. However, basic operations can be compared and should be compatible for common intervals. @item @uref{http://www.cs.utep.edu/interval-comp/,Interval related collection of links} @end itemize interval-3.2.0/doc/chapter/preface.texinfo0000644000000000000000000003167613316017127016702 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2017 Oliver Heimlich. @c Copyright 2017 Joel Dahne @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @include macros.texinfo @unnumbered Preface Welcome to the user manual of the @dfn{interval package} for GNU Octave. This chapter presents background information and may safely be skipped. First-time users who want to cut right to the chase should read @ref{Getting Started}, which teaches basic concepts and first steps with the package. Users who are not familiar with interval arithmetic should read @ref{Introduction to Interval Arithmetic} first. Still feeling undecided? Look at the @ref{Examples} and see how easy you can put this software to great use! Development of the GNU Octave Interval Package started in September 2014. The IEEE standard for interval arithmetic, IEEE Std 1788-2015, had been drafted by its working group until July 2014 and was about to enter the balloting process. In January 2015 a first package release could be made, which contained the full set of functions required by the standard's draft. On June 11 the standard finally became approved and this interval package can be seen as the first ever completed standard conforming interval arithmetic library. The creation of the interval package has been straightforward, although the author had no previous experience with Octave. Octave is a great environment for getting things done and its active community helps a lot. In this spirit, the interval package wants to be an easy to use tool for experimenting with and quick prototyping of interval arithmetic algorithms and applications. Originally it was intended to only implement the operations required by the standard document, but support for fundamental concepts of Octave as well as interval vectors and interval matrices have soon been added. Today the package contains many useful interval analysis algorithms and solvers, which, together with basic arithmetic functions, form a powerful and versatile library. In 2017 the Google Summer of Code (GSoC) program has lead to @uref{https://gsocinterval.blogspot.com/,support for N-dimensional arrays of intervals}. @myimage{image/octave-interval.svg,GNU Octave Interval Pun} Like Octave, the interval package has nothing to do with music. Above picture is a pun and shows an “octave interval” between the notes d' and d''. The frequencies of these notes can be enclosed by an interval which is a subset of [293, 588] Hz. @menu * Acknowledgments:: * Philosophy:: * Distribution and Development:: * Getting Help:: @end menu @node Acknowledgments @section Acknowledgments The GNU Octave interval package is build upon great third-party software. @itemize @item Most correctly rounded arithmetic operations are based on the @uref{http://www.mpfr.org/,GNU MPFR library} by Guillaume Hanrot, Vincent Lefèvre, Patrick Pélissier, Philippe Théveny and Paul Zimmermann. @item Several correctly rounded arithmetic operations are based on the @uref{http://lipforge.ens-lyon.fr/www/crlibm/,correctly rounded math library} by Jean-Michel Muller, Florent de Dinechin, Christoph Lauter, David Defour, Catherine Daramy-Loirat, Matthieu Gallet, and Nicolas Gast. @item Jiří Rohn has published his comprehensive verification toolbox @uref{http://uivtx.cs.cas.cz/~rohn/matlab/,VERSOFT} as free software on July 26, 2016. On November 24 he has fully disclosed the source code and several high-level functions could be included in the interval package with minor adjustments, e. g., @funref{@@infsup/chol}, @funref{vereigvec}, and @funref{verlinprog}. Also, many thanks to Vladik Kreinovich who has helped to clear the licensing issue with VERSOFT. @item A linear system solver @funref{@@infsup/mldivide} and a polynomial evaluation algorithm @funref{@@infsup/polyval} for bare intervals are derived from routines developed for @uref{http://www2.math.uni-wuppertal.de/~xsc/,C-XSC} at University of Wuppertal, Germany. @item @ref{Introduction to Interval Arithmetic} is partly based on the documentation for the former SIMP package for Octave by Simone Pernice. @item A French translation of the package description has been made by Rodéric Moitié. @item In the @ref{Examples} for finding root enclosures a function and code by Helmut Podhaisky has been used. @item The @uref{http://iamooc.ensta-bretagne.fr/, online course on interval analysis} by Luc Jaulin and Jordan Ninin at ENSTA-Bretagne has inspired me to implement the set inversion algorithms in @funref{@@infsup/fsolve}. @item I have gained access to scientific literature thanks to the @uref{https://www.hswt.de/about-us/central-facilities/library.html, Weihenstephan-Triesdorf University of Applied Sciences}. @item Most unit tests are written in portable ITL format and converted into GNU Octave test cases with the @uref{https://github.com/nehmeier/ITF1788,Interval Testing Framework for IEEE 1788}. The framework has been developed by Maximilian Kiesner and Marco Nehmeier, Chair of Software Engineering, Department of Computer Science, University of Würzburg, Germany. @item Several unit tests are derived from @uref{https://github.com/nehmeier/libieeep1788,libieeep1788}, a C++ implementation of IEEE Std 1788-2015, IEEE standard for interval arithmetic. The library contains several unit tests for its IEEE 754 flavor, which is compatible with the arithmetic of the GNU Octave interval package. I have converted nearly 6000 of these test cases into portable ITL format for verification of this package. @comment libieeep1788/NOTICE @comment According to the Apache License, this shall be included in the documentation @indentedblock @verbatiminclude license/libieeep1788.NOTICE @end indentedblock @item Several unit tests are derived from @uref{http://perso.ens-lyon.fr/nathalie.revol/software.html,MPFI}, a C++ interval arithmetic library based on GNU MPFR. The library contains several unit tests for binary64 numbers, which are compatible with the arithmetic of the GNU Octave interval package. I have converted nearly 1500 of these test cases into portable ITL format for verification of this package. @item Several unit tests are derived from @uref{http://www2.math.uni-wuppertal.de/wrswt/software/filib.html,FI_LIB}, an ANSI-C interval arithmetic library based on binary64 numbers. The library contains several unit tests, which are compatible with the arithmetic of the GNU Octave interval package. I have converted 800 of these test cases into portable ITL format for verification of this package. @item Some unit tests are derived from @uref{http://www2.math.uni-wuppertal.de/~xsc/xsc/cxsc_new.html,C-XSC}, a C++ class library for interval arithmetic. The library contains some unit tests, which are compatible with the arithmetic of the GNU Octave interval package. I have converted 160 of these test cases into portable ITL format for verification of this package. @item Fast matrix multiplication (see @funref{@@infsup/mtimes}) as well as the linear system solver (see @funref{@@infsup/mldivide}) use BLAS routines with directed rounding. An OCT-file interface for setting the rounding mode has been developed by Kai Torben Ohlus, Institute for Reliable Computing, Hamburg University of Technology, Germany. @end itemize Last, but not least, many thanks to everybody who has contributed to the success of free software! @node Philosophy @section Philosophy @noindent Features @itemize @item Free software licensed under the terms of the GNU General Public License (Version 3 or later) @item Many interval arithmetic functions with high, system-independent accuracy @item Conforming to IEEE Std 1788-2015, IEEE standard for interval arithmetic @item Support for interval vectors, interval matrices and N-dimensional interval arrays @itemize @item very accurate vector sum, vector dot and matrix multiplication (correctly rounded) @item fast matrix multiplication and fast solver for dense linear systems (BLAS routines) @item vectorized function evaluation @end itemize @item Easy usage @itemize @item GNU Octave function names @item convenient interval constructors @item broadcasting @end itemize @end itemize @noindent Limitations @itemize @item No complex numbers @item No sparse matrices (maybe in the future, if requested by users) @end itemize The interval arithmetic provided by the interval package focuses on easy usage, accuracy and correctness. It is rather slow compared to other arithmetic libraries. If accurate type checking during compile time—a substantial feature for verified computing—is needed, the user is advised to try third-party interval libraries for strongly typed programming languages like C/C++. The interval package for GNU Octave can nonetheless be used for prototyping of interval algorithms. @emph{Why is the interval package slow?} All arithmetic interval operations are simulated in high-level Octave language using C99 or multi-precision floating-point routines, which is a lot slower than a @uref{https://books.google.com/books?id=JTc4XdXFnQIC&pg=PA61,hardware implementation}. Building interval arithmetic operations from floating-point routines is easy for simple monotonic functions, e. g., addition and subtraction, but is complex for others, e. g., interval power function, atan2, or reverse functions. For some interval operations it is not even possible to rely on floating-point routines, since not all required routines are available in C99 or BLAS. For example, accurate multiplication of matrices with many elements becomes unfeasible as it takes a lot of time. @float Table,tab:runtime @caption{Approximate runtime for certain functions (wall clock time in seconds) — Results have been produced with GNU Octave 3.8.2 and Interval package 0.1.4 on an Intel Core i5-4340M CPU (2.9–3.6 GHz)} @shortcaption{Approximate runtime for certain functions} @multitable {matrix size} {accuracy} {accuracy} {accuracy} {accuracy} {accuracy} {accuracy} @headitem @tab@command{plus} @tab@command{log} @tab@command{pow} @tab@command{mtimes} @tab@command{mtimes} @tab@command{inv} @item Interval@*matrix size @tab tightest@*accuracy @tab tightest@*accuracy @tab tightest@*accuracy @tab valid@*accuracy @tab tightest@*accuracy @tab valid@*accuracy @item 10 × 10 @tab < 0.001 @tab 0.001 @tab 0.008 @tab 0.001 @tab 0.002 @tab 0.025 @item 100 × 100 @tab 0.003 @tab 0.055 @tab 0.61 @tab 0.012 @tab 0.53 @tab 0.30 @item 500 × 500 @tab 0.060 @tab 1.3 @tab 15 @tab 0.30 @tab 63 @tab 4.2 @end multitable @end float @emph{Why is the interval package accurate?} The GNU Octave built-in floating-point routines are not useful for interval arithmetic: Their results depend on hardware, system libraries and compilation options. The interval package handles all arithmetic functions with the help of the GNU MPFR library. With MPFR it is possible to compute system-independent, valid and tight enclosures of the correct results for most functions. However, it should be noted that some reverse operations and matrix operations do not exists in GNU MPFR and therefore cannot be computed with the same accuracy. It is possible to use faster (BLAS based) routines during computation of the matrix multiplication @funref{@@infsup/mtimes}, because correctly rounded matrix multiplication could be considered too slow for certain applications. However, this is not the default behavior and must be explicitly activated by the user. @node Distribution and Development @section Distribution and Development The interval package is free software: Everyone is encouraged to use it, copy it and redistribute it, as well as to make changes under the terms of the GNU General Public License. The interval package is part of Octave Forge, a sibling of the GNU Octave project. Official releases are published at @url{https://octave.sourceforge.io/}. The @uref{https://sourceforge.net/p/octave/interval/ci/default/tree/,source code repository} is located at Octave Forge and contains the latest development version. Information for developers can be found on the @uref{https://wiki.octave.org/Interval_package,package's page at Octave wiki}. Bug reports and feature requests for either the software or this manual may be posted under the @uref{https://savannah.gnu.org/projects/octave,Octave Project at Savannah}. Contributions to the software and this manual are highly appreciated. @node Getting Help @section Getting Help The interval package contains online help for every function, which can be accessed with the @command{help} command from Octave. The interval arithmetic is implemented with specialized data types, which override standard functions. Whilst the command @command{help @var{function name}} shows the documentation for core Octave functions, the interval variants of these functions can be requested with the command @command{help @@infsup/@var{function name}}. Further help can be seeked at the @uref{https://lists.gnu.org/mailman/listinfo/help-octave,Octave Help mailing list}. interval-3.2.0/doc/htmlxref.cnf0000644000000000000000000000010113316017127014545 0ustar 00000000000000octave node https://www.gnu.org/software/octave/doc/interpreter/ interval-3.2.0/doc/image/cameleon-animation.svg0000644000000000000000000046750613316017127017621 0ustar 00000000000000 Cameleon Problem, Transition Animation image/svg+xml Cameleon Problem, Transition Animation 2016-03-29 Oliver Heimlich Oliver Heimlich own work Hover/click to start animation interval-3.2.0/doc/image/cameleon-start-end.svg0000644000000000000000000001340313316017127017522 0ustar 00000000000000 Cameleon Problem, Start and End State image/svg+xml Cameleon Problem, Start and End State 2016-03-29 Oliver Heimlich Oliver Heimlich own work Start Position End Position Obstacles interval-3.2.0/doc/image/cameleon-transition.svg0000644000000000000000000002575213316017127020025 0ustar 00000000000000 Cameleon Problem, Transition States image/svg+xml Cameleon Problem, Transition States 2016-03-29 Oliver Heimlich Oliver Heimlich own work interval-3.2.0/doc/image/cameleon.m.texinfo0000644000000000000000000000744413316017127016743 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2016 Oliver Heimlich. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @example @group @c doctest: +SKIP # We can build the simple polygon from interval boxes global polygon_x = ... infsup ("[18,20] [0,20] [0, 2] [ 0,14] [12,14] [10,14]")'; global polygon_y = ... infsup ("[ 0,18] [0, 2] [0,14] [12,14] [ 6,14] [ 6, 8]")'; global obstacle_x = infsup ("[ 8,11] [25,28]"); global obstacle_y = infsup ("[10,10] [10,10]"); color_feasible = [238 232 213] ./ 255; color_uncertain = [220 50 47] ./ 255; color_path = [133 153 0] ./ 255; @end group @group function feasible = check_collision (obstacle_x, obstacle_y) global polygon_x; global polygon_y; feasible = infsup (zeros (size (obstacle_x)), ... ones (size (obstacle_x))); # Check if the obstacle is inside the polygon inside = any (... subset (obstacle_x, polygon_x) & subset (obstacle_y, polygon_y)); feasible(inside) = 0; # Check if the obstacle is outside the polygon outside = all (... disjoint (obstacle_x, polygon_x) | ... disjoint (obstacle_y, polygon_y)); feasible(outside) = 1; endfunction @end group @group function feasible = check_parameters (x_offset, angle) global obstacle_x; global obstacle_y; # Instead of rotating the polygon, we rotate the obstacles (reverse) s = sin (-angle); c = cos (-angle); f_x = @@(x, y) (x - x_offset) .* c - y .* s; f_y = @@(x, y) (x - x_offset) .* s + y .* c; # All obstacles must be considered feasible = 1; for i = 1 : numel (obstacle_x) feasible = min (feasible, ... check_collision (f_x (obstacle_x(i), obstacle_y(i)), ... f_y (obstacle_x(i), obstacle_y(i)))); endfor endfunction @end group @group # Compute a paving of feasible polygon states [x, paving, inner] = fsolve (... @@check_parameters, ... infsup ("[-28, 57] [-1.4, 2.7]"), ... 1, ... struct ('MaxIter', 21, 'TolX', 0.03)); hold on plot (paving(1, inner), paving(2, inner), color_feasible); plot (paving(1, not (inner)), paving(2, not (inner)), color_uncertain); # Consider only states that are guaranteed to be feasible paving = paving (:, inner); @end group @group # Path search start_idx = find (all (ismember ([0; 0], paving)), 1); end_idx = find (all (ismember ([17; 0], paving)), 1); adjacency = not (disjoint (paving(1, :), transpose (paving(1, :))) | ... disjoint (paving(2, :), transpose (paving(2, :)))); # Do a Dijkstra search until we reach end_idx distance = inf (columns (paving), 1); # nan = visited previous = zeros (columns (paving), 1); distance(start_idx) = 0; while (not (isnan (distance(end_idx)))) [pivot_distance, pivot_idx] = min (distance); visited = isnan (distance); neighbors_idx = adjacency(:, pivot_idx) & not (visited); if (not (any (neighbors_idx))) error ("Cannot reach target location") endif neighbors_distance = subsasgn (... distance, ... substruct ("()", @{neighbors_idx@}), ... pivot_distance + hypot (... # Compute distance between centers of boxes mid (paving(1, pivot_idx)) - mid (paving(1, neighbors_idx)), ... mid (paving(2, pivot_idx)) - mid (paving(2, neighbors_idx)))); shorter_path = neighbors_idx & (neighbors_distance < distance); previous(shorter_path) = pivot_idx; distance(shorter_path) = neighbors_distance(shorter_path); distance(pivot_idx) = nan; endwhile @end group @group # Plot the path to the target location last_idx = end_idx; while (last_idx != start_idx) next_idx = previous(last_idx); x1 = mid (paving(1, last_idx)); y1 = mid (paving(2, last_idx)); x2 = mid (paving(1, next_idx)); y2 = mid (paving(2, next_idx)); plot ([x1 x2], [y1 y2], 'linewidth', 2, 'color', color_path); last_idx = next_idx; endwhile @end group @end example interval-3.2.0/doc/image/contractor-rings-intersect.m.texinfo0000644000000000000000000000301513316017127022442 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2016 Oliver Heimlich. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @example @ifset m-file @group @c doctest: +SKIP ## General ring contractor function [fval, cx1, cx2] = ctc_ring (y, c1, c2, x1, x2) x1_c1 = x1 - c1; x2_c2 = x2 - c2; sqr_x1_c1 = x1_c1 .^ 2; sqr_x2_c2 = x2_c2 .^ 2; fval = hypot (x1_c1, x2_c2); y = intersect (y, fval); sqr_y = y .^ 2; sqr_x1_c1 = intersect (sqr_x1_c1, sqr_y - sqr_x2_c2); sqr_x2_c2 = intersect (sqr_x2_c2, sqr_y - sqr_x1_c1); x1_c1 = sqrrev (sqr_x1_c1, x1_c1); x2_c2 = sqrrev (sqr_x2_c2, x2_c2); cx1 = intersect (x1, x1_c1 + c1); cx2 = intersect (x2, x2_c2 + c2); endfunction @end group @group ## Ring 1 with center at (1, 3) ## Ring 2 with center at (2, -1) ctc_ring1 = @@(y, x1, x2) ctc_ring (y, 1, 3, x1, x2); ctc_ring2 = @@(y, x1, x2) ctc_ring (y, 2, -1, x1, x2); @end group @end ifset @group @c doctest: +SKIP ## Intersect ring 1 with radius 3..4 and ring 2 with radius 5..6 ctc_intersection_of_rings = ctc_intersect (ctc_ring1, "[3, 4]", ... ctc_ring2, "[5, 6]"); @end group @group ## Compute a paving to approximate the intersection of rings ## in the area x, y = -10..10 [~, paving] = fsolve (ctc_intersection_of_rings, ... infsup ("[-10, 10] [-10, 10]"), ... struct ("Contract", true)); plot (paving(1, :), paving(2, :)) axis equal @end group @end example interval-3.2.0/doc/image/contractor-rings-union.m.texinfo0000644000000000000000000000275613316017127021605 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2016 Oliver Heimlich. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @example @group @c doctest: +SKIP ## General ring contractor function [fval, cx1, cx2] = ctc_ring (y, c1, c2, x1, x2) ## Forward evaluation x1_c1 = x1 - c1; x2_c2 = x2 - c2; sqr_x1_c1 = x1_c1 .^ 2; sqr_x2_c2 = x2_c2 .^ 2; fval = hypot (x1_c1, x2_c2); ## Reverse evaluation y = intersect (y, fval); sqr_y = y .^ 2; sqr_x1_c1 = intersect (sqr_x1_c1, sqr_y - sqr_x2_c2); sqr_x2_c2 = intersect (sqr_x2_c2, sqr_y - sqr_x1_c1); x1_c1 = sqrrev (sqr_x1_c1, x1_c1); x2_c2 = sqrrev (sqr_x2_c2, x2_c2); cx1 = intersect (x1, x1_c1 + c1); cx2 = intersect (x2, x2_c2 + c2); endfunction @end group @group ## Ring 1 with center at (1, 3) ## Ring 2 with center at (2, -1) ctc_ring1 = @@(y, x1, x2) ctc_ring (y, 1, 3, x1, x2); ctc_ring2 = @@(y, x1, x2) ctc_ring (y, 2, -1, x1, x2); @end group @group ## Unite ring 1 with radius 3..4 and ring 2 with radius 5..6 ctc_union_of_rings = ctc_union (ctc_ring1, "[3, 4]", ... ctc_ring2, "[5, 6]"); @end group @group ## Compute a paving to approximate the union of rings ## in the area x, y = -10..10 [~, paving] = fsolve (ctc_union_of_rings, ... infsup ("[-10, 10] [-10, 10]"), ... struct ("Contract", true)); plot (paving(1, :), paving(2, :)) axis equal @end group @end example interval-3.2.0/doc/image/interval-plot3.m.texinfo0000644000000000000000000000102613316017127020031 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2016 Oliver Heimlich. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @example @group @c doctest: +SKIP red = [220 50 47] ./ 255; shade = [238 232 213] ./ 255; @end group @group x = midrad (1 : 6, 0.25); y = midrad (-3 : 3, 0.25); [x, y] = meshgrid (x, y); z = atan2 (y, x); plot3 (x, y, z, shade, red) @end group @group view ([-35, 30]) box off set (gca, "xgrid", "on", "ygrid", "on", "zgrid", "on") @end group @end example interval-3.2.0/doc/image/interval-sombrero.m0000644000000000000000000000245513316017127017154 0ustar 00000000000000## This is part of the GNU Octave Interval Package Manual. ## Copyright 2015-2016 Oliver Heimlich. ## See the file manual.texinfo for copying conditions. clf hold on light = [253 246 227] ./ 255; blue = [38 139 210] ./ 255; green = [133 153 0] ./ 255; yellow = [181 137 0] ./ 255; orange = [203 75 22] ./ 255; red = [220 50 47] ./ 255; range = mince (infsupdec (-8, 8), 13); [x, y] = meshgrid (range); h = hypot (x, y); z = sin (h) ./ h; ## The sombrero function would suffer from the dependency problem ## Thus, we compute an interval version of the function, which works around it. select = mag (h) < pi; z (select) = hull (sin (mag (h (select))) ./ mag (h (select)), ... sin (mig (h (select))) ./ mig (h (select))); z (mig (h) == 0) = union (z (mig (h) == 0), 1); flat = sup (z) < .3; low = ismember (sup (z), infsup (0.3, 0.8)); mid = ismember (sup (z), infsup (0.8, 0.9)); high = ismember (sup (z), infsup (0.9, 1)); top = sup (z) >= 1; plot3 (x (flat), y (flat), z (flat), blue, light) plot3 (x (low), y (low), z (low), green, light) plot3 (x (mid), y (mid), z (mid), yellow, light) plot3 (x (high), y (high), z (high), orange, light) plot3 (x (top), y (top), z (top), red, light) view ([-37.5, 30]) zlim ([-.4, 1]) box off set (gca, "xgrid", "on", "ygrid", "on", "zgrid", "on") %!assert(1); interval-3.2.0/doc/image/interval-vs-normal-plot.m.texinfo0000644000000000000000000000115113316017127021661 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2016 Oliver Heimlich. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @example @group @c doctest: +SKIP hold on blue = [38 139 210] ./ 255; shade = [238 232 213] ./ 255; @end group @group ## Interval plotting x = mince (2*infsup (0, "pi"), 6); plot (x, sin (x), shade) @end group @group ## Classical plotting x = linspace (0, 2*pi, 7); plot (x, sin (x), 'linewidth', 2, 'color', blue) @end group @group set (gca, 'XTick', 0 : pi : 2*pi) set (gca, 'XTickLabel', @{'0', 'pi', '2 pi'@}) @end group @end example interval-3.2.0/doc/image/inverse-power.svg0000644000000000000000000010454113316017127016651 0ustar 00000000000000 Inserse Power Functionimage/svg+xmlInserse Power Function2012-10-11Oliver HeimlichCopyright 2012-2016 Oliver Heimlichown workGraphical interpretation of reverse power operations. The (twodimensional) inverse image of z is hatched and outlined in the figure, in the shown example it is z = [2, 3]. A, for given intervals y and z find every x with x^y ∩ z ≠ Ø. B, for given intervals x and z find every y with x^y ∩ z ≠ Ø. x x y A B x y y -1 -2 0 1 2 2 1 0 -1 -2 0 1 2 2 1 0 interval-3.2.0/doc/image/octave-interval.ly0000644000000000000000000000122313316017127016765 0ustar 00000000000000%% This is part of the GNU Octave Interval Package Manual. %% Copyright 2015-2016 Oliver Heimlich. %% See the file manual.texinfo for copying conditions. \include "lilypond-book-preamble.ly" \paper { indent = 0\mm line-width = 6\in % offset the left padding, also add 1mm as lilypond creates cropped % images with a little space on the right line-width = #(- line-width (* mm 3.000000) (* mm 1)) } \score { % Between d' and d'' lies an octave interval. \new Voice = "" { { 1 } } % Frequency of d' in just intonation is approx. 293,7 Hz, % wheras d'' has this doubled. \addlyrics { \lyricmode { "[293, 588]" } } \layout { } } interval-3.2.0/doc/image/octave-interval.svg0000644000000000000000000003344513316017127017153 0ustar 00000000000000 image/svg+xmlinterval-3.2.0/doc/image/poly-example-roots-simple.m.texinfo0000644000000000000000000000231213316017127022214 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2016 Oliver Heimlich. @c Copyright 2015 Helmut Podhaisky. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @example @group @c doctest: +SKIP f = @@(x,y) ... -(5.*y - 20.*y.^3 + 16.*y.^5).^6 + ... (-(5.*x - 20.*x.^3 + 16.*x.^5).^3 + ... 5.*y - 20.*y.^3 + 16.*y.^5).^2; X = Y = infsup ("[-1, 1]"); has_roots = n = 1; @end group @group for iter = 1 : 10 ## Bisect [i,j] = ind2sub ([n,n], has_roots); X = infsup ([X.inf,X.inf,X.mid,X.mid],[X.mid,X.mid,X.sup,X.sup]); Y = infsup ([Y.inf,Y.mid,Y.inf,Y.mid],[Y.mid,Y.sup,Y.mid,Y.sup]); ii = [2*(i-1)+1,2*(i-1)+2,2*(i-1)+1,2*(i-1)+2] ; jj = [2*(j-1)+1,2*(j-1)+1,2*(j-1)+2,2*(j-1)+2] ; has_roots = sub2ind ([2*n,2*n], ii, jj); n *= 2; ## Check if function value covers zero fval = f (X, Y); zero_contained = find (ismember (0, fval)); ## Discard values without roots has_roots = has_roots(zero_contained); X = X(zero_contained); Y = Y(zero_contained); endfor @end group @group colormap gray B = false (n); B(has_roots) = true; imagesc (B) axis equal axis off @end group @end example interval-3.2.0/doc/image/poly-example-roots-with-deriv.m.texinfo0000644000000000000000000000375413316017127023020 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2016 Oliver Heimlich. @c Copyright 2015 Helmut Podhaisky. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @example @group @c doctest: +SKIP f_dx = @@(x,y) ... -6.*(5 - 60.*x.^2 + 80.*x.^4) .* ... (5.*x - 20.*x.^3 + 16.*x.^5).^2 .* ... (-(5.*x - 20.*x.^3 + 16.*x.^5).^3 + ... 5.*y - 20.*y.^3 + 16.*y.^5); f_dy = @@(x,y) ... -6.*(5 - 60.*y.^2 + 80.*y.^4) .* ... (5.*y - 20.*y.^3 + 16.*y.^5).^5 + ... 2.*(5 - 60.*y.^2 + 80.*y.^4) .* ... (-(5.*x - 20.*x.^3 + 16.*x.^5).^3 + ... 5.*y - 20.*y.^3 + 16.*y.^5); @ifset m-file f = @@(x,y) ... -(5.*y - 20.*y.^3 + 16.*y.^5).^6 + ... (-(5.*x - 20.*x.^3 + 16.*x.^5).^3 + ... 5.*y - 20.*y.^3 + 16.*y.^5).^2; X = Y = infsup ("[-1, 1]"); has_roots = n = 1; @end ifset @end group @group for iter = 1 : 10 @ifset m-file ## Bisect [i,j] = ind2sub ([n,n], has_roots); X = infsup ([X.inf,X.inf,X.mid,X.mid],[X.mid,X.mid,X.sup,X.sup]); Y = infsup ([Y.inf,Y.mid,Y.inf,Y.mid],[Y.mid,Y.sup,Y.mid,Y.sup]); ii = [2*(i-1)+1,2*(i-1)+2,2*(i-1)+1,2*(i-1)+2] ; jj = [2*(j-1)+1,2*(j-1)+1,2*(j-1)+2,2*(j-1)+2] ; has_roots = sub2ind ([2*n,2*n], ii, jj); n *= 2; @end ifset @ifclear m-file @dots{} @end ifclear ## Check if function value covers zero fval1 = f (X, Y); fval2 = f (mid (X), mid (Y)) + ... (X - mid (X)) .* f_dx (X, Y) + ... (Y - mid (Y)) .* f_dy (X, Y); fval = intersect (fval1, fval2); @ifclear m-file @dots{} @end ifclear @ifset m-file zero_contained = find (ismember (0, fval)); ## Discard values without roots has_roots = has_roots(zero_contained); X = X(zero_contained); Y = Y(zero_contained); @end ifset endfor @end group @ifset m-file @group colormap gray B = false (n); B(has_roots) = true; imagesc (B) axis equal axis off @end group @end ifset @end example interval-3.2.0/doc/image/poly-example-surf.m0000644000000000000000000000027313316017127017067 0ustar 00000000000000f=@(x,y)-(5.*y - 20.*y.^3 + 16.*y.^5).^6 + (-(5.*x - 20.*x.^3 + 16.*x.^5).^3 + 5.*y - 20.*y.^3 + 16.*y.^5).^2; [x, y] = meshgrid (-1:0.01:1, -1:0.01:1); surf(x, y, f(x, y)) %!assert(1); interval-3.2.0/doc/license/apache-2.00000644000000000000000000002613613316017127015327 0ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. interval-3.2.0/doc/license/gpl-3.0.texi0000644000000000000000000010471213316017127015636 0ustar 00000000000000@c The GNU General Public License. @center Version 3, 29 June 2007 @c This file is intended to be included within another document, @c hence no sectioning command or @node. @display Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @heading Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program---to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. @heading TERMS AND CONDITIONS @html
@end html @enumerate 0 @item Definitions. ``This License'' refers to version 3 of the GNU General Public License. ``Copyright'' also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. ``The Program'' refers to any copyrightable work licensed under this License. Each licensee is addressed as ``you''. ``Licensees'' and ``recipients'' may be individuals or organizations. To ``modify'' a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a ``modified version'' of the earlier work or a work ``based on'' the earlier work. A ``covered work'' means either the unmodified Program or a work based on the Program. To ``propagate'' a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To ``convey'' a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays ``Appropriate Legal Notices'' to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. @item Source Code. The ``source code'' for a work means the preferred form of the work for making modifications to it. ``Object code'' means any non-source form of a work. A ``Standard Interface'' means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The ``System Libraries'' of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A ``Major Component'', in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The ``Corresponding Source'' for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. @item Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. @item Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. @item Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. @item Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: @html
@end html @enumerate a @item The work must carry prominent notices stating that you modified it, and giving a relevant date. @item The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to ``keep intact all notices''. @item You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. @item If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. @end enumerate A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an ``aggregate'' if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. @item Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: @html
@end html @enumerate a @item Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. @item Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. @item Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. @item Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. @item Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. @end enumerate A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A ``User Product'' is either (1) a ``consumer product'', which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, ``normally used'' refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. ``Installation Information'' for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. @item Additional Terms. ``Additional permissions'' are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: @html
@end html @enumerate a @item Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or @item Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or @item Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or @item Limiting the use for publicity purposes of names of licensors or authors of the material; or @item Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or @item Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. @end enumerate All other non-permissive additional terms are considered ``further restrictions'' within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. @item Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. @item Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. @item Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An ``entity transaction'' is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. @item Patents. A ``contributor'' is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's ``contributor version''. A contributor's ``essential patent claims'' are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, ``control'' includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a ``patent license'' is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To ``grant'' such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. ``Knowingly relying'' means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is ``discriminatory'' if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. @item No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. @item Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. @item Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License ``or any later version'' applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. @item Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW@. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE@. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU@. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. @item Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. @item Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. @end enumerate @heading END OF TERMS AND CONDITIONS @heading How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found. @smallexample @var{one line to give the program's name and a brief idea of what it does.} Copyright (C) @var{year} @var{name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE@. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see @url{http://www.gnu.org/licenses/}. @end smallexample Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: @smallexample @var{program} Copyright (C) @var{year} @var{name of author} This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. This is free software, and you are welcome to redistribute it under certain conditions; type @samp{show c} for details. @end smallexample The hypothetical commands @samp{show w} and @samp{show c} should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an ``about box''. You should also get your employer (if you work as a programmer) or school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see @url{http://www.gnu.org/licenses/}. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}. interval-3.2.0/doc/license/libieeep1788.NOTICE0000644000000000000000000000053513316017127016672 0ustar 00000000000000libieeep1788 ============ Copyright 2013 - 2015 Marco Nehmeier (nehmeier@informatik.uni-wuerzburg.de) Department of Computer Science, University of Wuerzburg, Germany This product includes software developed at Chair of Software Engineering, Department of Computer Science, University of Wuerzburg, Germany http://se.informatik.uni-wuerzburg.de/ interval-3.2.0/doc/macros.texinfo0000644000000000000000000000307313316017127015121 0ustar 00000000000000@c This is part of the GNU Octave Interval Package Manual. @c Copyright 2015-2017 Oliver Heimlich. @c See the file manual.texinfo for copying conditions. @documentencoding UTF-8 @ifcommandnotdefined myimage @macro myimage{file, description} @ifnothtml @center @image{\file\,,,\description\,} @end ifnothtml @html \description\ @end html @end macro @end ifcommandnotdefined @ifcommandnotdefined funref @macro funref{function} @c We want to have links from the package manual to the function reference. @c The function reference is not compiled by texinfo as part of the @c package manual compilation, so we can't use simple Texinfo references. @c The file names of the function reference do not use HTML special @c character escaping (like Texinfo does), so we can't use Texinfo @c references to external nodes. However, the url can easily be @c constructed from the function name or the class and method name. @c If the manual is generated for publication on Octave Forge, we can @c use relative links (from ../package_doc/ to ../function/). @c Otherwise, if a standalone manual is generated, we need external @c links to Octave Forge (there is no local function reference so we fall @c back to using the online reference). @c In the printed manual (PDF), we don't use links and format the function's @c name like a command name. @inlinefmtifelse{html,@uref{@inlineifset{octave-forge,..}@inlineifclear{octave-forge,https://octave.sourceforge.io/interval}/function/\function\.html,\function\},@command{\function\}} @end macro @end ifcommandnotdefined interval-3.2.0/doc/manual.css0000644000000000000000000000606013316017127014225 0ustar 00000000000000/* This is part of the GNU Octave Interval Package Manual. Copyright 2015-2017 Oliver Heimlich. See the file manual.texinfo for copying conditions. */ /* Use custom fonts */ code, kbd, samp, tt, pre { font-family: 'Fantasque Sans Mono', 'Consolas', monospace; } code, kbd, samp, tt { font-style: italic; padding: 0 0.1ex; /* slightly increase margin to surrounding text */ } body, span.sansserif { font-family: 'Lato', 'Roboto Condensed', 'Calibri', sans-serif; } h1, h2, h3, h4, h5, span.roman, pre.menu-comment, pre.menu-preformatted { font-family: 'Lato', 'Roboto Condensed', 'Calibri', serif; } /* Use colors from the solarized color theme (sparsely), the main text will remain in default colors for optimal readability (black on white). */ pre.example, .header, .float-caption, hr { /* base00 ~ body text in light solarized theme */ color: #657b83; border-color: #657b83; } pre.example { /* base3 ~ background color in light solarized theme */ background-color: #fdf6e3; padding: 0.5em; } a { color: #268bd2; /* blue */ } a:visited { color: #d33682; /* magenta */ } /* Center floating tables and images */ .float table, .float img, .float object { margin-left: auto; margin-right: auto; } /* Decrease table width, but not on small screens */ .float table { max-width: 38em; } /* Use horizontal lines: above/below tables and after table headers (Chicago Style) */ .float table, .float th { border-collapse: collapse; border-top: 1px solid black; border-bottom: 1px solid black; } .float th, .float td { padding: 0.5em; } /* Use horizontal ruler with double lines */ hr { border-width: 0; border-top-width: 3px; border-style: double; } /* Smaller gap between subsequent @group blocks */ .example { margin-bottom: 1em; } .example + .example { margin-top: -0.5em } /* Smaller gap between definition and its description */ dd > p:first-child { margin-top: 0.5em; } /* Limit maximum body width such that text is easier to read */ body { max-width: 42em; margin-left: 0.5em; margin-right: 0.5em; } /* On small screens don't indent the code examples to prevent overflow */ div.example { margin-left: auto; max-width: 38.8em; } /* Use left margin such that text is easier to read, but don't sacrifice space on small screens. */ @media screen and (min-width: 43em) { /* Smooth transition for screens between 43em and 57em */ body { margin-left: auto; margin-right: auto; } @media (min-width: 57em) { body { margin-left: 7.5em; } } } /* Workaround for missing support of alpha lists and lists starting from zero in Texinfo's HTML output. FIXME: This should be fixed upstream. */ div.alpha-list + ol { list-style-type:lower-alpha; } div.zero-list + ol { counter-reset: item -1; } div.zero-list + ol > li { display:block; } div.zero-list + ol > li:before { content: counter(item) "."; counter-increment: item; display:inline-block; margin-left: -2.5em; min-width: 2em; margin-right: 0.2em; text-align: right; } /* Improve display of large graphics. FIXME: This should go into Octave's CSS file. */ div.float img, body > img { display: block; max-width: 42em; } object { max-width: 100% } interval-3.2.0/doc/manual.texinfo0000644000000000000000000000575413316017127015122 0ustar 00000000000000\input texinfo @setfilename manual.info @settitle GNU Octave Interval Package Manual @documentencoding UTF-8 @tex % U and the following characters have been predefined in TexInfo 6 @ifcommandnotdefined U \DeclareUnicodeCharacter{00A0}{\ } \DeclareUnicodeCharacter{00A7}{\S} \DeclareUnicodeCharacter{00B1}{$\pm$} \DeclareUnicodeCharacter{00B2}{${}^2$} \DeclareUnicodeCharacter{00B7}{$\cdot$} \DeclareUnicodeCharacter{00BD}{1/2} \DeclareUnicodeCharacter{00D7}{$\times$} \DeclareUnicodeCharacter{00F7}{$\div$} @end ifcommandnotdefined \DeclareUnicodeCharacter{03C0}{$\pi$} \DeclareUnicodeCharacter{202F}{\thinspace} \DeclareUnicodeCharacter{2080}{$_0$} \DeclareUnicodeCharacter{2081}{$_1$} \DeclareUnicodeCharacter{2200}{$\forall$} \DeclareUnicodeCharacter{2203}{$\exists$} \DeclareUnicodeCharacter{2208}{$\in$} \DeclareUnicodeCharacter{221E}{$\infty$} \DeclareUnicodeCharacter{2227}{$\wedge$} \DeclareUnicodeCharacter{2229}{$\cap$} \DeclareUnicodeCharacter{2264}{$\leq$} \DeclareUnicodeCharacter{2265}{$\geq$} \DeclareUnicodeCharacter{2282}{$\subset$} \DeclareUnicodeCharacter{2287}{$\supseteq$} \DeclareUnicodeCharacter{2713}{$\ast$} @end tex @copying This manual is for the GNU Octave interval package, version @value{version}. Copyright @copyright{} 2015–2018 Oliver Heimlich Copyright @copyright{} 2017 Joel Dahne Copyright @copyright{} 2008-2009 Simone Pernice Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. A copy of the license is included in @ref{GNU General Public License}. @end copying @include macros.texinfo @titlepage @title GNU Octave Interval Package @subtitle User Manual @vskip 0pt plus 3filll @myimage{image/interval-sombrero.m,Interval sombrero} @vskip 0pt plus 1filll @author Oliver Heimlich @page @vskip 0pt plus 1filll @insertcopying @end titlepage @ifnottex @insertcopying @end ifnottex @node Top @ifnottex @top @end ifnottex @menu How to install and use the interval package for GNU Octave * Preface:: Background information before usage * Getting Started:: Quick-start guide for the basics * Introduction to Interval Arithmetic:: Fundamental concepts * Examples:: Showcase of use cases * Advanced Topics:: Get the most out of it Appendix * IEEE Std 1788-2015:: IEEE standard for interval arithmetic * GNU General Public License:: The license for this software and its manual @end menu @ifhtml @myimage{image/interval-sombrero.m,Interval sombrero} @end ifhtml @contents @node Preface @include chapter/preface.texinfo @node Getting Started @include chapter/getting-started.texinfo @node Introduction to Interval Arithmetic @include chapter/introduction-to-interval-arithmetic.texinfo @node Examples @include chapter/examples.texinfo @node Advanced Topics @include chapter/advanced-topics.texinfo @node IEEE Std 1788-2015 @include chapter/ieee-1788.texinfo @node GNU General Public License @appendix GNU General Public License @include license/gpl-3.0.texi @bye interval-3.2.0/inst/@infsup/abs.m0000644000000000000000000000777513316017127015013 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} abs (@var{X}) ## ## Compute the absolute value of numbers. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## abs (infsup (2.5, 3.5)) ## @result{} ans = [2.5, 3.5] ## abs (infsup (-0.5, 5.5)) ## @result{} ans = [0, 5.5] ## @end group ## @end example ## @seealso{@@infsup/mag, @@infsup/mig} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = abs (x) if (nargin ~= 1) print_usage (); return endif ## This is already correct, if the interval(s) are non-negative. l = x.inf; u = x.sup; ## This is even correct, if the interval(s) are empty. notpositive = (x.sup <= 0); l(notpositive) = -x.sup(notpositive); u(notpositive) = -x.inf(notpositive); zerointerior = (x.inf < 0 & not (notpositive)); l(zerointerior) = -0; u(zerointerior) = max (-x.inf(zerointerior), x.sup(zerointerior)); x.inf = l; x.sup = u; endfunction %!# Empty interval %!assert (abs (infsup ()) == infsup ()); %!# Singleton intervals %!assert (abs (infsup (1)) == infsup (1)); %!assert (abs (infsup (0)) == infsup (0)); %!assert (abs (infsup (-1)) == infsup (1)); %!assert (abs (infsup (realmax)) == infsup (realmax)); %!assert (abs (infsup (realmin)) == infsup (realmin)); %!assert (abs (infsup (-realmin)) == infsup (realmin)); %!assert (abs (infsup (-realmax)) == infsup (realmax)); %!# Bounded intervals %!assert (abs (infsup (1, 2)) == infsup (1, 2)); %!assert (abs (infsup (0, 1)) == infsup (0, 1)); %!assert (abs (infsup (-1, 1)) == infsup (0, 1)); %!assert (abs (infsup (-1, 0)) == infsup (0, 1)); %!assert (abs (infsup (-2, -1)) == infsup (1, 2)); %!# Unbounded intervals %!assert (abs (infsup (0, inf)) == infsup (0, inf)); %!assert (abs (infsup (-inf, inf)) == infsup (0, inf)); %!assert (abs (infsup (-inf, 0)) == infsup (0, inf)); %!assert (abs (infsup (1, inf)) == infsup (1, inf)); %!assert (abs (infsup (-1, inf)) == infsup (0, inf)); %!assert (abs (infsup (-inf, -1)) == infsup (1, inf)); %!assert (abs (infsup (-inf, 1)) == infsup (0, inf)); %!# from the documentation string %!assert (abs (infsup (2.5, 3.5)) == infsup (2.5, 3.5)); %!assert (abs (infsup (-0.5, 5.5)) == infsup (0, 5.5)); %!# correct use of signed zeros %!assert (signbit (inf (abs (infsup (-1, 0))))); %!test %! x = abs (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.abs; %! for testcase = [testcases]' %! assert (isequaln (... %! abs (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.abs; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (abs (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.abs; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (abs (in1), out)); interval-3.2.0/inst/@infsup/absrev.m0000644000000000000000000001243413316017127015514 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} absrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsup} {@var{X} =} absrev (@var{C}) ## ## Compute the reverse absolute value function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{abs (x) ∈ @var{C}}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## absrev (infsup (-2, 1)) ## @result{} ans = [-1, +1] ## @end group ## @end example ## @seealso{@@infsup/abs} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = absrev (c, x) if (nargin < 1 || nargin > 2) print_usage (); return endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (nargin < 2) x = infsup (-inf, inf); elseif (not (isa (x, "infsup"))) x = infsup (x); endif ## Compute the pre-image of abs for positive and negative x separately. p = intersect (c, infsup (0, inf)); n = -p; result = union (intersect (p, x), intersect (n, x)); endfunction %!# Empty interval %!assert (absrev (infsup ()) == infsup ()); %!assert (absrev (infsup (0, 1), infsup ()) == infsup ()); %!assert (absrev (infsup (0, 1), infsup (7, 9)) == infsup ()); %!assert (absrev (infsup (), infsup (0, 1)) == infsup ()); %!assert (absrev (infsup (-2, -1)) == infsup ()); %!# Singleton intervals %!assert (absrev (infsup (1)) == infsup (-1, 1)); %!assert (absrev (infsup (0)) == infsup (0)); %!assert (absrev (infsup (-1)) == infsup ()); %!assert (absrev (infsup (realmax)) == infsup (-realmax, realmax)); %!assert (absrev (infsup (realmin)) == infsup (-realmin, realmin)); %!assert (absrev (infsup (-realmin)) == infsup ()); %!assert (absrev (infsup (-realmax)) == infsup ()); %!# Bound intervals %!assert (absrev (infsup (1, 2)) == infsup (-2, 2)); %!assert (absrev (infsup (1, 2), infsup (0, 2)) == infsup (1, 2)); %!assert (absrev (infsup (0, 1), infsup (-0.5, 2)) == infsup (-0.5, 1)); %!assert (absrev (infsup (-1, 1)) == infsup (-1, 1)); %!assert (absrev (infsup (-1, 0)) == infsup (0)); %!# Unbound intervals %!assert (absrev (infsup (0, inf)) == infsup (-inf, inf)); %!assert (absrev (infsup (-inf, inf)) == infsup (-inf, inf)); %!assert (absrev (infsup (-inf, 0)) == infsup (0)); %!assert (absrev (infsup (1, inf), infsup (-inf, 0)) == infsup (-inf, -1)); %!assert (absrev (infsup (-1, inf)) == infsup (-inf, inf)); %!assert (absrev (infsup (-inf, -1)) == infsup ()); %!assert (absrev (infsup (-inf, 1)) == infsup (-1, 1)); %!# from the documentation string %!assert (absrev (infsup (-2, 1)) == infsup (-1, 1)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation with one argument %! testcases = testdata.NoSignal.infsup.absRev; %! for testcase = [testcases]' %! assert (isequaln (... %! absrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation with one argument %! testcases = testdata.NoSignal.infsup.absRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (absrev (in1), out)); %!test %! # N-dimensional array evaluation with one argument %! testcases = testdata.NoSignal.infsup.absRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (absrev (in1), out)); %!test %! # Scalar evaluation with two arguments %! testcases = testdata.NoSignal.infsup.absRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! absrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation with two arguments %! testcases = testdata.NoSignal.infsup.absRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (absrev (in1, in2), out)); %!test %! # N-dimensional array evaluation with two arguments %! testcases = testdata.NoSignal.infsup.absRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (absrev (in1, in2), out)); interval-3.2.0/inst/@infsup/acos.m0000644000000000000000000000735713316017127015167 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} acos (@var{X}) ## ## Compute the inverse cosine in radians (arccosine). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## acos (infsup (.5)) ## @result{} ans ⊂ [1.0471, 1.0472] ## @end group ## @end example ## @seealso{@@infsup/cos} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-06 function x = acos (x) if (nargin ~= 1) print_usage (); return endif persistent domain = infsup (-1, 1); x = intersect (x, domain); ## acos is monotonically decreasing from (-1, pi) to (+1, 0) if (__check_crlibm__ ()) l = crlibm_function ('acos', -inf, x.sup); u = crlibm_function ('acos', +inf, x.inf); else l = mpfr_function_d ('acos', -inf, x.sup); u = mpfr_function_d ('acos', +inf, x.inf); endif l(l == 0) = -0; emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; x.inf = l; x.sup = u; endfunction %!# Empty interval %!assert (acos (infsup ()) == infsup ()); %!# Singleton intervals %!assert (acos (infsup (-1)) == infsup ("pi")); %!assert (subset (acos (infsup (-.5)), union ((infsup ("pi") / 2), infsup ("pi")))); %!assert (acos (infsup (0)) == infsup ("pi") / 2); %!assert (subset (acos (infsup (.5)), union ((infsup ("pi") / 2), infsup (0)))); %!assert (acos (infsup (1)) == infsup (0)); %!# Bounded intervals %!assert (acos (infsup (-1, 0)) == union ((infsup ("pi") / 2), infsup ("pi"))); %!assert (acos (infsup (0, 1)) == union ((infsup ("pi") / 2), infsup (0))); %!assert (acos (infsup (-1, 1)) == infsup (0, "pi")); %!assert (acos (infsup (-2, 2)) == infsup (0, "pi")); %!# Unbounded intervals %!assert (acos (infsup (0, inf)) == union ((infsup ("pi") / 2), infsup (0))); %!assert (acos (infsup (-inf, 0)) == union ((infsup ("pi") / 2), infsup ("pi"))); %!assert (acos (infsup (-inf, inf)) == infsup (0, "pi")); %!# from the documentation string %!assert (acos (infsup (.5)) == "[0x1.0C152382D7365, 0x1.0C152382D7366]"); %!# correct use of signed zeros %!test %! x = acos (infsup (1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.acos; %! for testcase = [testcases]' %! assert (isequaln (... %! acos (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.acos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (acos (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.acos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (acos (in1), out)); interval-3.2.0/inst/@infsup/acosh.m0000644000000000000000000000653313316017127015332 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} acosh (@var{X}) ## ## Compute the inverse hyperbolic cosine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## acosh (infsup (2)) ## @result{} ans ⊂ [1.3169, 1.317] ## @end group ## @end example ## @seealso{@@infsup/cosh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function x = acosh (x) if (nargin ~= 1) print_usage (); return endif persistent domain = infsup (1, inf); x = intersect (x, domain); ## acosh is monotonically increasing from (1, 0) to (inf, inf) l = mpfr_function_d ('acosh', -inf, x.inf); u = mpfr_function_d ('acosh', +inf, x.sup); l(l == 0) = -0; emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; x.inf = l; x.sup = u; endfunction %!# Empty interval %!assert (acosh (infsup ()) == infsup ()); %!# Singleton intervals %!assert (acosh (infsup (0)) == infsup ()); %!assert (acosh (infsup (1)) == infsup (0)); %!test %! x = infsup (1 : 3 : 100); %! assert (min (subset (acosh (x), log (x + sqrt (x + 1) .* sqrt (x - 1))))); %!# Bounded intervals %!assert (acosh (infsup (0, 1)) == infsup (0)); %!# Unbounded intervals %!assert (acosh (infsup (-inf, 0)) == infsup ()); %!assert (acosh (infsup (-inf, 1)) == infsup (0)); %!assert (acosh (infsup (0, inf)) == infsup (0, inf)); %!assert (acosh (infsup (1, inf)) == infsup (0, inf)); %!assert (subset (acosh (infsup (2, inf)), infsup (1, inf))); %!# from the documentation string %!assert (acosh (infsup (2)) == "[0x1.5124271980434, 0x1.5124271980435]"); %!# correct use of signed zeros %!test %! x = acosh (infsup (1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.acosh; %! for testcase = [testcases]' %! assert (isequaln (... %! acosh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.acosh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (acosh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.acosh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (acosh (in1), out)); interval-3.2.0/inst/@infsup/asin.m0000644000000000000000000000562713316017127015172 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} asin (@var{X}) ## ## Compute the inverse sine in radians (arcsine). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## asin (infsup (.5)) ## @result{} ans ⊂ [0.52359, 0.5236] ## @end group ## @end example ## @seealso{@@infsup/sin} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-06 function x = asin (x) if (nargin ~= 1) print_usage (); return endif persistent domain = infsup (-1, 1); x = intersect (x, domain); ## asin is monotonically increasing from (-1, -pi/2) to (1, pi/2) if (__check_crlibm__ ()) l = crlibm_function ('asin', -inf, x.inf); u = crlibm_function ('asin', +inf, x.sup); else l = mpfr_function_d ('asin', -inf, x.inf); u = mpfr_function_d ('asin', +inf, x.sup); endif l(l == 0) = -0; emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; x.inf = l; x.sup = u; endfunction %!# Empty interval %!assert (asin (infsup ()) == infsup ()); %!# from the documentation string %!assert (asin (infsup (.5)) == "[0x1.0C152382D7365p-1, 0x1.0C152382D7366p-1]"); %!# correct use of signed zeros %!test %! x = asin (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.asin; %! for testcase = [testcases]' %! assert (isequaln (... %! asin (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.asin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (asin (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.asin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (asin (in1), out)); interval-3.2.0/inst/@infsup/asinh.m0000644000000000000000000000511213316017127015327 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} asinh (@var{X}) ## ## Compute the inverse hyperbolic sine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## asinh (infsup (1)) ## @result{} ans ⊂ [0.88137, 0.88138] ## @end group ## @end example ## @seealso{@@infsup/sinh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function x = asinh (x) if (nargin ~= 1) print_usage (); return endif ## asinh is monotonically increasing ## This also works for empty intervals! l = mpfr_function_d ('asinh', -inf, x.inf); u = mpfr_function_d ('asinh', +inf, x.sup); l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (asinh (infsup (1)) == "[0x1.C34366179D426p-1, 0x1.C34366179D427p-1]"); %!# correct use of signed zeros %!test %! x = asinh (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.asinh; %! for testcase = [testcases]' %! assert (isequaln (... %! asinh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.asinh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (asinh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.asinh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (asinh (in1), out)); interval-3.2.0/inst/@infsup/atan.m0000644000000000000000000000537613316017127015164 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} atan (@var{X}) ## ## Compute the inverse tangent in radians. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## atan (infsup (1)) ## @result{} ans ⊂ [0.78539, 0.7854] ## @end group ## @end example ## @seealso{@@infsup/tan, @@infsup/atan2} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-06 function x = atan (x) if (nargin ~= 1) print_usage (); return endif ## atan is monotonically increasing if (__check_crlibm__ ()) l = crlibm_function ('atan', -inf, x.inf); u = crlibm_function ('atan', +inf, x.sup); else l = mpfr_function_d ('atan', -inf, x.inf); u = mpfr_function_d ('atan', +inf, x.sup); endif l(l == 0) = -0; emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (atan (infsup (1)) == "[0x1.921FB54442D18p-1, 0x1.921FB54442D19p-1]"); %!# correct use of signed zeros %!test %! x = atan (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.atan; %! for testcase = [testcases]' %! assert (isequaln (... %! atan (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.atan; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (atan (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.atan; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (atan (in1), out)); interval-3.2.0/inst/@infsup/atan2.m0000644000000000000000000001320613316017127015235 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} atan2 (@var{Y}, @var{X}) ## ## Compute the inverse tangent with two arguments. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## atan2 (infsup (1), infsup (-1)) ## @result{} ans ⊂ [2.3561, 2.3562] ## @end group ## @end example ## @seealso{@@infsup/tan} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-06 function y = atan2 (y, x) if (nargin ~= 2) print_usage (); return endif if (not (isa (y, "infsup"))) y = infsup (y); endif if (not (isa (x, "infsup"))) x = infsup (x); endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, y.inf))) x.inf = ones (size (y.inf)) .* x.inf; x.sup = ones (size (y.inf)) .* x.sup; y.inf = ones (size (x.inf)) .* y.inf; y.sup = ones (size (x.inf)) .* y.sup; endif ## Partitionize the function's domain ## y ## ^ ## p1 | p2 ## ------0------> ## p4 | p3 x ## persistent pos = infsup (0, inf); persistent neg = infsup (-inf, 0); x1 = x4 = intersect (x, neg); y1 = y2 = intersect (y, pos); x2 = x3 = intersect (x, pos); y3 = y4 = intersect (y, neg); ## Intersect each partition with atan2's domain p1 = not (isempty (x1) | isempty (y1)) & (x1.inf < 0 | y1.sup > 0); p2 = not (isempty (x2) | isempty (y2)) & (x2.sup > 0 | y2.sup > 0); p3 = not (isempty (x3) | isempty (y3)) & (x3.sup > 0 | y3.inf < 0); p4 = not (isempty (x4) | isempty (y4)) & (x4.inf < 0 | y4.inf < 0); ## Prevent wrong limit values of atan2 (0, 0) in cases with y = 0. select = (p1 & y1.sup == 0); x1.inf(select) = x1.sup(select) = -1; select = (p2 & y2.sup == 0); x2.inf(select) = x2.sup(select) = 1; select = (p3 & y3.inf == 0); x3.inf(select) = x3.sup(select) = 1; p4(y4.inf == 0) = false (); # don't consider y >= 0 in partition 4 ## Prevent wrong limit values of atan2 (0, 0) in cases with x = 0. select = (p1 & x1.inf == 0); y1.inf(select) = y1.sup(select) = 1; select = (p2 & x2.sup == 0); y2.inf(select) = y2.sup(select) = 1; y3.inf(p3 & x3.sup == 0) = y3.sup(p3 & x3.sup == 0) = -1; select = (p4 & x4.inf == 0); y4.inf(select) = y4.sup(select) = -1; ## Fix interval boundaries for y = 0 and x < 0, because atan2 (±0, -eps) = ±pi y1.inf(p1 & y1.inf == 0) = +0; y4.sup(p4 & y4.sup == 0) = -0; ## Compute lower boundary (atan2 is increasing from p4 to p1) l = inf (size (p1)); select = p4; l(select) = mpfr_function_d ('atan2', -inf, y4.sup(select), x4.inf(select)); select = p3 & not (p4); l(select) = mpfr_function_d ('atan2', -inf, y3.inf(select), x3.inf(select)); select = p2 & not (p3 | p4); l(select) = mpfr_function_d ('atan2', -inf, y2.inf(select), x2.sup(select)); select = p1 & not (p2 | p3 | p4); l(select) = mpfr_function_d ('atan2', -inf, y1.sup(select), x1.sup(select)); ## Compute upper boundary (atan2 is decreasing from p1 to p4) u = -inf (size (p1)); select = p1; u(select) = mpfr_function_d ('atan2', +inf, y1.inf(select), x1.inf(select)); select = p2 & not (p1); u(select) = mpfr_function_d ('atan2', +inf, y2.sup(select), x2.inf(select)); select = p3 & not (p1 | p2); u(select) = mpfr_function_d ('atan2', +inf, y3.sup(select), x3.sup(select)); select = p4 & not (p1 | p2 | p3); u(select) = mpfr_function_d ('atan2', +inf, y4.inf(select), x4.sup(select)); ## Now, we have computed l and u for all cases where p1 | p2 | p3 | ## p4. In all other cases, l and u will produce an empty interval. l(l == 0) = -0; y.inf = l; y.sup = u; endfunction %!test "from the documentation string"; %!assert (atan2 (infsup (1), infsup (-1)) == "[0x1.2D97C7F3321D2p1, 0x1.2D97C7F3321D3p1]"); %!# correct use of signed zeros %!test %! x = atan2 (0, infsup (1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.atan2; %! for testcase = [testcases]' %! assert (isequaln (... %! atan2 (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.atan2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (atan2 (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.atan2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (atan2 (in1, in2), out)); interval-3.2.0/inst/@infsup/atan2rev1.m0000644000000000000000000001623013316017127016033 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{Y} =} atan2rev1 (@var{B}, @var{C}, @var{Y}) ## @deftypemethodx {@@infsup} {@var{Y} =} atan2rev1 (@var{B}, @var{C}) ## ## Compute the reverse atan2 function for the first parameter. ## ## That is, an enclosure of all @code{y ∈ @var{Y}} where ## @code{atan2 (y, b) ∈ @var{C}} for any @code{b ∈ @var{B}}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## atan2rev1 (infsup (1, 2), infsup ("pi") / 4) ## @result{} ans ⊂ [0.99999, 2.0001] ## @end group ## @end example ## @seealso{@@infsup/atan2} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = atan2rev1 (b, c, y) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) y = infsup (-inf, inf); endif if (not (isa (b, "infsup"))) b = infsup (b); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (y, "infsup"))) y = infsup (y); endif ## Resize, if broadcasting is needed if (not (size_equal (b.inf, c.inf))) b.inf = ones (size (c.inf)) .* b.inf; b.sup = ones (size (c.inf)) .* b.sup; c.inf = ones (size (b.inf)) .* c.inf; c.sup = ones (size (b.inf)) .* c.sup; endif if (not (size_equal (b.inf, y.inf))) b.inf = ones (size (y.inf)) .* b.inf; b.sup = ones (size (y.inf)) .* b.sup; c.inf = ones (size (y.inf)) .* c.inf; c.sup = ones (size (y.inf)) .* c.sup; y.inf = ones (size (b.inf)) .* y.inf; y.sup = ones (size (b.inf)) .* y.sup; endif persistent pi = infsup ("pi"); idx.type = '()'; emptyresult = isempty (y) | isempty (b) | isempty (c) | ... c.inf >= sup (pi) | c.sup <= inf (-pi); result = repmat (infsup (), size (y.inf)); ## c1 is the part of c where y >= 0 and x <= 0 c1 = intersect (c, infsup (inf (pi) / 2, sup (pi))); select = not (emptyresult | isempty (c1) | ... b.inf > 0 | y.sup < 0 | c1.sup == inf (pi) / 2 | ... (b.inf >= 0 & y.sup <= 0) | ... (b.inf >= 0 & c1.inf > inf (pi) / 2)); if (any (select(:))) ## The inverse function is y = b * tan (c) ## minimum is located at b.sup, c.sup ## maximum is located at b.inf, c.inf l = zeros (size (result.inf)); select_l = select & c1.sup < sup (pi) & b.sup < 0; l (select_l) = ... max (0, ... inf (b.sup (select_l) .* tan (infsup (c1.sup (select_l))))); u = inf (size (result.inf)); select_u = select & c1.inf > inf (pi) / 2 & b.inf > -inf; u (select_u) = ... sup (b.inf (select_u) .* tan (infsup (c1.inf (select_u)))); idx.subs = {select}; result = subsasgn (result, idx, ... intersect (subsref (y, idx), ... infsup (subsref (l, idx), subsref (u, idx)))); endif ## c2 is the part of c where y >= 0 and x >= 0 c2 = intersect (c, infsup (0, sup (pi) / 2)); select = not (emptyresult | isempty (c2) | b.sup < 0 | y.sup < 0 | ... c2.inf == sup (pi) / 2 | ... (b.sup <= 0 & y.sup <= 0) | ... (b.sup <= 0 & c2.sup < sup (pi) / 2)); if (any (select(:))) ## The inverse function is y = b * tan (c) ## minimum is located at b.inf, c.inf ## maximum is located at b.sup, c.sup l = zeros (size (result.inf)); select_l = select & c2.inf > 0 & b.inf > 0; l (select_l) = ... max (0, ... inf (b.inf (select_l) .* tan (infsup (c2.inf (select_l))))); u = inf (size (result.inf)); u (c2.sup == 0) = 0; select_u = select & c2.sup ~= 0 & c2.sup < sup (pi) / 2 & b.sup < inf; u (select_u) = ... sup (b.sup (select_u) .* tan (infsup (c2.sup (select_u)))); idx.subs = {select}; result = subsasgn (result, idx, ... union (subsref (result, idx), ... intersect (subsref (y, idx), ... infsup (subsref (l, idx), ... subsref (u, idx))))); endif ## c3 is the part of c where y <= 0 and x >= 0 c3 = intersect (c, infsup (inf (-pi) / 2, 0)); select = not (emptyresult | isempty (c3) | b.sup < 0 | y.inf > 0 | ... c3.sup == inf (-pi) / 2 | (b.sup <= 0 & y.inf >= 0) | ... (b.sup <= 0 & c2.inf > inf (-pi) / 2)); if (any (select(:))) ## The inverse function is y = b * tan (c) ## minimum is located at b.sup, c.inf ## maximum is located at b.inf, c.sup l = -inf (size (result.inf)); l (c3.inf == 0) = 0; select_l = select & c3.inf ~= 0 & c3.inf > inf (-pi) / 2 & b.sup < inf; l (select_l) = ... inf (b.sup (select_l) .* tan (infsup (c3.inf (select_l)))); u = zeros (size (result.inf)); select_u = select & c3.sup ~= 0 & b.inf > 0; u (select_u) = ... sup (b.inf (select_u) .* tan (infsup (c3.sup (select_u)))); idx.subs = {select}; result = subsasgn (result, idx, ... union (subsref (result, idx), ... intersect (subsref (y, idx), ... infsup (subsref (l, idx), ... subsref (u, idx))))); endif ## c4 is the part of c where y <= 0 and x <= 0 c4 = intersect (c, infsup (inf (-pi), sup (-pi) / 2)); select = not (emptyresult | isempty (c4) | b.inf > 0 | y.inf > 0 | ... c4.inf == sup (-pi) / 2 | (b.inf >= 0 & y.inf >= 0) | ... (b.inf >= 0 & c4.sup < sup (-pi) / 2)); if (any (select(:))) ## The inverse function is y = b * tan (c) ## minimum is located at b.inf, c.sup ## maximum is located at b.sup, c.inf l = -inf (size (result.inf)); select_l = select & c4.sup < sup (-pi) / 2 & b.inf > -inf; l (select_l) = ... inf (b.inf (select_l) .* tan (infsup (c4.sup (select_l)))); u = zeros (size (result.inf)); select_u = select & c4.inf > inf (-pi) & b.sup < 0; u (select_u) = ... min (0, ... sup (b.sup (select_u) .* tan (infsup (c4.sup (select_u))))); idx.subs = {select}; result = subsasgn (result, idx, ... union (subsref (result, idx), ... intersect (subsref (y, idx), ... infsup (subsref (l, idx), ... subsref (u, idx))))); endif endfunction %!# from the documentation string %!assert (atan2rev1 (infsup (1, 2), infsup ("pi") / 4) == "[0x1.FFFFFFFFFFFFFp-1, 0x1.0000000000001p1]"); interval-3.2.0/inst/@infsup/atan2rev2.m0000644000000000000000000001614713316017127016043 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} atan2rev2 (@var{A}, @var{C}, @var{X}) ## @deftypemethodx {@@infsup} {@var{X} =} atan2rev2 (@var{A}, @var{C}) ## ## Compute the reverse atan2 function for the second parameter. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{atan2 (a, x) ∈ @var{C}} for any @code{a ∈ @var{A}}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## atan2rev2 (infsup (1, 2), infsup ("pi") / 4) ## @result{} ans ⊂ [0.99999, 2.0001] ## @end group ## @end example ## @seealso{@@infsup/atan2} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = atan2rev2 (a, c, x) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) x = infsup (-inf, inf); endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (x, "infsup"))) x = infsup (x); endif ## Resize, if broadcasting is needed if (not (size_equal (a.inf, c.inf))) a.inf = ones (size (c.inf)) .* a.inf; a.sup = ones (size (c.inf)) .* a.sup; c.inf = ones (size (a.inf)) .* c.inf; c.sup = ones (size (a.inf)) .* c.sup; endif if (not (size_equal (a.inf, x.inf))) a.inf = ones (size (x.inf)) .* a.inf; a.sup = ones (size (x.inf)) .* a.sup; c.inf = ones (size (x.inf)) .* c.inf; c.sup = ones (size (x.inf)) .* c.sup; x.inf = ones (size (a.inf)) .* x.inf; x.sup = ones (size (a.inf)) .* x.sup; endif pi = infsup ("pi"); idx.type = '()'; emptyresult = isempty (x) | isempty (a) | isempty (c) | ... c.inf >= sup (pi) | c.sup <= inf (-pi); result = repmat (infsup (), size (x.inf)); ## c1 is the part of c where y >= 0 and x <= 0 c1 = intersect (c, infsup (inf (pi) / 2, sup (pi))); select = not (emptyresult | isempty (c1) | x.inf > 0 | a.sup < 0 | ... c1.sup == inf (pi) / 2 | ... (x.inf >= 0 & a.sup <= 0) | ... (a.sup <= 0 & c1.inf > inf (pi) / 2)); if (any (select(:))) ## The inverse function is x = a / tan (c) ## minimum is located at a.sup, c.sup ## maximum is located at a.inf, c.inf l = -inf (size (result.inf)); select_l = select & c1.sup < sup (pi) & a.sup < inf; l (select_l) = ... inf (a.sup (select_l) ./ tan (infsup (c1.sup (select_l)))); u = zeros (size (result.inf)); select_u = select & c1.inf > inf (pi) / 2 & a.inf > 0; u (select_u) = ... sup (a.inf (select_u) ./ tan (infsup (c1.inf (select_u)))); idx.subs = {select}; result = subsasgn (result, idx, ... intersect (subsref (x, idx), ... infsup (subsref (l, idx), subsref (u, idx)))); endif ## c2 is the part of c where y >= 0 and x >= 0 c2 = intersect (c, infsup (0, sup (pi) / 2)); select = not (emptyresult | isempty (c2) | x.sup < 0 | a.sup < 0 | ... c2.inf == sup (pi) / 2 | ... (x.sup <= 0 & a.sup <= 0) | (c2.sup <= 0 & a.inf > 0) | ... (a.sup <= 0 & c2.inf > 0)); if (any (select(:))) ## The inverse function is x = a / tan (c) ## minimum is located at a.inf, c.sup ## maximum is located at a.sup, c.inf l = zeros (size (result.inf)); select_l = select & c2.sup ~= 0 & c2.sup < sup (pi) / 2; l (select_l) = ... max (0, ... inf (a.inf (select_l) ./ tan (infsup (c2.sup (select_l))))); u = inf (size (result.inf)); select_u = select & c2.inf ~= 0 & c2.sup ~= 0 & a.sup < inf; u (select_u) = ... sup (a.sup (select_u) ./ tan (infsup (c2.inf (select_u)))); idx.subs = {select}; result = subsasgn (result, idx, ... union (subsref (result, idx), ... intersect (subsref (x, idx), ... infsup (subsref (l, idx), ... subsref (u, idx))))); endif ## c3 is the part of c where y <= 0 and x >= 0 c3 = intersect (c, infsup (inf (-pi) / 2, 0)); select = not (emptyresult | isempty (c3) | x.sup < 0 | a.inf > 0 | ... c3.sup == inf (-pi) / 2 | (x.sup <= 0 & a.inf >= 0) | ... (c3.inf >= 0 & a.sup < 0) | (a.inf >= 0 & c3.sup < 0)); if (any (select(:))) ## The inverse function is x = a / tan (c) ## minimum is located at a.sup, c.inf ## maximum is located at a.inf, c.sup l = zeros (size (result.inf)); select_l = select & c3.inf > inf (-pi) / 2 & c3.inf ~= 0; l (select_l) = ... max (0, ... inf (a.sup (select_l) ./ tan (infsup (c3.inf (select_l))))); u = inf (size (result.inf)); select_u = select & c3.inf ~= 0 & c3.sup ~= 0 & a.inf < inf; u (select_u) = ... sup (a.inf (select_u) ./ tan (infsup (c3.sup (select_u)))); idx.subs = {select}; result = subsasgn (result, idx, ... union (subsref (result, idx), ... intersect (subsref (x, idx), ... infsup (subsref (l, idx), ... subsref (u, idx))))); endif ## c4 is the part of c where y <= 0 and x <= 0 c4 = intersect (c, infsup (inf (-pi), sup (-pi) / 2)); select = not (emptyresult | isempty (c4) | x.inf > 0 | a.inf > 0 | ... c4.inf == sup (-pi) / 2 | (x.inf >= 0 & a.inf >= 0) | ... (a.inf >= 0 & c4.inf > inf (-pi))); if (any (select(:))) ## The inverse function is x = a / tan (c) ## minimum is located at a.inf, c.inf ## maximum is located at a.sup, c.sup l = -inf (size (result.inf)); select_l = select & c4.inf > inf (-pi) & a.inf > -inf; l (select_l) = ... inf (a.inf (select_l) ./ tan (infsup (c4.inf (select_l)))); u = zeros (size (result.inf)); select_u = select & c4.sup < sup (-pi) / 2 & a.sup < 0; u (select_u) = ... sup (a.sup (select_u) ./ tan (infsup (c4.sup (select_u)))); idx.subs = {select}; result = subsasgn (result, idx, ... union (subsref (result, idx), ... intersect (subsref (x, idx), ... infsup (subsref (l, idx), ... subsref (u, idx))))); endif endfunction %!# from the documentation string %!assert (atan2rev2 (infsup (1, 2), infsup ("pi") / 4) == "[0x1.FFFFFFFFFFFFEp-1, 0x1.0000000000001p1]"); interval-3.2.0/inst/@infsup/atanh.m0000644000000000000000000000532513316017127015326 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} atanh (@var{X}) ## ## Compute the inverse hyperbolic tangent. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## atanh (infsup (.5)) ## @result{} ans ⊂ [0.5493, 0.54931] ## @end group ## @end example ## @seealso{@@infsup/tanh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function x = atanh (x) if (nargin ~= 1) print_usage (); return endif x = intersect (x, infsup (-1, 1)); ## atanh is monotonically increasing between (-1, -inf) and (1, inf) l = mpfr_function_d ('atanh', -inf, x.inf); u = mpfr_function_d ('atanh', +inf, x.sup); emptyresult = isempty (x) | x.sup <= -1 | x.inf >= 1; l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (atanh (infsup (.5)) == "[0x1.193EA7AAD030Ap-1, 0x1.193EA7AAD030Bp-1]"); %!# correct use of signed zeros %!test %! x = atanh (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.atanh; %! for testcase = [testcases]' %! assert (isequaln (... %! atanh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.atanh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (atanh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.atanh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (atanh (in1), out)); interval-3.2.0/inst/@infsup/bisect.m0000644000000000000000000001062613316017127015504 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {[@var{A}, @var{B}] =} bisect (@var{X}) ## ## Bisect an interval into two intervals, which contain half the amount of ## binary64 numbers each. ## ## Instead of bisecting the values of numbers in the interval at ## @code{mid (@var{X})}, this function bisects a function that counts them. In ## a bisect method this eliminates exactly half of the solutions and avoids ## slow convergence speeds in extreme cases. ## ## If all numbers in interval @var{X} are of equal sign, the pivot element used ## for bisection is @code{pow2 (mid (log2 (abs (@var{X}))))}. If @var{X} is no ## empty interval, the intervals @var{A} and @var{B} are non-empty and satisfy ## @code{@var{A}.sup == @var{B}.inf}. ## ## @example ## @group ## [a, b] = bisect (infsup (2, 32)) ## @result{} ## a = [2, 8] ## b = [8, 32] ## @end group ## @end example ## @seealso{@@infsup/mince, @@infsup/nextout} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-05-25 function [a, b] = bisect (x) if (nargin > 1) print_usage (); return endif m = zeros (size (x.inf)); idx.type = '()'; positive = x.inf >= 0 & x.sup > 0; if (any (positive(:))) idx.subs = {positive}; bounded = intersect (infsup (pow2 (-1074), realmax), subsref (x, idx)); m(positive) = min (realmax, pow2 (mid (log2 (bounded)))); endif negative = x.inf < 0 & x.sup <= 0; if (any (negative(:))) idx.subs = {negative}; bounded = intersect (infsup (-realmax, -pow2 (-1074)), subsref (x, idx)); m(negative) = ... uminus (min (realmax, pow2 (mid (log2 (uminus (bounded)))))); endif both_signs = x.inf < 0 & x.sup > 0; both_signs_p = both_signs & x.sup > -x.inf; if (any (both_signs_p(:))) idx.subs = {both_signs_p}; bounded_n = intersect (infsup (-realmax, -pow2 (-1074)), subsref (x, idx)); bounded_p = intersect (infsup (pow2 (-1074), realmax), subsref (x, idx)); m(both_signs_p) = min (realmax, pow2 ( mid (log2 (bounded_p)) ... - mid (log2 (uminus (bounded_n))) ... - 1074)); endif both_signs_n = both_signs & x.sup < -x.inf; if (any (both_signs_n(:))) idx.subs = {both_signs_n}; bounded_n = intersect (infsup (-realmax, -pow2 (-1074)), subsref (x, idx)); bounded_p = intersect (infsup (pow2 (-1074), realmax), subsref (x, idx)); m(both_signs_n) = uminus (min (realmax, ... pow2 (mid (log2 (uminus (bounded_n))) ... - mid (log2 (bounded_p)) ... - 1074))); endif m = min (max (m, x.inf), x.sup); a = b = x; m(isempty (x)) = -inf; a.sup = m; m(isempty (x)) = inf; m(m == 0) = -0; b.inf = m; endfunction %!test %! # from the documentation string %! [a, b] = bisect (infsup (2, 32)); %! assert (a == infsup (2, 8)); %! assert (b == infsup (8, 32)); %!test %! [a, b] = bisect (infsup (-inf, inf)); %! assert (a == infsup (-inf, 0)); %! assert (b == infsup (0, inf)); %!test %! [a, b] = bisect (infsup (0)); %! assert (a == 0); %! assert (b == 0); %!test %! [a, b] = bisect (infsup ()); %! assert (isempty (a)); %! assert (isempty (b)); %!test %! [a, b] = bisect (infsup (0, inf)); %! assert (a == infsup (0, pow2 (-25))); %! assert (b == infsup (pow2 (-25), inf)); %!test %! [a, b] = bisect (infsup (-inf, 0)); %! assert (a == infsup (-inf, -pow2 (-25))); %! assert (b == infsup (-pow2 (-25), 0)); %!# correct use of signed zeros %!test %! [a, b] = bisect (infsup (0)); %! assert (signbit (inf (a))); %! assert (signbit (inf (b))); %! assert (not (signbit (sup (a)))); %! assert (not (signbit (sup (b)))); interval-3.2.0/inst/@infsup/bitunpack.m0000644000000000000000000000464313316017127016215 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} bitunpack (@var{X}) ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## ## Encode bare interval @var{X} in interchange format. ## ## The result is a raw bit pattern of length 128 that derive from two binary64 ## numbers. Bits are in increasing order. Byte order depends on the system's ## endianness. First 8 bytes come from the lower interval boundary, last ## 8 bytes come from the upper interval boundary. ## ## The result is a row vector if @var{X} is a row vector; otherwise, it is a ## column vector. ## ## For all scalar intervals the following equation holds: ## @code{@var{X} == interval_bitpack (bitunpack (@var{X}))}. ## ## @seealso{interval_bitpack} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-12-23 function result = bitunpack (x) if (nargin ~= 1) print_usage (); return endif ## The exchange representation of [Empty] is (+inf, -inf). The exchange ## representation of [0, 0] is (-0, +0). Both is guaranteed by the infsup ## constructor. l = bitunpack (x.inf); u = bitunpack (x.sup); ## Initialize result vector result = zeros (1, length (l) + length (u), 'logical'); if (not (isrow (l))) result = result'; endif ## Merge 64 bit blocks from l and u (alternating) together into result. target = reshape (1 : length (result), 64, numel (x.inf) + numel (x.sup)); target(:, 2 : 2 : size (target, 2)) = []; result(target) = l; result(target + 64) = u; endfunction %!test; %! littleendian = bitunpack (uint16 (1))(1); %! b = zeros (1, 128); %! if (littleendian) %! b([52, 63, 117, 127]) = 1; %! else %! b([7, 12, 71, 77]) = 1; %! endif %! assert (bitunpack (infsup (3, 4)), logical (b)); interval-3.2.0/inst/@infsup/cancelminus.m0000644000000000000000000000750613316017127016537 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{Z} =} cancelminus (@var{X}, @var{Y}) ## ## Recover interval @var{Z} from intervals @var{X} and @var{Y}, given that one ## knows @var{X} was obtained as the sum @var{Y} + @var{Z}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cancelminus (infsup (2, 3), infsup (1, 1.5)) ## @result{} ans = [1, 1.5] ## @end group ## @end example ## @seealso{@@infsup/cancelplus} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function x = cancelminus (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif l = mpfr_function_d ('minus', -inf, x.inf, y.inf); u = mpfr_function_d ('minus', +inf, x.sup, y.sup); wid_x1 = wid (intersect (x, infsup (-inf, 0))); wid_x2 = wid (intersect (x, infsup (0, inf))); wid_y1 = wid (intersect (y, infsup (-inf, 0))); wid_y2 = wid (intersect (y, infsup (0, inf))); [wid_x1, wid_x2] = deal (max (wid_x1, wid_x2), min (wid_x1, wid_x2)); [wid_y1, wid_y2] = deal (max (wid_y1, wid_y2), min (wid_y1, wid_y2)); entireresult = (isempty (y) & not (isempty (x))) | ... y.inf == -inf | y.sup == inf | ... x.inf == -inf | x.sup == inf | ... ## We have to check for wid (x) < wid (y), which is difficult ## for wid > realmax, because of overflow and ## for interior zero, because of rounding errors. (iscommoninterval (x) & iscommoninterval (y) & ... (wid_x1 - wid_y1) + (wid_x2 - wid_y2) < 0); l(entireresult) = -inf; u(entireresult) = inf; emptyresult = isempty (x) & not (entireresult); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (cancelminus (infsup (2, 3), infsup (1, 1.5)) == infsup (1, 1.5)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.cancelMinus; %! for testcase = [testcases]' %! assert (isequaln (... %! cancelminus (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.cancelMinus; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (cancelminus (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.cancelMinus; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cancelminus (in1, in2), out)); interval-3.2.0/inst/@infsup/cancelplus.m0000644000000000000000000000621413316017127016362 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{Z} =} cancelplus (@var{X}, @var{Y}) ## ## Recover interval @var{Z} from intervals @var{X} and @var{Y}, given that one ## knows @var{X} was obtained as the difference @var{Z} - @var{Y}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cancelplus (infsup (2, 3), infsup (1, 1.5)) ## @result{} ans = [3.5, 4] ## @end group ## @end example ## @seealso{@@infsup/cancelminus} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = cancelplus (x, y) if (nargin ~= 2) print_usage (); return endif result = cancelminus (x, -y); endfunction %!# from the documentation string %!assert (cancelplus (infsup (2, 3), infsup (1, 1.5)) == infsup (3.5, 4)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.cancelPlus; %! for testcase = [testcases]' %! assert (isequaln (... %! cancelplus (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.cancelPlus; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (cancelplus (in1, in2), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.cancelPlus; %! for testcase = [testcases]' %! assert (isequaln (... %! cancelplus (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.cancelPlus; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (cancelplus (in1, in2), out)); %!test %! # N-dimensional array vector evaluation %! testcases = testdata.NoSignal.infsupdec.cancelPlus; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cancelplus (in1, in2), out)); interval-3.2.0/inst/@infsup/cat.m0000644000000000000000000000453713316017127015006 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} cat (@var{DIM}, @var{ARRAY1}, @var{ARRAY2}, @dots{}) ## ## Return the concatenation of N-D interval arrays @var{ARRAY1}, @var{ARRAY2}, ## … along dimension @var{DIM}. ## ## @example ## @group ## cat (2, infsup (magic (3)), infsup (pascal (3))) ## @result{} 3×6 interval matrix ## ## [8] [1] [6] [1] [1] [1] ## [3] [5] [7] [1] [2] [3] ## [4] [9] [2] [1] [3] [6] ## @end group ## @end example ## @seealso{@@infsup/horzcat, @@infsup/vertcat} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-19 function result = cat (dim, varargin) if (isa (dim, "infsup")) print_usage (); return endif ## Conversion of non-interval parameters to intervals interval_idx = cellfun ("isclass", varargin, "infsup"); to_convert_idx = not (interval_idx); varargin(to_convert_idx) = cellfun (@infsup, ... varargin(to_convert_idx), ... "UniformOutput", false); ## Stack intervals along dimension dim s = cellfun ("struct", varargin); # struct array result = infsup (); result.inf = cat (dim, s.inf); result.sup = cat (dim, s.sup); endfunction %!assert (size (cat (1, infsup ([]), infsup ([]))), [0 0]); %!assert (cat (1, infsup (1), infsup (2)) == infsup (cat (1, 1, 2))); %!assert (cat (2, infsup (1), infsup (2)) == infsup (cat (2, 1, 2))); %!assert (cat (5, infsup (1), infsup (2)) == infsup (cat (5, 1, 2))); %!assert (cat (1, infsup (zeros (2, 2, 2)), infsup (ones (2, 2, 2))) == infsup (cat (1, zeros (2, 2, 2), ones (2, 2, 2)))); interval-3.2.0/inst/@infsup/cbrt.m0000644000000000000000000000465713316017127015174 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} cbrt (@var{X}) ## ## Compute the cube root. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cbrt (infsup (-27, 27)) ## @result{} ans = [-3, +3] ## @end group ## @end example ## @seealso{@@infsup/realsqrt, @@infsup/nthroot} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function x = cbrt (x) if (nargin ~= 1) print_usage (); return endif x.inf = mpfr_function_d ('cbrt', -inf, x.inf); x.sup = mpfr_function_d ('cbrt', +inf, x.sup); endfunction %!# from the documentation string %!assert (cbrt (infsup (-27, 27)) == infsup (-3, 3)); %!# correct use of signed zeros %!test %! x = cbrt (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.cbrt; %! for testcase = [testcases]' %! assert (isequaln (... %! cbrt (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.cbrt; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (cbrt (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.cbrt; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cbrt (in1), out)); interval-3.2.0/inst/@infsup/ceil.m0000644000000000000000000000717513316017127015154 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} ceil (@var{X}) ## ## Round each number in interval @var{X} towards +Inf. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## ceil (infsup (2.5, 3.5)) ## @result{} ans = [3, 4] ## ceil (infsup (-0.5, 5)) ## @result{} ans = [0, 5] ## @end group ## @end example ## @seealso{@@infsup/floor, @@infsup/round, @@infsup/roundb, @@infsup/fix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = ceil (x) if (nargin ~= 1) print_usage (); return endif x.inf = ceil (x.inf); x.sup = ceil (x.sup); x.sup(x.sup == 0) = +0; endfunction %!# Empty interval %!assert (ceil (infsup ()) == infsup ()); %!# Singleton intervals %!assert (ceil (infsup (0)) == infsup (0)); %!assert (ceil (infsup (0.5)) == infsup (1)); %!assert (ceil (infsup (-0.5)) == infsup (0)); %!# Bounded intervals %!assert (ceil (infsup (-0.5, 0)) == infsup (0)); %!assert (ceil (infsup (0, 0.5)) == infsup (0, 1)); %!assert (ceil (infsup (0.25, 0.5)) == infsup (1)); %!assert (ceil (infsup (-1, 0)) == infsup (-1, 0)); %!assert (ceil (infsup (-1, 1)) == infsup (-1, 1)); %!assert (ceil (infsup (-realmin, realmin)) == infsup (0, 1)); %!assert (ceil (infsup (-realmax, realmax)) == infsup (-realmax, realmax)); %!# Unbounded intervals %!assert (ceil (infsup (-realmin, inf)) == infsup (0, inf)); %!assert (ceil (infsup (-realmax, inf)) == infsup (-realmax, inf)); %!assert (ceil (infsup (-inf, realmin)) == infsup (-inf, 1)); %!assert (ceil (infsup (-inf, realmax)) == infsup (-inf, realmax)); %!assert (ceil (infsup (-inf, inf)) == infsup (-inf, inf)); %!# from the documentation string %!assert (ceil (infsup (2.5, 3.5)) == infsup (3, 4)); %!assert (ceil (infsup (-.5, 5)) == infsup (0, 5)); %!# correct use of signed zeros %!test %! x = ceil (infsup (-0.5)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = ceil (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.ceil; %! for testcase = [testcases]' %! assert (isequaln (... %! ceil (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.ceil; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (ceil (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.ceil; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (ceil (in1), out)); interval-3.2.0/inst/@infsup/chol.m0000644000000000000000000001222213316017127015152 0ustar 00000000000000## Copyright 2008 Jiří Rohn ## Copyright 2016 Oliver Heimlich ## ## This program is derived from verchol in VERSOFT, published on ## 2016-07-26, which is distributed under the terms of the Expat license, ## a.k.a. the MIT license. Original Author is Jiří Rohn. Migration to Octave ## code has been performed by Oliver Heimlich. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{R} = } chol (@var{A}) ## @deftypemethodx {@@infsup} {[@var{R}, @var{P}] = } chol (@var{A}) ## @deftypemethodx {@@infsup} {[@var{R}, @dots{}] = } chol (@dots{}, "upper") ## @deftypemethodx {@@infsup} {[@var{L}, @dots{}] = } chol (@dots{}, "lower") ## Compute the Cholesky factor, @var{R}, of each symmetric positive definite ## matrix in @var{A}. ## ## The Cholsky factor is defined by ## @display ## @var{R}' * @var{R} = @var{A}. ## @end display ## ## @example ## @group ## chol (infsup (pascal (3))) ## @result{} ans = 3×3 interval matrix ## ## [1] [1] [1] ## [0] [1] [2] ## [0] [0] [1] ## ## @end group ## @end example ## ## Called using the @option{lower} flag, @command{chol} returns the lower ## triangular factorization such that ## @display ## @var{L} * @var{L}' = @var{A}. ## @end display ## ## @example ## @group ## chol (infsup (pascal (3)), "lower") ## @result{} ans = 3×3 interval matrix ## ## [1] [0] [0] ## [1] [1] [0] ## [1] [2] [1] ## ## @end group ## @end example ## ## Warning: Output data widths may grow rapidly with increasing dimensions. ## ## Called with one output argument this function fails if each symmetric matrix ## in @var{A} is guaranteed to be not positive definite. With two output ## arguments @var{P} flags whether each symmetric matrix was guaranteed to be ## not positive definite and the function does not fail. A positive value of ## @var{P} indicates that each symmetric matrix in A is guaranteed to be not ## positive definite. Otherwise @var{P} is zero. ## ## This function tries to guarantee that each symmetric matrix in @var{A} is ## positive definite. If that fails, a warning is triggered. ## ## @example ## @group ## A = infsup (pascal (3)); ## A(3, 3) = "[5, 6]"; ## chol (A) ## @print{} warning: chol: matrix is not guaranteed to be positive definite ## @result{} ans = 3×3 interval matrix ## ## [1] [1] [1] ## [0] [1] [2] ## [0] [0] [0, 1] ## ## @end group ## @end example ## ## @seealso{@@infsup/lu, @@infsup/qr} ## @end deftypemethod ## Author: Jiří Rohn ## Keywords: interval ## Created: 2008-02-02 function [fact, P] = chol (A, option) if (nargin > 2) print_usage (); return elseif (nargin < 2) option = "upper"; endif if (not (ischar (option) && any (strcmp (option, {"upper", "lower"})))) print_usage (); return endif [m, n] = size (A); if (m ~= n) error ("chol: matrix is not square"); endif ## Matrix is symmetric by definition, eliminate illegal values A = intersect (A, A'); P = 0; ## columnwise computation of L done in frame of A for k = 1 : n idx_diag = substruct ("()", {k, k}); ## row vector # enables vectorized computation el = subsref (A, substruct ("()", {k, 1 : k - 1})); ## first main formula (diagonal entry) alpha = subsref (A, idx_diag) - el * el'; if (inf (alpha) <= 0) if (sup (alpha) <= 0) ## each symmetric Ao in A verified not to be PD P = -alpha.sup; if (nargout < 2) error ("chol: matrix is not positive definite"); endif else ## continue only on PD values, but warn about it warning ("chol:PD", ... "chol: matrix is not guaranteed to be positive definite"); endif endif s = sqrt (alpha); A = subsasgn (A, idx_diag, s); ## second main formula (subdiagonal entries) idx_subdiag = substruct ("()", {k + 1 : n, k}); A = subsasgn (A, idx_subdiag, ... (subsref (A, idx_subdiag) - ... subsref (A, substruct ("()", {k + 1 : n, 1 : k - 1})) * ... el') ./ s); endfor ## verified Cholesky decomposition found L = tril (A); # lower triangular part extracted switch (option) case "lower" fact = L; case "upper" fact = L'; endswitch endfunction %!assert (chol (infsup (pascal (10))) == chol (pascal (10))); %!assert (chol (infsupdec (pascal (10))) == chol (pascal (10))); %!test %! A = infsup ([2, 1; 1, 1]); %! R = chol (A); %! assert (ismember ([sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)], R)); %! assert (wid (R) < 1e-15); interval-3.2.0/inst/@infsup/columns.m0000644000000000000000000000245513316017127015714 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} columns (@var{A}) ## ## Return the number of columns of @var{A}. ## @seealso{@@infsup/numel, @@infsup/size, @@infsup/length, @@infsup/rows, @@infsup/end} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function result = columns (a) if (nargin ~= 1) print_usage (); return endif result = columns (a.inf); endfunction %!assert (columns (infsup (zeros (3, 4))), 4); %!assert (columns (infsup (zeros (0, 4))), 4); %!assert (columns (infsup (zeros (3, 0))), 0); %!assert (columns (infsup (zeros (3, 1))), 1); interval-3.2.0/inst/@infsup/cos.m0000644000000000000000000001303713316017127015016 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} cos (@var{X}) ## ## Compute the cosine in radians. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cos (infsup (1)) ## @result{} ans ⊂ [0.5403, 0.54031] ## @end group ## @end example ## @seealso{@@infsup/acos, @@infsup/sec, @@infsup/cosh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-05 function x = cos (x) if (nargin ~= 1) print_usage (); return endif l = u = sinsignl = sinsignu = zeros (size (x.inf)); ## Check, if wid (x) is certainly greater than 2*pi. This can save the ## computation if some cosine values. width = mpfr_function_d ('minus', -inf, x.sup, x.inf); persistent pi = infsup ("pi"); persistent twopi = 2 .* pi; certainlyfullperiod = width >= sup (twopi); l(certainlyfullperiod) = -1; u(certainlyfullperiod) = 1; possiblynotfullperiod = not (certainlyfullperiod); if (__check_crlibm__ ()) l(possiblynotfullperiod) = min (crlibm_function ('cos', -inf, ... x.inf(possiblynotfullperiod)), ... crlibm_function ('cos', -inf, ... x.sup(possiblynotfullperiod))); u(possiblynotfullperiod) = max (crlibm_function ('cos', inf, ... x.inf(possiblynotfullperiod)), ... crlibm_function ('cos', inf, ... x.sup(possiblynotfullperiod))); ## We use sign (-sin) to know the gradient at the boundaries. sinsignl(possiblynotfullperiod) = sign (-crlibm_function ('sin', .5, ... x.inf(possiblynotfullperiod))); sinsignu(possiblynotfullperiod) = sign (-crlibm_function ('sin', .5, ... x.sup(possiblynotfullperiod))); else l(possiblynotfullperiod) = min (mpfr_function_d ('cos', -inf, ... x.inf(possiblynotfullperiod)), ... mpfr_function_d ('cos', -inf, ... x.sup(possiblynotfullperiod))); u(possiblynotfullperiod) = max (mpfr_function_d ('cos', inf, ... x.inf(possiblynotfullperiod)), ... mpfr_function_d ('cos', inf, ... x.sup(possiblynotfullperiod))); ## We use sign (-sin) to know the gradient at the boundaries. sinsignl(possiblynotfullperiod) = sign (-mpfr_function_d ('sin', .5, ... x.inf(possiblynotfullperiod))); sinsignu(possiblynotfullperiod) = sign (-mpfr_function_d ('sin', .5, ... x.sup(possiblynotfullperiod))); endif ## In case of sign (-sin) == 0, we conservatively use sign (-sin) of nextout. sinsignl(sinsignl == 0) = (-1) .* sign (l(sinsignl == 0)); sinsignu(sinsignu == 0) = sign (u(sinsignu == 0)); containsinf = possiblynotfullperiod & ((sinsignl == -1 & sinsignu == 1) | ... (sinsignl == sinsignu & ... width >= sup (pi))) ... & ne (0, x); l(containsinf) = -1; containssup = possiblynotfullperiod & ((sinsignl == 1 & sinsignu == -1) | ... (sinsignl == sinsignu & ... width >= sup (pi))); u(containssup) = 1; emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (cos (infsup (1)) == "[0x1.14A280FB5068Bp-1, 0x1.14A280FB5068Cp-1]"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.cos; %! for testcase = [testcases]' %! assert (isequaln (... %! cos (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.cos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (cos (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.cos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cos (in1), out)); interval-3.2.0/inst/@infsup/cosh.m0000644000000000000000000000523213316017127015164 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} cosh (@var{X}) ## ## Compute the hyperbolic cosine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cosh (infsup (1)) ## @result{} ans ⊂ [1.543, 1.5431] ## @end group ## @end example ## @seealso{@@infsup/acosh, @@infsup/sech, @@infsup/sinh, @@infsup/tanh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function x = cosh (x) if (nargin ~= 1) print_usage (); return endif ## cosh is symmetric and has its global minimum located at (0, 1). if (__check_crlibm__ ()) l = crlibm_function ('cosh', -inf, mig (x)); u = crlibm_function ('cosh', +inf, mag (x)); else l = mpfr_function_d ('cosh', -inf, mig (x)); u = mpfr_function_d ('cosh', +inf, mag (x)); endif emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (cosh (infsup (1)) == "[0x1.8B07551D9F55, 0x1.8B07551D9F551]"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.cosh; %! for testcase = [testcases]' %! assert (isequaln (... %! cosh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.cosh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (cosh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.cosh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cosh (in1), out)); interval-3.2.0/inst/@infsup/coshrev.m0000644000000000000000000000723513316017127015706 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} coshrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsup} {@var{X} =} coshrev (@var{C}) ## ## Compute the reverse hyperbolic cosine function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{cosh (x) ∈ @var{C}}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## coshrev (infsup (-2, 1)) ## @result{} ans = [0] ## @end group ## @end example ## @seealso{@@infsup/cosh} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = coshrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsup (-inf, inf); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (x, "infsup"))) x = infsup (x); endif p = acosh (c); n = uminus (p); result = union (intersect (p, x), intersect (n, x)); endfunction %!# from the documentation string %!assert (coshrev (infsup (-2, 1)) == 0); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.coshRev; %! for testcase = [testcases]' %! assert (isequaln (... %! coshrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.coshRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (coshrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.coshRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (coshrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.coshRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! coshrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.coshRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (coshrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.coshRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (coshrev (in1, in2), out)); interval-3.2.0/inst/@infsup/cosrev.m0000644000000000000000000001671513316017127015541 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} cosrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsup} {@var{X} =} cosrev (@var{C}) ## ## Compute the reverse cosine function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{cos (x) ∈ @var{C}}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## cosrev (infsup (0), infsup (6, 9)) ## @result{} ans ⊂ [7.8539, 7.854] ## @end group ## @end example ## @seealso{@@infsup/cos} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = cosrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsup (-inf, inf); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (x, "infsup"))) x = infsup (x); endif arccosine = acos (c); result = x; ## Resize, if broadcasting is needed if (not (size_equal (arccosine.inf, result.inf))) arccosine.inf = ones (size (result.inf)) .* arccosine.inf; arccosine.sup = ones (size (result.inf)) .* arccosine.sup; result.inf = ones (size (arccosine.inf)) .* result.inf; result.sup = ones (size (arccosine.inf)) .* result.sup; endif result.inf(isempty (arccosine)) = inf; result.sup(isempty (arccosine)) = -inf; idx.type = '()'; persistent pi = infsup ("pi"); select = not (isempty (result)) ... & not (subset (infsup (0, pi.sup), arccosine)); if (any (select(:))) ## Find a smaller upper bound for x, if the restriction from c allows it u = inf (size (result.inf)); select_u = select & result.sup < inf; ## Find n, such that result.sup is within a distance of pi/2 ## around (n + 1/2) * pi. n = result.sup; n(select_u) = floor (sup (n(select_u) ./ pi)); arccosineshifted = arccosine; idx.subs = {(select_u & rem (n, 2) == 0)}; arccosineshifted = subsasgn (arccosineshifted, idx, ... subsref (arccosine, idx) + ... subsref (n, idx) .* pi); idx.subs = {(select_u & rem (n, 2) ~= 0)}; arccosineshifted = subsasgn (arccosineshifted, idx, ... (infsup (subsref (n, idx)) + 1) .* pi - ... subsref (arccosine, idx)); overlapping = not (isempty (intersect (result, arccosineshifted))); u(select_u & overlapping) = ... min (result.sup(select_u & overlapping), ... arccosineshifted.sup(select_u & overlapping)); m = n; m(select_u & ~overlapping) = ... mpfr_function_d ('minus', +inf, m(select_u & ~overlapping), 1); idx.subs = {(select_u & ~overlapping & rem (n, 2) == 0)}; u(idx.subs {1}) = ... sup (subsref (n, idx) .* pi - subsref (arccosine, idx)); idx.subs = {(select_u & ~overlapping & rem (n, 2) ~= 0)}; u(idx.subs {1}) = ... sup (subsref (arccosine, idx) + subsref (m, idx) .* pi); ## Find a larger lower bound for x, if the restriction from c allows it l = -inf (size (result.inf)); select_l = select & result.inf > -inf; ## Find n, such that result.inf is within a distance of pi/2 ## around (n + 1/2) * pi. n = result.inf; n(select_l) = floor (inf (n(select_l) ./ pi)); arccosineshifted = arccosine; idx.subs = {(select_l & rem (n, 2) == 0)}; arccosineshifted = subsasgn (arccosineshifted, idx, ... subsref (arccosine, idx) + ... subsref (n, idx) .* pi); idx.subs = {(select_l & rem (n, 2) ~= 0)}; arccosineshifted = subsasgn (arccosineshifted, idx, ... (infsup (subsref (n, idx)) + 1) .* pi - ... subsref (arccosine, idx)); overlapping = not (isempty (intersect (result, arccosineshifted))); l(select_l & overlapping) = ... max (result.inf(select_l & overlapping), ... arccosineshifted.inf(select_l & overlapping)); m = n; m(select_l & ~overlapping) = ... mpfr_function_d ('plus', -inf, m(select_l & ~overlapping), 1); idx.subs = {(select_l & ~overlapping & rem (n, 2) == 0)}; l(idx.subs {1}) = ... inf ((infsup (subsref (m, idx)) + 1) .* pi - subsref (arccosine, idx)); idx.subs = {(select_l & ~overlapping & rem (n, 2) ~= 0)}; l(idx.subs {1}) = ... inf (subsref (arccosine, idx) + subsref (m, idx) .* pi); result.inf(select) = max (l(select), result.inf(select)); result.sup(select) = min (u(select), result.sup(select)); result.inf(result.inf > result.sup) = inf; result.sup(result.inf > result.sup) = -inf; endif endfunction %!# from the documentation string %!assert (cosrev (0, infsup (6, 9)) == "[0x1.F6A7A2955385Ep2, 0x1.F6A7A2955386p2]"); %!# correct use of signed zeros %!test %! x = cosrev (infsup (1), infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.cosRev; %! for testcase = [testcases]' %! assert (isequaln (... %! cosrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.cosRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (cosrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.cosRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cosrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.cosRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! cosrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.cosRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (cosrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.cosRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cosrev (in1, in2), out)); interval-3.2.0/inst/@infsup/cot.m0000644000000000000000000000636713316017127015027 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} cot (@var{X}) ## ## Compute the cotangent in radians, that is the reciprocal tangent. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cot (infsup (1)) ## @result{} ans ⊂ [0.64209, 0.6421] ## @end group ## @end example ## @seealso{@@infsup/tan, @@infsup/csc, @@infsup/sec} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function x = cot (x) if (nargin ~= 1) print_usage (); return endif l = u = zeros (size (x)); ## Check, if wid (x) is certainly greater than pi. This may save computation of ## some cotangent values. width = mpfr_function_d ('minus', -inf, x.sup, x.inf); persistent pi = infsup ("pi"); certainlyfullperiod = width >= sup (pi); possiblynotfullperiod = not (certainlyfullperiod); l(possiblynotfullperiod) = ... mpfr_function_d ('cot', -inf, x.sup(possiblynotfullperiod)); u(possiblynotfullperiod) = ... mpfr_function_d ('cot', +inf, x.inf(possiblynotfullperiod)); l(x.sup == 0) = -inf; u(x.inf == 0) = +inf; singularity = certainlyfullperiod | ... l > u | (... width > 2 & (... sign (l) == sign (u) | ... max (abs (l), abs (u)) < 1)); l(singularity) = -inf; u(singularity) = inf; emptyresult = isempty (x) | (x.inf == 0 & x.sup == 0); l(emptyresult) = inf; u(emptyresult) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (cot (infsup (1)) == "[0x1.48C05D04E1CFDp-1, 0x1.48C05D04E1CFEp-1]"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.cot; %! for testcase = [testcases]' %! assert (isequaln (... %! cot (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.cot; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (cot (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.cot; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cot (in1), out)); interval-3.2.0/inst/@infsup/coth.m0000644000000000000000000000546513316017127015175 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} coth (@var{X}) ## ## Compute the hyperbolic cotangent, that is the reciprocal hyperbolic tangent. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## coth (infsup (1)) ## @result{} ans ⊂ [1.313, 1.3131] ## @end group ## @end example ## @seealso{@@infsup/tanh, @@infsup/csch, @@infsup/sech} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function x = coth (x) if (nargin ~= 1) print_usage (); return endif l = u = zeros (size (x.inf)); select = x.inf >= 0 | x.sup <= 0; if (any (select(:))) l(select) = mpfr_function_d ('coth', -inf, x.sup(select)); l(select & x.sup == 0) = -inf; u(select) = mpfr_function_d ('coth', +inf, x.inf(select)); u(select & x.inf == 0) = inf; endif select = x.inf < 0 & x.sup > 0; if (any (select(:))) l(select) = -inf; u(select) = inf; endif emptyresult = isempty (x) | (x.inf == 0 & x.sup == 0); l(emptyresult) = inf; u(emptyresult) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (coth (infsup (1)) == "[0x1.50231499B6B1D, 0x1.50231499B6B1E]"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.coth; %! for testcase = [testcases]' %! assert (isequaln (... %! coth (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.coth; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (coth (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.coth; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (coth (in1), out)); interval-3.2.0/inst/@infsup/csc.m0000644000000000000000000000757613316017127015015 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} csc (@var{X}) ## ## Compute the cosecant in radians, that is the reciprocal sine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## csc (infsup (1)) ## @result{} ans ⊂ [1.1883, 1.1884] ## @end group ## @end example ## @seealso{@@infsup/sin, @@infsup/sec, @@infsup/cot} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function x = csc (x) if (nargin ~= 1) print_usage (); return endif l = u = derivl = derivu = zeros (size (x.inf)); ## Check, if wid (x) is certainly greater than 2*pi. This can save the ## computation if some values. width = mpfr_function_d ('minus', -inf, x.sup, x.inf); persistent pi = infsup ("pi"); certainlysingularity = width >= sup (pi); ## We simply compute the cosecant for both endpoints. x.inf(x.inf == 0) = +0; x.sup(x.sup == 0) = -0; select = not (certainlysingularity); l(select) = min (... mpfr_function_d ('csc', -inf, x.inf(select)), ... mpfr_function_d ('csc', -inf, x.sup(select))); u(select) = max (... mpfr_function_d ('csc', inf, x.inf(select)), ... mpfr_function_d ('csc', inf, x.sup(select))); ## A change of sign is a sufficient singularity indicator certainlysingularity = certainlysingularity | (select & sign (l) ~= sign (u)); l(certainlysingularity) = -inf; u(certainlysingularity) = inf; ## Check, whether the interval contains a local extremum using the derivative select = not (certainlysingularity); derivl(select) = -mpfr_function_d ('csc', 0, x.inf(select)) .* ... mpfr_function_d ('cot', 0, x.inf(select)); derivu(select) = -mpfr_function_d ('csc', 0, x.sup(select)) .* ... mpfr_function_d ('cot', 0, x.sup(select)); hasextremum = select & ((derivl <= 0 & derivu >= 0) | ... (derivl >= 0 & derivu <= 0)); l(hasextremum & l > 0) = 1; u(hasextremum & u < 0) = -1; emptyresult = isempty (x) | (x.inf == 0 & x.sup == 0); l(emptyresult) = inf; u(emptyresult) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (csc (infsup (1)) == "[0x1.303AA9620B223, 0x1.303AA9620B224]"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.csc; %! for testcase = [testcases]' %! assert (isequaln (... %! csc (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.csc; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (csc (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.csc; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (csc (in1), out)); interval-3.2.0/inst/@infsup/csch.m0000644000000000000000000000572713316017127015161 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} csch (@var{X}) ## ## Compute the hyperbolic cosecant, that is the reciprocal hyperbolic sine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## csch (infsup (1)) ## @result{} ans ⊂ [0.85091, 0.85092] ## @end group ## @end example ## @seealso{@@infsup/sinh, @@infsup/sech, @@infsup/coth} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function x = csch (x) if (nargin ~= 1) print_usage (); return endif l = u = zeros (size (x.inf)); select = x.inf >= 0 | x.sup <= 0; if (any (select(:))) l(select) = mpfr_function_d ('csch', -inf, x.sup(select)); l(select & x.sup == 0) = -inf; u(select) = mpfr_function_d ('csch', +inf, x.inf(select)); u(select & x.inf == 0) = inf; endif select = x.inf < 0 & x.sup > 0; if (any (select(:))) l(select) = -inf; u(select) = inf; endif emptyresult = isempty (x) | (x.inf == 0 & x.sup == 0); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (csch (infsup (1)) == "[0x1.B3AB8A78B90Cp-1, 0x1.B3AB8A78B90C1p-1]"); %!# correct use of signed zeros %!test %! x = csch (infsup (0, inf)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.csch; %! for testcase = [testcases]' %! assert (isequaln (... %! csch (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.csch; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (csch (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.csch; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (csch (in1), out)); interval-3.2.0/inst/@infsup/ctranspose.m0000644000000000000000000000244413316017127016413 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} ctranspose (@var{X}) ## @defopx Operator {@@infsup} {@var{X}'} ## ## Return the complex conjugate transpose of @var{X}. ## ## Since intervals are only defined for real numbers, this function and ## @code{transpose} are equivalent. ## ## @seealso{@@infsup/transpose} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function result = ctranspose (x) if (nargin ~= 1) print_usage (); return endif result = transpose (x); endfunction %!assert (ctranspose (infsup (magic (3))) == infsup (magic (3)')); interval-3.2.0/inst/@infsup/det.m0000644000000000000000000000476713316017127015020 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} det (@var{A}) ## ## Compute the determinant of matrix @var{A}. ## ## The determinant for matrices of size 3×3 or greater is computed via L-U ## decomposition and may be affected by overestimation due to the dependency ## problem. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## det (infsup (magic (3))) ## @result{} ans = [-360] ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-10-23 function result = det (x) if (nargin ~= 1) print_usage (); return endif if (not (issquare (x.inf))) error ("det: argument must be a square matrix"); endif if (any (isempty (x)(:))) result = infsup (); return endif switch (rows (x.inf)) case 0 result = infsup (1); return case 1 result = x; return case 2 ## det ([1, 3; 2, 4]) = 4*1 - 3*2 ## The result will be tightest. result = mtimes (infsup ([x.inf(4), -x.sup(3)], ... [x.sup(4), -x.inf(3)]), ... infsup (x.inf(:, 1), x.sup(:, 1))); return endswitch zero = x.inf == 0 & x.sup == 0; if (any (all (zero, 1)) || any (all (zero, 2))) ## One column or row being zero result = infsup (0); return endif ## P * x = L * U, with ## det (P) = ±1 and det (L) = 1 and det (U) = prod (diag (U)) ## ## => det (x) = det (P) * det (U) [~, U, P] = lu (x); result = times (det (P), prod (diag (U))); ## Integer matrix, determinant must be integral if (all (all (fix (x.inf) == x.inf & fix (x.sup) == x.sup))) result.inf = ceil (result.inf); result.sup = floor (result.sup); endif endfunction %!# from the documentation string %!assert (det (infsup (magic (3))) == -360); interval-3.2.0/inst/@infsup/diag.m0000644000000000000000000000462713316017127015143 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {M =} diag (@var{V}) ## @deftypemethodx {@@infsup} {V =} diag (@var{M}) ## @deftypemethodx {@@infsup} {M =} diag (@var{V}, @var{K}) ## @deftypemethodx {@@infsup} {M =} diag (@var{V}, @var{M}, @var{N}) ## @deftypemethodx {@@infsup} {V =} diag (@var{M}, @var{K}) ## ## Create a diagonal matrix @var{M} with vector @var{V} on diagonal @var{K} or ## extract a vector @var{V} from the @var{K}-th diagonal of matrix @var{M}. ## ## With three arguments, create a matrix of size @var{M}×@var{N}. ## ## @example ## @group ## diag (infsup (1 : 3)) ## @result{} ans = 3×3 interval matrix ## ## [1] [0] [0] ## [0] [2] [0] ## [0] [0] [3] ## @end group ## @end example ## @seealso{@@infsup/tril, @@infsup/triu} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-10-23 function x = diag (x, varargin) if (nargin >= 2 && isa (varargin{1}, 'infsup')) error ('diag: invalid second argument; it must not be an interval'); endif if (nargin >= 3 && isa (varargin{2}, 'infsup')) error ('diag: invalid third argument; it must not be an interval'); endif if (nargin > 3) print_usage (); return endif l = diag (x.inf, varargin{:}); u = diag (x.sup, varargin{:}); l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!assert (diag (infsup (-inf, inf)) == "[Entire]"); %!assert (diag (infsup ()) == "[Empty]"); %!assert (numel (diag (infsup ([]))), 0); %!assert (isequal (diag (infsup (magic (3))), infsup ([8; 5; 2]))); %!assert (isequal (diag (infsup ([8 5 3])), infsup ([8 0 0; 0 5 0; 0 0 3]))); %!assert (isequal (diag (infsup (1:2), 2, 3), infsup ([1 0 0; 0 2 0]))); interval-3.2.0/inst/@infsup/dilog.m0000644000000000000000000000444613316017127015334 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} dilog (@var{X}) ## ## Compute the real part of the dilogarithm function. ## ## @tex ## $$ ## {\rm dilog} (x) = -\Re \int_0^x {{\log (1-t)} \over t} dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## x ## / log (1 - t) ## dilog (x) = - Re | ------------- dt ## / t ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## dilog (infsup (1)) ## @result{} ans ⊂ [1.6449, 1.645] ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-29 function x = dilog (x) if (nargin ~= 1) print_usage (); return endif l = inf (size (x.inf)); u = -l; ## Monotonically increasing for x1 x1 = intersect (x, infsup (-inf, 2)); select = not (isempty (x1)); if (any (select(:))) l(select) = mpfr_function_d ('dilog', -inf, x1.inf(select)); u(select) = mpfr_function_d ('dilog', +inf, x1.sup(select)); endif ## Monotonically decreasing for x2 x2 = intersect (x, infsup (2, inf)); select = not (isempty (x2)); if (any (select(:))) l(select) = min (l(select), ... mpfr_function_d ('dilog', -inf, x2.sup(select))); u(select) = mpfr_function_d ('dilog', +inf, x2.inf(select)); endif x.inf = l; x.sup = u; endfunction %!assert (dilog (infsup (-inf, inf)) == "[-Inf, +0x1.3BD3CC9BE45DFp1]"); %!# from the documentation string %!assert (dilog (infsup (1)) == "[0x1.A51A6625307D3, 0x1.A51A6625307D4]"); interval-3.2.0/inst/@infsup/disjoint.m0000644000000000000000000000541613316017127016057 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} disjoint (@var{A}, @var{B}) ## ## Evaluate disjoint comparison on intervals. ## ## True, if all numbers from @var{A} are not contained in @var{B} and vice ## versa. False, if @var{A} and @var{B} have at least one element in common. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/subset, @@infsup/interior} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function result = disjoint (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); endif result = (a.sup < b.inf | b.sup < a.inf); result(isempty (a) | isempty (b)) = true; endfunction %!assert (disjoint (infsup (3, 4), infsup (5, 6))); %!assert (not (disjoint (infsup (3, 4), infsup (4, 5)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.disjoint; %! for testcase = [testcases]' %! assert (isequaln (... %! disjoint (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.disjoint; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (disjoint (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.disjoint; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (disjoint (in1, in2), out)); interval-3.2.0/inst/@infsup/disp.m0000644000000000000000000001567613316017127015204 0ustar 00000000000000## Copyright 2015-2017 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} disp (@var{X}) ## ## Display the value of interval @var{X}. ## ## Interval boundaries are approximated with faithful decimal numbers. ## ## Interval arrays with many rows are wrapped according to the terminal ## width. @code{disp} prints nothing when @var{X} is an interval array ## without elements. ## ## Note that the output from @code{disp} always ends with a newline. ## ## If an output value is requested, @code{disp} prints nothing and returns the ## formatted output in a string. ## ## @example ## @group ## format long ## disp (infsupdec ("pi")) ## @result{} [3.141592653589793, 3.141592653589794]_com ## format short ## disp (infsupdec ("pi")) ## @result{} [3.1415, 3.1416]_com ## disp (infsupdec (1 : 5)) ## @result{} [1]_com [2]_com [3]_com [4]_com [5]_com ## s = disp (infsupdec (0)) ## @result{} s = [0]_com ## @end group ## @end example ## @seealso{@@infsup/display, intervaltotext} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-30 function varargout = disp (x) if (nargin ~= 1) print_usage (); return endif if (strcmp (disp (uint8 (255)), "ff\n")) ## hex output cs = "[.13a]"; else ## decimal output cs = cstrcat ("[.", num2str (output_precision ()) , "g]"); endif [s, isexact] = intervaltotext (x, cs); if (not (iscell (s))) ## Scalar interval if (nargout == 0) disp (s); else varargout{1} = cstrcat (s, "\n"); varargout{2} = isexact; endif return endif loose_spacing = __loosespacing__ (); columnwidth = max (cellfun ("length", s), [], 1); columnwidth += 3; # add 3 spaces between columns buffer = ""; numberofmatrixparts = prod (size (x.inf)(3:end)); for matrixpart = 1:numberofmatrixparts ## Print the current submatrix if (rows (x.inf) > 0) ## FIXME: See display.m for how current_print_indent_level is used global current_print_indent_level; maxwidth = terminal_size ()(2) - current_print_indent_level; if (ndims (x) > 2) ## Loose format: Use extra newline between previous matrix and current label, ## unless the submatrix is scalar if (loose_spacing && matrixpart > 1 && ... (rows (x.inf) > 1 || columns (x.inf) > 1)) buffer = cstrcat (buffer, "\n"); endif ## Print the index for the current matrix in the array buffer = cstrcat (buffer, sprintf("ans(:,:")); matrixpartsubscript = cell (1, ndims (x) - 2); [matrixpartsubscript{:}] = ind2sub (size (x.inf)(3:end), matrixpart); buffer = cstrcat (buffer, ... sprintf(",%d", ... matrixpartsubscript{1:ndims (x.inf) - 2})); ## FIXME: How should we handle the equal sign, "=", when the ## representation is not exact? buffer = cstrcat (buffer, sprintf(") =")); if (rows (x.inf) > 1 || columns (x.inf) > 1) buffer = cstrcat (buffer, ifelse (loose_spacing, "\n\n", "\n")); endif endif cstart = uint32 (1); cend = cstart - 1; while (cstart <= columns (x.inf)) ## Determine number of columns to print, print at least one column usedwidth = 0; submatrix = ""; do cend ++; submatrix = strcat (submatrix, ... prepad (strjust (char (s(:, cend, ... matrixpart))), ... columnwidth(1, cend, matrixpart), ... " ", 2)); usedwidth += columnwidth(cend); until (cend == columns (x.inf) || ... (split_long_rows () && ... usedwidth + columnwidth(cend + 1) > maxwidth)) if (cstart > 1 || cend < columns (x.inf)) if (loose_spacing && cstart > 1) buffer = cstrcat (buffer, "\n"); endif if (cend > cstart) buffer = cstrcat (buffer, ... sprintf(" Columns %d through %d:\n", ... cstart, cend)); ... else buffer = cstrcat (buffer, ... sprintf(" Column %d:\n", cstart)); endif if (loose_spacing) buffer = cstrcat (buffer, "\n"); endif endif ## Convert string matrix into string with newlines buffer = cstrcat (buffer, strjoin (cellstr (submatrix), "\n"), "\n"); if (nargout == 0) printf (buffer); buffer = ""; endif cstart = cend + 1; endwhile endif endfor if (nargout > 0) varargout{1} = buffer; varargout{2} = isexact; endif endfunction %!assert (disp (infsup([])), ""); %!assert (disp (infsup(zeros (0, 1))), ""); %!assert (disp (infsup(zeros (1, 0))), ""); %!assert (disp (infsup(0)), "[0]\n"); %!assert (disp (infsup(0, 1)), "[0, 1]\n"); %!assert (disp (infsup([0 0])), " [0] [0]\n"); %!assert (disp (infsup([0 0; 0 0])), " [0] [0]\n [0] [0]\n"); %!assert (disp (infsup([0; 0])), " [0]\n [0]\n"); %!assert (disp (infsup (zeros (1, 1, 1, 0))), ""); %!assert (disp (infsup(zeros(2, 2, 2))), "ans(:,:,1) =\n\n [0] [0]\n [0] [0]\n\nans(:,:,2) =\n\n [0] [0]\n [0] [0]\n") %!test %! i = infsupdec (reshape (1:24, 2, 3, 4)); %! i(1, 1, 2) = entire (); %! i(1, 1, 3) = empty (); %! i(1, 1, 4) = nai (); %! assert (disp (i(1,1,:)), "ans(:,:,1) = [1]_com\nans(:,:,2) = [Entire]_dac\nans(:,:,3) = [Empty]_trv\nans(:,:,4) = [NaI]\n") %!test %! x = infsup (zeros ([1 2 2])); %! unwind_protect %! format compact %! compact = disp (x); %! format loose %! loose = disp (x); %! unwind_protect_cleanup %! format %! end_unwind_protect %! assert (compact, "ans(:,:,1) =\n [0] [0]\nans(:,:,2) =\n [0] [0]\n"); %! assert (loose, "ans(:,:,1) =\n\n [0] [0]\n\nans(:,:,2) =\n\n [0] [0]\n"); %!test %! x = infsup (zeros ([1 1 2])); %! unwind_protect %! format compact %! compact = disp (x); %! format loose %! loose = disp (x); %! unwind_protect_cleanup %! format %! end_unwind_protect %! assert (compact, "ans(:,:,1) = [0]\nans(:,:,2) = [0]\n"); %! assert (loose, "ans(:,:,1) = [0]\nans(:,:,2) = [0]\n");interval-3.2.0/inst/@infsup/display.m0000644000000000000000000001473113316017127015701 0ustar 00000000000000## Copyright 2014-2018 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} display (@var{X}) ## ## Display the variable name and value of interval @var{X}. ## ## Interval boundaries are approximated with faithful decimal numbers. ## ## If @var{X} is a variable, the interval is display together with its variable ## name. The variable name is followed by an equality sign if all decimal ## boundaries exactly represent the actual boundaries. Otherwise a subset ## symbol is used instead (this feature is not available on Microsoft Windows). ## ## For non-scalar intervals the size and classification (interval vector, ## interval matrix or interval array) is displayed before the content. ## ## @example ## @group ## display (infsupdec (2)); ## @result{} [2]_com ## @end group ## @end example ## @example ## @group ## x = infsupdec (2); display (x); ## @result{} x = [2]_com ## @end group ## @end example ## @example ## @group ## y = infsupdec (eps); display (y); ## @result{} y ⊂ [2.2204e-16, 2.2205e-16]_com ## @end group ## @end example ## @example ## @group ## z = infsupdec (pascal (2)); display (z); ## @result{} z = 2×2 interval matrix ## [1]_com [1]_com ## [1]_com [2]_com ## @end group ## @end example ## @seealso{@@infsup/disp, intervaltotext} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-28 function display (x) if (nargin ~= 1) print_usage (); return endif loose_spacing = __loosespacing__ (); global current_print_indent_level; save_current_print_indent_level = current_print_indent_level; unwind_protect label = inputname (1); if (isempty (label) && regexp(argn, '^\[\d+,\d+\]$')) ## During output of cell array contents label = argn; ## FIXME: Need access to octave_value::current_print_indent_level ## for correctly formatted nested cell array output current_print_indent_level = 2; else current_print_indent_level = 0; endif line_prefix = " "(ones (1, current_print_indent_level)); [s, isexact] = disp (x); printf (line_prefix); if (not (isempty (label))) printf (label); if (isexact || ispc ()) printf (" = "); else ## The Microsoft Windows console does not support this multibyte ## character. printf (" ⊂ "); endif endif if (isscalar (x)) ## Scalar interval printf (s); if (isempty (label)) printf ("\n"); endif return endif printf ("%d", size (x, 1)) if (ispc ()) printf ("x%d", size (x)(2:end)) else ## The Microsoft Windows console does not support multibyte characters. printf ("×%d", size (x)(2:end)) endif if (isvector (x)) printf (" interval vector"); elseif (ismatrix (x)) printf (" interval matrix"); else printf (" interval array") endif printf ("\n"); if (not (isempty (s))) if (loose_spacing) printf ("\n"); endif printf (line_prefix); if (current_print_indent_level > 0) s = strrep (s, "\n", cstrcat ("\n", line_prefix)); s(end - current_print_indent_level + 1 : end) = ""; endif printf (s); ## FIXME: The built-in display function prints an extra line break, ## if called with “display (var name)”—even with compact format ## spacing. We assume that this method is always called for output ## after expression evaluation. if (loose_spacing) printf ("\n"); endif endif unwind_protect_cleanup current_print_indent_level = save_current_print_indent_level; end_unwind_protect endfunction %!# Test for the display function are also largely done with the help of the %!# doctest package. %!# evalc has been introduced in Octave 4.2 %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=")) %! assert (evalc ("display (infsup ())"), "[Empty]\n\n"); %! assert (evalc ("display (infsupdec ())"), "[Empty]_trv\n\n"); %! endif %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=")) %! assert (evalc ("a = infsup ()"), "a = [Empty]\n"); %! assert (evalc ("b = infsupdec ()"), "b = [Empty]_trv\n"); %! endif %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=")) %! assert (evalc ("a = infsup (); display (a)"), "a = [Empty]\n"); %! assert (evalc ("b = infsupdec (); display (b)"), "b = [Empty]_trv\n"); %! endif %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=") && !ispc ()) %! assert (evalc ("display (infsup (magic (3)))"), ... %! ["3×3 interval matrix\n", ... %! "\n", ... %! " [8] [1] [6]\n", ... %! " [3] [5] [7]\n", ... %! " [4] [9] [2]\n", ... %! "\n"]); %! endif %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=") && !ispc ()) %! assert (evalc ("infsup (magic (3))"), ... %! ["ans = 3×3 interval matrix\n", ... %! "\n", ... %! " [8] [1] [6]\n", ... %! " [3] [5] [7]\n", ... %! " [4] [9] [2]\n", ... %! "\n"]); %! endif %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=") && !ispc ()) %! assert (evalc ("infsup ('pi')"), "ans ⊂ [3.1415, 3.1416]\n"); %! endif %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=") && !ispc ()) %! assert (evalc ("infsup (1:3)"), ... %! ["ans = 1×3 interval vector\n", ... %! "\n", ... %! " [1] [2] [3]\n", ... %! "\n"]); %! endif %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=") && !ispc ()) %! assert (evalc ("infsup (ones(2, 2, 2))"), ... %! ["ans = 2×2×2 interval array\n", ... %! "\n", ... %! "ans(:,:,1) =\n", ... %! "\n", ... %! " [1] [1]\n", ... %! " [1] [1]\n", ... %! "\n", ... %! "ans(:,:,2) =\n", ... %! "\n", ... %! " [1] [1]\n", ... %! " [1] [1]\n", ... %! "\n"]); %! endif interval-3.2.0/inst/@infsup/dot.m0000644000000000000000000001172113316017127015016 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} dot (@var{X}, @var{Y}) ## @defmethodx {@@infsup} dot (@var{X}, @var{Y}, @var{DIM}) ## ## Compute the dot product of two interval vectors. ## ## If @var{X} and @var{Y} are arrays, calculate the dot products along the ## first non-singleton dimension. If the optional argument @var{DIM} is given, ## calculate the dot products along this dimension. ## ## Conceptually this is equivalent to @code{sum (@var{X} .* @var{Y})} ## but it is computed in such a way that no intermediate round-off ## errors are introduced. ## ## Broadcasting is performed along all dimensions except if @var{X} ## and @var{Y} are both vectors and @var{DIM} is not specified, in ## which case they are aligned along dimension 1. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## dot ([infsup(1), 2, 3], [infsup(2), 3, 4]) ## @result{} ans = [20] ## @end group ## @group ## dot (infsup ([realmax; realmin; realmax]), [1; -1; -1], 1) ## @result{} ans ⊂ [-2.2251e-308, -2.225e-308] ## @end group ## @end example ## @seealso{@@infsup/plus, @@infsup/sum, @@infsup/times, @@infsup/sumabs, @@infsup/sumsq} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-26 function x = dot (x, y, dim) if (nargin < 2 || nargin > 3) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif if (nargin < 3) if (isvector (x.inf) && isvector (y.inf)) ## Align vectors along common dimension dim = 1; x = vec (x, dim); y = vec (y, dim); else ## Try to find non-singleton dimension xsize = size (x.inf); ysize = size (y.inf); xsize(end+1:ndims (y)) = 1; ysize(end+1:ndims (x)) = 1; dim = find (and (xsize ~= 1, ysize ~= 1), 1); if (isempty (dim)) dim = 1; endif endif endif [l u] = mpfr_vector_dot_d (x.inf, y.inf, x.sup, y.sup, dim); l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# matrix × matrix %!assert (dot (infsup (magic (3)), magic (3)) == [89, 107, 89]); %!assert (dot (infsup (magic (3)), magic (3), 1) == [89, 107, 89]); %!assert (dot (infsup (magic (3)), magic (3), 2) == [101; 83; 101]); %!# matrix × vector %!assert (dot (infsup (magic (3)), [1, 2, 3]) == [28; 34; 28]); %!assert (dot (infsup (magic (3)), [1, 2, 3], 1) == [15, 30, 45]); %!assert (dot (infsup (magic (3)), [1, 2, 3], 2) == [28; 34; 28]); %!assert (dot (infsup (magic (3)), [1; 2; 3]) == [26, 38, 26]); %!assert (dot (infsup (magic (3)), [1; 2; 3], 1) == [26, 38, 26]); %!assert (dot (infsup (magic (3)), [1; 2; 3], 2) == [15; 30; 45]); %!# matrix × scalar %!assert (dot (infsup (magic (3)), 42) == [630, 630, 630]); %!assert (dot (infsup (magic (3)), 42, 1) == [630, 630, 630]); %!assert (dot (infsup (magic (3)), 42, 2) == [630; 630; 630]); %!# vector x vector %!assert (dot (infsup([1, 2, 3]), [4, 5, 6]) == 32); %!assert (dot (infsup([1, 2, 3]), [4, 5, 6], 1) == [4, 10, 18]); %!assert (dot (infsup([1, 2, 3]), [4, 5, 6], 2) == 32); %!assert (dot (infsup([1; 2; 3]), [4; 5; 6]) == 32); %!assert (dot (infsup([1; 2; 3]), [4; 5; 6], 1) == 32); %!assert (dot (infsup([1; 2; 3]), [4; 5; 6], 2) == [4; 10; 18]); %!# vector × scalar %!assert (dot (infsup ([1, 2, 3]), 42) == 252); %!assert (dot (infsup ([1, 2, 3]), 42, 1) == [42, 84, 126]); %!assert (dot (infsup ([1, 2, 3]), 42, 2) == 252); %!assert (dot (infsup ([1; 2; 3]), 42) == 252); %!assert (dot (infsup ([1; 2; 3]), 42, 1) == 252); %!assert (dot (infsup ([1; 2; 3]), 42, 2) == [42; 84; 126]); %!# N-dimensional arrays %!test %! x = infsup (reshape (1:24, 2, 3, 4)); %! y = infsup (2.*ones (2, 3, 4)); %! assert (dot (x, y, 3) == infsup ([80, 96, 112; 88, 104, 120])) %!test %! x = infsup (ones (2, 2, 2, 2)); %! y = infsup (1); %! assert (size (dot (x, y)), [1, 2, 2, 2]); %! assert (size (dot (x, y, 1)), [1, 2, 2, 2]); %! assert (size (dot (x, y, 2)), [2, 1, 2, 2]); %! assert (size (dot (x, y, 3)), [2, 2, 1, 2]); %! assert (size (dot (x, y, 4)), [2, 2, 2]); %! assert (size (dot (x, y, 5)), [2, 2, 2, 2]); %!# from the documentation string %!assert (dot ([infsup(1), 2, 3], [infsup(2), 3, 4]) == 20); %!assert (dot (infsup ([realmax; realmin; realmax]), [1; -1; -1], 1) == -realmin); interval-3.2.0/inst/@infsup/ei.m0000644000000000000000000000370613316017127014631 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} ei (@var{X}) ## ## Compute the exponential integral for positive arguments. ## ## @tex ## $$ ## {\rm ei} (x) = \int_{-\infty}^x {{\exp t} \over t} dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## x ## / exp (t) ## ei (x) = | --------- dt ## / t ## -∞ ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## ei (infsup (1)) ## @result{} ans ⊂ [1.8951, 1.8952] ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-29 function x = ei (x) if (nargin ~= 1) print_usage (); return endif l = inf (size (x.inf)); u = -l; ## ei is monotonically increasing and defined for x > 0 defined = x.sup > 0; l(defined) = mpfr_function_d ('ei', -inf, max (0, x.inf(defined))); u(defined) = mpfr_function_d ('ei', +inf, x.sup(defined)); l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!assert (isempty (ei (infsup (0)))); %!assert (isempty (ei (infsup (-inf, -2)))); %!assert (isentire (ei (infsup (0, inf)))); %!# from the documentation string %!assert (ei (infsup (1)) == "[0x1.E52670F350D08, 0x1.E52670F350D09]"); interval-3.2.0/inst/@infsup/end.m0000644000000000000000000000354113316017127014777 0ustar 00000000000000## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} end (@var{A}, @var{k}, @var{n}) ## ## The magic index @code{end} refers to the last valid entry in an indexing ## operation. ## ## For @var{n} = 1 the output of the indexing operation is a column vector and a ## single index is used to address all entries in column-first order. For ## @var{n} > 1 the @var{k}'th dimension is addressed separately. ## ## @example ## @group ## A = infsup ([1 2 3; 4 5 6]); ## A(1, end) ## @result{} ans = [3] ## A(end, 1) ## @result{} ans = [4] ## A(end) ## @result{} ans = [6] ## @end group ## @end example ## @seealso{@@infsup/size, @@infsup/length, @@infsup/numel, @@infsup/rows, @@infsup/columns} ## @end defmethod ## Author: Joel Dahne ## Keywords: interval ## Created: 2017-03-27 function ret = end (a, k, n) if (n == k) ret = prod (size (a.inf)(n:ndims (a.inf))); else ret = size (a.inf, k); endif endfunction %!assert (infsup (magic (3))(end) == 2); %!assert (infsup (magic (3))(end, 2) == 9); %!assert (infsup (magic (3))(2, end) == 7); %!assert (infsup ([1 2; 3 4; 5 6])(end:-1:1, :) == [5 6; 3 4; 1 2]); %!assert (reshape (infsup (1:24), 2, 3, 4)(end, end) == 24) interval-3.2.0/inst/@infsup/eq.m0000644000000000000000000000742513316017127014643 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} eq (@var{A}, @var{B}) ## @defopx Operator {@@infsup} {@var{A} == @var{B}} ## ## Compare intervals @var{A} and @var{B} for equality. ## ## True, if all numbers from @var{A} are also contained in @var{B} and vice ## versa. False, if @var{A} contains a number which is not a member in @var{B} ## or vice versa. ## ## @example ## @group ## x = infsup (2, 3); ## y = infsup (1, 2); ## x == y ## @result{} ans = 0 ## @end group ## @end example ## @seealso{@@infsup/subset, @@infsup/interior, @@infsup/disjoint} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function result = eq (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); elseif (isa (b, "infsupdec")) ## Workaround for bug #42735 result = eq (a, b); return endif result = (a.inf == b.inf & a.sup == b.sup); endfunction %!test "Empty interval"; %! assert (eq (infsup (), infsup ()) == true); %! assert (eq (infsup (), infsup (1)) == false); %! assert (eq (infsup (0), infsup ()) == false); %! assert (eq (infsup (-inf, inf), infsup ()) == false); %!test "Singleton intervals"; %! assert (eq (infsup (0), infsup (1)) == false); %! assert (eq (infsup (0), infsup (0)) == true); %!test "Bounded intervals"; %! assert (eq (infsup (1, 2), infsup (3, 4)) == false); %! assert (eq (infsup (1, 2), infsup (2, 3)) == false); %! assert (eq (infsup (1, 2), infsup (1.5, 2.5)) == false); %! assert (eq (infsup (1, 2), infsup (1, 2)) == true); %!test "Unbounded intervals"; %! assert (eq (infsup (0, inf), infsup (-inf, 0)) == false); %! assert (eq (infsup (0, inf), infsup (0, inf)) == true); %! assert (eq (infsup (-inf, 0), infsup (-inf, 0)) == true); %! assert (eq (infsup (-inf, inf), infsup (42)) == false); %! assert (eq (infsup (-inf, 0), infsup (-inf, inf)) == false); %! assert (eq (infsup (-inf, inf), infsup (-inf, inf)) == true); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.equal; %! for testcase = [testcases]' %! assert (isequaln (... %! eq (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.equal; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (eq (in1, in2), out)); %!test %! # N-dimensional array evaluations %! testcases = testdata.NoSignal.infsup.equal; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (eq (in1, in2), out)); interval-3.2.0/inst/@infsup/erf.m0000644000000000000000000000370313316017127015005 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} erf (@var{X}) ## ## Compute the error function. ## ## @tex ## $$ ## {\rm erf} (x) = {2 \over \sqrt{\pi}}\int_0^x \exp (-t^2) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## x ## 2 / ## erf (x) = ----- | exp (-t²) dt ## √π / ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## erf (infsup (1)) ## @result{} ans ⊂ [0.8427, 0.84271] ## @end group ## @end example ## @seealso{@@infsup/erfc} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-28 function x = erf (x) if (nargin ~= 1) print_usage (); return endif ## erf is monotonically increasing l = mpfr_function_d ('erf', -inf, x.inf); u = mpfr_function_d ('erf', +inf, x.sup); emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (erf (infsup (1)) == "[0x1.AF767A741088Ap-1, 0x1.AF767A741088Bp-1]"); %!# correct use of signed zeros %!test %! x = erf (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); interval-3.2.0/inst/@infsup/erfc.m0000644000000000000000000000400313316017127015142 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} erfc (@var{X}) ## ## Compute the complementary error function @code{1 - erf (@var{X})}. ## ## @tex ## $$ ## {\rm erfc} (x) = {2 \over \sqrt{\pi}}\int_x^\infty \exp (-t^2) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## ∞ ## 2 / ## erfc (x) = ----- | exp (-t²) dt ## √π / ## x ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## erfc (infsup (1)) ## @result{} ans ⊂ [0.15729, 0.1573] ## @end group ## @end example ## @seealso{@@infsup/erf} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-28 function x = erfc (x) if (nargin ~= 1) print_usage (); return endif ## erf is monotonically decreasing l = mpfr_function_d ('erfc', -inf, x.sup); u = mpfr_function_d ('erfc', +inf, x.inf); emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (erfc (infsup (1)) == "[0x1.4226162FBDDD4p-3, 0x1.4226162FBDDD5p-3]"); %!# correct use of signed zeros %!test %! x = erfc (infsup (realmax)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); interval-3.2.0/inst/@infsup/exp.m0000644000000000000000000000544613316017127015033 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} exp (@var{X}) ## ## Compute the exponential function. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## exp (infsup (1)) ## @result{} ans ⊂ [2.7182, 2.7183] ## @end group ## @end example ## @seealso{@@infsup/log, @@infsup/pow} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function x = exp (x) if (nargin ~= 1) print_usage (); return endif ## exp is monotonically increasing from (-inf, 0) to (inf, inf) if (__check_crlibm__ ()) l = crlibm_function ('exp', -inf, x.inf); # this also works for empty intervals u = crlibm_function ('exp', +inf, x.sup); # ... this does not else l = mpfr_function_d ('exp', -inf, x.inf); # this also works for empty intervals u = mpfr_function_d ('exp', +inf, x.sup); # ... this does not endif l(l == 0) = -0; u(isempty (x)) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (exp (infsup (1)) == infsup ("e")); %!# correct use of signed zeros %!test %! x = exp (infsup (-realmax)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.exp; %! for testcase = [testcases]' %! assert (isequaln (... %! exp (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.exp; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (exp (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.exp; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (exp (in1), out)); interval-3.2.0/inst/@infsup/expm.m0000644000000000000000000001001213316017127015171 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} expm (@var{A}) ## ## Compute the matrix exponential of square matrix @var{A}. ## ## The matrix exponential is defined as the infinite Taylor series ## ## @tex ## $$ ## {\rm expm} (A) = \sum_{k = 0}^{\infty} {A^k \over k!} ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## A² A³ ## expm (A) = I + A + ---- + ---- + … ## 2! 3! ## @end verbatim ## @end group ## @end ifnottex ## ## The function implements the following algorithm: 1. The matrix is scaled, ## 2. an enclosure of the Taylor series is computed using the Horner scheme, ## 3. the matrix is squared. That is, the algorithm computes ## @code{expm (@var{A} ./ pow2 (@var{L})) ^ pow2 (@var{L})}. The scaling ## reduces the matrix norm below 1, which reduces errors during exponentiation. ## Exponentiation typically is done by Padé approximation, but that doesn't ## work for interval matrices, so we compute a Horner evaluation of the Taylor ## series. Finally, the exponentiation with @code{pow2 (@var{L})} is computed ## with @var{L} successive interval matrix square operations. Interval matrix ## square operations can be done without dependency errors (regarding each ## single step). ## ## The algorithm has been published by Alexandre Goldsztejn and Arnold ## Neumaier (2009), “On the Exponentiation of Interval Matrices.” ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## vec (expm (infsup(magic (3)))) ## @result{} ans ⊂ 9×1 interval vector ## ## [1.0897e+06, 1.0898e+06] ## [1.0896e+06, 1.0897e+06] ## [1.0896e+06, 1.0897e+06] ## [1.0895e+06, 1.0896e+06] ## [1.0897e+06, 1.0898e+06] ## [1.0897e+06, 1.0898e+06] ## [1.0896e+06, 1.0897e+06] ## [1.0896e+06, 1.0897e+06] ## [1.0896e+06, 1.0897e+06] ## ## @end group ## @end example ## @seealso{@@infsup/mpower, @@infsup/exp} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-01-26 function result = expm (A) if (nargin ~= 1) print_usage (); return endif if (isscalar (A)) ## Short-circuit for scalars result = exp (A); return endif if (not (issquare (A.inf))) error ("interval:InvalidOperand", ... "expm: must be square matrix"); endif ## Choose L such that ||A|| / 2^L < 0.1 and 10 <= L <= 100 L = min (max (inf (ceil (log2 (10 * norm (A, inf)))), 10), 100); ## Choose K such that K + 2 > ||A|| and 10 <= K <= 170 K = min (max (inf (ceil (norm (A, inf) - 2)), 10), 170); ## 1. Scale A = rdivide (A, pow2 (L)); ## 2. Compute Taylor series ## Compute Horner scheme: I + A*(I + A/2*(I + A/3*( ... (I + A/K) ... ))) result = I = eye (size (A.inf)); for k = K : -1 : 1 result = I + A ./ k * result; endfor ## Truncation error for the exponential series alpha = norm (A, inf); rho = pown (alpha, K + 1) ./ ... (factorial (infsup (K + 1)) * (1 - alpha ./ (K + 2))); warning ("off", "interval:ImplicitPromote", "local"); truncation_error = rho .* infsup (-1, 1); result = result + truncation_error; ## 3. Squaring result = mpower (result, pow2 (L)); endfunction %!# from the paper %!test %! A = infsup ([0 1; 0 -3], [0 1; 0 -2]); %! assert (all (all (subset (infsup ([1, 0.316738; 0, 0.0497871], [1, 0.432332; 0, 0.135335]), expm (A))))); interval-3.2.0/inst/@infsup/expm1.m0000644000000000000000000000557213316017127015271 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} expm1 (@var{X}) ## ## Compute @code{exp (@var{X}) - 1} accurately in the neighborhood of zero. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## expm1 (infsup (eps)) ## @result{} ans ⊂ [2.2204e-16, 2.2205e-16] ## @end group ## @end example ## @seealso{@@infsup/exp, @@infsup/log1p} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-20 function x = expm1 (x) if (nargin ~= 1) print_usage (); return endif ## expm1 is monotonically increasing from (-inf, 0) to (inf, inf) if (__check_crlibm__ ()) l = crlibm_function ('expm1', -inf, x.inf); # this also works for [Empty] u = crlibm_function ('expm1', +inf, x.sup); # ... this does not else l = mpfr_function_d ('expm1', -inf, x.inf); # this also works for [Empty] u = mpfr_function_d ('expm1', +inf, x.sup); # ... this does not endif l(l == 0) = -0; u(isempty (x)) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (expm1 (infsup (eps)) == "[0x1p-52, 0x1.0000000000001p-52]"); %!# correct use of signed zeros %!test %! x = expm1 (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.expm1; %! for testcase = [testcases]' %! assert (isequaln (... %! expm1 (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.expm1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (expm1 (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.expm1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (expm1 (in1), out)); interval-3.2.0/inst/@infsup/factorial.m0000644000000000000000000000447713316017127016206 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} factorial (@var{N}) ## ## Compute the factorial of @var{N} where @var{N} is a non-negative integer. ## ## If @var{N} is a scalar, this is equivalent to ## @display ## factorial (@var{N}) = 1 * 2 * @dots{} * @var{N}. ## @end display ## For vector, matrix or array arguments, return the factorial of each ## element in the array. ## ## For non-integers see the generalized factorial function @command{gamma}. ## Note that the factorial function grows large quite quickly, and the result ## cannot be represented exactly in binary64 for @var{N} ≥ 23 and will overflow ## for @var{N} ≥ 171. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## factorial (infsup (6)) ## @result{} ans = [720] ## @end group ## @end example ## @seealso{@@infsup/prod, @@infsup/gamma, @@infsup/gammaln} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-01-31 function x = factorial (x) if (nargin ~= 1) print_usage (); return endif l = max (0, ceil (x.inf)); u = floor (x.sup); emptyresult = l > u; l(emptyresult) = inf; u(emptyresult) = -inf; l(not (emptyresult)) = ... mpfr_function_d ("factorial", -inf, l(not (emptyresult))); u(not (emptyresult)) = ... mpfr_function_d ("factorial", +inf, u(not (emptyresult))); x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (factorial (infsup (6)) == 720); %!assert (factorial (infsup (0)) == 1); %!assert (factorial (infsup ("[0, 1.99]")) == 1); %!assert (factorial (infsup ("[0, 2]")) == "[1, 2]"); %!assert (factorial (infsup ("[1.4, 1.6]")) == "[Empty]"); interval-3.2.0/inst/@infsup/fix.m0000644000000000000000000000764313316017127015026 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} fix (@var{X}) ## ## Truncate fractional portion of each number in interval @var{X}. This is ## equivalent to rounding towards zero. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## fix (infsup (2.5, 3.5)) ## @result{} ans = [2, 3] ## fix (infsup (-0.5, 5)) ## @result{} ans = [0, 5] ## @end group ## @end example ## @seealso{@@infsup/floor, @@infsup/ceil, @@infsup/round, @@infsup/roundb} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = fix (x) if (nargin ~= 1) print_usage (); return endif x.inf = fix (x.inf); x.sup = fix (x.sup); x.inf(x.inf == 0) = -0; x.sup(x.sup == 0) = +0; endfunction %!# Empty interval %!assert (fix (infsup ()) == infsup ()); %!# Singleton intervals %!assert (fix (infsup (0)) == infsup (0)); %!assert (fix (infsup (1)) == infsup (1)); %!assert (fix (infsup (1+eps)) == infsup (1)); %!assert (fix (infsup (-1)) == infsup (-1)); %!assert (fix (infsup (0.5)) == infsup (0)); %!assert (fix (infsup (-0.5)) == infsup (0)); %!# Bounded intervals %!assert (fix (infsup (-0.5, 0)) == infsup (0)); %!assert (fix (infsup (0, 0.5)) == infsup (0)); %!assert (fix (infsup (0.25, 0.5)) == infsup (0)); %!assert (fix (infsup (-1, 0)) == infsup (-1, 0)); %!assert (fix (infsup (-1, 1)) == infsup (-1, 1)); %!assert (fix (infsup (-realmin, realmin)) == infsup (0)); %!assert (fix (infsup (-realmax, realmax)) == infsup (-realmax, realmax)); %!# Unbounded intervals %!assert (fix (infsup (-realmin, inf)) == infsup (0, inf)); %!assert (fix (infsup (-realmax, inf)) == infsup (-realmax, inf)); %!assert (fix (infsup (-inf, realmin)) == infsup (-inf, 0)); %!assert (fix (infsup (-inf, realmax)) == infsup (-inf, realmax)); %!assert (fix (infsup (-inf, inf)) == infsup (-inf, inf)); %!# from the documentation string %!assert (fix (infsup (2.5, 3.5)) == infsup (2, 3)); %!assert (fix (infsup (-0.5, 5)) == infsup (0, 5)); %!# correct use of signed zeros %!test %! x = fix (infsup (0.5)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = fix (infsup (-0.5)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = fix (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.trunc; %! for testcase = [testcases]' %! assert (isequaln (... %! fix (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.trunc; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (fix (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.trunc; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (fix (in1), out)); interval-3.2.0/inst/@infsup/floor.m0000644000000000000000000000724313316017127015355 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} floor (@var{X}) ## ## Round each number in interval @var{X} towards -Inf. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## floor (infsup (2.5, 3.5)) ## @result{} ans = [2, 3] ## floor (infsup (-0.5, 5)) ## @result{} ans = [-1, +5] ## @end group ## @end example ## @seealso{@@infsup/ceil, @@infsup/round, @@infsup/roundb, @@infsup/fix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = floor (x) if (nargin ~= 1) print_usage (); return endif x.inf = floor (x.inf); x.sup = floor (x.sup); x.inf(x.inf == 0) = -0; endfunction %!# Empty interval %!assert (floor (infsup ()) == infsup ()); %!# Singleton intervals %!assert (floor (infsup (0)) == infsup (0)); %!assert (floor (infsup (0.5)) == infsup (0)); %!assert (floor (infsup (-0.5)) == infsup (-1)); %!# Bounded intervals %!assert (floor (infsup (-0.5, 0)) == infsup (-1, 0)); %!assert (floor (infsup (0, 0.5)) == infsup (0)); %!assert (floor (infsup (0.25, 0.5)) == infsup (0)); %!assert (floor (infsup (-1, 0)) == infsup (-1, 0)); %!assert (floor (infsup (-1, 1)) == infsup (-1, 1)); %!assert (floor (infsup (-realmin, realmin)) == infsup (-1, 0)); %!assert (floor (infsup (-realmax, realmax)) == infsup (-realmax, realmax)); %!# Unbounded intervals %!assert (floor (infsup (-realmin, inf)) == infsup (-1, inf)); %!assert (floor (infsup (-realmax, inf)) == infsup (-realmax, inf)); %!assert (floor (infsup (-inf, realmin)) == infsup (-inf, 0)); %!assert (floor (infsup (-inf, realmax)) == infsup (-inf, realmax)); %!assert (floor (infsup (-inf, inf)) == infsup (-inf, inf)); %!# from the documentation string %!assert (floor (infsup (2.5, 3.5)) == infsup (2, 3)); %!assert (floor (infsup (-0.5, 5)) == infsup (-1, 5)); %!# correct use of signed zeros %!test %! x = floor (infsup (0.5)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = floor (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.floor; %! for testcase = [testcases]' %! assert (isequaln (... %! floor (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.floor; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (floor (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.floor; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (floor (in1), out)); interval-3.2.0/inst/@infsup/fma.m0000644000000000000000000001375113316017127015000 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} fma (@var{X}, @var{Y}, @var{Z}) ## ## Fused multiply and add @code{@var{X} * @var{Y} + @var{Z}}. ## ## This function is semantically equivalent to evaluating multiplication and ## addition separately, but in addition guarantees a tight enclosure of the ## result. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## output_precision (16, 'local') ## fma (infsup (1+eps), infsup (7), infsup ("0.1")) ## @result{} ans ⊂ [7.100000000000001, 7.100000000000003] ## infsup (1+eps) * infsup (7) + infsup ("0.1") ## @result{} ans ⊂ [7.1, 7.100000000000003] ## @end group ## @end example ## @seealso{@@infsup/plus, @@infsup/times} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-03 function x = fma (x, y, z) if (nargin ~= 3) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif if (not (isa (z, "infsup"))) z = infsup (z); endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, y.inf))) x.inf = ones (size (y.inf)) .* x.inf; x.sup = ones (size (y.inf)) .* x.sup; y.inf = ones (size (x.inf)) .* y.inf; y.sup = ones (size (x.inf)) .* y.sup; endif if (not (size_equal (y.inf, z.inf))) y.inf = ones (size (z.inf)) .* y.inf; y.sup = ones (size (z.inf)) .* y.sup; z.inf = ones (size (y.inf)) .* z.inf; z.sup = ones (size (y.inf)) .* z.sup; endif if (not (size_equal (x.inf, z.inf))) x.inf = ones (size (z.inf)) .* x.inf; x.sup = ones (size (z.inf)) .* x.sup; z.inf = ones (size (x.inf)) .* z.inf; z.sup = ones (size (x.inf)) .* z.sup; endif ## [Empty] × anything = [Empty] ## [0] × anything = [0] × [0] ## [Entire] × anything but [0] = [Entire] × [Entire] ## This prevents the cases where 0 × inf would produce NaNs. entireproduct = isentire (x) | isentire (y); zeroproduct = (x.inf == 0 & x.sup == 0) | (y.inf == 0 & y.sup == 0); emptyresult = isempty (x) | isempty (y) | isempty (z); x.inf(entireproduct) = y.inf(entireproduct) = -inf; x.sup(entireproduct) = y.sup(entireproduct) = inf; x.inf(zeroproduct) = x.sup(zeroproduct) = ... y.inf(zeroproduct) = y.sup(zeroproduct) = 0; ## It is hard to determine, which boundaries of x and y take part in the ## multiplication of fma. Therefore, we simply compute the fma for each triple ## of boundaries where the min/max could be located. ## ## How to construct complicated cases: a = rand, b = rand, c = rand, ## d = a * b / c (with round towards -infinity for multiplication and towards ## +infinity for division). Then, it is not possible to decide in 50% of all ## cases whether a * b would be greater or less than c * d by computing the ## products in double-precision. l = min (min (min (... mpfr_function_d ('fma', -inf, x.inf, y.inf, z.inf), ... mpfr_function_d ('fma', -inf, x.inf, y.sup, z.inf)), ... mpfr_function_d ('fma', -inf, x.sup, y.inf, z.inf)), ... mpfr_function_d ('fma', -inf, x.sup, y.sup, z.inf)); u = max (max (max (... mpfr_function_d ('fma', +inf, x.inf, y.inf, z.sup), ... mpfr_function_d ('fma', +inf, x.inf, y.sup, z.sup)), ... mpfr_function_d ('fma', +inf, x.sup, y.inf, z.sup)), ... mpfr_function_d ('fma', +inf, x.sup, y.sup, z.sup)); l(emptyresult) = +inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (fma (infsup (1+eps), infsup (7), infsup ("0.1")) == "[0x1.C666666666668p2, 0x1.C666666666669p2]"); %!# correct use of signed zeros %!test %! x = fma (infsup (0), 0, 0); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = fma (infsup (1), 0, 0); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = fma (infsup (1), 1, -1); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.fma; %! for testcase = [testcases]' %! assert (isequaln (... %! fma (testcase.in{1}, testcase.in{2}, testcase.in{3}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.fma; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! assert (isequaln (fma (in1, in2, in3), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.fma; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! in3 = reshape ([in3; in3(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (fma (in1, in2, in3), out)); interval-3.2.0/inst/@infsup/fminsearch.m0000644000000000000000000002120013316017127016340 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} fminsearch (@var{f}, @var{X0}) ## @deftypemethodx {@@infsup} {[@var{X}, @var{FVAL}] =} fminsearch (@var{f}, @var{X0}, @var{options}) ## ## Minimize the function @var{f} over the interval box @var{X0} and return ## rigorous bounds. ## ## The function @var{f} may be multivariate, that is, the interval box ## @var{X0} may be a vector, a matrix or an array of intervals. The ## output of the function must be scalar. ## ## The rigorous bounds on @var{FVAL} satisfy 0 ≤ min @{f (@var{x}) | ## @var{x} ∈ @var{X0}@} - inf (@var{FVAL}) ≤ 1e-4 by default. Different ## accuracy requirements may be defined using @var{options}.TolFun. ## ## @example ## @group ## [x, fval] = fminsearch (@@cos, infsup ("[0, 4]")) ## @result{} ## x ⊂ [3.114, 3.1858] ## fval ⊂ [-1, -0.99996] ## @end group ## @end example ## ## During each iteration the interval is bisected at its widest coordinate ## until the desired accuracy has been reached. ## ## @example ## @group ## f = @@(x) x(1) .^ 2 - x(2) .^ 2; ## [x, fval] = fminsearch (f, infsup ("[-1, 1] [-1, 1]")) ## @result{} ## x ⊂ 1×2 interval vector ## ## [7.8828e-11, 8.8786e-06] [0.99991, 1] ## ## fval ⊂ [-1, -0.99991] ## @end group ## @end example ## ## Note that the algorithm tries to minimize @var{FVAL} and the returned ## value for @var{X} need not contain the minimum value of the function over ## @var{X0}; the value @var{X} is just “close” to one of possibly several ## places where the minimum occurs, that is, hull (f (@var{X})) overlaps ## [@var{M}-ε, @var{M}+ε], where @var{M} is the actual minimum of the ## function f over @var{X0} and ε equals @var{options}.TolFun. Also, it holds ## @var{M} ∈ @var{FVAL}, but in general it does @emph{not} hold ## f (@var{X}) ⊆ @var{FVAL}. ## ## It is possible to use the following optimization @var{options}: ## @option{Display}, @option{MaxFunEvals}, @option{MaxIter}, ## @option{OutputFcn}, @option{TolFun}, @option{TolX}. ## ## @example ## @group ## f = @@(x) -sin (hypot (x(1), x(2))) / hypot (x(1), x(2)); ## [x, fval] = fminsearch (f, infsup ("[-1, 1] [-1, 1]"), ... ## optimset ('MaxIter', 20)) ## @result{} ## x ⊂ 1×2 interval vector ## ## [0, 1.9763e-323] [0, 1.9763e-323] ## ## fval ⊂ [-inf, -0.99999] ## @end group ## @end example ## ## The function utilizes the Skelboe-Moore algorithm and has been implemented ## after Algorithm 6.1 in R. E. Moore, R. B. Kearfott, and M. J. Cloud. 2009. ## Introduction to Interval Analysis. Society for Industrial and Applied ## Mathematics. ## ## @seealso{optimset} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-09-18 function [X, FVAL, iter] = fminsearch (f, X, options) if (nargin < 2) print_usage (); return endif if (not (is_function_handle (f)) && not (ischar (f))) error ("interval:InvalidOperand", ... "fminsearch: Parameter f is no function handle") elseif (not (isa (X, "infsup"))) error ("interval:InvalidOperand", ... "fminsearch: Parameter X0 is no interval") endif defaultoptions = optimset (optimset, 'TolFun', 1e-4); if (nargin < 3) options = defaultoptions; else options = optimset (defaultoptions, options); endif displayiter = strcmp (options.Display, "iter"); ## 1 Rigorous upper bound on the minimum of f over X fmX = feval (f, infsup (mid (X))); if (not (isa (fmX, "infsup")) || not (isscalar (fmX))) error ("interval:InvalidOperand", ... "fminsearch: Function f does not return scalar intervals") endif if (isempty (fmX)) f_ub = inf; else f_ub = sup (fmX); endif ## 3 Initialize queues ## C: Completed boxes where accuracy has been reached (it suffices to store a ## single element, because this function doesn't return all candidates) ## L: Boxes where accuracy has not been reached yet L.X = C.X = {}; L.fX = C.fX = infsup ([]); iter = 0; feval_count = 1; cancel_algorithm = false (); idx.type = "()"; while (true) iter ++; if (displayiter) display (X); endif ## 4 Bisect X at the coordinate i with the widest interval X1 = X2 = X; [~, i] = max (vec (wid (X))); idx.subs = {i}; [pt1, pt2] = bisect (subsref (X, idx)); X1 = subsasgn (X1, idx, pt1); X2 = subsasgn (X2, idx, pt2); if (not (isempty (options.OutputFcn))) feval (options.OutputFcn, X1); feval (options.OutputFcn, X2); endif ## 5 Improve upper bound fmX1 = feval (f, infsup (mid (X1))); if (not (isempty (fmX1))) f_ub = min (f_ub, sup (fmX1)); endif fmX2 = feval (f, infsup (mid (X2))); if (not (isempty (fmX2))) f_ub = min (f_ub, sup (fmX2)); endif ## 6 Quit current X box if accuracy has been reached f1 = feval (f, X1); f2 = feval (f, X2); feval_count += 4; cancel_algorithm = feval_count >= options.MaxFunEvals || ... iter >= options.MaxIter || ... f_ub <= -realmax (); if (min (f_ub, max (sup (f1), sup (f2))) ... - min (inf (f1), inf (f2)) < options.TolFun ... || max (max (wid (X1))) < options.TolX ... || cancel_algorithm) ## Accuracy has been reached for X1 and X2 C = merge_candidates (C, X1, f1); C = merge_candidates (C, X2, f2); else ## Put intervals into work queue if (inf (f1) < f_ub) L = insert_ordered_list (L, X1, f1); endif if (inf (f2) < f_ub) L = insert_ordered_list (L, X2, f2); endif endif ## More refinement to do on other boxes? if (isempty (L.X) || cancel_algorithm) break endif ## (i) Use next item from L [L, X, fX] = pop_ordered_list (L); ## (ii) Check whether improvement is still possible if (inf (fX) > f_ub) break endif endwhile assert (not (isempty (C.X))); [C, X, FVAL] = pop_ordered_list (C); if (isfinite (f_ub)) FVAL = intersect (FVAL, infsup (-inf, f_ub)); endif if (any (strcmp (options.Display, {"iter", "final"})) || ... (cancel_algorithm && strcmp (options.Display, "notify"))) printf ('\nTarget accuracy has%s been reached after %d step(s)\n', ... ' not'(1:end * cancel_algorithm), ... iter); display (X); display (FVAL); endif endfunction function candidate = merge_candidates (candidate, X, fX) if (isempty (candidate.X) || inf (fX) < inf (candidate.fX)) candidate.X = {X}; candidate.fX = fX; endif endfunction function list = insert_ordered_list (list, X, fX) position = find (inf (list.fX) >= inf (fX), 1); if (isempty (position)) list.fX = vertcat (list.fX, fX); list.X = vertcat (list.X, {X}); elseif (position == 1) list.fX = vertcat (fX, list.fX); list.X = vertcat ({X}, list.X); else idx1.type = idx2.type = "()"; idx1.subs = {1:(position - 1)}; idx2.subs = {position:numel(list.X)}; list.fX = vertcat (subsref (list.fX, idx1), ... fX, ... subsref (list.fX, idx2)); idx.type = "{}"; list.X = vertcat (subsref (list.X, idx1), ... {X}, ... subsref (list.X, idx2)); endif endfunction function [list, X, fX] = pop_ordered_list (list) X = list.X {1}; idx.type = "()"; if (nargout >= 3) idx.subs = {1}; fX = subsref (list.fX, idx); endif if (numel (list.X) == 1) list.fX = infsup ([]); list.X = {}; else idx.subs = {2:numel(list.X)}; list.fX = subsref (list.fX, idx); list.X = subsref (list.X, idx); endif endfunction %!test %! sqr = @(x) x .^ 2; %! [x, y] = fminsearch (sqr, infsup (-inf, inf)); %! assert (y == 0); %!demo %! clf %! hold on %! draw = @(x) plot (x(1), x(2), [238 232 213]/255, [88 110 117]/255); %! f = @(x) (x(1) - 2) .^ 2 - x(2) .^ 2; %! fminsearch (f, infsup ("[1, 3] [0, 1]"), ... %! optimset ('OutputFcn', draw)); %! hold off interval-3.2.0/inst/@infsup/fprintf.m0000644000000000000000000000431313316017127015677 0ustar 00000000000000## Copyright 2018 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} fprintf (@var{fid}, @var{template}, @var{X}) ## @defmethodx {@@infsup} fprintf (@var{template}, @var{X}) ## ## Write interval @var{X} under the control of a template string ## @var{template} to the file descriptor @code{fid} and return the number of ## characters printed. ## ## If @var{fid} is omitted, the output is written to @code{stdout} making the ## function exactly equivalent to @command{printf}. ## ## See @command{help intervaltotext} for the syntax of the template string. ## ## @example ## @group ## fprintf ("The result lies within the box %[4g].\n", infsup (2, 3)) ## @result{} The result lies within the box [ 2, 3]. ## @end group ## @end example ## ## @seealso{intervaltotext, @@infsup/printf, @@infsup/sprintf} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2018-06-30 function chars_printed = fprintf (fid, template, x) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) [fid, template, x] = deal (stdout, fid, template); endif if (isa (fid, "infsup")) error ("handle FID must be an output stream"); endif [template, literals] = printf_prepare (template, x); if (nargout >= 1) chars_printed = fprintf (fid, template, literals{:}); else fprintf (fid, template, literals{:}); endif endfunction %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=")) %! assert (evalc ("n = fprintf ('%g', infsup ('pi'));"), "3.14159 3.1416"); %! assert (n, 14); %! endif interval-3.2.0/inst/@infsup/fsolve.m0000644000000000000000000005127113316017127015532 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} fsolve (@var{F}) ## @deftypemethodx {@@infsup} {@var{X} =} fsolve (@var{F}, @var{X0}) ## @deftypemethodx {@@infsup} {@var{X} =} fsolve (@var{F}, @var{X0}, @var{Y}) ## @deftypemethodx {@@infsup} {@var{X} =} fsolve (@dots{}, @var{OPTIONS}) ## @deftypemethodx {@@infsup} {[@var{X}, @var{X_PAVING}, @var{X_INNER_IDX}] =} fsolve (@dots{}) ## ## Compute the preimage of the set @var{Y} under function @var{F}. ## ## Parameter @var{Y} is optional and without it solve ## @code{@var{F}(@var{x}) = 0} for @var{x} ∈ @var{X0}. Without a starting box ## @var{X0} the function is assumed to be univariate and the solution is ## searched among all real numbers. ## ## The function must be an interval arithmetic function and may be ## multivariate, that is, @var{X0} and @var{Y} may be vectors or arrays of ## intervals. The computational complexity largely depends on the dimension of ## @var{X0}. ## ## Return value @var{X} is an interval enclosure of ## @code{@{@var{x} ∈ @var{X0} | @var{F}(@var{x}) ∈ @var{Y}@}}. The optional ## return value @var{X_PAVING} is a matrix of non-overlapping interval values ## for @var{x} in each column, which form a more detailed enclosure for the ## preimage of @var{Y}. An index vector @var{X_INNER_IDX} indicates the ## columns of @var{X_PAVING}, which are guaranteed to be subsets of the ## preimage of @var{Y}. ## ## This function uses the set inversion via interval arithmetic (SIVIA) ## algorithm. That is, @var{X} is bisected until @var{F}(@var{X}) is either ## a subset of @var{Y} or until they are disjoint. ## ## @example ## @group ## fsolve (@@cos, infsup(0, "pi")) ## @result{} ans ⊂ [1.5646, 1.5708] ## @end group ## @end example ## ## It is possible to use the following optimization @var{options}: ## @option{MaxFunEvals}, @option{MaxIter}, @option{TolFun}, @option{TolX}, ## @option{Vectorize}, @option{Contract}. ## ## If @option{Vectorize} is @code{true}, the function @var{F} will be called ## with input arguments @code{@var{x}(1)}, @code{@var{x}(2)}, @dots{}, ## @code{@var{x}(numel (@var{X0}))} and each input argument will carry a vector ## of different values which shall be computed simultaneously. If @var{Y} is a ## scalar or vector, @option{Vectorize} defaults to @code{true}. If ## @option{Vectorize} is @code{false}, the function @var{F} will receive only ## one input argument @var{x} at a time, which has the size of @var{X0}. ## ## @example ## @group ## # Solve x1 ^ 2 + x2 ^ 2 = 1 for -3 ≤ x1, x2 ≤ 3, ## # the exact solution is a unit circle ## x = fsolve (@@(x1, x2) x1.^2 + x2.^2, infsup ([-3; -3], [3; 3]), 1) ## @result{} x ⊂ 2×1 interval vector ## ## [-1.002, +1.002] ## [-1.0079, +1.0079] ## ## @end group ## @end example ## ## If @option{Contract} is @code{true}, the function @var{F} will be called ## with @var{Y} as an additional leading input argument and, in addition to the ## function value, must return a @dfn{contraction} of its input argument(s). ## A contraction for input argument @var{x} is a subset of @var{x} which ## contains all possible solutions for the equation ## @code{@var{F} (@var{x}) = @var{Y}}. Contractions can be computed using ## interval reverse operations, for example with @code{@@infsup/absrev} which ## contracts the input argument for the absolute value function. ## ## @example ## @group ## # Solve x1 ^ 2 + x2 ^ 2 = 1 for -3 ≤ x1, x2 ≤ 3 again, ## # but now contractions speed up the algorithm. ## function [fval, cx1, cx2] = f (y, x1, x2) ## # Forward evaluation ## x1_sqr = x1 .^ 2; ## x2_sqr = x2 .^ 2; ## fval = x1_sqr + x2_sqr; ## ## # Reverse evaluation and contraction ## y = intersect (y, fval); ## # Contract the squares ## x1_sqr = intersect (x1_sqr, y - x2_sqr); ## x2_sqr = intersect (x2_sqr, y - x1_sqr); ## # Contract the parameters ## cx1 = sqrrev (x1_sqr, x1); ## cx2 = sqrrev (x2_sqr, x2); ## endfunction ## ## x = fsolve (@@f, infsup ([-3; -3], [3; 3]), 1, ... ## struct ('Contract', true)) ## @result{} x = 2×1 interval vector ## ## [-1, +1] ## [-1, +1] ## ## @end group ## @end example ## ## It is possible to combine options @option{Vectorize} and @option{Contract}. ## Depending on the combination, function @var{F} should have one of the ## following signatures. ## ## @table @code ## @item function fval = f (x) ## @option{Vectorize} = @code{false} and @option{Contract} = @code{false}. ## @item function fval = f (x1, x2, @dots{}, xN) ## @option{Vectorize} = @code{true} and @option{Contract} = @code{false}. ## @item function [fval, cx] = f (y, x) ## @option{Vectorize} = @code{false} and @option{Contract} = @code{true}. ## @code{cx} is a contraction of @code{x}. ## @item function [fval, cx1, cx2, @dots{}, cxN] = f (y, x1, x2, @dots{}, xN) ## @option{Vectorize} = @code{true} and @option{Contract} = @code{true}. ## @code{cx1} is a contraction of @code{x1}, @code{cx2} is a contraction of ## @code{x2}, and so on. ## @end table ## ## Note on performance: The bisection method is a brute-force approach to ## exhaust the function's domain and requires a lot of function evaluations. ## It is highly recommended to use a function @var{F} which allows ## vectorization. For higher dimensions of @var{X0} it is also necessary to ## use a contraction function. ## ## Accuracy: The result is a valid enclosure. ## ## @seealso{@@infsup/fzero, ctc_union, ctc_intersect, optimset} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-11-28 function [x, x_paving, x_inner_idx] = fsolve (f, x0, y, options) ## Set default parameters warning ("off", "", "local") # disable optimset warning defaultoptions = optimset (optimset, ... 'MaxIter', 20, ... 'MaxFunEval', 3000, ... 'TolX', 1e-2, ... 'TolFun', 1e-2, ... 'Vectorize', [], ... 'Contract', false); switch (nargin) case 1 x0 = infsup (-inf, inf); y = infsup (0); options = defaultoptions; case 2 y = infsup (0); if (isstruct (x0)) options = optimset (defaultoptions, x0); x0 = infsup (-inf, inf); else options = defaultoptions; endif case 3 if (isstruct (y)) options = optimset (defaultoptions, y); y = infsup (0); else options = defaultoptions; endif case 4 options = optimset (defaultoptions, options); otherwise print_usage (); return endswitch ## Convert x0 and y to intervals if (not (isa (x0, "infsup"))) if (isa (y, "infsupdec")) x0 = infsupdec (x0); else x0 = infsup (x0); endif endif if (not (isa (y, "infsup"))) if (isa (x0, "infsupdec")) y = infsupdec (y); else y = infsup (y); endif endif ## Check parameters if (isempty (x0) || isempty (y) || numel (x0) == 0 || numel (y) == 0) error ("interval:InvalidOperand", ... "fsolve: Initial interval is empty, nothing to do") elseif (not (is_function_handle (f)) && not (ischar (f))) error ("interval:InvalidOperand", ... "fsolve: Parameter F is no function handle") endif ## Strip decoration part if (isa (x0, "infsupdec")) if (isnai (x0)) x = x0; x_paving = {x0}; x_inner_idx = false; return endif x0 = intervalpart (x0); endif if (isa (y, "infsupdec")) if (isnai (y)) x = y; x_paving = {y}; x_inner_idx = false; return endif y = intervalpart (y); endif ## Try to vectorize function evaluation if (isempty (options.Vectorize) && isvector (y)) try f_argn = nargin (f); if (options.Contract) options.Vectorize = (f_argn > 2 || f_argn < 0 || numel (x0) == 1); else options.Vectorize = (f_argn > 1 || f_argn < 0 || numel (x0) == 1); endif catch ## nargin doesn't work for built-in functions, which happen to agree ## with infsup methods. Try to vectorize these. options.Vectorize = true; end_try_catch endif if (options.Vectorize) if (nargout >= 2) [x, x_paving, x_inner_idx] = vectorized (f, x0, y, options); else x = vectorized (f, x0, y, options); endif return endif warning ("off", "interval:ImplicitPromote", "local"); x = empty (size (x0)); x_paving = {}; x_inner_idx = false (0); queue = {x0}; x_scalar = isscalar (x0); ## Test functions verify_subset = @(fval) all (subset (fval, y)(:)); verify_disjoint = @(fval) any (disjoint (fval, y)(:)); check_contradiction = @(x) any (isempty (x)(:)); max_wid = @(interval) max (wid (interval)(:)); ## Utility functions for bisection if (x_scalar) bisect_coord = {1}; exchange_coordinate = @(interval, coord, l, u) infsup (l, u); else largest_coordinate = @(interval, max_wid) ... find (wid (interval) == max_wid, 1); exchange_coordinate = @replace_coordinate; endif while (not (isempty (queue))) ## Evaluate f(x) options.MaxFunEvals -= numel (queue); options.MaxIter --; if (options.Contract) [fval, contractions] = cellfun (f, {y}, queue, ... "UniformOutput", false); ## Sanitize the contractions returned by the function queue = cellfun (@intersect, queue, contractions, ... "UniformOutput", false); ## Utilize contradictions to discard candidates contradiction = cellfun (check_contradiction, queue); queue = queue(not (contradiction)); if (isempty (queue)) break endif fval = fval(not (contradiction)); else fval = cellfun (f, queue, "UniformOutput", false); endif ## Check whether x is outside of the preimage of y ## or x is inside the preimage of y is_outside = cellfun (verify_disjoint, fval); is_inside = cellfun (verify_subset, fval) & not (is_outside); ## Store the verified subsets of the preimage of y and continue only on ## elements that are not verified x = hull (x, queue(is_inside){:}); x_paving = vertcat (x_paving, queue(is_inside)); x_inner_idx = vertcat (x_inner_idx, true (sum (is_inside), 1)); queue = queue(not (is_inside | is_outside)); ## Stop after MaxIter or MaxFunEvals if (options.MaxIter <= 0 || options.MaxFunEvals <= 0) x = hull (x, queue{:}); x_paving = vertcat (x_paving, queue); x_inner_idx = vertcat (x_inner_idx, false (numel (queue), 1)); break endif ## Stop iteration for small intervals if (not (isempty (options.TolFun))) fval = fval(not (is_inside | is_outside)); widths = cellfun (max_wid, fval); is_small = widths < options.TolFun; else is_small = false (size (queue)); endif widths = cellfun (max_wid, queue); is_small = is_small | (widths < options.TolX); x = hull (x, queue(is_small){:}); x_paving = vertcat (x_paving, queue(is_small)); x_inner_idx = vertcat (x_inner_idx, false (sum (is_small), 1)); queue = queue(not (is_small)); widths = widths(not (is_small)); ## Bisect remaining intervals at the largest coordinate. ## ## Since the bisect function is the most costly, we want to call it only ## once. Thus, we extract the largest coordinate from each interval array ## inside queue and combine them into an interval vector [l_coord, u_coord] ## with the length of queue. We call the bisect function on this vector, ## which bisects each interval component and produces vectors ## [l_coord, m_coord] and [m_coord, u_coord]. These are used to replace the ## largest coordinate from each original interval array. if (x_scalar) [l_coord, u_coord] = ... cellfun (@(interval) ... deal (interval.inf, interval.sup), ... queue); else bisect_coord = cellfun (largest_coordinate, ... queue, num2cell (widths), ... "UniformOutput", false); [l_coord, u_coord] = ... cellfun (@(interval, coord) ... deal (interval.inf(coord), interval.sup(coord)), ... queue, bisect_coord); endif m_coord = mid (infsup (l_coord, u_coord)); l_coord = num2cell (l_coord); m_coord = num2cell (m_coord); u_coord = num2cell (u_coord); queue = vertcat (... cellfun (exchange_coordinate, ... queue, bisect_coord, l_coord, m_coord, ... "UniformOutput", false), ... cellfun (exchange_coordinate, ... queue, bisect_coord, m_coord, u_coord, ... "UniformOutput", false)); ## Short-circuit if no paving must be computed and remaining intervals ## are subsets of the already computed interval enclosure. if (isempty (queue)) break endif if (nargout < 2) x_bare = intervalpart (x); queue = queue(not (cellfun (@(q) all (subset (q, x_bare)(:)), ... queue))); endif endwhile x = intervalpart (x); if (nargout >= 2) x_paving = cellfun (@vec, x_paving, "UniformOutput", false); x_paving = horzcat (x_paving{:}); endif endfunction function interval = replace_coordinate (interval, coord, l, u) interval.inf(coord) = l; interval.sup(coord) = u; endfunction ## Variant of above algorithm, which utilized vectorized evaluation of f function [x, x_paving, x_inner_idx] = vectorized (f, x0, y, options) warning ("off", "Octave:broadcast", "local"); ## Make vectorization dimension cat_dim orthogonal to the dimension ## of the data in y to allow simple function definitions. if (iscolumn (y)) x0 = vec (x0); data_dim = 1; cat_dim = 2; else assert (isrow (y)); x0 = transpose (vec (x0)); data_dim = 2; cat_dim = 1; endif x = intervalpart (empty (size (x0))); s = size (x0); s(cat_dim) = 0; x_paving = infsup (zeros (s)); x_inner_idx = false (0); queue = x0; x_scalar = isscalar (x0); ## Test functions verify_subset = @(fval) all (subset (fval, y), data_dim); verify_disjoint = @(fval) any (disjoint (fval, y), data_dim); ## Utility functions for indexing the queue idx.type = '()'; idx.subs = {:, :}; while (not (isempty (queue.inf))) ## Evaluate f(x) f_args = cell(); idx.subs = {:, :}; for i=1:numel(x0) idx.subs{data_dim} = i; f_args{i} = subsref (queue, idx); endfor idx.subs = {:, :}; options.MaxFunEvals --; options.MaxIter --; if (options.Contract) fval_and_contractions = nthargout (1 : (1 + length (x0)), ... @feval, f, y, f_args{:}); fval = fval_and_contractions{1}; contractions = cat (data_dim, fval_and_contractions{2 : end}); ## Sanitize the contractions returned by the function queue = intersect (queue, contractions); ## Utilize contradictions to discard candidates contradiction = any (isempty (queue), data_dim); idx.subs{cat_dim} = not (contradiction); queue = subsref (queue, idx); if (isempty (queue.inf)) break endif fval = subsref (fval, idx); else fval = feval (f, f_args{:}); endif ## Check whether x is outside of the preimage of y ## or x is inside the preimage of y is_outside = verify_disjoint (fval); is_inside = verify_subset (fval) & not (is_outside); ## Store the verified subsets of the preimage of y and continue only on ## elements that are not verified idx.subs{cat_dim} = is_inside; queue_inside = subsref (queue, idx); x = union (cat (cat_dim, x, queue_inside), [], cat_dim); x_paving = cat (cat_dim, x_paving, queue_inside); x_inner_idx = cat (cat_dim, x_inner_idx, is_inside(is_inside)); idx.subs{cat_dim} = not (is_inside | is_outside); queue = subsref (queue, idx); ## Stop after MaxIter or MaxFunEvals if (options.MaxIter <= 0 || options.MaxFunEvals <= 0) x = union (cat (cat_dim, x, queue), [], cat_dim); x_paving = cat (cat_dim, x_paving, queue); s = size (queue); s(data_dim) = 1; x_inner_idx = cat (cat_dim, x_inner_idx, false (s)); break endif ## Stop iteration for small intervals if (not (isempty (options.TolFun))) idx.subs{cat_dim} = not (is_inside | is_outside); fval = subsref (fval, idx); widths = max (wid (fval), [], data_dim); is_small = widths < options.TolFun; else s = size (queue); s(data_dim) = 1; is_small = false (s); endif [widths, bisect_coord] = max (wid (queue), [], data_dim); is_small = is_small | (widths < options.TolX); idx.subs{cat_dim} = is_small; queue_is_small = subsref (queue, idx); x = union (cat (cat_dim, x, queue_is_small), [], cat_dim); x_paving = cat (cat_dim, x_paving, queue_is_small); x_inner_idx = cat (cat_dim, x_inner_idx, not (is_small(is_small))); idx.subs{cat_dim} = not (is_small); queue = subsref (queue, idx); widths = widths(not (is_small)); bisect_coord = bisect_coord(not (is_small)); ## Bisect remaining intervals at the largest coordinate. x1 = x2 = queue; if (x_scalar) coord = queue; else coord_idx.type = "()"; if (data_dim == 1) coord_idx.subs = {bisect_coord - 1 + ... (1 : rows (queue.inf) : numel (queue.inf))}; else coord_idx.subs = {bisect_coord - 1 + ... (1 : columns (queue.inf) : numel (queue.inf)).'}; endif coord = subsref (queue, coord_idx); endif m_coord = mid (coord); if (x_scalar) x1.sup = x2.inf = m_coord; else x1.sup = subsasgn (x1.sup, coord_idx, m_coord); x2.inf = subsasgn (x2.inf, coord_idx, m_coord); endif queue = cat (cat_dim, x1, x2); if (isempty (queue.inf)) break endif ## Short-circuit if no paving must be computed and remaining intervals ## are subsets of the already computed interval enclosure. if (nargout < 2) idx.subs{cat_dim} = not (all (subset (queue, x), data_dim)); queue = subsref (queue, idx); endif endwhile if (nargout >= 2 && data_dim != 1) x_paving = transpose (x_paving); endif endfunction %!test %! sqr = @(x) x .^ 2; %! assert (subset (sqrt (infsup (2)), fsolve (sqr, infsup (0, 3), 2))); %!test %! sqr = @(x) x .^ 2; %! assert (subset (sqrt (infsup (2)), fsolve (sqr, infsup (0, 3), 2, struct ("Vectorize", false)))); %!function [fval, x] = contractor (y, x) %! fval = x .^ 2; %! y = intersect (y, fval); %! x = sqrrev (y, x); %!endfunction %!assert (subset (sqrt (infsup (2)), fsolve (@contractor, infsup (0, 3), 2, struct ("Contract", true)))); %!assert (subset (sqrt (infsup (2)), fsolve (@contractor, infsup (0, 3), 2, struct ("Contract", true, "Vectorize", false)))); %!demo %! clf %! hold on %! grid on %! axis equal %! shade = [238 232 213] / 255; %! blue = [38 139 210] / 255; %! cyan = [42 161 152] / 255; %! red = [220 50 47] / 255; %! # 2D ring %! f = @(x, y) hypot (x, y); %! [outer, paving, inner] = fsolve (f, infsup ([-3; -3], [3; 3]), ... %! infsup (0.5, 2), ... %! optimset ('TolX', 0.1)); %! # Plot the outer interval enclosure %! plot (outer(1), outer(2), shade) %! # Plot the guaranteed inner interval enclosures of the preimage %! plot (paving(1, inner), paving(2, inner), blue, cyan); %! # Plot the boundary of the preimage %! plot (paving(1, not (inner)), paving(2, not (inner)), red); %!demo %! clf %! hold on %! grid on %! shade = [238 232 213] / 255; %! blue = [38 139 210] / 255; %! # This 3D ring is difficult to approximate with interval boxes %! f = @(x, y, z) hypot (hypot (x, y) - 2, z); %! [~, paving, inner] = fsolve (f, infsup ([-4; -4; -2], [4; 4; 2]), ... %! infsup (0, 0.5), ... %! optimset ('TolX', 0.2)); %! plot3 (paving(1, not (inner)), ... %! paving(2, not (inner)), ... %! paving(3, not (inner)), shade, blue); %! view (50, 60) interval-3.2.0/inst/@infsup/fzero.m0000644000000000000000000001656113316017127015364 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} fzero (@var{F}, @var{X0}) ## @deftypemethodx {@@infsup} {@var{X} =} fzero (@var{F}, @var{X0}, @var{DF}) ## @deftypemethodx {@@infsup} {@var{X} =} fzero (@var{F}, @var{X0}, @var{OPTIONS}) ## @deftypemethodx {@@infsup} {@var{X} =} fzero (@var{F}, @var{X0}, @var{DF}, @var{OPTIONS}) ## ## Compute the enclosure of all roots of function @var{F} in interval @var{X0}. ## ## Parameters @var{F} and (possibly) @var{DF} may either be a function handle, ## inline function, or string containing the name of the function to evaluate. ## ## The function must be an interval arithmetic function. ## ## Optional parameters are the function's derivative @var{DF} and the maximum ## recursion steps @var{OPTIONS}.MaxIter (default: 200) to use. If @var{DF} is ## given, the algorithm tries to apply the interval newton method for finding ## the roots; otherwise pure bisection is used (which is slower). ## ## The result is a column vector with one element for each root enclosure that ## has been be found. Each root enclosure may contain more than one root and ## each root enclosure must not contain any root. However, all numbers in ## @var{X0} that are not covered by the result are guaranteed to be no roots of ## the function. ## ## Best results can be achieved when (a) the function @var{F} does not suffer ## from the dependency problem of interval arithmetic, (b) the derivative ## @var{DF} is given, (c) the derivative is non-zero at the function's roots, ## and (d) the derivative is continuous. ## ## It is possible to use the following optimization @var{options}: ## @option{Display}, @option{MaxFunEvals}, @option{MaxIter}, ## @option{OutputFcn}, @option{TolFun}, @option{TolX}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## f = @@(x) cos (x); ## df = @@(x) -sin (x); ## fzero (f, infsup ("[-10, 10]"), df) ## @result{} ans ⊂ 6×1 interval vector ## ## [-7.854, -7.8539] ## [-4.7124, -4.7123] ## [-1.5708, -1.5707] ## [1.5707, 1.5708] ## [4.7123, 4.7124] ## [7.8539, 7.854] ## sqr = @@(x) x .^ 2; ## fzero (sqr, infsup ("[Entire]")) ## @result{} ans ⊂ [-3.2968e-161, +3.2968e-161] ## @end group ## @end example ## ## @seealso{@@infsup/fsolve, optimset} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-01 function x = fzero (f, x0, df, options) if (nargin > 4 || nargin < 2) print_usage (); return endif ## Set default parameters defaultoptions = optimset (optimset, 'MaxIter', 200); if (nargin == 2) df = []; options = defaultoptions; elseif (nargin == 3) if (isstruct (df)) options = optimset (defaultoptions, options); df = []; else options = defaultoptions; endif else options = optimset (defaultoptions, options); endif ## Check parameters if (not (isa (x0, "infsup"))) error ("interval:InvalidOperand", "fzero: Parameter X0 is no interval") elseif (not (isscalar (x0))) error ("interval:InvalidOperand", ... "fzero: Parameter X0 must be a scalar / F must be univariate") elseif (isempty (x0)) error ("interval:InvalidOperand", ... "fzero: Initial interval is empty, nothing to do") elseif (not (is_function_handle (f)) && not (ischar (f))) error ("interval:InvalidOperand", ... "fzero: Parameter F is no function handle") elseif (not (isempty (df)) && ... not (is_function_handle (df)) && ... not (ischar (df))) error ("interval:InvalidOperand", ... "fzero: Parameter DF is not function handle") endif ## Does not work on decorated intervals, strip decoration part if (isa (x0, "infsupdec")) if (isnai (x0)) result = x0; return endif x0 = intervalpart (x0); endif [l, u] = findroots (f, df, x0, 0, options); x = infsup (); x.inf = l; x.sup = u; endfunction ## This function will perform the recursive newton / bisection steps function [l, u] = findroots (f, df, x0, stepcount, options) l = u = zeros (0, 1); ## Try the newton step, if derivative is known if (not (isempty (df))) m = infsup (mid (x0)); [a, b] = mulrev (feval (df, x0), feval (f, m)); if (isempty (a) && isempty (b)) ## Function evaluated outside of its domain a = x0; else a = intersect (x0, m - a); b = intersect (x0, m - b); if (isempty (a)) [a, b] = deal (b, a); endif endif else a = x0; b = infsup (); endif ## Switch to bisection if the newton step did not produce two intervals if ((eq (x0, a) || isempty (b)) && not (issingleton (a)) && not (isempty (a))) ## When the interval is very large, bisection at the midpoint would ## take “forever” to converge, because floating point numbers are not ## distributed evenly on the real number lane. ## ## We enumerate all floating point numbers within a with ## 1, 2, ... 2n and split the interval at n. ## ## When the interval is small, this algorithm will choose ## approximately mid (a). [a, b] = bisect (a); elseif (b < a) ## Sort the roots in ascending order [a, b] = deal (b, a); endif for x1 = {a, b} x1 = x1 {1}; if (strcmp (options.Display, "iter")) display (x1); endif f_x1 = feval (f, x1); if (not (ismember (0, f_x1))) ## The interval evaluation of f over x1 proves that there are no roots ## or x1 is empty continue endif if (isentire (f_x1) || ... wid (f_x1) / max (realmin (), wid (x1)) < pow2 (-20)) ## Slow convergence detected, cancel iteration soon options.MaxIter = options.MaxIter / 1.5; endif if (eq (x1, x0) || stepcount >= options.MaxIter || wid (x1) <= options.TolX || wid (f_x1) <= options.TolFun) ## Stop recursion if result is accurate enough or if no improvement [newl, newu] = deal (x1.inf, x1.sup); else [newl, newu] = findroots (f, df, x1, stepcount + 1, options); endif if (not (isempty (newl))) if (isempty (l)) l = newl; u = newu; elseif (u (end) == newl (1)) ## Merge intersecting intervals u (end) = newu (1); l = [l; newl(2 : end, 1)]; u = [u; newu(2 : end, 1)]; else l = [l; newl]; u = [u; newu]; endif endif endfor endfunction %!test "from the documentation string"; %! f = @(x) cos (x); %! df = @(x) -sin (x); %! zeros = fzero (f, infsup ("[-10, 10]"), df); %! assert (all (subset (pi * (-2.5:1:2.5)', zeros))); %! assert (max (rad (zeros)) < 8 * eps); %! sqr = @(x) x .^ 2; %! zeros = fzero (sqr, infsup ("[Entire]")); %! assert (all (subset (0, zeros))); %! assert (max (rad (zeros)) < eps); interval-3.2.0/inst/@infsup/gamma.m0000644000000000000000000001562213316017127015316 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} gamma (@var{X}) ## ## Compute the gamma function. ## ## @tex ## $$ ## {\rm gamma} (x) = \int_0^\infty t^(x-1) \exp (-t) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## ∞ ## / ## gamma (x) = | t^(x - 1) * exp (-t) dt ## / ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a valid enclosure. The result is tightest for ## @var{X} >= -10. ## ## @example ## @group ## gamma (infsup (1.5)) ## @result{} ans ⊂ [0.88622, 0.88623] ## @end group ## @end example ## @seealso{@@infsup/psi, @@infsup/gammaln, @@infsup/factorial} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-01 function result = gamma (x) if (nargin ~= 1) print_usage (); return endif ## Positive x ================================================================ ## https://oeis.org/A030169 persistent x_min_inf = 1.4616321449683623; persistent x_min_sup = 1.4616321449683624; ## Both gamma (infsup (x_min_inf)) and gamma (infsup (x_min_sup)) contain ## the exact minimum value of gamma. Thus we can simply split the function's ## domain in half and assume that each is strictly monotonic. l = inf (size (x.inf)); u = -l; ## Monotonically decreasing for x1 x1 = intersect (x, infsup (0, x_min_sup)); select = not (isempty (x1)) & x1.sup > 0; if (any (select(:))) x1.inf(x1.inf == 0) = 0; # fix negative zero l(select) = mpfr_function_d ('gamma', -inf, x1.sup(select)); u(select) = mpfr_function_d ('gamma', +inf, x1.inf(select)); endif ## Monotonically increasing for x2 x2 = intersect (x, infsup (x_min_inf, inf)); select = not (isempty (x2)); if (any (select(:))) l(select) = mpfr_function_d ('gamma', -inf, x2.inf(select)); u(select) = max (u(select), ... mpfr_function_d ('gamma', +inf, x2.sup(select))); endif pos = infsup (); pos.inf = l; pos.sup = u; ## Negative x ================================================================ x = intersect (x, infsup (-inf, 0)); u = inf (size (x.inf)); l = -u; nosingularity = floor (x.inf) + 1 == ceil (x.sup); if (any (nosingularity(:))) negative_value = nosingularity & mod (ceil (x.sup), 2) == 0; positive_value = nosingularity & not (negative_value); x.sup(x.sup == 0) = -0; # fix negative zero psil = psiu = zeros (size (x.inf)); psil(nosingularity) = mpfr_function_d ('psi', 0, x.inf(nosingularity)); psil(isnan (psil)) = -inf; psiu(nosingularity) = mpfr_function_d ('psi', 0, x.sup(nosingularity)); psiu(isnan (psiu)) = inf; encloses_extremum = false (size (x.inf)); encloses_extremum(nosingularity) = ... psil(nosingularity) <= 0 & psiu(nosingularity) >= 0; encloses_extremum(x.sup == x.inf + 1) = true (); select = encloses_extremum & negative_value & ... fix (x.inf) ~= x.inf & fix (x.sup) ~= x.sup; if (any (select(:))) l(select) = min (mpfr_function_d ('gamma', -inf, x.inf(select)), ... mpfr_function_d ('gamma', -inf, x.sup(select))); endif select = encloses_extremum & positive_value & ... fix (x.inf) ~= x.inf & fix (x.sup) ~= x.sup; if (any (select(:))) u(select) = max (mpfr_function_d ('gamma', +inf, x.inf(select)), ... mpfr_function_d ('gamma', +inf, x.sup(select))); endif select = not (encloses_extremum) & negative_value; u(select) = -inf; select = not (encloses_extremum) & positive_value; l(select) = inf; select = nosingularity & not (encloses_extremum); if (any (select(:))) l(select) = min (l(select), ... min (mpfr_function_d ('gamma', -inf, x.inf(select)), ... mpfr_function_d ('gamma', -inf, x.sup(select)))); u(select) = max (u(select), ... max (mpfr_function_d ('gamma', +inf, x.inf(select)), ... mpfr_function_d ('gamma', +inf, x.sup(select)))); endif select = encloses_extremum & negative_value; if (any (select(:))) u(select) = find_extremum (x.inf(select), x.sup(select)); endif select = encloses_extremum & positive_value; if (any (select(:))) l(select) = find_extremum (x.inf(select), x.sup(select)); endif endif emptyresult = (x.inf == x.sup & fix (x.inf) == x.inf & x.inf <= 0) | ... x.inf > 0; l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; neg = infsup (); neg.inf = l; neg.sup = u; ## =========================================================================== result = union (pos, neg); endfunction function y = find_extremum (l, u) ## Compute the extremum's value of gamma between l and u. l and u ## are negative and lie between two subsequent integral numbers. y = zeros (size (l)); # inaccurate, but already correct ## Tightest values for l >= -10 n = floor (l); y(n == -1) = -3.544643611155005; y(n == -2) = 2.3024072583396799; y(n == -3) = -.8881363584012418; y(n == -4) = .24512753983436624; y(n == -5) = -.052779639587319397; y(n == -6) = .009324594482614849; y(n == -7) = -.001397396608949767; y(n == -8) = 1.8187844490940416e-4; y(n == -9) = -2.0925290446526666e-5; y(n == -10) = 2.1574161045228504e-6; ## From Euler's reflection formula it follows: ## gamma (-x) = pi / ( sin (pi * (x + 1)) * gamma (x + 1) ) ## ## The extremum is located at -x = n + epsilon, ## where epsilon < 0.3 for n <= -10. Thus, we can estimate ## abs (pi / sin (pi * (x + 1))) >= 3.88 for n <= -10. ## Also it holds gamma (x + 1) = gamma (-n - epsilon + 1) <= gamma (-n + 1). ## ## Now, altogether we can estimate: abs (gamma (-x)) >= 3.88 / gamma (-n + 1) ## for n <= -10 remaining_estimates = n < -10; if (any (remaining_estimates(:))) y(remaining_estimates) = ... (-1) .^ (rem (n(remaining_estimates), 2) == -1) * ... mpfr_function_d ('rdivide', -inf, 3.88, ... mpfr_function_d ('gamma', +inf, ... -n(remaining_estimates) + 1)); endif endfunction %!# from the documentation string %!assert (gamma (infsup (1.5)) == "[0x1.C5BF891B4EF6Ap-1, 0x1.C5BF891B4EF6Bp-1]"); interval-3.2.0/inst/@infsup/gammaln.m0000644000000000000000000000640213316017127015644 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} gammaln (@var{X}) ## ## Compute the logarithm of the gamma function for positive arguments. ## ## @tex ## $$ ## {\rm gammaln} (x) = \log \int_0^\infty t^{x-1} \exp (-t) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## ∞ ## / ## gammaln (x) = log | t^(x-1) exp (-t) dt ## / ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## gammaln (infsup (1.5)) ## @result{} ans ⊂ [-0.12079, -0.12078] ## @end group ## @end example ## @seealso{@@infsup/psi, @@infsup/gamma, @@infsup/factorial} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-28 function x = gammaln (x) if (nargin ~= 1) print_usage (); return endif ## The gamma function is also defined for negative, non-integral arguments and ## its logarithm would be defined for −2n <= x <= −2n+1. ## However, we only compute the function for x > 0. ## https://oeis.org/A030169 persistent x_min_inf = 1.4616321449683623; persistent x_min_sup = 1.4616321449683624; ## Both gammaln (infsup (x_min_inf)) and gammaln (infsup (x_min_sup)) contain ## the exact minimum value of gammaln. Thus we can simply split the function's ## domain in half and assume that each is strictly monotonic. l = inf (size (x.inf)); u = -l; ## Monotonically decreasing for x1 x1 = intersect (x, infsup (0, x_min_sup)); select = not (isempty (x1)) & x1.sup > 0; if (any (select(:))) x1.inf(x1.inf == 0) = 0; # fix negative zero l(select) = mpfr_function_d ('gammaln', -inf, x1.sup(select)); u(select) = mpfr_function_d ('gammaln', +inf, x1.inf(select)); endif ## Monotonically increasing for x2 x2 = intersect (x, infsup (x_min_inf, inf)); select = not (isempty (x2)); if (any (select(:))) l(select) = mpfr_function_d ('gammaln', -inf, x2.inf(select)); u(select) = max (u (select), ... mpfr_function_d ('gammaln', +inf, x2.sup(select))); endif l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!assert (gammaln (infsup (-inf, inf)) == "[-0x1.F19B9BCC38A42p-4, +Inf]"); %!# from the documentation string %!assert (gammaln (infsup (1.5)) == "[-0x1.EEB95B094C192p-4, -0x1.EEB95B094C191p-4]"); %!# correct use of signed zeros %!test %! x = gammaln (infsup (1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = gammaln (infsup (2)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); interval-3.2.0/inst/@infsup/gauss.m0000644000000000000000000001565513316017127015364 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{x} =} gauss (@var{A}, @var{b}) ## ## Solve a linear interval system @var{A} * @var{x} = @var{b} using Gaussian ## elimination. ## ## The found enclosure is improved with the help of the Gauß-Seidel-method. ## ## Note: This algorithm is very inaccurate and slow for matrices of a dimension ## greater than 3. A better solver is provided by @code{mldivide}. The ## inaccuracy mainly comes from the dependency problem of interval arithmetic ## during back-substitution of the solution's enclosure. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## gauss (infsup ([1, 0; 0, 2]), [2, 0; 0, 4]) ## @result{} ans = 2×2 interval matrix ## [2] [0] ## [0] [2] ## @end group ## @end example ## @seealso{@@infsup/mldivide} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-31 function result = gauss (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif if (isscalar (x) || isscalar (y)) result = rdivide (y, x); return endif ## x must be square assert (size (x.inf, 1) == size (x.inf, 2), ... "gauss: nonconformant arguments, X is not square"); ## vertical sizes of x and y must equal assert (rows (x.inf) == rows (y.inf), ... "gauss: nonconformant arguments, first dimension mismatch"); n = length (x.inf); m = columns (y.inf); ## We have to compute z = inv (x) * y. ## This can be done by Gaußian elimination by solving the following equation ## for the variable z: x * z = y ## Step 1: Perform LUP decomposition of x into triangular matrices L, U and ## permutation matrix P ## P * x = L * U [L, U, P] = lu (x); ## Step 2: Forward substitution ## Solve L * s = inv (P) * y s = permute (inv (P), y); curelement.type = prevvars.type = "()"; for i = 1 : m ## Special case: k == 1 ## s (k, i) already is correct for k = 2 : n curelement.subs = {k, i}; prevvars.subs = {1 : k, i}; varcol = subsref (s, prevvars); Lrow = subsref (L, substruct ("()", {k, 1 : k})); ## We have to subtract varcol (1 : (k - 1)) * Lrow (1 : (k - 1)) from ## s (k, i). Since varcol (k) == s (k, i), we can simply set ## Lrow (k) = -1 and the dot product will compute the difference for us ## with high accurracy. Lrow.inf(k) = Lrow.sup(k) = -1; ## Then, we only have to flip the sign afterwards. s = subsasgn (s, curelement, -dot (Lrow, varcol)); endfor endfor ## Step 3: Backward substitution ## Solve U * z = s z = s; Urowstart.type = Urowrest.type = "()"; for i = 1 : m ## Special case: k == n curelement.subs = {n, i}; Urowstart.subs = {n, n}; z = subsasgn (z, curelement, ... mulrev (subsref (U, Urowstart), subsref (z, curelement))); for k = (n - 1) : -1 : 1 curelement.subs = {k, i}; Urowstart.subs = {k, k}; prevvars.subs = {k : n, i}; Urowrest.subs = {k, k : n}; varcol = subsref (z, prevvars); Urow = subsref (U, Urowrest); ## Use the same trick like above during forward substitution. Urow.inf(1) = Urow.sup(1) = -1; ## Additionally we must divide the element by the current diagonal ## element of U. z = subsasgn (z, curelement, ... mulrev (subsref (U, Urowstart), -dot (Urow, varcol))); endfor endfor ## Now we have solved inv (P) * L * U * z = y for z. ## ## The current result for z is only a rough estimation in general, ## because inv (P) * L * U is only an enclosure of the original ## linear interval system x * z = y and the Gaußian elimination ## above introduces several inaccuracies because of aggregated ## intermediate results and accumulated rounding errors. ## ## We can further try to improve the boundaries of the result with ## the original linear system. This is an iterative method using ## the mulrev operation. It is quite accurate in each step, because ## it only depends on one (tightest) dot operation and one ## (tightest) mulrev operation. However, the convergence speed is ## slow and each cycle is costly, so we have to cancel after one ## iteration. ## ## The method used here is similar to the Gauß-Seidel-method. ## Instead of diagonal elements of the matrix we use an arbitrary ## element that does not contain zero as an inner element. migx = mig (x); migx (isnan (migx)) = 0; for k = 1 : m zcol = subsref (z, substruct ("()", {1 : n, k})); for j = n : -1 : 1 z_jk = subsref (zcol, substruct ("()", {j})); if (isempty (z_jk) || issingleton (z_jk)) ## No improvement can be achieved. continue endif i = find (migx(:, j) == max (migx(:, j)), 1); xrow = subsref (x, substruct ("()", {i, 1 : n})); if (xrow.inf(j) < 0 && xrow.sup(j) > 0) ## No improvement can be achieved. continue endif x_ij = subsref (xrow, substruct ("()", {j})); yelement = subsref (y, substruct ("()", {i, k})); ## x(i, 1 : n) * z(1 : n, k) shall equal y(i, k). ## 1. Solve this equation for x(i, j) * z(j, k). ## 2. Compute a (possibly better) enclosure for z(j, k). xrow.inf(j) = yelement.inf; xrow.sup(j) = yelement.sup; zcol.inf(j) = zcol.sup(j) = -1; z_jk = mulrev (x_ij, -dot (xrow, zcol), z_jk); zcol.inf(j) = z.inf(j, k) = z_jk.inf; zcol.sup(j) = z.sup(j, k) = z_jk.sup; endfor endfor result = z; endfunction ## Apply permutation matrix P to an interval matrix: B = P * A. ## This is much faster than a matrix product, because the matrix product would ## use a lot of dot products. function B = permute (P, A) ## Note: [B.inf, B.sup] = deal (P * A.inf, P * A.sup) is not possible, ## because empty or unbound intervals would create NaNs during ## multiplication with P. B = A; for i = 1 : rows (P) targetrow = find (P(i, :) == 1, 1); B.inf(targetrow, :) = A.inf(i, :); B.sup(targetrow, :) = A.sup(i, :); endfor endfunction %!# from the documentation string %!assert (gauss (infsup ([1, 0; 0, 2]), [2, 0; 0, 4]) == [2, 0; 0, 2]); interval-3.2.0/inst/@infsup/ge.m0000644000000000000000000000244513316017127014626 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} ge (@var{A}, @var{B}) ## @defopx Operator {@@infsup} {@var{A} >= @var{B}} ## ## Compare intervals @var{A} and @var{B} for weakly greater. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/le, @@infsup/gt} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function result = ge (a, b) if (nargin ~= 2) print_usage (); return endif result = le (b, a); endfunction %!assert (ge (infsup (2, 3), infsup (1, 3))); interval-3.2.0/inst/@infsup/gt.m0000644000000000000000000000253213316017127014642 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} gt (@var{A}, @var{B}) ## @defopx Operator {@@infsup} {@var{A} > @var{B}} ## ## Compare intervals @var{A} and @var{B} for strict greater. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/lt, @@infsup/ge} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function result = gt (a, b) if (nargin ~= 2) print_usage (); return endif result = lt (b, a); endfunction %!assert (not (gt (infsup (2, 3), infsup (1, 3)))); %!assert (gt (infsup (2, 3.1), infsup (1, 3))); interval-3.2.0/inst/@infsup/hdist.m0000644000000000000000000000561013316017127015343 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} hdist (@var{X}, @var{Y}) ## ## Compute the Hausdorff distance between two intervals as sets. ## ## The Hausdorff distance for closed real intervals is the maximum distance ## between both pairs of interval boundaries. ## ## If any interval is empty, the result is NaN. For interval arrays the ## result is computed entry-wise. ## ## Accuracy: The result is correctly-rounded (towards infinity). ## ## @example ## @group ## hdist (infsup (1, 6), infsup (2, 8)) ## @result{} ans = 2 ## @end group ## @end example ## @seealso{@@infsup/sdist, @@infsup/idist} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-06-11 function result = hdist (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, y.inf))) x.inf = ones (size (y.inf)) .* x.inf; x.sup = ones (size (y.inf)) .* x.sup; y.inf = ones (size (x.inf)) .* y.inf; y.sup = ones (size (x.inf)) .* y.sup; endif result = zeros (size (x.inf)); select = x.inf < y.inf; if (any (select(:))) result(select) = ... mpfr_function_d ('minus', +inf, y.inf(select), x.inf(select)); endif select = x.inf > y.inf; if (any (select(:))) result(select) = max (result(select), ... mpfr_function_d ('minus', +inf, x.inf(select), ... y.inf(select))); endif select = x.sup < y.sup; if (any (select(:))) result(select) = max (result(select), ... mpfr_function_d ('minus', +inf, y.sup(select), ... x.sup(select))); endif select = x.sup > y.sup; if (any (select(:))) result(select) = max (result(select), ... mpfr_function_d ('minus', +inf, x.sup(select), ... y.sup(select))); endif result(isempty (x) | isempty (y)) = nan (); endfunction %!# from the documentation string %!assert (hdist (infsup (1, 6), infsup (2, 8)), 2); interval-3.2.0/inst/@infsup/horzcat.m0000644000000000000000000000300113316017127015672 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} horzcat (@var{ARRAY1}, @var{ARRAY2}, @dots{}) ## @defopx Operator {@@infsup} {[@var{ARRAY1}, @var{ARRAY2}, @dots{}]} ## ## Return the horizontal concatenation of interval array objects along ## dimension 2. ## ## @example ## @group ## a = infsup (2, 5); ## [a, a, a] ## @result{} ans = 1×3 interval vector ## [2, 5] [2, 5] [2, 5] ## @end group ## @end example ## @seealso{@@infsup/vertcat} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function result = horzcat (varargin) result = cat (2, varargin{:}); endfunction %!assert (horzcat (infsup (1), infsup (2)) == infsup (horzcat (1, 2))); %!test %! # from the documentation string %! a = infsup (2, 5); %! assert (horzcat (a, a, a) == infsup ([2, 2, 2], [5, 5, 5])); interval-3.2.0/inst/@infsup/hypot.m0000644000000000000000000000577113316017127015403 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} hypot (@var{X}, @var{Y}) ## ## Compute the euclidean norm. ## ## @code{hypot (@var{x}, @var{y}) = sqrt (@var{x}^2 + @var{y}^2)} ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (2, 3); ## y = infsup (1, 2); ## hypot (x, y) ## @result{} ans ⊂ [2.236, 3.6056] ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-20 function x = hypot (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif l = mpfr_function_d ('hypot', -inf, mig (x), mig (y)); u = mpfr_function_d ('hypot', +inf, mag (x), mag (y)); emptyresult = isempty (x) | isempty (y); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (hypot (infsup (2, 3), infsup (1, 2)) == "[0x1.1E3779B97F4A7p1, 0x1.CD82B446159F4p1]"); %!# correct use of signed zeros %!test %! x = hypot (infsup (0), infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.hypot; %! for testcase = [testcases]' %! assert (isequaln (... %! hypot (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.hypot; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (hypot (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.hypot; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (hypot (in1, in2), out)); interval-3.2.0/inst/@infsup/idist.m0000644000000000000000000000512513316017127015345 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} idist (@var{X}, @var{Y}) ## ## Compute the inner distance between two intervals as sets. ## ## The inner distance for closed real intervals is the minimum distance ## between each pair of numbers. That is, the inner distance equals zero if ## a number can be found in both intervals. Otherwise the inner distance is ## the size of the gap between both intervals on the real number lane. ## ## If any interval is empty, the result is NaN. For interval arrays the ## result is computed entry-wise. ## ## Accuracy: The result is correctly-rounded (towards infinity). ## ## @example ## @group ## idist (infsup (0, 6), infsup (7, 20)) ## @result{} ans = 1 ## @end group ## @end example ## @seealso{@@infsup/sdist, @@infsup/hdist} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-06-11 function result = idist (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, y.inf))) x.inf = ones (size (y.inf)) .* x.inf; x.sup = ones (size (y.inf)) .* x.sup; y.inf = ones (size (x.inf)) .* y.inf; y.sup = ones (size (x.inf)) .* y.sup; endif result = zeros (size (x.inf)); select = x.sup < y.inf; if (any (select(:))) result(select) = ... mpfr_function_d ('minus', +inf, y.inf(select), x.sup(select)); endif select = x.inf > y.sup; if (any (select(:))) result(select) = max (result(select), ... mpfr_function_d ('minus', +inf, x.inf(select), ... y.sup(select))); endif result(isempty (x) | isempty (y)) = nan (); endfunction %!# from the documentation string %!assert (idist (infsup (0, 6), infsup (7, 20)), 1); interval-3.2.0/inst/@infsup/inf.m0000644000000000000000000000453413316017127015010 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} inf (@var{X}) ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## ## Get the (greatest) lower boundary for all numbers of interval @var{X}. ## ## If @var{X} is empty, @code{inf (@var{X})} is positive infinity. ## ## Accuracy: The result is exact. ## ## @example ## @group ## inf (infsup (2.5, 3.5)) ## @result{} ans = 2.5000 ## @end group ## @end example ## @seealso{@@infsup/sup, @@infsup/mid} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-27 function result = inf (x) if (nargin ~= 1) print_usage (); return endif result = x.inf; endfunction %!# from the documentation string %!assert (inf (infsup (2.5, 3.5)), 2.5); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.inf; %! for testcase = [testcases]' %! assert (isequaln (... %! inf (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.inf; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (inf (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.inf; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (inf (in1), out)); interval-3.2.0/inst/@infsup/infsup.m0000644000000000000000000014222313316017127015536 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypeop Constructor {@@infsup} {[@var{X}, @var{ISEXACT}] =} infsup () ## @deftypeopx Constructor {@@infsup} {[@var{X}, @var{ISEXACT}] =} infsup (@var{M}) ## @deftypeopx Constructor {@@infsup} {[@var{X}, @var{ISEXACT}] =} infsup (@var{S}) ## @deftypeopx Constructor {@@infsup} {[@var{X}, @var{ISEXACT}] =} infsup (@var{L}, @var{U}) ## ## Create an interval (from boundaries). Convert boundaries to double ## precision. ## ## The syntax without parameters creates an (exact) empty interval. The syntax ## with a single parameter @code{infsup (@var{M})} equals ## @code{infsup (@var{M}, @var{M})}. The syntax @code{infsup (@var{S})} parses ## an interval literal in inf-sup form or as a special value, where ## @code{infsup ("[S1, S2]")} is equivalent to @code{infsup ("S1", "S2")}. A ## second, logical output @var{ISEXACT} indicates if @var{X}'s boundaries both ## have been converted without precision loss. ## ## Each boundary can be provided in the following formats: literal constants ## [+-]inf[inity], e, pi; scalar real numeric data types, i. e., double, ## single, [u]int[8,16,32,64]; or decimal numbers as strings of the form ## [+-]d[,.]d[[eE][+-]d]; or hexadecimal numbers as string of the form ## [+-]0xh[,.]h[[pP][+-]d]; or decimal numbers in rational form ## [+-]d/d. ## ## Also it is possible, to construct intervals from the uncertain form in the ## form @code{m?ruE}, where @code{m} is a decimal mantissa, ## @code{r} is empty (= half ULP) or a decimal integer ULP count or a ## second @code{?} character for unbounded intervals, @code{u} is ## empty or a direction character (u: up, d: down), and @code{E} is an ## exponential field. ## ## If decimal or hexadecimal numbers are no binary64 floating point numbers, a ## tight enclosure will be computed. int64 and uint64 numbers of high ## magnitude (> 2^53) can also be affected from precision loss. ## ## For the creation of interval arrays, arguments may be provided as (1) cell ## arrays with arbitrary/mixed types, (2) numeric arrays, or for matrices (3) ## strings. Scalar values do broadcast. ## ## Non-standard behavior: This class constructor is not described by IEEE Std ## 1788-2015, IEEE standard for interval arithmetic, however it implements both ## standard functions numsToInterval and textToInterval for bare intervals. ## ## @example ## @group ## infsup () ## @result{} ans = [Empty] ## infsup ("[1]") ## @result{} ans = [1] ## infsup (2, 3) ## @result{} ans = [2, 3] ## infsup ("0.1") ## @result{} ans ⊂ [0.099999, 0.10001] ## infsup ("0.1", "0.2") ## @result{} ans ⊂ [0.099999, 0.20001] ## infsup ("0xff", "0x1.ffp14") ## @result{} ans = [255, 32704] ## infsup ("1/3") ## @result{} ans ⊂ [0.33333, 0.33334] ## infsup ("[1/9, 47/11]") ## @result{} ans ⊂ [0.11111, 4.2728] ## infsup ("7.3?9u") ## @result{} ans ⊂ [7.2999, 8.2001] ## infsup ("0??") ## @result{} ans = [Entire] ## infsup ("911??de-2") ## @result{} ans ⊂ [-inf, +9.1101] ## infsup ("10?") ## @result{} ans = [9.5, 10.5] ## @end group ## @end example ## @seealso{exacttointerval} ## @end deftypeop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-27 function [x, isexact, overflow, isnai] = infsup (l, u) persistent scalar_empty_interval = class (struct ("inf", inf, ... "sup", -inf), ... "infsup"); warning ("off", "Octave:broadcast", "local"); ## Part 1 ## ## Split any arguments into l and u, where l and u denote lower and upper ## boundaries. l and u shall be either numeric arrays or cell arrays with ## strings or numeric entries. The size of l and u will equal the interval ## array size of the final result (unless broadcasting is going to be applied ## as a very last step). ## ## Strings in l and u will be normalized, that is, trimmed and converted to ## lower case. switch nargin case 0 ## empty interval x = scalar_empty_interval; isexact = true; isnai = overflow = false; return case 1 if (isa (l, "infsup")) ## already an interval—nothing to be done x = l; isexact = true (); isnai = overflow = false (size (l.inf)); return endif if (ischar (l)) ## Character string may contain a vector or a matrix of intervals, ## split the interval literals into a cell array of strings. ## Interval literals will be trimmed by the split function. l = __split_interval_literals__ (lower (l)); char_idx = true (size (l)); elseif (iscell (l)) ## Make sure that in a cell array (with possibly mixed types) all ## strings are trimmed. This is required during splitting of ## interval literals into lower and upper bounds. char_idx = cellfun ("ischar", l); l(char_idx) = lower (strtrim (l(char_idx))); else ## Not cell or char, e. g. numeric array. ## Syntax infsup (x) has to be equivalent with infsup (x, x). ## No need to trim or normalize character case. u = l; endif ## Correct construction of empty intervals is only possible by calling ## this constructor without arguments (see above), or by using one of ## the two interval literals [] or [empty]. ## Otherwise, construction of empty intervals must signal ## “UndefinedOperation”. ## In particular, the interval literal [+inf, -inf] is illegal and ## “numsToInterval (+inf, -inf)” would be an illegal function call, ## according to IEEE Std 1788-2015. ## ## 1. isnai defaults to -1 (unknown). ## 2. any non-empty interval (l <= u) is legal and we set isnai to ## false for those in the end. ## 3. for legal empty interval literals we set isnai = false ## explicitly. ## 4. for certain illegal interval literals we give a special warning ## and set isnai = true explicitly. ## 5. it remains isnai = -1 for any illegal intervals which have not ## been handled with, we give a warning and we return an empty ## interval in these cases. isnai = -ones (size (l), "int8"); illegal_boundary = struct ("inf", false (size (l)), ... "sup", false (size (l))); if (iscell (l)) ## At this point, only a cell array can contain interval literals ## as string. Split intervals and interval literals into lower and ## upper bounds. Except for empty intervals, strings are not ## converted into numeric values yet. ## ## [] -> (+inf, -inf) ## [empty] -> (+inf, -inf) ## [entire] -> (, ) ## [,] -> (, ) ## [l, u] -> (l, u) ## [m] -> (m, m) ## m -> (m, m) ## m?r -> (m?r, m?r) ## m?ru -> (m, m?r) ## m?rd -> (m?r, m) ## m?? -> (, ) ## m??u -> (m, ) ## m??d -> (, m) ## Initialize u such that the syntax infsup (x) is equivalent with ## infsup (x, x) unless interval literals are used. u = l; ## Find interval literals with square brackets. The strings are ## trimmed already, so they will start at the first character. square_bracket_idx = strncmp (l, "[", 1); %!# Verify correct behaviour of strncmp for empty strings and non-string %!# values within the cell array. %!assert (strncmp ({"[", double("["), ""}, "[", 1), logical ([1 0 0])); ## A bare interval literal which starts with a square bracket ## must end with a square bracket as well. square_bracket_idx = ... find (square_bracket_idx)(... cellfun (@(s) s(end) == "]", ... l(square_bracket_idx))); ## Strip square brackets and white space within square brackets. nobrackets = strtrim (cellfun (@(s) s([2 : (end - 1)]), ... l(square_bracket_idx), ... "UniformOutput", false)); ## Construction of empty intervals with the correct literal either ## [empty] or [] is legit. empty_interval_local_idx = strcmp (nobrackets, "empty") ... | cellfun ("isempty", nobrackets); empty_interval_idx = square_bracket_idx(empty_interval_local_idx); isnai(empty_interval_idx) = false; ## We remove the empty interval cases from the current work basket ## and don't need special handling of comma-less strings below ## ([] represents the empty interval, whereas [,] represents the ## set of all real numbers). square_bracket_idx = ... square_bracket_idx(not (empty_interval_local_idx)); nobrackets = nobrackets(not (empty_interval_local_idx)); char_idx(empty_interval_idx) = false; l(empty_interval_idx) = +inf; u(empty_interval_idx) = -inf; ## [entire] is equivalent to [,] nobrackets(strcmp (nobrackets, "entire")) = {""}; ## Split [l, u] literals into l and u strings at the comma. nobrackets = cellfun ("strsplit", nobrackets, {","}, ... "UniformOutput", false); nobrackets_parts = cellfun ("numel", nobrackets); ## For point intervals [m] we have removed the square brackets, ## trimmed any white space inside the square brackets and must ## store m into both l and u for further parsing below. ## Each boundary will be parsed individually with opposite rounding ## direction. point_interval_local_idx = (nobrackets_parts == 1); point_interval_idx = square_bracket_idx(point_interval_local_idx); l(point_interval_idx) = u(point_interval_idx) = ... vertcat ({}, nobrackets(point_interval_local_idx){:}); ## For infsup intervals [l, u] we can store the trimmed l and u ## strings for further parsing below. infsup_interval_local_idx = (nobrackets_parts == 2); infsup_interval_idx = square_bracket_idx(infsup_interval_local_idx); l(infsup_interval_idx) = strtrim (vertcat ({}, ... cellindexmat (nobrackets(infsup_interval_local_idx), 1){:})); u(infsup_interval_idx) = strtrim (vertcat ({}, ... cellindexmat (nobrackets(infsup_interval_local_idx), 2){:})); ## Find interval literals in uncertain form. uncertain_idx = char_idx; uncertain_idx(square_bracket_idx) = false; # already processed ## Find uncertain form with directed uncertainty (down or up) [~, ~, ~, ~, groups] = regexp (l(uncertain_idx), ... ["([^?]+)", ... # 1: mantissa "([?])", ... # 2: ? "(.*)", ... # 3: uncertainty "([du])", ... # 4: direction "(.*)"]); # 5: exponent directed_local_idx = not (cellfun ("isempty", groups)); directed_uncertain_idx = uncertain_idx; directed_uncertain_idx(uncertain_idx) = directed_local_idx; groups = vertcat ({}, groups(directed_local_idx){:}); ## Remove directed down/up uncertainty. for direction = ["d", "u"] direction_local_idx = strcmp (... vertcat ({}, ... cellindexmat (groups, ... 4){:}), ... direction); direction_idx = directed_uncertain_idx; direction_idx(directed_uncertain_idx) = direction_local_idx; ## Remove direction character persistent join_groups = @(parts) strcat (parts{:}); undirected_uncertain_form = ... cellfun (... join_groups, ... cellindexmat (groups(direction_local_idx), ... [1 2 3 5]), ... "UniformOutput", false); ## Also remove uncertainty undirected_certain_form = ... cellfun (... join_groups, ... cellindexmat (groups(direction_local_idx), ... [1 5]), ... "UniformOutput", false); ## Store uncertain boundaries without directed uncertainty switch direction case "d" l(direction_idx) = undirected_uncertain_form; u(direction_idx) = undirected_certain_form; case "u" l(direction_idx) = undirected_certain_form; u(direction_idx) = undirected_uncertain_form; endswitch ## Remove parsed uncertain form from work basket to prevent ## double parsing (strings with both d and u uncertainty). directed_uncertain_idx(direction_idx) = false; groups = groups(not (direction_local_idx)); endfor ## Remove unbound uncertainty ?? ## FIXME We should verify correctness of the interval literal more ## thoroughly. Otherwise we would ignore illegal literals which ## contain the double question mark. l_unbound_idx = uncertain_idx; l_unbound_idx(uncertain_idx) = ... not (cellfun ("isempty", strfind (l(uncertain_idx), "??"))); l(l_unbound_idx) = {""}; u_unbound_idx = uncertain_idx; u_unbound_idx(uncertain_idx) = ... not (cellfun ("isempty", strfind (u(uncertain_idx), "??"))); u(u_unbound_idx) = {""}; endif case 2 ## Split interval vectors if supplied as strings. if (ischar (l)) l = __split_interval_literals__ (l); endif if (ischar (u)) u = __split_interval_literals__ (u); endif ## Check dimensions and whether broadcasting is possible for dim = 1 : max (ndims (l), ndims (u)) if (size (l, dim) != 1 && size (u, dim) != 1 && ... size (l, dim) != size (u, dim)) warning ("interval:InvalidOperand", ... ["infsup: Dimensions of lower and upper ", ... "boundaries are not compatible"]); ## Unable to recover from this kind of error x = scalar_empty_interval; isexact = false; overflow = false; isnai = true; return endif endfor ## Compute result size after broadcasting and mark any empty intervals ## as illegal (will trigger “UndefinedOperation” signal later on). ## Construction of silent empty intervals is impossible with two args. isnai = zeros (size (l), "int8") - ones (size (u), "int8"); #-1=unknown illegal_boundary = struct ("inf", false (size (l)), ... "sup", false (size (u))); for argument = ["l", "u"] switch argument case "l" current_arg = l; case "u" current_arg = u; endswitch if (iscell (current_arg)) ## Normalize strings: trim and convert to lower case ## (as is done in the nargin == 1 case). char_idx = cellfun ("ischar", current_arg); current_arg(char_idx) = ... lower (strtrim (current_arg(char_idx))); ## In contrast to the nargin == 1 case we cannot allow interval ## literals here. Only simple boundaries are allowed if two ## arguments are given. square_bracket_idx = strncmp (current_arg, "[", 1); uncertain_idx = char_idx; uncertain_idx(square_bracket_idx) = false; uncertain_idx(uncertain_idx) = ... not (cellfun ("isempty", ... strfind (current_arg(uncertain_idx), "?"))); illegal_literal_idx = (square_bracket_idx | uncertain_idx); if (any (illegal_literal_idx(:))) switch argument case "l" warning ("interval:UndefinedOperation", ... "Lower boundary contains an interval literal"); current_arg(illegal_literal_idx) = +inf; illegal_boundary.inf(illegal_literal_idx) = true; case "u" warning ("interval:UndefinedOperation", ... "Upper boundary contains an interval literal"); current_arg(illegal_literal_idx) = -inf; illegal_boundary.sup(illegal_literal_idx) = true; endswitch endif switch argument case "l" l = current_arg; case "u" u = current_arg; endswitch endif endfor otherwise # nargin >= 3 print_usage (); return endswitch ## Part 2 ## ## Boundaries have been split into lower and upper boundaries and shall be ## converted to binary64 arrays with string parsing and outward rounding. ## ## l contains a cell array or an array of lower boundaries. ## u contains a cell array or an array of upper boundaries. ## ## Each of l and u will be converted into binary64 individually and will be ## stored in x.inf and x.sup respectively. isexact = true (); x = struct ("inf", inf (size (l)), ... "sup", -inf (size (u))); for [boundaries, key] = struct ("inf", {l}, "sup", {u}) if (isfloat (boundaries) && isreal (boundaries)) ## Simple case: the boundaries already are binary floating point ## numbers in single or double precision. ## This kind of operation is often used in internal functions and shall ## be fast. We check for NaNs later. x.(key) = double (boundaries); possiblyundefined.(key) = overflow.(key) = false (size (boundaries)); continue endif if (not (iscell (boundaries))) if (not (isnumeric (boundaries))) warning ("interval:InvalidOperand", ... ["infsup: Invalid argument type, only strings, ", ... "numerics, and cell arrays thereof are allowed"]); ## Unable to recover from this kind of error x = scalar_empty_interval; isexact = false; overflow = false; isnai = true; return endif boundaries = num2cell (boundaries); endif overflow.(key) = true (size (boundaries)); possiblyundefined.(key) = false (size (boundaries)); ## Track the entries in cell array boundaries, which haven't been ## converted yet. todo = true (size (boundaries)); ## [,] = [-inf, +inf] unbound_idx = cellfun ("isempty", boundaries); switch key case "inf" x.inf(unbound_idx) = -inf; case "sup" x.sup(unbound_idx) = +inf; endswitch overflow.(key)(unbound_idx) = false; todo(unbound_idx) = false; ## In the cell array each entry must represent a scalar value. non_scalar_entry_idx = todo & not (... cellfun ("isscalar", boundaries) |... cellfun ("ischar", boundaries)); if (any (non_scalar_entry_idx(:))) warning ("interval:UndefinedOperation", ... "Cell arrays of matrix entries do not contain scalar values"); # Use default value of [empty] for these entries and continue todo(non_scalar_entry_idx) = false; illegal_boundary.(key)(non_scalar_entry_idx) = true; endif ## 64 bit integers: approximate in double precision. integer_idx = find (todo & ( ... cellfun ("isa", boundaries, {"uint64"}) ... | cellfun ("isa", boundaries, {"int64"}))); integers = vertcat (boundaries{integer_idx}); converted_integers = double (integers); exact_integer_local_idx = (converted_integers == integers); if (any (not (exact_integer_local_idx(:)))) isexact = false; possiblyundefined.(key)(integer_idx(not (exact_integer_local_idx))) ... = true; endif ## Fix conversion in cases where rounding to nearest has resulted in the ## wrong value, i. e., in a value that has not been rounded outward, ## but inward. switch key case "inf" wrong_round_local_idx = (converted_integers > integers); converted_integers(wrong_round_local_idx) = ... mpfr_function_d ('minus', -inf, ... converted_integers(wrong_round_local_idx), ... pow2 (-1074)); case "sup" wrong_round_local_idx = (converted_integers < integers); converted_integers(wrong_round_local_idx) = ... mpfr_function_d ('plus', +inf, ... converted_integers(wrong_round_local_idx), ... pow2 (-1074)); endswitch x.(key)(integer_idx) = converted_integers; overflow.(key)(integer_idx) = false; todo(integer_idx) = false; ## Lossless conversion from binary32, binary64, (u)int8, (u)int16, (u)int32 ## and logicals. real_idx = todo & ... ( ... ( ... cellfun ("isreal", boundaries) ... & cellfun ("isfloat", boundaries) ... ) ... | cellfun ("isinteger", boundaries) ... | cellfun ("islogical", boundaries) ); x.(key)(real_idx) = double (vertcat (boundaries{real_idx})); overflow.(key)(real_idx) = false; todo(real_idx) = false; ## Complex numbers: not allowed, will be mapped to [empty]. complex_idx = todo & cellfun ("iscomplex", boundaries); if (any (complex_idx(:))) warning ("interval:InvalidOperand", ... "infsup: Complex arguments are not permitted"); todo(complex_idx) = false; illegal_boundary.(key)(complex_idx) = true; endif ## Other kinds of parameters that are not strings char_idx = todo & cellfun ("ischar", boundaries); if (any ((todo & not (char_idx))(:))) warning ("interval:InvalidOperand", ... "infsup: Illegal boundary: must be numeric or string"); illegal_boundary.(key)(todo & not (char_idx)) = true; endif todo = char_idx; ## Hex strings hex_idx = find (todo & (strncmp (boundaries, "0x", 2) ... | strncmp (boundaries, "+0x", 3) ... | strncmp (boundaries, "-0x", 3))); switch key case "inf" direction = -inf; case "sup" direction = inf; endswitch for i = vec (hex_idx, 2) try [x.(key)(i), exact_conversion] = ... hex2double (boundaries{i}, direction); possiblyundefined.(key)(i) = not (exact_conversion); isexact = isexact && exact_conversion; catch warning ("interval:UndefinedOperation", lasterr ()); illegal_boundary.(key)(i) = true; end_try_catch endfor overflow.(key)(hex_idx) = false; todo(hex_idx) = false; ## Selected boundary literals persistent boundary_const = struct (... "inf", ... struct (... "-inf", -inf, ... "-infinity", -inf, ... "inf", inf, ... "+inf", inf, ... "infinity", inf, ... "+infinity", inf, ... "e", 0x56FC2A2 ... * pow2 (-25) ... + 0x628AED2 ... * pow2 (-52), ... "pi", 0x6487ED5 ... * pow2 (-25) ... + 0x442D180 ... * pow2 (-55)), ... "sup", ... struct (... "-inf", -inf, ... "-infinity", -inf, ... "inf", inf, ... "+inf", inf, ... "infinity", inf, ... "+infinity", inf, ... "e", 0x56FC2A2 ... * pow2 (-25) ... + 0x628AED4 ... * pow2 (-52), ... "pi", 0x6487ED5 ... * pow2 (-25) ... + 0x442D190 .... * pow2 (-55))); for [val, lit] = boundary_const.(key) const_idx = todo & strcmp (boundaries, lit); x.(key)(const_idx) = val; overflow.(key)(const_idx) = false; possiblyundefined.(key)(const_idx) = isfinite (val); todo(const_idx) = false; endfor ## It remains the decimal boundary strings for i = vec (find (todo), 2) try boundary = boundaries{i}; ## We have to parse a decimal string boundary and round the ## result up or down depending on the boundary ## (inf = down, sup = up). ## str2double will produce the correct answer in 50 % of ## all cases, because it uses rounding mode “to nearest”. ## The input and a double format approximation can be ## compared in a decimal floating point format without ## precision loss. if (strfind (boundary, "?")) ## Special case: uncertain-form [boundary, uncertain] = uncertainsplit (boundary); else uncertain = []; endif if (strfind (boundary, "/")) ## Special case: rational form boundary = strsplit (boundary, "/"); if (length (boundary) ~= 2) warning ("interval:UndefinedOperation", ... ["illegal " key " boundary: ", ... "rational form must have single slash"]); illegal_boundary.(key)(i) = true; continue; endif [decimal, remainder] = decimaldivide (... str2decimal (boundary{1}), ... str2decimal (boundary{2}), 18); if (not (isempty (remainder.m))) ## This will guarantee the enclosure of the exact ## value decimal.m(19, 1) = 1; isexact = false (); if (key == "inf") possiblyundefined.(key)(i) = true; endif endif ## Write result back into boundary for conversion to ## double boundary = ["0.", num2str(decimal.m)', ... "e", num2str(decimal.e)]; if (decimal.s) boundary = ["-", boundary]; endif else decimal = str2decimal (boundary); endif ## Parse and add uncertainty if (not (isempty (uncertain))) uncertain = str2decimal (uncertain); if ((key == "inf") == decimal.s) uncertain.s = decimal.s; else uncertain.s = not (decimal.s); endif decimal = decimaladd (decimal, uncertain); ## Write result back into boundary for conversion to ## double boundary = ["0.", num2str(decimal.m)', ... "e", num2str(decimal.e)]; if (decimal.s) boundary = ["-", boundary]; endif endif clear uncertain; ## Check if number is outside of range ## Realmax == 1.7...e308 == 0.17...e309 if (decimal.e > 309 || ... (decimal.e == 309 && ... decimal.s && ... decimalcompare (double2decimal (-realmax ()), ... decimal) > 0) || ... (decimal.e == 309 && ... not (decimal.s) && ... decimalcompare (double2decimal (realmax ()), ... decimal) < 0)) switch key case "inf" if (decimal.s) # -inf ... -realmax x.inf(i) = -inf; else # realmax ... inf x.inf(i) = realmax (); overflow.inf(i) = false; endif case "sup" if (decimal.s) # -inf ... -realmax x.sup(i) = -realmax (); overflow.sup(i) = false; else # realmax ... inf x.sup(i) = inf; endif endswitch possiblyundefined.(key)(i) = true; isexact = false; continue endif overflow.(key)(i) = false; ## Compute approximation, this only works between ± realmax binary = str2double (strrep (boundary, ",", ".")); ## Check approximation value comparison = decimalcompare (double2decimal (binary), ... decimal); if (comparison ~= 0) possiblyundefined.(key)(i) = true; isexact = false; endif if (comparison == 0 || ... # approximation is exact (comparison < 0 && key == "inf") || ... # lower bound (comparison > 0 && key == "sup")) # upper bound x.(key)(i) = binary; else ## Approximation is not exact and not rounded as needed ## However, because of faithful rounding the ## approximation is right next to the desired number. switch key case "inf" x.inf(i) = mpfr_function_d ('minus', -inf, ... binary, pow2 (-1074)); case "sup" x.sup(i) = mpfr_function_d ('plus', +inf, ... binary, pow2 (-1074)); endswitch endif catch warning ("interval:UndefinedOperation", lasterr ()); illegal_boundary.(key)(i) = true; end_try_catch endfor endfor ## Part 3 ## ## Check boundaries individually after conversion to double ## NaNs are illegal values for [boundary, key] = struct ("inf", {x.inf}, "sup", {x.sup}) nanvalue = isnan (boundary); if (any (nanvalue(:))) warning ("interval:UndefinedOperation", ... "input contains NaN values"); illegal_boundary.(key)(nanvalue) = true; endif endfor ## normalize boundaries: ## representation of the set containing only zero is always [-0,+0] x.inf(x.inf == 0) = -0; x.sup(x.sup == 0) = +0; ## Part 4 ## ## Broadcast boundaries and final checks if (nargout >= 3) overflow = overflow.inf | overflow.sup; overflow(x.inf > -inf & x.sup < inf) = false; endif x.inf = x.inf - zeros (size (x.sup)); x.sup = x.sup + zeros (size (x.inf)); possiblyundefined = possiblyundefined.inf & possiblyundefined.sup; if (any (possiblyundefined(:))) if (not (iscell (l)) && not (iscell (u))) ## infsup (x, x) or infsup (x) is not possibly undefined possiblyundefined(l == u) = false; else ## infsup ("x", "x") or infsup ("x") is not possibly undefined if (not (iscell (l))) l = num2cell (l); endif if (not (iscell (u))) u = num2cell (u); endif possiblyundefined(cellfun ("isequal", l, u)) = false; endif endif ## Non-empty intervals are always legal. isnai(x.inf <= x.sup) = false; ## Check for illegal boundaries [inf,inf] and [-inf,-inf]. illegal_inf_idx = not (isfinite (x.inf (x.inf == x.sup))); if (any (illegal_inf_idx(:))) warning ("interval:UndefinedOperation", ... "illegal interval boundaries: infimum = supremum = +/- infinity"); isnai(find (x.inf == x.sup)(illegal_inf_idx)) = true; endif ## Illegal boundaries make illegal intervals, ## we have triggered a warning already (see above). isnai(illegal_boundary.inf | illegal_boundary.sup) = true; ## Check boundary order ## isnai has been initialized with -1. Any non-empty or legal empty intervals ## have been set to 0. Any illegal interval literals or illegal boundaries ## have been set to +1. Any intervals with inf > sup still have their initial ## value of -1. wrong_boundary_order_idx = signbit (isnai); if (any (wrong_boundary_order_idx(:))) warning ("interval:UndefinedOperation", ... "illegal interval boundaries: infimum greater than supremum"); isnai(wrong_boundary_order_idx) = true; endif isnai = logical(isnai); ## Return [empty] for any illegal intervals. x.inf(isnai) = +inf; x.sup(isnai) = -inf; possiblyundefined(isnai) = false; isexact = isexact && not (any (isnai(:))); ## Check for possibly wrong boundary order. if (any (possiblyundefined(:))) ## Let a, b, and c be three consecutive floating point numbers. ## ## If a < u < b < l < c, then u and l will both be mapped to the same ## number b by outward rounding. ## ## If a < u < l < b, then u and l will both be mapped to consecutive ## floating point numbers a and b. if (any ((x.inf(possiblyundefined) == x.sup(possiblyundefined))(:)) ... || ... any ((max (-realmax, ... mpfr_function_d ('plus',... +inf, ... x.inf(possiblyundefined), ... pow2 (-1074))) ... == x.sup(possiblyundefined))(:))) warning ("interval:PossiblyUndefinedOperation", ... "infimum may be greater than supremum"); endif endif x = class (x, "infsup"); endfunction %!# Empty intervals %!test %! x = infsup (); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!test %! x = infsup ("[]"); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!test %! x = infsup ("[ ]"); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!test %! x = infsup ("[\t]"); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!test %! x = infsup ("[empty]"); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!test %! x = infsup ("[EMPTY]"); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!test %! x = infsup ("[ empty ]"); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!test %! x = infsup ("\t[\t Empty\t]\t"); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!# Entire interval %!test %! x = infsup ("[,]"); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!test %! x = infsup ("[entire]"); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!test %! x = infsup ("[ENTIRE]"); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!test %! x = infsup ("[ entire ]"); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!test %! x = infsup (" [Entire \t] "); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!test %! x = infsup ("[-inf,+inf]"); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!test %! x = infsup ("[-infinity, +infinity]"); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!test %! x = infsup ("[-INF, +INFinitY]"); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!# double boundaries %!test %! x = infsup (0); %! assert (inf (x), 0); %! assert (sup (x), 0); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = infsup (2, 3); %! assert (inf (x), 2); %! assert (sup (x), 3); %!test %! x = infsup (-inf, 0.1); %! assert (inf (x), -inf); %! assert (sup (x), 0.1); %!test %! x = infsup (-inf, +inf); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!# NaN values %!warning id=interval:UndefinedOperation %! x = infsup (nan); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!warning id=interval:UndefinedOperation %! x = infsup (nan, 2); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!warning id=interval:UndefinedOperation %! x = infsup (3, nan); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!# illegal numeric boundaries %!warning id=interval:UndefinedOperation %! x = infsup (+inf, -inf); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!warning id=interval:UndefinedOperation %! x = infsup (+inf, +inf); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!warning id=interval:UndefinedOperation %! x = infsup (-inf, -inf); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!warning id=interval:UndefinedOperation %! x = infsup (3, 2); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!warning id=interval:UndefinedOperation %! x = infsup (3, -inf); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!# double matrix %!test %! x = infsup (magic (4)); %! assert (inf (x), magic (4)); %! assert (sup (x), magic (4)); %!test %! x = infsup (magic (3), magic (3) + 1); %! assert (inf (x), magic (3)); %! assert (sup (x), magic (3) + 1); %!warning id=interval:UndefinedOperation %! x = infsup (nan (3)); %! assert (inf (x), +inf (3)); %! assert (sup (x), -inf (3)); %!test %! x = infsup (-inf (3), +inf (3)); %! assert (inf (x), -inf (3)); %! assert (sup (x), +inf (3)); %!# decimal boundaries %!test %! x = infsup ("0.1"); %! assert (inf (x), 0.1 - eps / 16); %! assert (sup (x), 0.1); %!test %! x = infsup ("0.1e1"); %! assert (inf (x), 1); %! assert (sup (x), 1); %!# hexadecimal boundaries %!test %! x = infsup ("0xff"); %! assert (inf (x), 255); %! assert (sup (x), 255); %!test %! x = infsup ("0xff.1"); %! assert (inf (x), 255.0625); %! assert (sup (x), 255.0625); %!test %! x = infsup ("0xff.1p-1"); %! assert (inf (x), 127.53125); %! assert (sup (x), 127.53125); %!# named constants %!test %! x = infsup ("pi"); %! assert (inf (x), pi); %! assert (sup (x), pi + 2 * eps); %!test %! x = infsup ("e"); %! assert (inf (x), e); %! assert (sup (x), e + eps); %!# uncertain form %!test %! x = infsup ("32?"); %! assert (inf (x), 31.5); %! assert (sup (x), 32.5); %!test %! x = infsup ("32?8"); %! assert (inf (x), 24); %! assert (sup (x), 40); %!test %! x = infsup ("32?u"); %! assert (inf (x), 32); %! assert (sup (x), 32.5); %!test %! x = infsup ("32?d"); %! assert (inf (x), 31.5); %! assert (sup (x), 32); %!test %! x = infsup ("32??"); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!test %! x = infsup ("32??d"); %! assert (inf (x), -inf); %! assert (sup (x), 32); %!test %! x = infsup ("32??u"); %! assert (inf (x), 32); %! assert (sup (x), +inf); %!test %! x = infsup ("32?e5"); %! assert (inf (x), 3150000); %! assert (sup (x), 3250000); %!# rational form %!test %! x = infsup ("6/9"); %! assert (inf (x), 2 / 3); %! assert (sup (x), 2 / 3 + eps / 2); %!test %! x = infsup ("6e1/9"); %! assert (inf (x), 20 / 3 - eps * 2); %! assert (sup (x), 20 / 3); %!test %! x = infsup ("6/9e1"); %! assert (inf (x), 2 / 30); %! assert (sup (x), 2 / 30 + eps / 16); %!test %! x = infsup ("-6/9"); %! assert (inf (x), -(2 / 3 + eps / 2)); %! assert (sup (x), -2 / 3); %!test %! x = infsup ("6/-9"); %! assert (inf (x), -(2 / 3 + eps / 2)); %! assert (sup (x), -2 / 3); %!test %! x = infsup ("-6/-9"); %! assert (inf (x), 2 / 3); %! assert (sup (x), 2 / 3 + eps / 2); %!test %! x = infsup ("6.6/9.9"); %! assert (inf (x), 2 / 3); %! assert (sup (x), 2 / 3 + eps / 2); %!# inf-sup interval literal %!test %! x = infsup ("[2, 3]"); %! assert (inf (x), 2); %! assert (sup (x), 3); %!test %! x = infsup ("[0.1]"); %! assert (inf (x), 0.1 - eps / 16); %! assert (sup (x), 0.1); %!test %! x = infsup ("[0xff, 0xff.1]"); %! assert (inf (x), 255); %! assert (sup (x), 255.0625); %!test %! x = infsup ("[e, pi]"); %! assert (inf (x), e); %! assert (sup (x), pi + 2 * eps); %!test %! x = infsup ("[6/9, 6e1/9]"); %! assert (inf (x), 2 / 3); %! assert (sup (x), 20 / 3); %!# corner cases %!test %! x = infsup (","); %! assert (inf (x), -inf); %! assert (sup (x), +inf); %!test %! x = infsup ("[, 3]"); %! assert (inf (x), -inf); %! assert (sup (x), 3); %!test %! x = infsup ("", "3"); %! assert (inf (x), -inf); %! assert (sup (x), 3); %!test %! x = infsup ("[2, ]"); %! assert (inf (x), 2); %! assert (sup (x), inf); %!test %! x = infsup ("2", ""); %! assert (inf (x), 2); %! assert (sup (x), inf); %!# decimal vector %!test %! x = infsup (["0.1"; "0.2"; "0.3"]); %! assert (inf (x), [0.1 - eps / 16; 0.2 - eps / 8; 0.3]); %! assert (sup (x), [0.1; 0.2; 0.3 + eps / 8]); %!test %! x = infsup ("0.1; 0.2; 0.3"); %! assert (inf (x), [0.1 - eps / 16; 0.2 - eps / 8; 0.3]); %! assert (sup (x), [0.1; 0.2; 0.3 + eps / 8]); %!test %! x = infsup ("0.1\n0.2\n0.3"); %! assert (inf (x), [0.1 - eps / 16; 0.2 - eps / 8; 0.3]); %! assert (sup (x), [0.1; 0.2; 0.3 + eps / 8]); %!# cell array with mixed boundaries %!test %! x = infsup ({"0.1", 42; "e", "3.2/8"}, {"0xffp2", "42e1"; "pi", 2}); %! assert (inf (x), [0.1 - eps / 16, 42; e, 0.4 - eps / 4]); %! assert (sup (x), [1020, 420; pi + 2 * eps, 2]); %!test %! x = infsup ({"[2, 3]", "3/4", "[Entire]", "42?3", 1, "0xf"}); %! assert (inf (x), [2, 0.75, -inf, 39, 1, 15]); %! assert (sup (x), [3, 0.75, +inf, 45, 1, 15]); %!# broadcasting %!test %! x = infsup (magic (3), 10); %! assert (inf (x), magic (3)); %! assert (sup (x), 10 .* ones (3)); %!test %! x = infsup (zeros (1, 20), ones (20, 1)); %! assert (inf (x), zeros (20, 20)); %! assert (sup (x), ones (20, 20)); %!# nai %!warning id=interval:UndefinedOperation %! x = infsup ("[nai]"); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!warning id=interval:UndefinedOperation %! x = infsup ("Ausgeschnitzel"); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!# interval literals vs. two arguments %!warning id=interval:UndefinedOperation %! x = infsup ("[empty]", 42); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!warning id=interval:UndefinedOperation %! x = infsup ("0?", 42); %! assert (inf (x), +inf); %! assert (sup (x), -inf); %!# extraction of single errors %!warning id=interval:UndefinedOperation %! x = infsup ("0 1 2 [xxx] 3 4"); %! assert (inf (x), [0 1 2 +inf 3 4]); %! assert (sup (x), [0 1 2 -inf 3 4]); %!warning id=interval:UndefinedOperation %! x = infsup ({1 2; 3 "[xxx]"}); %! assert (inf (x), [1 2; 3 +inf]); %! assert (sup (x), [1 2; 3 -inf]); %!# complex values %!warning id=interval:InvalidOperand %! x = infsup ([1 2 3+i 4+0i]); %! assert (inf (x), [1 2 +inf 4]); %! assert (sup (x), [1 2 -inf 4]); %!# inaccurate conversion %!warning id=interval:PossiblyUndefinedOperation %! x = infsup ("1.000000000000000000002", "1.000000000000000000001"); %! assert (inf (x), 1); %! assert (sup (x), 1 + eps); %!test %! n = uint64(2 ^ 53); %! x = infsup (n, n + 1); %! assert (inf (x), double (n)); %! assert (sup (x), double (n + 2)); %!test %! n = uint64(2 ^ 53); %! x = infsup ({n}, n + 1); %! assert (inf (x), double (n)); %! assert (sup (x), double (n + 2)); %!test %! n = uint64(2 ^ 53); %! x = infsup (n + 1, n + 1); %! assert (inf (x), double (n)); %! assert (sup (x), double (n + 2)); %!test %! n = uint64(2 ^ 54); %! x = infsup (n, n + 1); %! assert (inf (x), double (n)); %! assert (sup (x), double (n + 4)); %!warning id=interval:PossiblyUndefinedOperation %! n = uint64(2 ^ 54); %! x = infsup (n + 1, n + 2); %! assert (inf (x), double (n)); %! assert (sup (x), double (n + 4)); %!warning id=interval:PossiblyUndefinedOperation %! x = infsup ("pi", "3.141592653589793"); %! assert (inf (x), pi); %! assert (sup (x), pi); %!warning id=interval:PossiblyUndefinedOperation %! x = infsup ("pi", "3.1415926535897932"); %! assert (inf (x), pi); %! assert (sup (x), pi + 2 * eps); %!# isexact flag %!test %! [~, isexact] = infsup (); %! assert (isexact); %!test %! [~, isexact] = infsup (0); %! assert (isexact); %!test %! [~, isexact] = infsup ("1 2 3"); %! assert (isexact, true); %!test %! [~, isexact] = infsup ("1 2 3.1"); %! assert (isexact, false); %!warning %! [~, isexact] = infsup ("[nai]"); %! assert (not (isexact)); %!# overflow flag %!test %! [~, ~, overflow] = infsup (); %! assert (not (overflow)); %!test %! [~, ~, overflow] = infsup (0); %! assert (not (overflow)); %!test %! [~, ~, overflow] = infsup ([1 2 3]); %! assert (overflow, false (1, 3)); %!warning %! [~, ~, overflow] = infsup ("[nai]"); %! assert (not (overflow)); %!test %! [~, ~, overflow] = infsup ("1e3000"); %! assert (overflow); %!test %! [~, ~, overflow] = infsup ("[1, inf]"); %! assert (not (overflow)); %!# isnai flag %!test %! [~, ~, ~, isnai] = infsup (); %! assert (not (isnai)); %!test %! [~, ~, ~, isnai] = infsup (0); %! assert (not (isnai)); %!test %! [~, ~, ~, isnai] = infsup ([1 2 3]); %! assert (isnai, false (1, 3)); %!warning %! [~, ~, ~, isnai] = infsup ("[nai]"); %! assert (isnai); %!warning %! [~, ~, ~, isnai] = infsup ("xxx"); %! assert (isnai); %!warning %! [~, ~, ~, isnai] = infsup ("1 2 xxx 4"); %! assert (isnai, [false, false, true, false]); %!warning %! [~, ~, ~, isnai] = infsup ("[-inf, inf] [inf, inf]"); %! assert (isnai, [false, true]); %!# N-dimensional arrays %!test %! x = infsup (zeros (2, 2, 2)); %! assert (x.inf, zeros (2, 2, 2)); %! assert (x.sup, zeros (2, 2, 2)); %!test %! x = infsup (zeros (2, 2, 2), ones (2, 2, 2)); %! assert (x.inf, zeros (2, 2, 2)); %! assert (x.sup, ones (2, 2, 2)); %!test %! x = infsup (zeros (2, 1, 2, 1, 2, 1), ones (1, 3, 1, 3, 1, 3)); %! assert (x.inf, zeros (2, 3, 2, 3, 2, 3)); %! assert (x.sup, ones (2, 3, 2, 3, 2, 3)); %!test %! c1 = reshape ({1, 2, 3, 4, 5, 6, 7, 8}, 2, 2, 2); %! c2 = reshape ({2, 3, 4, 5, 6, 7, 8, 9}, 2, 2, 2); %! x = infsup (c1, c2); %! assert (x.inf, reshape (1:8, 2, 2, 2)); %! assert (x.sup, reshape (2:9, 2, 2, 2)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.("b-numsToInterval"); %! for testcase = [testcases]' %! assert (isequaln (... %! infsup (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.("b-numsToInterval"); %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (infsup (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.("b-numsToInterval"); %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (infsup (in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.("b-textToInterval"); %! for testcase = [testcases]' %! assert (isequaln (... %! infsup (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.("b-textToInterval"); %! in1 = vertcat (testcases.in); %! out = vertcat (testcases.out); %! assert (isequaln (infsup (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.("b-numsToInterval"); %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (infsup (in1, in2), out)); %!warning %! testcases = testdata.PossiblyUndefinedOperation.infsup.("b-textToInterval"); %! for testcase = [testcases]' %! lastwarn ("", ""); %! assert (isequaln (... %! infsup (testcase.in{1}), ... %! testcase.out)); %! assert (nthargout (2, @lastwarn), "interval:PossiblyUndefinedOperation"); %! endfor %!warning %! testcases = testdata.UndefinedOperation.infsup.("b-textToInterval"); %! for testcase = [testcases]' %! lastwarn ("", ""); %! assert (isequaln (... %! infsup (testcase.in{1}), ... %! testcase.out)); %! assert (nthargout (2, @lastwarn), "interval:UndefinedOperation"); %! endfor %!warning %! testcases = testdata.UndefinedOperation.infsup.("b-numsToInterval"); %! for testcase = [testcases]' %! lastwarn ("", ""); %! assert (isequaln (... %! infsup (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! assert (nthargout (2, @lastwarn), "interval:UndefinedOperation"); %! endfor interval-3.2.0/inst/@infsup/interior.m0000644000000000000000000000555113316017127016067 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} interior (@var{A}, @var{B}) ## ## Evaluate interior comparison on intervals. ## ## True, if all numbers from @var{A} are also contained in @var{B}, but are no ## boundaries of @var{B}. False, if @var{A} contains a number which is not a ## member in @var{B} or which is a boundary of @var{B}. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/subset, @@infsup/disjoint} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function result = interior (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); endif result = ((b.inf < a.inf | (b.inf == -inf & a.inf == -inf)) & ... (a.sup < b.sup | (a.sup == inf & b.sup == inf))); result(isempty (a) & isempty (b)) = true (); endfunction %!assert (interior (infsup (1, 2), infsup (0, 3))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.interior; %! for testcase = [testcases]' %! assert (isequaln (... %! interior (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.interior; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (interior (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.interior; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (interior (in1, in2), out)); interval-3.2.0/inst/@infsup/intersect.m0000644000000000000000000001224013316017127016225 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} intersect (@var{A}) ## @defmethodx {@@infsup} intersect (@var{A}, @var{B}) ## @defmethodx {@@infsup} intersect (@var{A}, [], @var{DIM}) ## ## Intersect intervals. ## ## With two arguments the intersection is built pair-wise. Otherwise the ## intersection is computed for all interval members along dimension @var{DIM}, ## which defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (1, 3); ## y = infsup (2, 4); ## intersect (x, y) ## @result{} ans = [2, 3] ## @end group ## @end example ## @seealso{@@infsup/union, @@infsup/setdiff, @@infsup/setxor} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-02 function a = intersect (a, b, dim) if (not (isa (a, "infsup"))) a = infsup (a); endif switch (nargin) case 1 l = max (a.inf); u = min (a.sup); case 2 if (not (isa (b, "infsup"))) b = infsup (b); endif l = max (a.inf, b.inf); u = min (a.sup, b.sup); case 3 if (not (builtin ("isempty", b))) warning ("intersect: second argument is ignored"); endif l = max (a.inf, [], dim); u = min (a.sup, [], dim); otherwise print_usage (); return endswitch ## If the intervals do not intersect, the result must be empty. emptyresult = l > u; l(emptyresult) = inf; u(emptyresult) = -inf; a.inf = l; a.sup = u; endfunction %!# Empty interval %!assert (intersect (infsup (), infsup ()) == infsup ()); %!assert (intersect (infsup (), infsup (1)) == infsup ()); %!assert (intersect (infsup (0), infsup ()) == infsup ()); %!assert (intersect (infsup (-inf, inf), infsup ()) == infsup ()); %!# Singleton intervals %!assert (intersect (infsup (0), infsup (1)) == infsup ()); %!assert (intersect (infsup (0), infsup (0)) == infsup (0)); %!# Bounded intervals %!assert (intersect (infsup (1, 2), infsup (3, 4)) == infsup ()); %!assert (intersect (infsup (1, 2), infsup (2, 3)) == infsup (2)); %!assert (intersect (infsup (1, 2), infsup (1.5, 2.5)) == infsup (1.5, 2)); %!assert (intersect (infsup (1, 2), infsup (1, 2)) == infsup (1, 2)); %!# Unbounded intervals %!assert (intersect (infsup (0, inf), infsup (-inf, 0)) == infsup (0)); %!assert (intersect (infsup (1, inf), infsup (-inf, -1)) == infsup ()); %!assert (intersect (infsup (-1, inf), infsup (-inf, 1)) == infsup (-1, 1)); %!assert (intersect (infsup (-inf, inf), infsup (42)) == infsup (42)); %!assert (intersect (infsup (42), infsup (-inf, inf)) == infsup (42)); %!assert (intersect (infsup (-inf, 0), infsup (-inf, inf)) == infsup (-inf, 0)); %!assert (intersect (infsup (-inf, inf), infsup (-inf, inf)) == infsup (-inf, inf)); %!# from the documentation string %!assert (intersect (infsup (1, 3), infsup (2, 4)) == infsup (2, 3)); %!# correct use of signed zeros %!test %! x = intersect (infsup (0), infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = intersect (infsup (0), infsup (0, 1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = intersect (infsup (0, 1), infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = intersect (infsup (-1, 0), infsup (0, 1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.intersection; %! for testcase = [testcases]' %! assert (isequaln (... %! intersect (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.intersection; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (intersect (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.intersection; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (intersect (in1, in2), out)); interval-3.2.0/inst/@infsup/intervaltoexact.m0000644000000000000000000000301213316017127017436 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{S} =} intervaltoexact (@var{X}) ## ## Build an exact representation of the interval @var{X} in ## hexadecimal-significand form. ## ## The interval boundaries are stored in binary floating point format and can ## be converted to hexadecimal format without precision loss. ## ## The equation @code{@var{X} == exacttointerval (intervaltoexact (@var{X}))} ## holds for all intervals @var{X}. ## ## Accuracy: The output is exact. ## @seealso{exacttointerval} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-01 function s = intervaltoexact (x) if (nargin ~= 1) print_usage (); return endif s = intervaltotext (x, "exact hexadecimal"); endfunction %!assert (intervaltoexact (infsup (1 + eps)), "[0x1.0000000000001p+0]"); interval-3.2.0/inst/@infsup/inv.m0000644000000000000000000000406013316017127015022 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} inv (@var{A}) ## ## Compute the inverse of the square matrix @var{A}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## inv (infsup ([2, 1, 1; 0, 1, 0; 1, 0, 0])) ## @result{} ans = 3×3 interval matrix ## [0] [0] [1] ## [0] [1] [0] ## [1] [-1] [-2] ## inv (infsup ([1, 2, 3; 4, 0, 6; 0, 0, 1])) ## @result{} ans = 3×3 interval matrix ## [0] [0.25] [-1.5] ## [0.5] [-0.125] [-0.75] ## [0] [0] [1] ## @end group ## @end example ## @seealso{@@infsup/mrdivide} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-31 function result = inv (x) if (nargin ~= 1) print_usage (); return endif n = length (x); if (n <= 1) result = rdivide (1, x); return endif result = mldivide (x, eye (n)); endfunction %!# from the wiki %!test %! A = infsup ([1, 2, 3; 4, 0, 0; 0, 0, 1]); %! A (2, 3) = "[0, 6]"; %! B = inv (A); %! assert (inf (B) == [0, .25, -1.5; .5, -.125, -1.5; 0, 0, 1]); %! assert (sup (B) == [0, .25, 0; .5, -.125, -.75; 0, 0, 1]); %!# from the documentation string %!assert (inv (infsup ([2, 1, 1; 0, 1, 0; 1, 0, 0])) == [0, 0, 1; 0, 1, 0; 1, -1, -2]); %!assert (inv (infsup ([1, 2, 3; 4, 0, 6; 0, 0, 1])) == [0, .25, -1.5; .5, -.125, -.75; 0, 0, 1]); interval-3.2.0/inst/@infsup/iscolumn.m0000644000000000000000000000260313316017127016060 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} iscolumn (@var{A}) ## ## Return true if @var{A} is an interval column vector. ## ## @seealso{@@infsup/isvector, @@infsup/isrow} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-18 ## FIXME This function is only required, because of a regression in octave 4.0 function result = iscolumn (A) if (nargin ~= 1) print_usage (); return endif result = iscolumn (A.inf); endfunction %!assert (not (iscolumn (infsup ([])))); %!assert (iscolumn (infsup (0))); %!assert (not (iscolumn (infsup (zeros (1, 2))))); %!assert (iscolumn (infsup (zeros (2, 1)))); %!assert (not (iscolumn (infsup (zeros (5))))); interval-3.2.0/inst/@infsup/iscommoninterval.m0000644000000000000000000000760613316017127017630 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} iscommoninterval (@var{X}) ## ## Check if the interval is a common interval, that is a nonemty, closed ## bounded real interval. ## ## Common intervals are used in class Moore interval arithmetic and are ## flavor-independent in IEEE Std 1788-2015 interval arithmetic. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/isentire, @@infsup/isempty, @@infsup/issingleton} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-23 function result = iscommoninterval (x) if (nargin ~= 1) print_usage (); return endif result = isfinite (x.inf) & isfinite (x.sup); endfunction %!assert (iscommoninterval (infsup (2, 3))); %!assert (not (iscommoninterval (infsup (2, inf)))); %!assert (not (iscommoninterval (infsup ()))); %!assert (not (iscommoninterval (infsup (-inf, inf)))); %!assert (iscommoninterval (infsupdec (2, 3, "com"))); %!assert (iscommoninterval (infsupdec (2, 3, "trv"))); %!assert (not (iscommoninterval (infsupdec (2, inf, "trv")))); %!assert (not (iscommoninterval (empty ()))); %!assert (not (iscommoninterval (entire ()))); %!warning assert (not (iscommoninterval (infsupdec (2, 1)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.isCommonInterval; %! for testcase = [testcases]' %! assert (isequaln (... %! iscommoninterval (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.isCommonInterval; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (iscommoninterval (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.isCommonInterval; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (iscommoninterval (in1), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.isCommonInterval; %! for testcase = [testcases]' %! assert (isequaln (... %! iscommoninterval (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.isCommonInterval; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (iscommoninterval (in1), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.isCommonInterval; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (iscommoninterval (in1), out)); interval-3.2.0/inst/@infsup/isempty.m0000644000000000000000000000450313316017127015722 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} isempty (@var{X}) ## ## Check if the interval represents the empty set. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## Warning: This function is not compatible with the builtin @code{isempty} ## function. ## ## @seealso{@@infsup/eq, @@infsup/isentire, @@infsup/issingleton} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-27 function result = isempty (x) if (nargin ~= 1) print_usage (); return endif result = (x.inf > x.sup); endfunction %!assert (isempty (infsup ())); %!assert (not (isempty (infsup (1, 2)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.isEmpty; %! for testcase = [testcases]' %! assert (isequaln (... %! isempty (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.isEmpty; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (isempty (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.isEmpty; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (isempty (in1), out)); interval-3.2.0/inst/@infsup/isentire.m0000644000000000000000000000645313316017127016060 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} isentire (@var{X}) ## ## Check if the interval represents the entire set of real numbers. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{entire, @@infsup/eq, @@infsup/isempty, @@infsup/issingleton} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-27 function result = isentire (x) if (nargin ~= 1) print_usage (); return endif result = (x.inf == -inf & x.sup == inf); endfunction %!assert (isentire (entire ())); %!assert (isentire (intervalpart (entire ()))); %!assert (not (isentire (empty ()))); %!assert (not (isentire (intervalpart (empty ())))); %!warning assert (not (isentire (infsupdec (2, 1)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.isEntire; %! for testcase = [testcases]' %! assert (isequaln (... %! isentire (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.isEntire; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (isentire (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.isEntire; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (isentire (in1), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.isEntire; %! for testcase = [testcases]' %! assert (isequaln (... %! isentire (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.isEntire; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (isentire (in1), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.isEntire; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (isentire (in1), out)); interval-3.2.0/inst/@infsup/ismatrix.m0000644000000000000000000000262413316017127016072 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} ismatrix (@var{A}) ## ## Return true if @var{A} is a 2-D interval array. ## ## @seealso{@@infsup/isscalar, @@infsup/isvector} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 ## FIXME: One happy day this function can be removed, because bug #42422 has ## been solved with GNU Octave 4.0. function result = ismatrix (A) if (nargin ~= 1) print_usage (); return endif result = ismatrix (A.inf); endfunction %!assert (ismatrix (infsup ([]))); %!assert (ismatrix (infsup (0))); %!assert (ismatrix (infsup (zeros (3, 1)))); %!assert (ismatrix (infsup (zeros (1, 4)))); %!assert (ismatrix (infsup (zeros (3, 4)))); interval-3.2.0/inst/@infsup/ismember.m0000644000000000000000000001024613316017127016034 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} ismember (@var{M}, @var{X}) ## ## Check if the interval @var{X} contains the number @var{M}. ## ## The number can be a numerical data type or a string representation of a ## decimal number. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/isentire, @@infsup/issingleton, @@infsup/isempty} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = ismember (real, interval) if (nargin ~= 2) print_usage (); return endif if (not (isa (interval, "infsup"))) interval = infsup (interval); endif if (isreal (real) && isfloat (real)) ## Simple checking is only possible with floating point numbers result = isfinite (real) & interval.inf <= real & real <= interval.sup; else ## Mixed mode comparison between integers and floats can be problematic ## as well as comparison with decimal numbers result = subset (infsup (real), interval); endif endfunction %!assert (ismember (0, entire ())); %!assert (ismember (0, intervalpart (entire ()))); %!assert (not (ismember (0, empty ()))); %!assert (not (ismember (0, intervalpart (empty ())))); %!warning assert (not (ismember (0, infsupdec (2, 1)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.isMember; %! for testcase = [testcases]' %! assert (isequaln (... %! ismember (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.isMember; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (ismember (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.isMember; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (ismember (in1, in2), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.isMember; %! for testcase = [testcases]' %! assert (isequaln (... %! ismember (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.isMember; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (ismember (in1, in2), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.isMember; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (ismember (in1, in2), out)); interval-3.2.0/inst/@infsup/isrow.m0000644000000000000000000000255313316017127015376 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} isrow (@var{A}) ## ## Return true if @var{A} is an interval row vector. ## ## @seealso{@@infsup/isvector, @@infsup/iscolumn} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-18 ## FIXME This function is only required, because of a regression in octave 4.0 function result = isrow (A) if (nargin ~= 1) print_usage (); return endif result = isrow (A.inf); endfunction %!assert (not (isrow (infsup ([])))); %!assert (isrow (infsup (0))); %!assert (isrow (infsup (zeros (1, 2)))); %!assert (not (isrow (infsup (zeros (2, 1))))); %!assert (not (isrow (infsup (zeros (5))))); interval-3.2.0/inst/@infsup/isscalar.m0000644000000000000000000000303213316017127016025 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} isscalar (@var{A}) ## ## Return true if @var{A} is an interval scalar. ## ## Scalars (1x1 matrices) are subsets of the more general vector or matrix and ## @code{isvector} and @code{ismatrix} will return true for these objects as ## well. ## @seealso{@@infsup/isvector, @@infsup/ismatrix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-02 ## FIXME This function is only required, because of bug #43925 function result = isscalar (A) if (nargin ~= 1) print_usage (); return endif result = isscalar (A.inf); endfunction %!assert (not (isscalar (infsup ([])))); %!assert (isscalar (infsup (0))); %!assert (not (isscalar (infsup (zeros (1, 2))))); %!assert (not (isscalar (infsup (zeros (2, 1))))); %!assert (not (isscalar (infsup (zeros (5))))); interval-3.2.0/inst/@infsup/issingleton.m0000644000000000000000000000675313316017127016577 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} issingleton (@var{X}) ## ## Check if the interval represents a set that contains a single real only. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/isentire, @@infsup/isempty} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function result = issingleton (x) if (nargin ~= 1) print_usage (); return endif ## This check also works for empty intervals (-inf ~= +inf) result = (x.inf == x.sup); endfunction %!assert (issingleton (infsup (0))); %!assert (issingleton (infsupdec (0))); %!assert (not (issingleton (entire ()))); %!assert (not (issingleton (intervalpart (entire ())))); %!assert (not (issingleton (empty ()))); %!assert (not (issingleton (intervalpart (empty ())))); %!warning assert (not (issingleton (infsupdec (2, 1)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.isSingleton; %! for testcase = [testcases]' %! assert (isequaln (... %! issingleton (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.isSingleton; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (issingleton (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.isSingleton; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (issingleton (in1), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.isSingleton; %! for testcase = [testcases]' %! assert (isequaln (... %! issingleton (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.isSingleton; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (issingleton (in1), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.isSingleton; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (issingleton (in1), out)); interval-3.2.0/inst/@infsup/issquare.m0000644000000000000000000000262213316017127016064 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} issquare (@var{A}) ## ## Return true if @var{A} is a square interval matrix. ## ## @seealso{@@infsup/isvector, @@infsup/ismatrix, @@infsup/isscalar} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-18 ## FIXME This function is only required, because of a regression in octave 4.0 function result = issquare (A) if (nargin ~= 1) print_usage (); return endif result = issquare (A.inf); endfunction %!assert (issquare (infsup ([]))); %!assert (issquare (infsup (0))); %!assert (not (issquare (infsup (zeros (1, 2))))); %!assert (not (issquare (infsup (zeros (2, 1))))); %!assert (issquare (infsup (zeros (5)))); interval-3.2.0/inst/@infsup/isvector.m0000644000000000000000000000276313316017127016074 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} isvector (@var{A}) ## ## Return true if @var{A} is an interval vector. ## ## Scalars (1x1 vectors) are subsets of the more general vector and ## @code{isvector} will return true for these objects as well. ## @seealso{@@infsup/isscalar, @@infsup/ismatrix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-02 ## FIXME This function is only required, because of regression #44498 function result = isvector (A) if (nargin ~= 1) print_usage (); return endif result = isvector (A.inf); endfunction %!assert (not (isvector (infsup ([])))); %!assert (isvector (infsup (0))); %!assert (isvector (infsup (zeros (1, 2)))); %!assert (isvector (infsup (zeros (2, 1)))); %!assert (not (isvector (infsup (zeros (5))))); interval-3.2.0/inst/@infsup/ldivide.m0000644000000000000000000000266013316017127015652 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} ldivide (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} .\ @var{Y}} ## ## Divide all numbers of interval @var{Y} by all numbers of @var{X}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (2, 3); ## y = infsup (1, 2); ## x .\ y ## @result{} ans ⊂ [0.33333, 1] ## @end group ## @end example ## @seealso{@@infsup/times} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function result = ldivide (x, y) if (nargin ~= 2) print_usage (); return endif result = rdivide (y, x); endfunction %!# from the documentation string %!assert (ldivide (infsup (2, 3), infsup (1, 2)) == "[1/3, 1]"); interval-3.2.0/inst/@infsup/le.m0000644000000000000000000000554013316017127014632 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} le (@var{A}, @var{B}) ## @defopx Operator {@@infsup} {@var{A} <= @var{B}} ## ## Compare intervals @var{A} and @var{B} for weakly less. ## ## True, if all numbers from @var{A} are weakly less than any number in ## @var{B}. False, if @var{A} contains a number which is strictly greater than ## all numbers in @var{B}. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/lt, @@infsup/ge, @@infsup/subset, @@infsup/interior, @@infsup/disjoint} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function result = le (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); elseif (isa (b, "infsupdec")) ## Workaround for bug #42735 result = le (a, b); return endif result = (a.inf <= b.inf & a.sup <= b.sup); endfunction %!assert (le (infsup (1, 3), infsup (3))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.less; %! for testcase = [testcases]' %! assert (isequaln (... %! le (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.less; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (le (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.less; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (le (in1, in2), out)); interval-3.2.0/inst/@infsup/length.m0000644000000000000000000000273013316017127015511 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} length (@var{A}) ## ## Return the length of interval object @var{A}. ## ## The length is 0 for empty objects, 1 for scalars, and the number of ## elements for vectors. For matrix or N-dimensional objects, the ## length is the number of elements along the largest dimension. ## @seealso{@@infsup/numel, @@infsup/size, @@infsup/rows, @@infsup/columns, @@infsup/end} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function result = length (a) result = length (a.inf); endfunction %!assert (length (infsup ([])), 0); %!assert (length (infsup (0)), 1); %!assert (length (infsup (zeros (3, 1))), 3); %!assert (length (infsup (zeros (1, 4))), 4); %!assert (length (infsup (zeros (3, 4))), 4); interval-3.2.0/inst/@infsup/linspace.m0000644000000000000000000000456713316017127016040 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} linspace (@var{BASE}, @var{LIMIT}) ## @defmethodx {@@infsup} linspace (@var{BASE}, @var{LIMIT}, @var{N}) ## ## Return a row vector of @var{N} linearly spaced members between @var{BASE} ## and @var{LIMIT}. ## ## If @var{BASE} is greater than @var{LIMIT}, members are returned in ## decreasing order. The default value for @var{N} is 100. ## ## If either @var{BASE} or @var{LIMIT} is not a scalar, the result is a matrix. ## ## Accuracy: The result is an accurate enclosure. ## ## @example ## @group ## transpose (linspace (infsup (0), infsup (10), 4)) ## @result{} ans ⊂ 4×1 interval vector ## ## [0] ## [3.3333, 3.3334] ## [6.6666, 6.6667] ## [10] ## @end group ## @end example ## @seealso{linspace} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-07-19 function base = linspace (base, limit, n) if (nargin < 2 || nargin > 3) print_usage (); return endif if (not (isa (base, "infsup"))) base = infsup (base); endif if (not (isa (limit, "infsup"))) limit = infsup (limit); endif if (nargin < 3) n = 100; endif l = mpfr_linspace_d (-inf, base.inf, limit.inf, n); u = mpfr_linspace_d (+inf, base.sup, limit.sup, n); empty = vec (isempty (base) | isempty (limit)); l(empty, :) = inf; u(empty, :) = -inf; l(l == 0) = -0; base.inf = l; base.sup = u; endfunction %!assert (isequal (linspace (infsup (0), infsup (10), 9), infsup (linspace (0, 10, 9)))); %!# correct use of signed zeros %!test %! x = linspace (infsup (0), infsup (0)); %! assert (all (signbit (inf (x)))); %! assert (all (not (signbit (sup (x))))); interval-3.2.0/inst/@infsup/log.m0000644000000000000000000000571713316017127015021 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} log (@var{X}) ## ## Compute the natural logarithm. ## ## The function is only defined where @var{X} is positive. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## log (infsup (2)) ## @result{} ans ⊂ [0.69314, 0.69315] ## @end group ## @end example ## @seealso{@@infsup/exp, @@infsup/log2, @@infsup/log10} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = log (x) if (nargin ~= 1) print_usage (); return endif x = intersect (x, infsup (0, inf)); ## log is monotonically increasing from (0, -inf) to (inf, inf) if (__check_crlibm__ ()) l = crlibm_function ('log', -inf, x.inf); # this works for empty intervals u = crlibm_function ('log', +inf, x.sup); # ... this does not else l = mpfr_function_d ('log', -inf, x.inf); # this works for empty intervals u = mpfr_function_d ('log', +inf, x.sup); # ... this does not endif l(x.sup == 0) = inf; l(l == 0) = -0; u(isempty (x) | x.sup == 0) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (log (infsup (2)) == "[0x1.62E42FEFA39EFp-1, 0x1.62E42FEFA39Fp-1]"); %!# correct use of signed zeros %!test %! x = log (infsup (1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.log; %! for testcase = [testcases]' %! assert (isequaln (... %! log (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.log; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (log (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.log; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (log (in1), out)); interval-3.2.0/inst/@infsup/log10.m0000644000000000000000000000577213316017127015163 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} log10 (@var{X}) ## ## Compute the decimal (base-10) logarithm. ## ## The function is only defined where @var{X} is positive. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## log10 (infsup (2)) ## @result{} ans ⊂ [0.30102, 0.30103] ## @end group ## @end example ## @seealso{@@infsup/pow10, @@infsup/log, @@infsup/log2} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = log10 (x) if (nargin ~= 1) print_usage (); return endif x = intersect (x, infsup (0, inf)); ## log10 is monotonically increasing from (0, -inf) to (inf, inf) if (__check_crlibm__ ()) l = crlibm_function ('log10', -inf, x.inf); # this works for empty intervals u = crlibm_function ('log10', +inf, x.sup); # ... this does not else l = mpfr_function_d ('log10', -inf, x.inf); # this works for empty intervals u = mpfr_function_d ('log10', +inf, x.sup); # ... this does not endif l(x.sup == 0) = inf; l(l == 0) = -0; u(isempty (x) | x.sup == 0) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (log10 (infsup (2)) == "[0x1.34413509F79FEp-2, 0x1.34413509F79FFp-2]"); %!# correct use of signed zeros %!test %! x = log10 (infsup (1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.log10; %! for testcase = [testcases]' %! assert (isequaln (... %! log10 (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.log10; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (log10 (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.log10; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (log10 (in1), out)); interval-3.2.0/inst/@infsup/log1p.m0000644000000000000000000000602013316017127015246 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} log1p (@var{X}) ## ## Compute @code{log (1 + @var{X})} accurately in the neighborhood of zero. ## ## The function is only defined where @var{X} is greater than -1. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## log1p (infsup (eps)) ## @result{} ans ⊂ [2.2204e-16, 2.2205e-16] ## @end group ## @end example ## @seealso{@@infsup/exp, @@infsup/log} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-20 function x = log1p (x) if (nargin ~= 1) print_usage (); return endif x = intersect (x, infsup (-1, inf)); ## log is monotonically increasing from (-1, -inf) to (inf, inf) if (__check_crlibm__ ()) l = crlibm_function ('log1p', -inf, x.inf); # this works for empty intervals u = crlibm_function ('log1p', +inf, x.sup); # ... this does not else l = mpfr_function_d ('log1p', -inf, x.inf); # this works for empty intervals u = mpfr_function_d ('log1p', +inf, x.sup); # ... this does not endif l(x.sup == -1) = inf; l(l == 0) = -0; u(isempty (x) | x.sup == -1) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (log1p (infsup (eps)) == "[0x1.FFFFFFFFFFFFFp-53, 0x1p-52]"); %!# correct use of signed zeros %!test %! x = log1p (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.logp1; %! for testcase = [testcases]' %! assert (isequaln (... %! log1p (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.logp1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (log1p (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.logp1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (log1p (in1), out)); interval-3.2.0/inst/@infsup/log2.m0000644000000000000000000000565213316017127015101 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} log2 (@var{X}) ## ## Compute the binary (base-2) logarithm. ## ## The function is only defined where @var{X} is positive. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## log2 (infsup (2)) ## @result{} ans = [1] ## @end group ## @end example ## @seealso{@@infsup/pow2, @@infsup/log, @@infsup/log10} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = log2 (x) if (nargin ~= 1) print_usage (); return endif x = intersect (x, infsup (0, inf)); ## log2 is monotonically increasing from (0, -inf) to (inf, inf) if (__check_crlibm__ ()) l = crlibm_function ('log2', -inf, x.inf); # this works for empty intervals u = crlibm_function ('log2', +inf, x.sup); # ... this does not else l = mpfr_function_d ('log2', -inf, x.inf); # this works for empty intervals u = mpfr_function_d ('log2', +inf, x.sup); # ... this does not endif l(x.sup == 0) = inf; l(l == 0) = -0; u(isempty (x) | x.sup == 0) = -inf; x.sup = u; x.inf = l; endfunction %!# from the documentation string %!assert (log2 (infsup (2)) == 1); %!# correct use of signed zeros %!test %! x = log2 (infsup (1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.log2; %! for testcase = [testcases]' %! assert (isequaln (... %! log2 (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.log2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (log2 (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.log2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (log2 (in1), out)); interval-3.2.0/inst/@infsup/lt.m0000644000000000000000000000613113316017127014646 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} lt (@var{A}, @var{B}) ## @defopx Operator {@@infsup} {@var{A} < @var{B}} ## ## Compare intervals @var{A} and @var{B} for strictly less. ## ## True, if all numbers from @var{A} are strict less than at least one number ## in @var{B}. False, if @var{A} contains a number which is greater than all ## numbers in @var{B} or is equal to the greatest number of @var{B}. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/le, @@infsup/gt, @@infsup/subset, @@infsup/interior, @@infsup/disjoint} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function result = lt (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); elseif (isa (b, "infsupdec")) ## Workaround for bug #42735 result = lt (a, b); return endif result = ((a.inf < b.inf | (a.inf == -inf & b.inf == -inf)) & ... (a.sup < b.sup | (a.sup == inf & b.sup == inf))); result (isempty (a) & isempty (b)) = true (); endfunction %!assert (not (lt (infsup (1, 3), infsup (3)))); %!assert (lt (infsup (1, 3), infsup (3.1))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.strictLess; %! for testcase = [testcases]' %! assert (isequaln (... %! lt (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.strictLess; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (lt (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.strictLess; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (lt (in1, in2), out)); interval-3.2.0/inst/@infsup/lu.m0000644000000000000000000001412713316017127014653 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {[@var{L}, @var{U}] = } lu (@var{A}) ## @deftypemethodx {@@infsup} {[@var{L}, @var{U}, @var{P}] = } lu (@var{A}) ## ## Compute the LU decomposition of @var{A}. ## ## @var{A} will be a subset of @var{L} * @var{U} with lower triangular matrix ## @var{L} and upper triangular matrix @var{U}. ## ## The result is returned in a permuted form, according to the optional return ## value @var{P}. ## ## Accuracy: The result is a valid enclosure. ## @seealso{@@infsup/qr, @@infsup/chol} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-31 function [L, U, P] = lu (x) if (nargin ~= 1) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (isscalar (x)) L = P = eye (size (x)); U = x; return endif ## x must be square assert (issquare (x.inf), ... "operator \: nonconformant arguments, X is not square"); n = rows (x.inf); if (nargout < 3) P = eye (n); else ## Compute P such that the computation of L below will not fail because of ## division by zero. P * x should not have zeros in its main diagonal. ## The computation of P is a greedy heuristic algorithm, which I developed ## for the implementation of this function. P = zeros (n); migU = mig (x); magU = mag (x); ## Empty intervals are as bad as intervals containing only zero. migU (isnan (migU)) = 0; magU (isnan (magU)) = 0; for i = 1 : n ## Choose next pivot in one of the columns with the fewest mig (U) > 0. columnrating = sum (migU > 0, 1); ## Don't choose used columns columnrating(max (migU, [], 1) == inf) = inf; ## Use first possible column possiblecolumns = columnrating == min (columnrating); column = find (possiblecolumns, 1); if (columnrating(column) >= 1) ## Greedy: Use only intervals that do not contain zero. possiblerows = migU(:, column) > 0; else ## Only intervals left which contain zero. Try to use an interval ## that additionally contains other numbers. possiblerows = migU(:, column) >= 0 & magU(:, column) > 0; if (not (max (possiblerows))) ## All possible intervals contain only zero. possiblerows = migU(:, column) >= 0; endif endif if (sum (possiblerows) == 1) ## Short-ciruit: Take the only remaining useful row row = find (possiblerows, 1); else ## There are several good choices, take the one that will hopefully ## not hinder the choice of further pivot elements. ## That is, the row with the least mig (U) > 0. rowrating = sum (migU > 0, 2); ## We weight the rating in the columns with few mig (U) > 0 in ## order to prevent problems during the choice of pivots in the ## near future. rowrating += 0.5 * sum (migU(:, possiblecolumns) > 0, 2); rowrating (not (possiblerows)) = inf; row = find (rowrating == min (rowrating), 1); endif # assert (0 <= migU (row, column) && migU (row, column) < inf); P(row, column) = 1; ## In mig (U), for the choice of further pivots: ## - mark used columns with inf ## - mark used rows in unused columns with -inf migU(row, :) -= inf; migU(isnan (migU)) = inf; migU(:, column) = inf; endfor endif ## Initialize L and U L = infsup (eye (n)); U = permute (P, x); ## Compute L and U varidx.type = rowstart.type = Urefrow.type = Urow.type = "()"; for i = 1 : (n - 1) varidx.subs = {i, i}; Urefrow.subs = {i, i : n}; ## Go through rows of the remaining matrix for k = (i + 1) : n rowstart.subs = {k, i}; ## Compute L Lcurrentelement = mulrev (subsref (U, varidx), subsref (U, rowstart)); L = subsasgn (L, rowstart, Lcurrentelement); ## Go through columns of the remaining matrix Urow.subs = {k, i : n}; ## Compute U minuend = subsref (U, Urow); subtrahend = Lcurrentelement .* subsref (U, Urefrow); U = subsasgn (U, Urow, minuend - subtrahend); endfor endfor ## Cleanup U U.inf = triu (U.inf); U.sup = triu (U.sup); endfunction ## Apply permutation matrix P to an interval matrix: B = P * A. ## This is much faster than a matrix product, because the matrix product would ## use a lot of dot products. function B = permute (P, A) ## Note: [B.inf, B.sup] = deal (P * A.inf, P * A.sup) is not possible, ## because empty or unbound intervals would create NaNs during ## multiplication with P. B = A; for i = 1 : rows (P) targetrow = find (P(i, :) == 1, 1); B.inf(targetrow, :) = A.inf(i, :); B.sup(targetrow, :) = A.sup(i, :); endfor endfunction %!test %! [l, u] = lu (infsup (magic (3))); %! assert (l == infsup ({1, 0, 0; .375, 1, 0; .5, "68/37", 1}));, ... %! assert (subset (u, infsup ({8, 1, 6; 0, 4.625, 4.75; 0, 0, "-0x1.3759F2298375Bp3"}, ... %! {8, 1, 6; 0, 4.625, 4.75; 0, 0, "-0x1.3759F22983759p3"}))); %!test %! A = magic (3); %! A([1, 5, 9]) = 0; %! [l, u, p] = lu (infsup (A)); %! assert (p, [0, 0, 1; 1, 0, 0; 0, 1, 0]); %! assert (l == infsup ({1, 0, 0; "4/3", 1, 0; 0, "1/9", 1})); %! assert (subset (u, infsup ({3, 0, 7; 0, 9, "-0x1.2AAAAAAAAAAACp3"; 0, 0, "0x1.C25ED097B425Ep2"}, ... %! {3, 0, 7; 0, 9, "-0x1.2AAAAAAAAAAAAp3"; 0, 0, "0x1.C25ED097B426p2"}))); interval-3.2.0/inst/@infsup/mag.m0000644000000000000000000000635113316017127014777 0ustar 00000000000000## Copyright 2014-2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} mag (@var{X}) ## ## Get the magnitude of numbers in interval @var{X}, that is the maximum of ## absolute values for each element. ## ## If @var{X} is empty, @code{mag (@var{X})} is NaN. ## ## Accuracy: The result is exact. ## ## @example ## @group ## mag (infsup (-3, 2)) ## @result{} ans = 3 ## @end group ## @end example ## @seealso{@@infsup/mig, @@infsup/smig, @@infsup/inf, @@infsup/sup} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function result = mag (x) if (nargin ~= 1) print_usage (); return endif result = max (abs (x.inf), abs (x.sup)); result(x.inf > x.sup) = nan (); endfunction %!assert (mag (infsup (-3, 4)), 4); %!assert (mag (infsup (-4, 3)), 4); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.mag; %! for testcase = [testcases]' %! assert (isequaln (... %! mag (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.mag; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (mag (in1), out)); %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.mag; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mag (in1), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.mag; %! for testcase = [testcases]' %! assert (isequaln (... %! mag (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.mag; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (mag (in1), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.mag; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mag (in1), out)); interval-3.2.0/inst/@infsup/max.m0000644000000000000000000000702713316017127015021 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} max (@var{X}) ## @defmethodx {@@infsup} max (@var{X}, @var{Y}) ## @defmethodx {@@infsup} max (@var{X}, [], @var{DIM}) ## ## Compute the maximum value chosen from intervals. ## ## This function does not return the greatest element of the interval (see ## @code{sup}), but returns an interval enclosure of the function: ## @display ## max (@var{x}, @var{y}) = ( (x + y) + abs (x - y) ) / 2 ## @end display ## ## With two arguments the function is applied element-wise. Otherwise the ## maximum is computed for all interval members along dimension @var{DIM}, ## which defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (2, 3); ## y = infsup (1, 2); ## max (x, y) ## @result{} ans = [2, 3] ## @end group ## @end example ## @seealso{@@infsup/min} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = max (x, y, dim) if (not (isa (x, "infsup"))) x = infsup (x); endif switch (nargin) case 1 l = max (x.inf); u = max (x.sup); u(any (isempty (x))) = -inf; case 2 if (not (isa (y, "infsup"))) y = infsup (y); endif l = max (x.inf, y.inf); u = max (x.sup, y.sup); u(isempty (x) | isempty (y)) = -inf; case 3 if (not (builtin ("isempty", y))) warning ("max: second argument is ignored"); endif l = max (x.inf, [], dim); u = max (x.sup, [], dim); u(any (isempty (x), dim)) = -inf; otherwise print_usage (); return endswitch x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (max (infsup (2, 3), infsup (1, 2)) == infsup (2, 3)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.max; %! for testcase = [testcases]' %! assert (isequaln (... %! max (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.max; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (max (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.max; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (max (in1, in2), out)); interval-3.2.0/inst/@infsup/mid.m0000644000000000000000000001002713316017127014777 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} mid (@var{X}) ## ## Get the midpoint of interval @var{X}. ## ## If @var{X} is empty, @code{mid (@var{X})} is NaN. ## If @var{X} is entire, @code{mid (@var{X})} is 0. ## If @var{X} is unbounded in one direction, @code{mid (@var{X})} is positive ## or negative @code{realmax ()}. ## ## Accuracy: The result is rounded to the nearest floating point number and ## may thus be exact or not. However, it is guaranteed that the interval ## @var{X} is tightly enclosed by ## @code{[mid (@var{X}) - rad (@var{X}), mid (@var{X}) + rad (@var{X})]}. ## ## @example ## @group ## mid (infsup (2.5, 3.5)) ## @result{} ans = 3 ## @end group ## @end example ## @seealso{@@infsup/inf, @@infsup/sup, @@infsup/rad} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-05 function result = mid (x) if (nargin ~= 1) print_usage (); return endif ## First divide by 2 and then add, because this will prevent overflow. ## The different rounding modes for division will make errors of 2^-1075 ## with subnormal numbers cancel each other out, or will make the round ## to nearest prefer the side that had an underflow error. l = mpfr_function_d ('rdivide', -inf, x.inf, 2); u = mpfr_function_d ('rdivide', +inf, x.sup, 2); result = l + u; result(x.inf == -inf) = -realmax (); result(x.sup == inf) = realmax (); result(isentire (x)) = 0; result(isempty (x)) = nan (); endfunction %!assert (mid (infsup (-inf, inf)), 0); %!# from the documentation string %!assert (mid (infsup (2.5, 3.5)), 3); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.mid; %! for testcase = [testcases]' %! assert (isequaln (... %! mid (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.mid; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (mid (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.mid; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mid (in1), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.mid; %! for testcase = [testcases]' %! assert (isequaln (... %! mid (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.mid; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (mid (in1), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.mid; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mid (in1), out)); interval-3.2.0/inst/@infsup/mig.m0000644000000000000000000000637213316017127015012 0ustar 00000000000000## Copyright 2014-2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} mig (@var{X}) ## ## Get the mignitude of numbers in interval @var{X}, that is the minimum of ## absolute values for each element. ## ## If @var{X} is empty, @code{mig (@var{X})} is NaN. ## ## Accuracy: The result is exact. ## ## @example ## @group ## mig (infsup (-2, -1)) ## @result{} ans = 1 ## @end group ## @end example ## @seealso{@@infsup/mag, @@infsup/inf, @@infsup/sup} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function result = mig (x) if (nargin ~= 1) print_usage (); return endif result = min (abs (x.inf), abs (x.sup)); result(sign (x.inf) ~= sign (x.sup)) = 0; result(x.inf > x.sup) = nan (); endfunction %!assert (mig (infsup (-1, 2)), 0); %!assert (mig (infsup (-42, -23)), 23); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.mig; %! for testcase = [testcases]' %! assert (isequaln (... %! mig (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.mig; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (mig (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.mig; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mig (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.mig; %! for testcase = [testcases]' %! assert (isequaln (... %! mig (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.mig; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (mig (in1), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.mig; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mig (in1), out)); interval-3.2.0/inst/@infsup/min.m0000644000000000000000000000702113316017127015011 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} min (@var{X}) ## @defmethodx {@@infsup} min (@var{X}, @var{Y}) ## @defmethodx {@@infsup} min (@var{X}, [], @var{DIM}) ## ## Compute the minimum value chosen from intervals. ## ## This function does not return the least element of the interval (see ## @code{inf}), but returns an interval enclosure of the function: ## @display ## min (@var{x}, @var{y}) = ( (x + y) - abs (x - y) ) / 2 ## @end display ## ## With two arguments the function is applied element-wise. Otherwise the ## minimum is computed for all interval members along dimension @var{DIM}, ## which defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (2, 3); ## y = infsup (1, 2); ## min (x, y) ## @result{} ans = [1, 2] ## @end group ## @end example ## @seealso{@@infsup/max} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = min (x, y, dim) if (not (isa (x, "infsup"))) x = infsup (x); endif switch (nargin) case 1 l = min (x.inf); u = min (x.sup); l(any (isempty (x))) = inf; case 2 if (not (isa (y, "infsup"))) y = infsup (y); endif l = min (x.inf, y.inf); u = min (x.sup, y.sup); l(isempty (x) | isempty (y)) = inf; case 3 if (not (builtin ("isempty", y))) warning ("min: second argument is ignored"); endif l = min (x.inf, [], dim); u = min (x.sup, [], dim); l(any (isempty (x), dim)) = inf; otherwise print_usage (); return endswitch x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (min (infsup (2, 3), infsup (1, 2)) == infsup (1, 2)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.min; %! for testcase = [testcases]' %! assert (isequaln (... %! min (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.min; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (min (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.min; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (min (in1, in2), out)); interval-3.2.0/inst/@infsup/mince.m0000644000000000000000000000424113316017127015322 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} mince (@var{X}) ## @defmethodx {@@infsup} mince (@var{X}, @var{N}) ## ## Mince interval @var{X} into a row vector of @var{N} sub-intervals of equal ## size. ## ## The sub-intervals are returned in ascending order and may overlap due to ## round-off errors. ## ## If @var{X} is not a scalar, the result is a matrix. The default value for ## @var{N} is 100. ## ## Accuracy: The result is an accurate enclosure. ## ## @example ## @group ## mince (infsup (0, 10), 4) ## @result{} ans = 1×4 interval vector ## ## [0, 2.5] [2.5, 5] [5, 7.5] [7.5, 10] ## @end group ## @end example ## @seealso{@@infsup/linspace, @@infsup/bisect} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-07-19 function x = mince (x, n) if (nargin > 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (nargin < 2) n = 100; endif base = limit = x; idx.type = '()'; idx.subs = {isfinite(x.inf)}; base = subsasgn (base, idx, infsup (subsref (x.inf, idx))); idx.subs = {isfinite(x.sup)}; limit = subsasgn (limit, idx, infsup (subsref (x.sup, idx))); boundaries = linspace (base, limit, n + 1); l = boundaries.inf(:, 1 : end - 1); u = boundaries.sup(:, 2 : end); empty = vec (isempty (x)); l(empty, :) = inf; u(empty, :) = -inf; x.inf = l; x.sup = u; endfunction %!assert (isequal (mince (infsup (0, 10), 10), infsup (0 : 9, 1 : 10))); interval-3.2.0/inst/@infsup/minus.m0000644000000000000000000000611413316017127015363 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} minus (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} - @var{Y}} ## ## Subtract all numbers of interval @var{Y} from all numbers of @var{X}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (2, 3); ## y = infsup (1, 2); ## x - y ## @result{} ans = [0, 2] ## @end group ## @end example ## @seealso{@@infsup/plus} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function x = minus (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); elseif (isa (y, "infsupdec")) ## Workaround for bug #42735 result = minus (x, y); return endif l = mpfr_function_d ('minus', -inf, x.inf, y.sup); u = mpfr_function_d ('minus', +inf, x.sup, y.inf); emptyresult = isempty (x) | isempty (y); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (infsup (2, 3) - infsup (1, 2) == infsup (0, 2)); %!# correct use of signed zeros %!test %! x = minus (infsup (0), infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sub; %! for testcase = [testcases]' %! assert (isequaln (... %! minus (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sub; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (minus (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sub; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (minus (in1, in2), out)); interval-3.2.0/inst/@infsup/mldivide.m0000644000000000000000000002241613316017127016030 0ustar 00000000000000## Copyright 1990-2000 Institut für Angewandte Mathematik, ## Universität Karlsruhe, Germany ## Copyright 2000-2014 Wissenschaftliches Rechnen/Softwaretechnologie, ## Universität Wuppertal, Germany ## Copyright 2015-2016 Oliver Heimlich ## ## This program is derived from FastLSS in CXSC, C++ library for eXtended ## Scientific Computing (V 2.5.4), which is distributed under the terms of ## LGPLv2+. Original Author is Michael Zimmer. Migration to Octave code has ## been performed by Oliver Heimlich. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} mldivide (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} \ @var{Y}} ## ## Return the interval matrix left division of @var{X} and @var{Y}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## infsup ([1, 0; 0, 2]) \ [2, 0; 0, 4] ## @result{} ans = 2×2 interval matrix ## [2] [0] ## [0] [2] ## @end group ## @end example ## @seealso{@@infsup/mtimes, @@infsup/gauss} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-17 function result = mldivide (A, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (A, "infsup"))) A = infsup (A); endif if (not (isa (b, "infsup"))) b = infsup (b); elseif (isa (b, "infsupdec")) ## Workaround for bug #42735 result = mldivide (A, b); return endif if (isscalar (A.inf)) result = ldivide (A, b); return elseif (not (issquare (A.inf))) error ("interval:InvalidOperand", "mldivide: Matrix is not square"); elseif (rows (A.inf) ~= rows (b.inf)) error ("interval:InvalidOperand", ["mldivide: ", ... "nonconformant arguments ", ... "(op1 is " num2str(rows (A.inf)) "×", ... num2str(columns (A.inf)) ",", ... " op2 is " num2str(rows (b.inf)) "×", ... num2str(columns (b.inf)) ")"]); elseif (isempty (A.inf)) result = infsup (zeros (0, columns (b.inf))); return endif ## Maximum number of iterations during the verification step cfg.maxIterVer = 5; ## Epsilon for the verification step ## (used for the Epsilon inflation during verification) cfg.epsVer = 1e-1; ## Maximum number of iterations during the refinement step cfg.maxIterRef = 5; ## Epsilon for the refinement step (stopping criterion for refinement step) cfg.epsRef = 1e-5; ## Maximum number of iterations during residual correction ## (not available for K=1) cfg.maxIterResCorr = 10; ## Epsilon for the residual correction cfg.epsResCorr = 1e-6; ## An approximate inverse R of A is computed. Then an approximate ## solution x1 is computed applying a conventional residual ## iteration. For the final verification, an interval residual ## iteration is performed. An enclosure of the unique solution is ## returned. ## ## If this first step fails, the solver will try to compute a ## verified solution by using an approximate inverse of double ## length. This second step takes considerably longer than the ## first step, because all computations must be performed using high ## precision scalar products. ## Compute midpoints of A and b for future reference Am = mid (A); bm = mid (b); ## Approximate inversion (non-interval computation) [R, cond] = inv (Am); if (cond == 0) result = gauss (A, b); return endif ## Part 1 ==================================================================== ## Approximate solution x1 (non-interval computation) x1 = R * bm; x1 += R * (bm - Am * x1); ## Interval residual x x = mtimes (R, b - mtimes (A, x1, "valid"), "valid"); C = eye (rows (R)) - mtimes (R, A, "valid"); ## Verify solution x1 + x [x, verified] = verify_and_refine (x, C, cfg, "valid"); if (verified) result = x1 + x; return endif ## Part 2 ==================================================================== ## R2 = inv (R * Am), with correctly rounded dot product R2 = zeros (size (R)); for i = 1 : rows (R) for j = 1 : columns (R) R2 (i, j) = mpfr_vector_dot_d (0.5, R (i, :), Am (:, j)); endfor endfor [R2, cond] = inv (R2); if (cond == 0) result = gauss (A, b); return endif ## R = R2 * R with correctly rounded dot product; error in R2 R1_ = R2_ = zeros (size (R)); for i = 1 : rows (R) for j = 1 : columns (R) [R1_(i, j), R2_(i, j)] = mpfr_vector_dot_d (0.5, R2 (i, :), R (:, j)); endfor endfor R = R1_; R2 = R2_; clear R1_ R2_; ## Loop over all right hand sides C_computed = false (); result = infsup (zeros (size (b.inf))); for s = 1 : columns (b.inf) s_idx.type = "()"; s_idx.subs = {":", s}; ## x1 = R * bm + R2 * bm with correctly rounded dot product; error in x0 x1 = x0 = zeros (rows (R), 1); parfor i = 1 : rows (R) [x1(i), x0(i)] = mpfr_vector_dot_d (0.5, [R(i, :), R2(i, :)], ... [bm(:, s); bm(:, s)]); endparfor ## Residual iteration (non-interval computation) for k = 1 : cfg.maxIterResCorr ## d = bm - Am * x1 - Am * x0 with correctly rounded dot product d = zeros (rows (R), 1); parfor i = 1 : rows (R) d (i) = mpfr_vector_dot_d (0.5, ... [bm(i, s), Am(i, :), Am(i, :)], ... [1; -x1; -x0]); endparfor ## y0 = x0 + R * d + R2 * d with correctly rounded dot product y0 = zeros (rows (R), 1); parfor i = 1 : rows (R) y0 (i) = mpfr_vector_dot_d (0.5, ... [x0(i), R(i, :), R2(i, :)], ... [1; d; d]); endparfor d = x1 + y0; p = relative_error (d, x1 + x0); if (p >= cfg.epsResCorr && k < cfg.maxIterResCorr) ## x0 = x1 + x0 - d with correctly rounded sum parfor i = 1 : rows (R) x0 (i) = mpfr_vector_sum_d (0.5, [x1(i), x0(i), -d(i)]); endparfor endif x1 = d; if (p < cfg.epsResCorr) break endif endfor ## compute enclosure y+Y1 of the residuum b-A*x1 of the approximation x1 ## and initialize x:= (R+R2)*(b-A*x1), C:= I-(R+R2)*A ## y = mid (b - A * x1) y = mid ([subsref(b, s_idx), A] * [1; -x1]); ## Y1 = b - A * x1 - y Y1 = [subsref(b, s_idx), A, y] * [1; -x1; -1]; ## x = R * y + R2 * y + R * Y1 + R2 * Y1 x = [R, R2, R, R2] * [y; y; Y1; Y1]; ## Verifying solution x1 + x ... if (all (x.inf == 0 & x.sup == 0)) ## exact solution! (however, not necessarily unique!) subsasgn (result, s_idx, x1); continue endif if (not (C_computed)) ## C = I - R * A - R2 * A (lazy computation) C = [eye(rows (R)), R, R2] * [eye(rows (R)); -A; -A]; C_computed = true (); endif [x, verified] = verify_and_refine (x, C, cfg, "tight"); if (not (verified)) error ("Verification failed") endif ## The exact solution lies x1 + x subsasgn (result, s_idx, x1 + x); endfor endfunction ## Perform an epsilon inflation function y = blow (x, eps) y = nextout ((1 + eps) .* x - eps .* x); endfunction ## Compute component-wise the maximum relative error function e = relative_error (new, old) nonzero = old ~= 0 & (1e6 * abs (new) >= abs (old)); e = max (abs ((new (nonzero) - old (nonzero)) ./ old (nonzero))); if (isempty (e)) e = 0; endif endfunction ## Interval iteration until inclusion is obtained (or max. iteration count) function [x, verified] = verify_and_refine (x0, C, cfg, accuracy) verified = false (); x = x0; for p = 1 : cfg.maxIterVer y = blow (x, cfg.epsVer); # epsilon inflation x = x0 + mtimes (C, y, accuracy); # new iterate verified = all (all (subset (x, y))); if (verified) break endif endfor if (verified) ## Iterative refinement for p = 1 : cfg.maxIterRef y = x; x = intersect (x0 + mtimes (C, x, accuracy), x); if (p == cfg.maxIterRef) break endif distance = max (abs (x.inf - y.inf), ... abs (x.sup - y.sup)); if (max (max (distance)) <= cfg.epsRef) break endif endfor endif endfunction %!# unique solution %!assert (infsup ([1, 0; 0, 2]) \ [2, 0; 0, 4] == [2, 0; 0 2]); %!# no solution %!assert (all (isempty (infsup ([1, 0; 2, 0]) \ [3; 0]))); %!# many solutions %!assert (infsup ([1, 0; 2, 0]) \ [4; 8] == infsup ([4; -inf], [4; inf])); %!assert (all (subset (infsup ([2, -1; -1, 2], [4, 1; 1, 4]) \ infsup ([-3; .8], [3; .8]), infsup ([-2.3; -1.1], [2.3; 1.6])))); interval-3.2.0/inst/@infsup/mod.m0000644000000000000000000002747313316017127015022 0ustar 00000000000000## Copyright 2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} mod (@var{X}, @var{Y}) ## ## Compute the modulus of @var{X} and @var{Y}. ## ## Conceptionally, it is given by the expression ## @code{@var{X} - @var{Y} .* floor (@var{X} ./ @var{Y})}. This function is ## undefined for @var{Y} = 0. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## mod (infsup (3), infsup (2)) ## @result{} ans = [1] ## mod (infsup (-3), infsup (2)) ## @result{} ans = [1] ## @end group ## @end example ## ## @seealso{@@infsup/rdivide, @@infsup/rem} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2017-10-02 function [result, d] = mod (x, y) if (nargin ~= 2) print_usage (); return endif ## Usually, the implementation of an interval arithmetic function is cleanly ## split into a bare and a decorated version. This function's decoration is ## quite complicated to be computed and depends on intermediate values that ## are used to compute the bare interval result. Thus, we also compute ## decoration information as a second output parameter for @infsupdec. if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif ## We can exploit the function's symmetric properties and ## compute each half-space by projection. y_p = intersect (y, infsup (0, inf)); y_n = intersect (y, infsup (-inf, 0)); [l1, u1, d1] = mod_positive_halfspace (x, y_p); [l2, u2, d2] = mod_positive_halfspace (x, -y_n); [l2, u2] = deal (-u2, -l2); l = min (l1, l2); u = max (u1, u2); warning ("off", "interval:UndefinedOperation", "local"); result = infsup (l, u); d = min (d1, d2); endfunction function [l, u, d] = mod_positive_halfspace (x, y) ## y = x / -1 *. ^ y .* y = x / 1 ## *. A | B .* ## *. | .* ## A *. | .* C ## y = x / -2 *. | .* y = x / 2 ## **.. *. | .* ..** ## **.. *. | .* ..** ## A **.. *. | .* ..** C ## **.. *. | .* ..** ## (and so on) **.*.|.*.** (and so on) ## ---------------------+---------------------> x ## ## Gradients: ## A: positive x, postitive y ## B: positive x ## C: positive x, negative y ## ## Limit values: ## x/y -> integer from above mod (x, y) -> 0 from above ## x -> 0 from below mod (x, y) -> y from below ## x/y -> integer n != 0 from below mod (x, y) -> x/n from below ## ## How to compute valid boundaries: ## x >= 0: This function is equivalent to rem and can be computed with mpfr ## x < 0: No corresponding mpfr function exists. For x/y = integer this ## function's value equals zero. Otherwise it can be computed with ## “rem (x, y) + y”. ## Compute fractions x ./ y at four corners of the interval box to detect ## cases with y = x ./ n inside the area, where the function is noncontinuous ## and takes extreme values. ## ## y = x / -1 *. ^ y .* y = x / 1 ## *. | .* ## *. r-----+-----s .* ## *. | | | .* ## y = x / -2 *. q-----+-----t .* y = x / 2 ## **.. *. | .* ..** ## **.. *. | .* ..** ## **.. *. | .* ..** ## **.. *. | .* ..** ## (and so on) **.*.|.*.** (and so on) ## ---------------------+---------------------> x div_by_zero_idx = (y.inf == -0); y.inf(div_by_zero_idx) = +0; q = mpfr_function_d ("rdivide", -inf, x.inf, y.inf); r = mpfr_function_d ("rdivide", -inf, x.inf, y.sup); s = mpfr_function_d ("rdivide", +inf, x.sup, y.sup); t = mpfr_function_d ("rdivide", +inf, x.sup, y.inf); r(isnan (r)) = -1; # -inf / inf s(isnan (s)) = +1; # +inf / inf div_by_zero_idx = (div_by_zero_idx & true (size (x.inf))); ## The gradient is always in positive x direction. Thus, the boundaries for ## the range of x/y can easily be computed as [a, b]. a = min (q, r); b = max (s, t); ## Check for roots mod (x, y) == 0 ceil_a = ceil (a); x_pos_idx = (x.inf > 0); ceil_a(a == 0 & x_pos_idx) = 1; # adjust limit values for y.inf = inf floor_b = floor (b); x_neg_idx = (x.sup < 0); floor_b(b == 0 & x_neg_idx) = -1; # adjust limit values for y.inf = inf a_root_idx = (a == ceil_a); discontinuity_idx = (ceil_a < floor_b | ... (ceil_a == floor_b & not (a_root_idx))); root_idx = (a_root_idx | discontinuity_idx); l = u = zeros (size (a)); d = _com ()(ones (size (a))); d(a_root_idx) = _dac (); d(discontinuity_idx) = _def (); d(div_by_zero_idx) = _trv (); ## If the interval box contains no cases with y = x/n, the minimum is ## located at x.inf. Otherwise the minimum is zero. select = (not (root_idx) & x_pos_idx); l(select) = mpfr_function_d ("rem", -inf, x.inf(select), y.sup(select)); select = (not (root_idx) & x_neg_idx); l(select) = max (0, mpfr_function_d ("plus", -inf, ... mpfr_function_d ("rem", -inf, x.inf(select), y.inf(select)), ... y.inf(select))); ## If the interval box contains no discontinuity, the maximum is located ## at x.sup. Otherwise the maximum is computed below. x_nonneg_idx = (x.inf >= 0); select = (not (discontinuity_idx) & x_nonneg_idx & not (div_by_zero_idx)); u(select) = mpfr_function_d ("rem", +inf, x.sup(select), y.inf(select)); select = (not (discontinuity_idx) & x_neg_idx); u(select) = mpfr_function_d ("plus", +inf, ... mpfr_function_d ("rem", +inf, x.sup(select), y.sup(select)), ... y.sup(select)); ## Consider the maximum for y = x/n, with n nearest to zero. n = zeros (size (u)); n(x_pos_idx) = ceil_a(x_pos_idx); n(x_neg_idx) = floor_b(x_neg_idx); ## If x/y = a, the maximum is located at n = a+1 select = (x_nonneg_idx & a_root_idx); n(select) = mpfr_function_d ("plus", 0, n(select), 1); ## Case 1: y.sup = x/n select = (discontinuity_idx & r <= n & n <= s); u(select) = y.sup(select); ## Case 2: y = x.sup/n select = (discontinuity_idx & n > 0 & s < n); u(select) = mpfr_function_d ("rdivide", +inf, x.sup(select), n(select)); ## Case 3: y = x.inf/n select = (discontinuity_idx & n < 0 & n < r); u(select) = max (... mpfr_function_d ("rdivide", +inf, x.inf(select), n(select)), ... mpfr_function_d ("plus", +inf, ... mpfr_function_d ("rem", +inf, x.sup(select), y.sup(select)), ... y.sup(select))); empty_result_idx = y.sup <= 0; l(empty_result_idx) = inf; u(empty_result_idx) = -inf; d(empty_result_idx) = _com (); endfunction function d = _com () d = uint8 (16); endfunction function d = _dac () d = uint8 (12); endfunction function d = _def () d = uint8 (8); endfunction function d = _trv () d = uint8 (4); endfunction %!assert (mod (infsup (), infsup ()) == infsup ()); %!assert (mod (infsup (0), infsup ()) == infsup ()); %!assert (mod (infsup (), infsup (0)) == infsup ()); %!assert (mod (infsup (0), infsup (0)) == infsup ()); %!assert (mod (infsup (1), infsup (0)) == infsup ()); %!assert (mod (infsup (0, 1), infsup (0)) == infsup ()); %!assert (mod (infsup (1, 2), infsup (0)) == infsup ()); %!assert (mod (infsup (0, inf), infsup (0)) == infsup ()); %!assert (mod (infsup (1, inf), infsup (0)) == infsup ()); %!assert (mod (infsup (realmax, inf), infsup (0)) == infsup ()); %!assert (mod (infsup (0), infsup (1)) == infsup (0)); %!assert (mod (infsup (0), infsup (0, 1)) == infsup (0)); %!assert (mod (infsup (0), infsup (1, 2)) == infsup (0)); %!assert (mod (infsup (0), infsup (0, inf)) == infsup (0)); %!assert (mod (infsup (0), infsup (1, inf)) == infsup (0)); %!assert (mod (infsup (0), infsup (realmax, inf)) == infsup (0)); %!assert (mod (infsup (1), infsup (1)) == infsup (0)); %!assert (mod (infsup (2), infsup (1)) == infsup (0)); %!assert (mod (infsup (4), infsup (2)) == infsup (0)); %!assert (mod (infsup (6), infsup (3)) == infsup (0)); %!assert (mod (infsup (8), infsup (2)) == infsup (0)); %!assert (mod (infsup (9), infsup (3)) == infsup (0)); %!assert (mod (infsup (realmax), infsup (realmax)) == infsup (0)); %!assert (mod (infsup (realmax), infsup (realmax / 2)) == infsup (0)); %!assert (mod (infsup (realmax), infsup (realmax / 4)) == infsup (0)); %!assert (mod (infsup (realmax), infsup (realmax / 8)) == infsup (0)); %!assert (mod (infsup (realmax), infsup (realmax / 16)) == infsup (0)); %!assert (mod (infsup (realmax), infsup (realmax / 32)) == infsup (0)); %!assert (mod (infsup (0.1), infsup (0.1)) == infsup (0)); %!assert (mod (infsup (0.1 * 2), infsup (0.1)) == infsup (0)); %!assert (mod (infsup (0.1 * 4), infsup (0.1)) == infsup (0)); %!assert (mod (infsup (pi), infsup (pi)) == infsup (0)); %!assert (mod (infsup (pi), infsup (pi / 2)) == infsup (0)); %!assert (mod (infsup (pi), infsup (pi / 4)) == infsup (0)); %!assert (mod (infsup (pow2 (-1074)), infsup (pow2 (-1074))) == infsup (0)); %!assert (mod (infsup (pow2 (-1073)), infsup (pow2 (-1074))) == infsup (0)); %!assert (mod (infsup (pow2 (-1072)), infsup (pow2 (-1074))) == infsup (0)); %!assert (mod (infsup (1), infsup (2)) == infsup (1)); %!assert (mod (infsup (0.5), infsup (1)) == infsup (0.5)); %!assert (mod (infsup (pi), infsup (3.15)) == infsup (pi)); %!assert (mod (infsup (1), infsup (2, 3)) == infsup (1)); %!assert (mod (infsup (1), infsup (2, inf)) == infsup (1)); %!assert (mod (infsup (0.5), infsup (1, 2)) == infsup (0.5)); %!assert (mod (infsup (0.5), infsup (1, inf)) == infsup (0.5)); %!assert (mod (infsup (pi), infsup (3.15)) == infsup (pi)); %!assert (mod (infsup (pi), infsup (3.15, inf)) == infsup (pi)); %!assert (mod (infsup (0, 1), infsup (0, 1)) == infsup (0, 1)); %!assert (mod (infsup (0, 2), infsup (0, 1)) == infsup (0, 1)); %!assert (mod (infsup (0, 1), infsup (0, 2)) == infsup (0, 1)); %!assert (mod (infsup (0, realmax), infsup (0, realmax)) == infsup (0, realmax)); %!assert (mod (infsup (realmax, inf), infsup (realmax, inf)) == infsup (0, inf)); %!assert (mod (infsup (0, inf), infsup (0, inf)) == infsup (0, inf)); %!assert (mod (infsup (0), infsup (1)) == infsup (0)); %!assert (mod (infsup (1), infsup (1)) == infsup (0)); %!assert (mod (infsup (0, 1), infsup (1)) == infsup (0, 1)); %!assert (mod (infsup (1, 2), infsup (1)) == infsup (0, 1)); %!assert (mod (infsup (0, inf), infsup (1)) == infsup (0, 1)); %!assert (mod (infsup (1, inf), infsup (1)) == infsup (0, 1)); %!assert (mod (infsup (realmax, inf), infsup (1)) == infsup (0, 1)); %!assert (mod (infsup (1), infsup (1)) == infsup (0)); %!assert (mod (infsup (1), infsup (0, 1)) == infsup (0, 0.5)); %!assert (mod (infsup (1), infsup (1, 2)) == infsup (0, 1)); %!assert (mod (infsup (1), infsup (0, inf)) == infsup (0, 1)); %!assert (mod (infsup (1), infsup (1, inf)) == infsup (0, 1)); %!assert (mod (infsup (1), infsup (2, inf)) == infsup (1)); %!assert (mod (infsup (1), infsup (realmax, inf)) == infsup (1)); interval-3.2.0/inst/@infsup/mpower.m0000644000000000000000000000652113316017127015543 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} mpower (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} ^ @var{Y}} ## ## Return the matrix power operation of @var{X} raised to the @var{Y} power. ## ## If @var{X} is a scalar, this function and @code{power} are equivalent. ## Otherwise, @var{X} must be a square matrix and @var{Y} must be a single ## integer. ## ## Warning: This function is not defined by IEEE Std 1788-2015. ## ## Accuracy: The result is a valid enclosure. The result is tightest for ## @var{Y} in @{0, 1, 2@}. ## ## @example ## @group ## infsup (magic (3)) ^ 2 ## @result{} ans = 3×3 interval matrix ## [91] [67] [67] ## [67] [91] [67] ## [67] [67] [91] ## @end group ## @end example ## @seealso{@@infsup/pow, @@infsup/pown, @@infsup/pow2, @@infsup/pow10, @@infsup/exp} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-31 function result = mpower (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (isscalar (x)) ## Short-circuit for scalars result = power (x, y); return endif if (not (isreal (y)) || fix (y) ~= y) error ("interval:InvalidOperand", ... "mpower: only integral powers can be computed"); endif if (not (issquare (x.inf))) error ("interval:InvalidOperand", ... "mpower: must be square matrix"); endif ## Implements log-time algorithm A.1 in ## Heimlich, Oliver. 2011. “The General Interval Power Function.” ## Diplomarbeit, Institute for Computer Science, University of Würzburg. ## http://exp.ln0.de/heimlich-power-2011.htm. result = infsup (eye (length (x))); while (y ~= 0) if (rem (y, 2) == 0) # y is even [x.inf, x.sup] = mpfr_matrix_sqr_d (x.inf, x.sup); y /= 2; else # y is odd result = mtimes (result, x); if (all (vec (isempty (result))) || all (vec (isentire (result)))) ## We can stop the computation here, this is a fixed point break endif if (y > 0) y --; else y ++; if (y == 0) ## Inversion after computation of a negative power. ## Inversion should be the last step, because it is not ## tightest and would otherwise increase rounding errors. result = inv (result); endif endif endif endwhile endfunction %!# from the documentation string %!assert (isequal (infsup (magic (3)) ^ 2, infsup (magic (3) ^ 2))); %!# correct use of signed zeros %!test %! x = mpower (infsup (eye (2)), 2); %! assert (signbit (inf (x(1, 2)))); %! assert (not (signbit (sup (x(1, 2))))); interval-3.2.0/inst/@infsup/mrdivide.m0000644000000000000000000000356413316017127016041 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} mrdivide (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} / @var{Y}} ## ## Return the interval matrix right division of @var{X} and @var{Y}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## infsup ([1, 2; 3, 4]) / [3, 4; 1, 2] ## @result{} ans = 2×2 interval matrix ## [0] [1] ## [1] [0] ## @end group ## @end example ## @seealso{@@infsup/mtimes} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-31 function result = mrdivide (x, y) if (nargin ~= 2) print_usage (); return endif if (isa (y, "infsupdec")) if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif elseif (not (isa (x, "infsup"))) x = infsup (x); endif if (isa (x, "infsupdec")) if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif elseif (not (isa (y, "infsup"))) y = infsup (y); endif if (isscalar (x) || isscalar (y)) result = rdivide (x, y); return endif result = mldivide (y', x')'; endfunction %!# from the documentation string %!assert (infsup ([1, 2; 3, 4]) / [3, 4; 1, 2] == infsup ([0, 1; 1, 0])); interval-3.2.0/inst/@infsup/mtimes.m0000644000000000000000000001223213316017127015524 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} mtimes (@var{X}, @var{Y}) ## @defopx Method {@@infsup} mtimes (@var{X}, @var{Y}, @var{ACCURACY}) ## @defopx Operator {@@infsup} {@var{X} * @var{Y}} ## ## Compute the interval matrix multiplication. ## ## The @var{ACCURACY} can be set to @code{tight} (default) or @code{valid}. ## With @code{valid} accuracy an algorithm for fast matrix multiplication based ## on BLAS routines is used. The latter is published by ## Siegried M. Rump (2012), “Fast interval matrix multiplication,” ## Numerical Algorithms 61(1), 1-34. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup ([1, 2; 7, 15], [2, 2; 7.5, 15]); ## y = infsup ([3, 3; 0, 1], [3, 3.25; 0, 2]); ## x * y ## @result{} ans = 2×2 interval matrix ## [3, 6] [5, 10.5] ## [21, 22.5] [36, 54.375] ## @end group ## @end example ## @seealso{@@infsup/mrdivide} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-31 function result = mtimes (x, y, accuracy) if (nargin < 2 || nargin > 3 || (nargin == 3 && not (ischar (accuracy)))) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); elseif (isa (y, "infsupdec")) ## Workaround for bug #42735 result = mtimes (x, y); return endif if (isscalar (x) || isscalar (y)) result = times (x, y); return endif if (size (x.inf, 2) ~= size (y.inf, 1)) error ("interval:InvalidOperand", ... "operator *: nonconformant arguments"); endif if (nargin >= 3) switch (accuracy) case "valid" ## Fast matrix multiplication uses rounding mode switches, which ## might not work on all systems. Thus, we validate whether the ## BLAS routines respect rounding modes correctly on the current ## platform and fall back to the slow implementation otherwise. persistent use_rounding_mode = check_rounding_mode (); if (use_rounding_mode) result = fast_mtimes (x, y); return else warning ('interval:rounding', ... ['mtimes: rounding modes not supported, falling ', ... 'back to slow but accurate matrix multiplication']); endif case "tight" ## Default mode otherwise print_usage(); return endswitch endif ## mtimes could also be computed with a for loop and the dot operation. ## However, that would take significantly longer (loop + missing JIT-compiler, ## several OCT-file calls), so we use an optimized ## OCT-file for that particular operation. [l, u] = mpfr_matrix_mul_d (x.inf, y.inf, x.sup, y.sup); result = infsup (l, u); endfunction function C = fast_mtimes (A, B) ## Implements Algorithm 4.8 ## IImul7: interval interval multiplication with 7 point matrix multiplications ## Rump, Siegried M. 2012. “Fast interval matrix multiplication.” ## Numerical Algorithms 61(1), 1-34. ## http://www.ti3.tu-harburg.de/paper/rump/Ru11a.pdf. ## ## Although this is the slowest of the published fast algorithms, it is the ## most accurate. [mA, rA] = rad (A); [mB, rB] = rad (B); rhoA = sign (mA) .* min (abs (mA), rA); rhoB = sign (mB) .* min (abs (mB), rB); unwind_protect __setround__ (+inf); rC = abs (mA) * rB + rA * (abs (mB) + rB) + (-abs (rhoA)) * abs (rhoB); u = mA * mB + rhoA * rhoB + rC; __setround__ (-inf); l = mA * mB + rhoA * rhoB - rC; unwind_protect_cleanup __setround__ (0.5); # restore default rounding mode (to nearest) end_unwind_protect C = infsup (l, u); endfunction function works = check_rounding_mode () try unwind_protect works = true (); __setround__ (+inf); works &= (1 + realmin > 1); works &= ([1 1 -1] * [1; realmin; realmin] > 1); __setround__ (-inf); works &= (1 + realmin == 1); works &= ([1 1 -1] * [1; realmin; realmin] < 1); unwind_protect_cleanup __setround__ (0.5); end_unwind_protect catch works = false (); end_try_catch endfunction %!# from the documentation string %!assert (infsup ([1, 2; 7, 15], [2, 2; 7.5, 15]) * infsup ([3, 3; 0, 1], [3, 3.25; 0, 2]) == infsup ([3, 5; 21, 36], [6, 10.5; 22.5, 54.375])); %!# matrix multiplication using BLAS routines %!assert (mtimes (infsup ([1, 2; 7, 15], [2, 2; 7.5, 15]), infsup ([3, 3; 0, 1], [3, 3.25; 0, 2]), 'valid') == infsup ([3, 5; 21, 36], [6, 10.5; 22.5, 54.375])); interval-3.2.0/inst/@infsup/mulrev.m0000644000000000000000000002705613316017127015552 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} mulrev (@var{B}, @var{C}, @var{X}) ## @deftypemethodx {@@infsup} {@var{X} =} mulrev (@var{B}, @var{C}) ## @deftypemethodx {@@infsup} {[@var{U}, @var{V}] =} mulrev (@var{B}, @var{C}) ## @deftypemethodx {@@infsup} {[@var{U}, @var{V}] =} mulrev (@var{B}, @var{C}, @var{X}) ## ## Compute the reverse multiplication function or the two-output division. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{x .* b ∈ @var{C}} for any @code{b ∈ @var{B}}. ## ## This function is similar to interval division @code{@var{C} ./ @var{B}}. ## However, it treats the case 0/0 as “any real number” instead of “undefined”. ## ## Interval division, considered as a set, can have zero, one or two disjoint ## connected components as a result. If called with two output parameters, ## this function returns the components separately. @var{U} contains the ## negative or unique component, whereas @var{V} contains the positive ## component in cases with two components. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## c = infsup (1); ## b = infsup (-inf, inf); ## [u, v] = mulrev (b, c) ## @result{} ## u = [-inf, 0] ## v = [0, inf] ## @end group ## @end example ## @seealso{@@infsup/times} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function [u, v] = mulrev (b, c, x) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) x = infsup (-inf, inf); endif if (not (isa (b, "infsup"))) b = infsup (b); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (x, "infsup"))) x = infsup (x); endif ## Resize, if broadcasting is needed if (not (size_equal (b.inf, c.inf))) b.inf = ones (size (c.inf)) .* b.inf; b.sup = ones (size (c.inf)) .* b.sup; c.inf = ones (size (b.inf)) .* c.inf; c.sup = ones (size (b.inf)) .* c.sup; endif u = v = x; u.inf = v.inf = inf (size (b.inf)); u.sup = v.sup = -inf (size (b.inf)); emptyresult = b.inf == inf | c.inf == inf ... | (b.inf == 0 & b.sup == 0 & (c.sup < 0 | c.inf > 0)); # x * 0 ~= 0 twocomponents = b.inf < 0 & b.sup > 0 & not (emptyresult) & ... (c.sup < 0 | c.inf > 0); onecomponent = not (twocomponents) & not (emptyresult); u.inf(twocomponents) = -inf; v.sup(twocomponents) = inf; dom = twocomponents & c.inf <= 0 & c.sup >= 0; u.sup(dom) = v.inf(dom) = 0; dom = twocomponents & c.inf > 0; if (not (isempty (dom))) u.sup(dom) = mpfr_function_d ('rdivide', +inf, c.inf(dom), b.inf(dom)); v.inf(dom) = mpfr_function_d ('rdivide', -inf, c.inf(dom), b.sup(dom)); endif dom = twocomponents & c.sup < 0; if (not (isempty (dom))) u.sup(dom) = mpfr_function_d ('rdivide', +inf, c.sup(dom), b.sup(dom)); v.inf(dom) = mpfr_function_d ('rdivide', -inf, c.sup(dom), b.inf(dom)); endif dom = onecomponent & b.inf >= 0 & c.inf >= 0; if (not (isempty (dom))) b.inf(dom & b.inf == 0) = +0; c.inf(dom & c.inf == 0) = +0; u.inf(dom) = mpfr_function_d ('rdivide', -inf, c.inf(dom), b.sup(dom)); u.sup(dom) = mpfr_function_d ('rdivide', +inf, c.sup(dom), b.inf(dom)); endif dom = onecomponent & b.sup <= 0 & c.inf >= 0; if (not (isempty (dom))) b.sup(dom & b.sup == 0) = -0; c.inf(dom & c.inf == 0) = +0; u.inf(dom) = mpfr_function_d ('rdivide', -inf, c.sup(dom), b.sup(dom)); u.sup(dom) = mpfr_function_d ('rdivide', +inf, c.inf(dom), b.inf(dom)); endif dom = onecomponent & b.inf >= 0 & c.sup <= 0; if (not (isempty (dom))) b.inf(dom & b.inf == 0) = +0; c.sup(dom & c.sup == 0) = -0; u.inf(dom) = mpfr_function_d ('rdivide', -inf, c.inf(dom), b.inf(dom)); u.sup(dom) = mpfr_function_d ('rdivide', +inf, c.sup(dom), b.sup(dom)); endif dom = onecomponent & b.sup <= 0 & c.sup <= 0; if (not (isempty (dom))) b.sup(dom & b.sup == 0) = -0; c.sup(dom & c.sup == 0) = -0; u.inf(dom) = mpfr_function_d ('rdivide', -inf, c.sup(dom), b.inf(dom)); u.sup(dom) = mpfr_function_d ('rdivide', +inf, c.inf(dom), b.sup(dom)); endif dom = onecomponent & c.inf < 0 & c.sup > 0 & b.inf > 0; if (not (isempty (dom))) u.inf(dom) = mpfr_function_d ('rdivide', -inf, c.inf(dom), b.inf(dom)); u.sup(dom) = mpfr_function_d ('rdivide', +inf, c.sup(dom), b.inf(dom)); endif dom = onecomponent & c.inf < 0 & c.sup > 0 & b.sup < 0; if (not (isempty (dom))) u.inf(dom) = mpfr_function_d ('rdivide', -inf, c.sup(dom), b.sup(dom)); u.sup(dom) = mpfr_function_d ('rdivide', +inf, c.inf(dom), b.sup(dom)); endif dom = onecomponent & b.inf <= 0 & b.sup >= 0 & c.inf <= 0 & c.sup >= 0; # x * 0 == 0 u.inf(dom) = -inf; u.sup(dom) = inf; u.inf(u.inf == 0) = -0; u.sup(u.sup == 0) = +0; v.inf(v.inf == 0) = -0; v.sup(v.sup == 0) = +0; ## Intersect u and v with x u.inf = max (u.inf, x.inf); u.sup = min (u.sup, x.sup); v.inf = max (v.inf, x.inf); v.sup = min (v.sup, x.sup); if (nargout < 2) u.inf(twocomponents) = min (u.inf(twocomponents), v.inf(twocomponents)); u.sup(twocomponents) = max (u.sup(twocomponents), v.sup(twocomponents)); emptyresult = u.inf > u.sup; u.inf(emptyresult) = inf; u.sup(emptyresult) = -inf; else empty_u = u.inf > u.sup; u.inf(empty_u) = inf; u.sup(empty_u) = -inf; empty_v = v.inf > v.sup; v.inf(empty_v) = inf; v.sup(empty_v) = -inf; ## It can happen that the twocomponents result has only one component, ## because x is positive for example. Then, only one component shall be ## returned swap = twocomponents & isempty (u) & not (isempty (v)); [u.inf(swap), u.sup(swap), v.inf(swap), ... v.sup(swap)] = deal (v.inf(swap), v.sup(swap), u.inf(swap), u.sup(swap)); endif endfunction %!#IEEE Std 1788-2015 mulRevToPair examples %!test %! [u, v] = mulrev (infsup (0), infsup (1, 2)); %! assert (isempty (u) & isempty (v)); %!test %! [u, v] = mulrev (infsup (0), infsup (0, 1)); %! assert (isentire (u) & isempty (v)); %!test %! [u, v] = mulrev (infsup (1), infsup (1, 2)); %! assert (eq (u, infsup (1, 2)) & isempty (v)); %!test %! [u, v] = mulrev (infsup (1, inf), infsup (1)); %! assert (eq (u, infsup (0, 1)) & isempty (v)); %!test %! [u, v] = mulrev (infsup (-1, 1), infsup (1, 2)); %! assert (eq (u, infsup (-inf, -1)) & eq (v, infsup (1, inf))); %!test %! [u, v] = mulrev (infsup (-inf, inf), infsup (1)); %! assert (eq (u, infsup (-inf, 0)) & eq (v, infsup (0, inf))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.mulRevToPair1; %! for testcase = [testcases]' %! assert (isequaln (... %! nthargout (1, 2, @mulrev, testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.mulRevToPair1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (nthargout (1, 2, @mulrev, in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.mulRevToPair1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (nthargout (1, 2, @mulrev, in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.mulRevToPair2; %! for testcase = [testcases]' %! assert (isequaln (... %! nthargout (2, @mulrev, testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.mulRevToPair2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (nthargout (2, @mulrev, in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.mulRevToPair2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (nthargout (2, @mulrev, in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.mulRev; %! for testcase = [testcases]' %! assert (isequaln (... %! mulrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.mulRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (mulrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.mulRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mulrev (in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.mulRevTen; %! for testcase = [testcases]' %! assert (isequaln (... %! mulrev (testcase.in{1}, testcase.in{2}, testcase.in{3}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.mulRevTen; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! assert (isequaln (mulrev (in1, in2, in3), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.mulRevTen; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! in3 = reshape ([in3; in3(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mulrev (in1, in2, in3), out)); interval-3.2.0/inst/@infsup/ndims.m0000644000000000000000000000253513316017127015345 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} ndims (@var{A}) ## ## Return the number of dimensions of @var{A}. ## ## For any array, the result will always be larger than or equal to 2. ## Trailing singleton dimensions are not counted. ## @seealso{@@infsup/length, @@infsup/numel, @@infsup/size, @@infsup/rows, @@infsup/columns} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function result = ndims (a) if (nargin ~= 1) print_usage (); return endif result = ndims (a.inf); endfunction %!assert (ndims (infsup ([])), 2); %!assert (ndims (infsup (0)), 2); %!assert (ndims (infsup (magic (3))), 2); interval-3.2.0/inst/@infsup/ne.m0000644000000000000000000000270013316017127014627 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} ne (@var{A}, @var{B}) ## @defopx Operator {@@infsup} {@var{A} ~= @var{B}} ## @defopx Operator {@@infsup} {@var{A} != @var{B}} ## ## Compare intervals @var{A} and @var{B} for inequality. ## ## True, if @var{A} contains a number which is not a member in @var{B} or vice ## versa. False, if all numbers from @var{A} are also contained in @var{B} and ## vice versa. ## ## @seealso{@@infsup/eq, @@infsup/subset, @@infsup/interior, @@infsup/disjoint} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function result = ne (a, b) if (nargin ~= 2) print_usage (); return endif result = not (eq (a, b)); endfunction %!assert (ne (infsup (1, 2), infsup (1, 3))); interval-3.2.0/inst/@infsup/newdec.m0000644000000000000000000000535013316017127015476 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} newdec (@var{X}) ## ## Create a decorated interval from a bare interval. ## ## The decorated interval will carry the best possible decoration, i. e., ## @code{trv} for empty intervals, @code{dac} for unbound intervals, and ## @code{com} for common intervals. ## ## If @var{X} already is decorated, nothing happens. In particular, the ## decoration will not be changed in order to not lose any information. ## ## @example ## @group ## newdec (infsup (2, 3)) ## @result{} ans = [2, 3]_com ## @end group ## @end example ## @seealso{@@infsupdec/infsupdec} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-12 function xd = newdec (x) if (nargin ~= 1) print_usage (); return endif warning ("off", "interval:ImplicitPromote", "local"); xd = infsupdec (x); endfunction %!# from the documentation string %!assert (isequal (newdec (infsup (2, 3)), infsupdec (2, 3))); %!assert (isequal (newdec (infsupdec (2, 3)), infsupdec (2, 3))); %!assert (isequal (newdec (infsupdec (1, "trv")), infsupdec (1, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.newDec; %! for testcase = [testcases]' %! assert (isequaln (... %! newdec (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.newDec; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (newdec (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.newDec; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (newdec (in1), out)); interval-3.2.0/inst/@infsup/nextout.m0000644000000000000000000000336713316017127015745 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} nextout (@var{X}) ## ## Increases the interval's boundaries in each direction to the next number. ## ## This is the equivalent function to IEEE 754's nextDown and nextUp. ## ## @example ## @group ## x = infsup (1); ## nextout (x) == infsup (1 - eps / 2, 1 + eps) ## @result{} ans = 1 ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function x = nextout (x) if (nargin ~= 1) print_usage (); return endif persistent delta = pow2 (-1074); l = mpfr_function_d ('minus', -inf, x.inf, delta); u = mpfr_function_d ('plus', +inf, x.sup, delta); l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!test %! x = nextout (infsup (1)); %! assert (inf (x), 1 - eps / 2); %! assert (sup (x), 1 + eps); %!# correct use of signed zeros %!test %! x = nextout (infsup (pow2 (-1074))); %! assert (signbit (inf (x))); %!test %! x = nextout (infsup (-pow2 (-1074))); %! assert (not (signbit (sup (x)))); interval-3.2.0/inst/@infsup/norm.m0000644000000000000000000001570613316017127015212 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} norm (@var{A}, @var{P}) ## @defmethodx {@@infsup} norm (@var{A}, @var{P}, @var{Q}) ## @defmethodx {@@infsup} norm (@var{A}, @var{P}, @var{OPT}) ## ## Compute the p-norm (or p,q-norm) of the matrix @var{A}. ## ## If @var{A} is a matrix: ## @table @asis ## @item @var{P} = 1 ## 1-norm, the largest column sum of the absolute values of @var{A}. ## @item @var{P} = inf ## Infinity norm, the largest row sum of the absolute values of @var{A}. ## @item @var{P} = "fro" ## Frobenius norm of @var{A}, @code{sqrt (sum (diag (@var{A}' * @var{A})))}. ## @end table ## ## If @var{A} is a vector or a scalar: ## @table @asis ## @item @var{P} = inf ## @code{max (abs (@var{A}))}. ## @item @var{P} = -inf ## @code{min (abs (@var{A}))}. ## @item @var{P} = "fro" ## Frobenius norm of @var{A}, @code{sqrt (sumsq (abs (A)))}. ## @item @var{P} = 0 ## Hamming norm - the number of nonzero elements. ## @item other @var{P}, @code{@var{P} > 1} ## p-norm of @var{A}, @code{(sum (abs (@var{A}) .^ @var{P})) ^ (1/@var{P})}. ## @item other @var{P}, @code{@var{P} < 1} ## p-pseudonorm defined as above. ## @end table ## ## It @var{Q} is used, compute the subordinate matrix norm induced by the ## vector p-norm and vector q-norm. The subordinate p,q-norm is defined as the ## maximum of @code{norm (@var{A} * @var{x}, @var{Q})}, where @var{x} can be ## chosen such that @code{norm (@var{x}, @var{P}) = 1}. For @code{@var{P} = 1} ## and @code{@var{Q} = inf} this is the max norm, ## @code{max (max (abs (@var{A})))}. ## ## If @var{OPT} is the value "rows", treat each row as a vector and compute its ## norm. The result returned as a column vector. Similarly, if @var{OPT} is ## "columns" or "cols" then compute the norms of each column and return a row ## vector. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## norm (infsup (magic (3)), "fro") ## @result{} ans ⊂ [16.881, 16.882] ## @end group ## @group ## norm (infsup (magic (3)), 1, "cols") ## @result{} ans = 1×3 interval vector ## ## [15] [15] [15] ## ## @end group ## @end example ## @seealso{@@infsup/abs, @@infsup/max} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-01-26 function result = norm (A, p, opt) if (nargin > 3 || not (isa (A, "infsup"))) print_usage (); return endif if (nargin < 2) p = 2; opt = ""; elseif (nargin < 3) opt = ""; endif if (strcmp (p, "inf")) p = inf; endif switch (opt) case "rows" dim = 2; case {"columns", "cols"} dim = 1; case "" if (isvector (A.inf)) ## Try to find non-singleton dimension dim = find (size (A.inf) > 1, 1); if (isempty (dim)) dim = 1; endif else dim = []; endif otherwise ## Subordinate p,q matrix norm q = opt; dim = []; if (strcmp (q, "inf")) q = inf; endif if (p == 1 && q == inf) ## Max norm result = max (max (abs (A))); return elseif (p == 1 && q == 1) ## 1-norm, computed below elseif (p == inf && q == inf) ## inf-norm, computed below elseif (p == inf && q == 1) ## inf,1-norm ## Computation via z' * A * y ## with y and z being vectors of -1 and 1 entries. ## Important papers by Jiří Rohn ## ## Computing the Norm || A ||_{inf,1} is NP-Hard ## Linear and Multilinear Algebra 47 (2000), 195-204. ## http://dx.doi.org/10.1080/03081080008818644 ## http://uivtx.cs.cas.cz/~rohn/publist/norm.pdf ## ## R. Farhadsefat, J. Rohn and T. Lotfi, ## Norms of Interval Matrices. ## Technical Report No. 1122, Institute of Computer Science, ## Academy of Sciences of the Czech Republic, Prague 2011. ## http://www3.cs.cas.cz/ics/reports/v1122-11.pdf ## http://uivtx.cs.cas.cz/~rohn/publist/normlaa.pdf result = 0; ## Unfortunately this is NP-hard # 2^n different logical vectors of length n y = dec2bin ((1 : pow2 (columns (A)))' - 1) == '1'; # 2^m different logical vectors of length m z = dec2bin ((1 : pow2 (rows (A)))' - 1) == '1'; for i = 1 : rows (y) idx = substruct ("()", {":", y(i, :)}); B = subsasgn (A, idx, ... uminus (subsref (A, idx))); for j = 1 : rows (z) idx = substruct ("()", {z(j, :), ":"}); C = subsasgn (B, idx, ... uminus (subsref (B, idx))); result = max (result, sum (vec (C))); endfor endfor return else error ("norm: Particular option or p,q-norm is not yet supported") endif endswitch if (isempty (dim)) ## Matrix norm switch (p) case 1 result = max (sum (abs (A), 1)); case inf result = max (sum (abs (A), 2)); case "fro" result = sqrt (sumsq (vec (A))); otherwise error ("norm: Particular matrix norm is not yet supported") endswitch else ## Vector norm switch (p) case inf result = max (abs (A), [], dim); case -inf result = min (abs (A), [], dim); case {"fro", 2} result = sqrt (sumsq (A, dim)); case 0 ## Hamming norm: the number of non-zero elements result = sum (subsasgn (subsasgn (subsasgn ... (A, ... substruct ... ("()", ... {ismember(0, A)}), ... "[0, 1]"), ... substruct ("()", {A == 0}), 0), ... substruct ("()", {A > 0 | A < 0}), 1), ... dim); otherwise warning ("off", "interval:ImplicitPromote", "local"); result = (sum (abs (A) .^ p, dim)) .^ (1 ./ infsup (p)); endswitch endif endfunction %!test %! A = infsup ("0 [Empty] [0, 1] 1"); %! assert (isequal (norm (A, 0, "cols"), infsup ("0 [Empty] [0, 1] 1"))); %!assert (norm (infsup (magic (3)), inf, 1) == 45); %!assert (norm (infsup (-magic (3), magic (3)), inf, 1) == "[0, 45]"); interval-3.2.0/inst/@infsup/nthroot.m0000644000000000000000000002006113316017127015722 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} nthroot (@var{X}, @var{N}) ## ## Compute the real n-th root of @var{X}. ## ## Accuracy: The result is a valid enclosure. The result is a tight ## enclosure for @var{n} ≥ -2. The result also is a tight enclosure if the ## reciprocal of @var{n} can be computed exactly in double-precision. ## @seealso{@@infsup/pown, @@infsup/pownrev, @@infsup/realsqrt, @@infsup/cbrt} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-20 function x = nthroot (x, n) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isnumeric (n)) || any ((fix (n) ~= n)(:))) error ("interval:InvalidOperand", "nthroot: degree is not an integer"); endif if (any ((n == 0)(:))) error ("interval:InvalidOperand", ... "nthroot: degree must be nonzero"); endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, n))) x.inf = ones (size (n)) .* x.inf; x.sup = ones (size (n)) .* x.sup; n = ones (size (x.inf)) .* n; endif even = mod (n, 2) == 0; odd = not (even); idx.type = "()"; idx.subs = {even}; x = subsasgn (x, idx, intersect (subsref (x, idx), infsup (0, inf))); positive = n > 0; negative = not (positive); emptyresult = isempty (x) ... | (even & negative & x.sup <= 0) ... | (negative & x.inf == 0 & x.sup == 0); ## Don't have to calculate empty results even = even & not (emptyresult); odd = odd & not (emptyresult); positive = positive & not (emptyresult); negative = negative & not (emptyresult); l = zeros (size (x.inf)); u = inf (size (x.inf)); ## Positive n l(positive) = mpfr_function_d ('nthroot', -inf, x.inf(positive), n(positive)); u(positive) = mpfr_function_d ('nthroot', +inf, x.sup(positive), n(positive)); ## Negative and even n select = even & negative & x.inf > 0 & isfinite (x.inf); u(select) = invrootrounded (x.inf(select), -n(select), +inf); select = even & negative & x.sup > 0 & isfinite (x.sup); l(select) = invrootrounded (x.sup(select), -n(select), -inf); ## Negative and odd n ## The result is computed as the union of the nthroot of the negative ## part and the positive part of x oddandnegative = odd & negative; ## Positive part of x l_positivepart = zeros (size (x.inf)); u_positivepart = inf (size (x.inf)); select = oddandnegative & x.inf > 0 & isfinite (x.inf); u_positivepart(select) = invrootrounded (x.inf(select), -n(select), +inf); select = oddandnegative & x.sup > 0 & isfinite (x.sup); l_positivepart(select) = invrootrounded (x.sup(select), -n(select), -inf); l_positivepart(x.sup <= 0) = inf; u_positivepart(x.sup <= 0) = -inf; l(l == 0) = -0; ## Negative part of x l_negativepart = zeros (size (x.inf)); u_negativepart = inf (size (x.inf)); select = oddandnegative & x.sup < 0 & isfinite (x.sup); u_negativepart(select) = invrootrounded (-x.sup(select), -n(select), +inf); select = oddandnegative & x.inf < 0 & isfinite (x.inf); l_negativepart(select) = invrootrounded (-x.inf(select), -n(select), -inf); l_negativepart(x.inf >= 0) = inf; u_negativepart(x.inf >= 0) = -inf; u(u == 0) = +0; ## Compute the union l(oddandnegative) = min (l_positivepart(oddandnegative), ... -u_negativepart(oddandnegative)); u(oddandnegative) = max (u_positivepart(oddandnegative), ... -l_negativepart(oddandnegative)); l(emptyresult) = inf; u(emptyresult) = -inf; u(u == 0) = +0; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction function x = invrootrounded (z, n, direction) ## We cannot compute the inverse of the n-th root of z in a single step. ## Thus, we use three different ways for computation, each of which has an ## intermediate result with possible rounding errors and can't guarantee to ## produce a correctly rounded result. ## When we finally merge the 3 results, it is still not guaranteed to be ## correctly rounded. However, chances are good that one of the three ways ## produced a “relatively good” result. ## ## x1: z ^ (- 1 / n) ## x2: 1 / root (z, n) ## x3: root (1 / z, n) inv_n = 1 ./ infsup (n); if (direction > 0) x1 = z; select = z > 1; x1(select) = mpfr_function_d ('pow', direction, z(select), ... -inv_n.inf(select)); select = z < 1; x1(select) = mpfr_function_d ('pow', direction, z(select), ... -inv_n.sup(select)); else x1 = z; select = z > 1; x1(select) = mpfr_function_d ('pow', direction, z(select), ... -inv_n.sup(select)); select = z < 1; x1(select) = mpfr_function_d ('pow', direction, z(select), ... -inv_n.inf(select)); endif exact = issingleton (inv_n); x = z; x(exact) = x1(exact); inexact = not (exact); if (any (inexact(:))) x2 = mpfr_function_d ('rdivide', direction, 1, ... mpfr_function_d ('nthroot', -direction, ... z(inexact), n(inexact))); x3 = mpfr_function_d ('nthroot', direction, ... mpfr_function_d ('rdivide', direction, ... 1, z(inexact)), n(inexact)); ## Choose the most accurate result if (direction > 0) x(inexact) = min (min (x1(inexact), x2), x3); else x(inexact) = max (max (x1(inexact), x2), x3); endif endif endfunction %!assert (nthroot (infsup (25, 36), 2) == infsup (5, 6)); %!# correct use of signed zeros %!test %! x = nthroot (infsup (0), 2); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = nthroot (infsup (0, inf), -2); %! assert (signbit (inf (x))); %!test %! x = nthroot (infsup (0, inf), -3); %! assert (signbit (inf (x))); %!assert (nthroot (infsup (-1, 1), 2) == infsup (0, 1)); %!assert (nthroot (infsup (-1, 1), 3) == infsup (-1, 1)); %!assert (nthroot (infsup (-1, 1), -2) == infsup (1, inf)); %!assert (nthroot (infsup (-1, 1), -3) == infsup (-inf, inf)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.rootn; %! for testcase = [testcases]' %! assert (isequaln (... %! nthroot (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.rootn; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (nthroot (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.rootn; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! if (i > numel (in1)) %! i = i - numel (in1); %! in1 = [in1; in1]; %! in2 = [in2; in2]; %! out = [out; out]; %! endif %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (nthroot (in1, in2), out)); interval-3.2.0/inst/@infsup/numel.m0000644000000000000000000000372113316017127015351 0ustar 00000000000000## Copyright 2014-2016,2018 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} numel (@var{A}) ## @defmethodx {@@infsup} numel (@var{A}, @var{idx1}, @var{idx2}, @dots{}) ## ## Return the number of elements in the interval object @var{A}. ## ## Optionally, if indices @var{idx1}, @var{idx2}, @dots{} are supplied, return ## the number of elements that would result from indexing ## @code{A(idx1, idx2, @dots{})}. ## @seealso{@@infsup/length, @@infsup/size, @@infsup/rows, @@infsup/columns, @@infsup/end} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function result = numel (a, varargin) if (not (isa (a, "infsup"))) error ("invalid use of interval as indexing parameter to numel ()") endif result = numel (a.inf(varargin{:})); endfunction %!assert (numel (infsup ([])), 0); %!assert (numel (infsup (0)), 1); %!assert (numel (infsup (zeros (3, 1))), 3); %!assert (numel (infsup (zeros (1, 4))), 4); %!assert (numel (infsup (zeros (3, 4))), 12); %!assert (numel (infsup (ones (2, 3)), 3:5), 3); %!assert (numel (infsup (ones (2, 3)), ":", 2), 2); %!assert (numel (infsup (ones (2, 3)), 2, ":"), 3); %!# numel is called implicitly during this subsref expression (see bug #53375) %!assert (infsup ()(:).inf, inf); %!error numel (1, infsup(1));interval-3.2.0/inst/@infsup/overlap.m0000644000000000000000000001731313316017127015703 0ustar 00000000000000## Copyright 2014-2017 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {[@var{STATE}, @var{BITMASK}] =} overlap(@var{A}, @var{B}) ## ## Extensively compare the positions of intervals @var{A} and @var{B} on the ## real number line. ## ## Return the @var{STATE} as a string and the @var{BITMASK} of the state as an ## uint16 number, which represents one of the 16 possible states by taking a ## value 2^i (i = 0 … 15). ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @table @asis ## @item @code{bothEmpty}, 2^0 ## Both intervals are empty ## @item @code{firstEmpty}, 2^1 ## Interval @var{A} is empty and @var{B} is not ## @item @code{secondEmpty}, 2^2 ## Interval @var{A} is not empty, but @var{B} is ## @item @code{before}, 2^3 ## [- - - @var{A} - - -]@ @ @ [- - - @var{B} - - -] ## @item @code{meets}, 2^4 ## [- - - @var{A} - - -][- - - @var{B} - - -] ## @*Interval @var{A}'s upper boundary equals interval @var{B}'s lower boundary ## and neither consists of a single point only. ## @item @code{overlaps}, 2^5 ## [- - - @var{A} - - - [= = =] - - - @var{B} - - -] ## @item @code{starts}, 2^6 ## [[= = = @var{A} = = =] - - - @var{B} - - -] ## @item @code{containedBy}, 2^7 ## [- - - @var{B} - - - [= = = @var{A} = = =] - - -] ## @item @code{finishes}, 2^8 ## [- - - @var{B} - - - [= = = @var{A} = = =]] ## @item @code{equals}, 2^9 ## Both intervals are equal (and not empty) ## @item @code{finishedBy}, 2^10 ## [- - - @var{A} - - - [= = = @var{B} = = =]] ## @item @code{contains}, 2^11 ## [- - - @var{A} - - - [= = = @var{B} = = =] - - -] ## @item @code{startedBy}, 2^12 ## [[= = = @var{B} = = =] - - - @var{A} - - -] ## @item @code{overlappedBy}, 2^13 ## [- - - @var{B} - - - [= = =] - - - @var{A} - - -] ## @item @code{metBy}, 2^14 ## [- - - @var{B} - - -][- - - @var{A} - - -] ## @*Interval @var{A}'s lower boundary equals interval @var{B}'s upper boundary ## and neither consists of a single point only. ## @item @code{after}, 2^15 ## [- - - @var{B} - - -]@ @ @ [- - - @var{A} - - -] ## @end table ## ## @seealso{@@infsup/eq, @@infsup/subset, @@infsup/interior, @@infsup/disjoint} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function [state, bitmask] = overlap (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); endif emptya = isempty (a); emptyb = isempty (b); notempty = not (emptya | emptyb); comparison = {... "bothEmpty", (emptya & emptyb); ... "firstEmpty", (emptya & not (emptyb)); ... "secondEmpty", (emptyb & not (emptya)); ... "before", (notempty & a.sup < b.inf); ... "meets", ... (notempty & a.inf < a.sup & a.sup == b.inf & b.inf < b.sup); ... "overlaps", ... (notempty & a.inf < b.inf & b.inf < a.sup & a.sup < b.sup); ... "starts", (notempty & a.inf == b.inf & a.sup < b.sup); ... "containedBy", (notempty & b.inf < a.inf & a.sup < b.sup); ... "finishes", (notempty & b.inf < a.inf & a.sup == b.sup); ... "equals", (notempty & a.inf == b.inf & a.sup == b.sup); ... "finishedBy", (notempty & a.inf < b.inf & b.sup == a.sup); ... "contains", (notempty & a.inf < b.inf & b.sup < a.sup); ... "startedBy", (notempty & b.inf == a.inf & b.sup < a.sup); ... "overlappedBy", ... (notempty & b.inf < a.inf & a.inf < b.sup & b.sup < a.sup); ... "metBy", ... (notempty & b.inf < b.sup & b.sup == a.inf & a.inf < a.sup); ... "after", (notempty & b.sup < a.inf)}; if (nargout >= 2) bitmask = zeros (size (comparison{1, 2}), "uint16"); for i = 1 : rows (comparison) bitmask(comparison{i, 2}) = pow2 (16 - i); endfor endif state = cell (size (comparison{1, 2})); for i = 1 : rows (comparison) state(comparison{i, 2}) = comparison{i, 1}; endfor if (numel (state) == 1) state = state{1}; endif endfunction %!test %! [s, n] = overlap (infsup (), infsup ()); %! assert (s, "bothEmpty"); %! assert (n, uint16 (32768)); %!test %! [s, n] = overlap (infsup (), infsup (0)); %! assert (s, "firstEmpty"); %! assert (n, uint16 (16384)); %!test %! [s, n] = overlap (infsup (0), infsup ()); %! assert (s, "secondEmpty"); %! assert (n, uint16 (8192)); %!test %! [s, n] = overlap (infsup (1, 2), infsup (3, 4)); %! assert (s, "before"); %! assert (n, uint16 (4096)); %!test %! [s, n] = overlap (infsup (1, 2), infsup (2, 3)); %! assert (s, "meets"); %! assert (n, uint16 (2048)); %!test %! [s, n] = overlap (infsup (1, 3), infsup (2, 4)); %! assert (s, "overlaps"); %! assert (n, uint16 (1024)); %!test %! [s, n] = overlap (infsup (1, 2), infsup (1, 3)); %! assert (s, "starts"); %! assert (n, uint16 (512)); %!test %! [s, n] = overlap (infsup (2, 3), infsup (1, 4)); %! assert (s, "containedBy"); %! assert (n, uint16 (256)); %!test %! [s, n] = overlap (infsup (2, 3), infsup (1, 3)); %! assert (s, "finishes"); %! assert (n, uint16 (128)); %!test %! [s, n] = overlap (infsup (1, 2), infsup (1, 2)); %! assert (s, "equals"); %! assert (n, uint16 (64)); %!test %! [s, n] = overlap (infsup (1, 3), infsup (2, 3)); %! assert (s, "finishedBy"); %! assert (n, uint16 (32)); %!test %! [s, n] = overlap (infsup (1, 4), infsup (2, 3)); %! assert (s, "contains"); %! assert (n, uint16 (16)); %!test %! [s, n] = overlap (infsup (1, 3), infsup (1, 2)); %! assert (s, "startedBy"); %! assert (n, uint16 (8)); %!test %! [s, n] = overlap (infsup (2, 4), infsup (1, 3)); %! assert (s, "overlappedBy"); %! assert (n, uint16 (4)); %!test %! [s, n] = overlap (infsup (2, 3), infsup (1, 2)); %! assert (s, "metBy"); %! assert (n, uint16 (2)); %!test %! [s, n] = overlap (infsup (3, 4), infsup (1, 2)); %! assert (s, "after"); %! assert (n, uint16 (1)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.overlap; %! for testcase = [testcases]' %! assert (isequaln (... %! overlap (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.overlap; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = {testcases.out}'; %! assert (isequaln (overlap (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.overlap; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = {testcases.out}'; %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (overlap (in1, in2), out)); interval-3.2.0/inst/@infsup/plot.m0000644000000000000000000001171313316017127015207 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} plot (@var{X}, @var{Y}) ## @defmethodx {@@infsup} plot (@var{Y}) ## @defmethodx {@@infsup} plot (@var{X}, @var{Y}, @var{COLOR}) ## @defmethodx {@@infsup} plot (@var{X}, @var{Y}, @var{COLOR}, @var{EDGECOLOR}) ## ## Create a 2D-plot of intervals. ## ## If either of @var{X} or @var{Y} is an empty interval, nothing is plotted. ## If both @var{X} and @var{Y} are singleton intervals, a single point is ## plotted. If only one of @var{X} and @var{Y} is a singleton interval, a ## single line is plotted. If neither of @var{X} and @var{Y} is a singleton ## interval, a filled rectangle is plotted. ## ## If @var{X} or @var{Y} are arrays, each pair of elements is plotted ## separately. No connection of the interval areas is plotted, because that ## kind of interpolation would be wrong in general (in the sense that the ## actual values are enclosed by the plot). ## ## Without parameter @var{X}, the intervals in @var{Y} are plotted as points or ## lines, which are parallel to the y axis, at the coordinates ## @code{@var{X} = [1, …, n]}. ## ## If no @var{COLOR} is given, the current @command{colormap} is used. Use ## @var{COLOR} = @option{none} to disable plotting of filled rectangles. If an ## optional parameter @var{EDGECOLOR} is given, rectangles will have visible ## edges in a distinct color. ## ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-05-10 function plot (x, y, color, edgecolor) if (nargin > 4) print_usage (); return endif warning ("off", "interval:ImplicitPromote", "local"); if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (nargin >= 2 && not (isa (y, "infsupdec"))) y = infsupdec (y); endif if (nargin < 2) y = x; ## x = 1 ... n x = infsupdec (reshape (1 : numel (y.inf), size (y.inf))); endif if (nargin < 3 || isempty (color)) # don't use last row of colormap, which would often be just white color = colormap ()(ceil (rows (colormap ()) / 2), :); if (nargin < 4) # will only be used for lines and dots edgecolor = colormap ()(1, :); endif elseif (nargin < 4) # will only be used for lines and dots edgecolor = color; endif oldhold = ishold (); if (not (oldhold)) clf hold on endif pointsize = 3; edgewidth = 2; unwind_protect empty = isempty (x) | isempty (y); points = issingleton (x) & issingleton (y); lines = xor (issingleton (x), issingleton (y)) & not (empty); boxes = not (points | lines | empty); if (any (points(:))) scatter (x.inf(points), y.inf(points), ... pointsize, ... edgecolor, ... 'filled'); endif if (any (lines(:))) x_line = [vec(x.inf(lines)), vec(x.sup(lines))]'; y_line = [vec(y.inf(lines)), vec(y.sup(lines))]'; line (x_line, y_line, ... 'color', edgecolor, ... 'linewidth', edgewidth); endif if (any (boxes(:))) x_box = [vec(x.inf(boxes)), vec(x.sup(boxes))](:, [1 2 2 1])'; y_box = [vec(y.inf(boxes)), vec(y.sup(boxes))](:, [1 1 2 2])'; if (nargin < 4) edgecolor = 'none'; endif patch (x_box, y_box, [], ... 'linewidth', edgewidth, ... 'edgecolor', edgecolor, ... 'facecolor', color); endif unwind_protect_cleanup ## Reset hold state if (not (oldhold)) hold off endif end_unwind_protect endfunction %!# this test is rather pointless %!test %! clf %! plot (empty ()); %! close %!demo %! clf %! hold on %! plot (infsup (0), infsup (0)); %! plot (infsup (1, 2), infsup (0)); %! plot (infsup (0), infsup (1, 2)); %! plot (infsup (1, 2), infsup (1, 2)); %! axis ([-.5, 2.5, -.5, 2.5]); %! hold off %!demo %! clf %! plot (infsup (-rand (50, 1), +rand (50, 1))); %!demo %! clf %! hold on %! axis off %! range = infsup (0, 9); %! x = linspace (inf (range), sup (range), 250); %! X = mince (range, 9); %! f = @ (x) 0.5 * sin (x) .* x .^ 2; %! y = f (x); %! Y = f (X); %! plot (range, f (range), [42 161 152]/255); %! plot (X, Y, [238 232 213]/255, [88 110 117]/255); %! plot (x, y, '-', 'color', [220 50 47]/255, 'linewidth', 2); %! hold off interval-3.2.0/inst/@infsup/plot3.m0000644000000000000000000002363013316017127015273 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} plot3 (@var{X}, @var{Y}, @var{Z}) ## @defmethodx {@@infsup} plot3 (@var{X}, @var{Y}, @var{Z}, @var{COLOR}) ## @defmethodx {@@infsup} plot3 (@var{X}, @var{Y}, @var{Z}, @var{COLOR}, @var{EDGECOLOR}) ## ## Create a 3D-plot of intervals. ## ## If either of @var{X}, @var{Y} or @var{Z} is an empty interval, nothing is ## plotted. If all are singleton intervals, a single point is plotted. If ## two intervals are a singleton interval, a line is plotted. If one interval ## is a singleton interval, a rectangle is plotted. If neither of @var{X}, ## @var{Y} and @var{Z} is a singleton interval, a cuboid is plotted. ## ## When interval arrays of equal size are given, each triple of elements is ## printed separately. ## ## No connection of the interval areas is plotted, because that kind of ## interpolation would be wrong in general (in the sense that the actual values ## are enclosed by the plot). ## ## If no @var{COLOR} is given, the current @command{colormap} is used. Use ## @var{COLOR} = @option{none} to disable plotting of filled rectangles. If an ## optional parameter @var{EDGECOLOR} is given, rectangles and cuboids will ## have visible edges in a distinct color. ## ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-05-17 function plot3 (x, y, z, color, edgecolor) if (nargin < 3 || nargin > 5) print_usage (); return endif warning ("off", "interval:ImplicitPromote", "local"); if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif if (not (isa (z, "infsupdec"))) z = infsupdec (z); endif if (nargin < 4 || isempty (color)) color = 'interp'; if (nargin < 5) # will only be used for lines and dots edgecolor = colormap ()(1, :); endif elseif (nargin < 5) # will only be used for lines and dots edgecolor = color; endif oldhold = ishold (); if (not (oldhold)) clf hold on endif pointsize = 3; edgewidth = 2; unwind_protect empty = isempty (x) | isempty (y) | isempty (z); number_of_singletons = issingleton (x) + issingleton (y) + issingleton (z); points = number_of_singletons == 3; lines = number_of_singletons == 2 & not (empty); boxes = number_of_singletons <= 1 & not (empty); if (any (points(:))) scatter3 (x.inf(points), y.inf(points), z.inf(points), ... pointsize, ... edgecolor, ... 'filled'); endif if (any (lines(:))) x_line = [vec(x.inf(lines)), vec(x.sup(lines))]'; y_line = [vec(y.inf(lines)), vec(y.sup(lines))]'; z_line = [vec(z.inf(lines)), vec(z.sup(lines))]'; line (x_line, y_line, z_line, ... 'linewidth', edgewidth, ... 'color', edgecolor); endif ## + z ## | ## ## B--------D ## /| /| ## / | / | ## / A-----/--C -+ ## F--------H / y ## | / | / ## |/ |/ ## E--------G ## ## / ## + x ## The variables A through H help indexing the relevant rows in vertices. [A, B, C, D, E, F, G, H] = num2cell ((0 : 7) * (sum (boxes(:)))) {:}; vertices = [vec(x.inf(boxes)), vec(y.inf(boxes)), vec(z.inf(boxes)); ... vec(x.inf(boxes)), vec(y.inf(boxes)), vec(z.sup(boxes)); ... vec(x.inf(boxes)), vec(y.sup(boxes)), vec(z.inf(boxes)); ... vec(x.inf(boxes)), vec(y.sup(boxes)), vec(z.sup(boxes)); ... vec(x.sup(boxes)), vec(y.inf(boxes)), vec(z.inf(boxes)); ... vec(x.sup(boxes)), vec(y.inf(boxes)), vec(z.sup(boxes)); ... vec(x.sup(boxes)), vec(y.sup(boxes)), vec(z.inf(boxes)); ... vec(x.sup(boxes)), vec(y.sup(boxes)), vec(z.sup(boxes))]; if (any (boxes(:))) ## To support gnuplot as a plotting backend, we have to use ## triangular instead of rectangular patches (see bug #45594). faces = zeros (0, 3); ## x-y rectangle at z.inf select = vec (find (x.inf(boxes) < x.sup(boxes) & ... y.inf(boxes) < y.sup(boxes))); faces = [faces; ... A+select, C+select, G+select; ... G+select, E+select, A+select]; ## x-z rectangle at y.inf select = vec (find (x.inf(boxes) < x.sup(boxes) & ... z.inf(boxes) < z.sup(boxes))); faces = [faces; ... A+select, E+select, F+select; ... F+select, B+select, A+select]; ## y-z rectangle at x.inf select = vec (find (y.inf(boxes) < y.sup(boxes) & ... z.inf(boxes) < z.sup(boxes))); faces = [faces; ... A+select, B+select, D+select; ... D+select, C+select, A+select]; ## The cuboids have 6 sides instead of only one select = vec (find (x.inf(boxes) < x.sup(boxes) & ... y.inf(boxes) < y.sup(boxes) & ... z.inf(boxes) < z.sup(boxes))); faces = [faces; ... ## x-y rectangle at z.sup B+select, F+select, H+select; ... H+select, D+select, B+select; ... ## x-z rectangle at y.sup C+select, D+select, H+select; H+select, G+select, C+select; ... ## y-z rectangle at x.inf E+select, G+select, H+select; ... H+select, F+select, E+select]; patch ('Vertices', vertices, ... 'Faces', faces, ... 'EdgeColor', 'none', ... 'FaceColor', color, ... 'FaceVertexCData', vertices (:, 3)); ## Draw edges for the rectangles. ## ## B B--------D D ## /| | | /| ## / | | | / | ## / A A--------C/ C or A--------C ## F / F--------H H / / / ## | / | | | / / / ## |/ | | |/ / / ## E E--------G G E--------G ## ## Note: The edges A-B, C-D, E-F, and G-H may be drawn twice. ## However, the benefit is that this approach produces only closed ## routes between the points, which is beneficial since it prevents ## graphics artifacts from line endings. Line endings might be rendered ## differently and we want to prevent that. if (nargin >= 5) faces = zeros (0, 4); ## x-y rectangle at z.inf select = vec (find (x.inf(boxes) < x.sup(boxes) & ... y.inf(boxes) < y.sup(boxes) & ... z.inf(boxes) == z.sup(boxes))); faces = [faces; ... A+select, C+select, G+select, E+select]; ## x-z rectangle at y.inf select = vec (find (x.inf(boxes) < x.sup(boxes) & ... z.inf(boxes) < z.sup(boxes))); faces = [faces; ... A+select, E+select, F+select, B+select]; ## y-z rectangle at x.inf select = vec (find (y.inf(boxes) < y.sup(boxes) & ... z.inf(boxes) < z.sup(boxes))); faces = [faces; ... A+select, B+select, D+select, C+select]; ## The cuboids have 6 sides instead of only one. ## It suffices to draw edges for 2 more sides (4 sides in total). select = vec (find (x.inf(boxes) < x.sup(boxes) & ... y.inf(boxes) < y.sup(boxes) & ... z.inf(boxes) < z.sup(boxes))); faces = [faces; ... ## x-z rectangle at y.sup C+select, D+select, H+select, G+select; ... ## y-z rectangle at x.inf E+select, G+select, H+select, F+select]; patch ('Vertices', vertices, ... 'Faces', faces, ... 'EdgeColor', edgecolor, ... 'LineWidth', edgewidth, ... 'FaceColor', 'none'); endif endif unwind_protect_cleanup ## Reset hold state and set the viewpoint for 3-D graphs (the latter would ## not happen automatically since above functions operate on 2-D objects). if (not (oldhold)) hold off view (3) endif end_unwind_protect endfunction %!# this test is rather pointless %!test %! clf %! plot3 (empty (), empty (), empty ()); %! close %!demo %! clf %! colormap hot %! x = y = z = (1 : 3) + infsup ("[0, 1]"); %! plot3 (x, y, z); %! grid on %!demo %! clf %! colormap jet %! z = 1 : 8; %! x = y = infsup ("[-1, 1]") ./ z; %! plot3 (x, y, z); %! grid on %!demo %! clf %! [x, y] = meshgrid (mince (infsup ("[-5, 5]"), 20), ... %! mince (infsup ("[0.1, 5]"), 10)); %! z = log (hypot (x, y)); %! blue = [38 139 210]/255; base2 = [238 232 213]/255; %! plot3 (x, y, z, base2, blue); %! view (330, 12) %!demo %! clf %! [x, y] = meshgrid (midrad (-10 : 0.5 : 10, .25)); %! z = sin (hypot (x, y)) .* hypot (x, y); %! plot3 (mid (x), mid (y), z); %! grid on interval-3.2.0/inst/@infsup/plus.m0000644000000000000000000000607713316017127015223 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} plus (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} + @var{Y}} ## ## Add all numbers of interval @var{X} to all numbers of @var{Y}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (2, 3); ## y = infsup (1, 2); ## x + y ## @result{} ans = [3, 5] ## @end group ## @end example ## @seealso{@@infsup/minus} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function x = plus (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); elseif (isa (y, "infsupdec")) ## Workaround for bug #42735 result = plus (x, y); return endif l = mpfr_function_d ('plus', -inf, x.inf, y.inf); u = mpfr_function_d ('plus', +inf, x.sup, y.sup); emptyresult = isempty (x) | isempty (y); l (emptyresult) = inf; u (emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (infsup (2, 3) + infsup (1, 2) == infsup (3, 5)); %!# correct use of signed zeros %!test %! x = plus (infsup (0), infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.add; %! for testcase = [testcases]' %! assert (isequaln (... %! plus (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.add; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (plus (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.add; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (plus (in1, in2), out)); interval-3.2.0/inst/@infsup/polyval.m0000644000000000000000000001201113316017127015707 0ustar 00000000000000## Copyright 1995 Rolf Hammer, Matthias Hocks, Dietmar Ratz ## Copyright 1990-2000 Institut für Angewandte Mathematik, ## Universität Karlsruhe, Germany ## Copyright 2000-2014 Wissenschaftliches Rechnen/Softwaretechnologie, ## Universität Wuppertal, Germany ## Copyright 2015-2016 Oliver Heimlich ## ## This program is derived from RPolyEval in CXSC, C++ library for eXtended ## Scientific Computing (V 2.5.4), which is distributed under the terms of ## LGPLv2+. Migration to Octave code has been performed by Oliver Heimlich. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} polyval (@var{P}, @var{X}) ## ## Evaluate polynomial @var{P} with argument @var{X}. ## ## Horner's scheme is used to evaluate a first approximation. The result is ## improved with iterative refinement. ## ## Accuracy: The result is a tight enclosure for polynomials of degree 1 or ## less. For polynomials of higher degree the result is a valid enclosure. ## For @var{X} being no singleton interval, the algorithm suffers from the ## dependency problem. ## ## @example ## @group ## output_precision (16, 'local') ## polyval (infsup ([3 4 2 1]), 42) # 3x^3 + 4x^2 + 2x^1 + 1 | x = 42 ## @result{} [229405] ## polyval (infsup ([3 4 2 1]), "42?") # ... | x = 41.5 .. 42.5 ## @result{} [221393.125, 237607.875] ## @end group ## @end example ## @seealso{@@infsup/fzero} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-05-29 function result = polyval (p, x) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (p, "infsup"))) p = infsup (p); endif if (not (isscalar (x))) error ('point of evaluation X must be a scalar') endif if (not (isvector (p))) error ('polynomial P must be a vector of coefficients') endif if (isempty (x)) result = x; endif; n = numel (p); switch (n) case 0 # empty sum result = infsup (0); return case 1 # p .* x.^0 result = p; return case 2 # p(1) .* x.^1 + p(2) .* x.^0 result = fma (x, subsref (p, substruct ("()", {1})), ... subsref (p, substruct ("()", {2}))); return endswitch if (x == 0) result = subsref (p, substruct ("()", {n})); return elseif (x == 1) result = sum (p); return elseif (x == -1) result = dot (p, (-1) .^ ((n : -1 : 1) - 1)); return endif kMax = 20; idxNext.type = '()'; idxLast.type = '()'; ## Compute first approximation using Horner's scheme yy = infsup (zeros (n, 1)); idxNext.subs = {1}; result = subsref (p, idxNext); yy = subsasgn (yy, idxNext, result); for i = 2 : n idxNext.subs = {i}; result = fma (result, x, subsref (p, idxNext)); yy = subsasgn (yy, idxNext, result); endfor y = zeros (n, kMax); for k = 1 : kMax lastresult = result; if (isempty (result)) break endif ## Iterative refinement ## Store middle of residual as the next correction of y y(:, k) = mid (yy); ## Computation of the residual [r] and ## evaluation of the interval system A*[y] = [r] yy = infsup (zeros (n, 1)); for i = 2 : n idxNext.subs = {i}; idxLast.subs = {i-1}; coef = subsref (p, idxNext); yy = subsasgn (yy, idxNext, dot ([subsref(yy, idxLast), ... coef, y(i, 1 : k), ... y(i - 1, 1 : k)], ... [x, ... 1, ... -ones(1, k), x.*ones(1, k)])); endfor ## Determination of a new enclosure of p (x) idxLast.subs = {n}; result = intersect (result, sum ([subsref(yy, idxLast), y(n, 1 : k)])); if (eq (result, lastresult)) ## No improvement break endif if (mpfr_function_d ('plus', +inf, inf (result), pow2 (-1074)) >= ... sup (result)) ## 1 ULP accuracy reached break endif endfor endfunction %!assert (polyval (infsup (42), 0) == 42); %!assert (polyval (infsup ([42 42]), 0) == 42); %!assert (polyval (infsup ([42 42]), 1) == 84); %!assert (polyval (infsup ([42 42]), -1) == 0); %!assert (polyval (infsup ([-42 42 42]), .5) == -42*0.5^2 + 42*0.5 + 42); %!assert (polyval (infsup (vec (pascal (3))), 0.1) == "[0X6.502E9A7231A08P+0, 0X6.502E9A7231A0CP+0]"); interval-3.2.0/inst/@infsup/postpad.m0000644000000000000000000000567313316017127015713 0ustar 00000000000000## Copyright 2015-2017 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} postpad (@var{X}, @var{L}) ## @defmethodx {@@infsup} postpad (@var{X}, @var{L}, @var{C}) ## @defmethodx {@@infsup} postpad (@var{X}, @var{L}, @var{C}, @var{DIM}) ## ## Append the scalar interval value @var{C} to the interval vector @var{X} ## until it is of length @var{L}. If @var{C} is not given, a value of 0 is ## used. ## ## If @code{length (@var{X}) > L}, elements from the end of @var{X} are removed ## until an interval vector of length @var{L} is obtained. ## ## If @var{X} is an interval matrix, elements are appended or removed from each ## row or column. ## ## If the optional argument DIM is given, operate along this dimension. ## ## If DIM is larger than the dimension of X, the result will have DIM ## dimensions. ## ## @example ## @group ## postpad (infsup (1 : 3), 5, 42) ## @result{} ans = 1×5 interval vector ## [1] [2] [3] [42] [42] ## @end group ## @end example ## @seealso{@@infsup/reshape, @@infsup/cat, @@infsup/prepad, @@infsup/resize} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-19 function x = postpad (x, len, c, dim) if (nargin < 2 || nargin > 4) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (isa (len, "infsup")) error ("interval:InvalidOperand", "postpad: len must not be an interval"); endif if (nargin < 3) c = infsup (0); elseif (not (isa (c, "infsup"))) c = infsup (c); endif if (nargin < 4) dim = find (size (x.inf) ~= 1, 1); if (isempty (dim)) dim = 1; endif elseif (isa (dim, "infsup")) error ("interval:InvalidOperand", "postpad: dim must not be an interval"); endif x.inf = postpad (x.inf, len, c.inf, dim); x.sup = postpad (x.sup, len, c.sup, dim); endfunction %!assert (postpad (infsup (1:3), 4, 4) == infsup (1:4)); %!assert (postpad (infsup (1:3), 2, 4) == infsup (1:2)); %!test %! if (compare_versions (OCTAVE_VERSION (), "4.0.0", ">=")) %! assert (postpad (infsup (0), 10, 0, 3) == infsup (zeros (1, 1, 10))) %! else %! # In Octave 3.8.x it is not possible to increase the number of dimensions. %! endif %!assert (postpad (infsup (zeros (1, 2, 2)), 3) == infsup (zeros (1, 3, 2))); interval-3.2.0/inst/@infsup/pow.m0000644000000000000000000001137113316017127015036 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} pow (@var{X}, @var{Y}) ## ## Compute the simple power function on intervals defined by ## @code{exp (@var{Y} * log (@var{X}))}. ## ## The function is only defined where @var{X} is positive or where @var{X} is ## zero and @var{Y} is positive. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## pow (infsup (5, 6), infsup (2, 3)) ## @result{} ans = [25, 216] ## @end group ## @end example ## @seealso{@@infsup/pown, @@infsup/pow2, @@infsup/pow10, @@infsup/exp, @@infsup/power} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = pow (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, y.inf))) x.inf = ones (size (y.inf)) .* x.inf; x.sup = ones (size (y.inf)) .* x.sup; y.inf = ones (size (x.inf)) .* y.inf; y.sup = ones (size (x.inf)) .* y.sup; endif ## Intersect with domain x = intersect (x, infsup (0, inf)); y.inf(x.sup == 0) = max (0, y.inf(x.sup == 0)); y.sup(y.inf > y.sup) = -inf; y.inf(y.inf > y.sup) = inf; ## Simple cases with no limit values, see Table 3.3 in ## Heimlich, Oliver. 2011. “The General Interval Power Function.” ## Diplomarbeit, Institute for Computer Science, University of Würzburg. ## http://exp.ln0.de/heimlich-power-2011.htm. ## ## The min/max is located at the boundaries of the input intervals. Like with ## the times function we do not start a case by case analysis but simply ## compute all four combinations for each result boundary. ## ## We have to compensate for boundary x.inf = -0 with the abs function. ## Otherwise the limit values of the MPFR pow function would be wrong. l = min (min (min (... mpfr_function_d ('pow', -inf, abs (x.inf), y.inf), ... mpfr_function_d ('pow', -inf, abs (x.inf), y.sup)), ... mpfr_function_d ('pow', -inf, x.sup, y.inf)), ... mpfr_function_d ('pow', -inf, x.sup, y.sup)); u = max (max (max (... mpfr_function_d ('pow', +inf, abs (x.inf), y.inf), ... mpfr_function_d ('pow', +inf, abs (x.inf), y.sup)), ... mpfr_function_d ('pow', +inf, x.sup, y.inf)), ... mpfr_function_d ('pow', +inf, x.sup, y.sup)); emptyresult = isempty (x) | isempty (y) | (x.sup == 0 & y.sup == 0); l(emptyresult) = inf; u(emptyresult) = -inf; ## Fix 0 ^ positive = 0 u(x.sup == 0 & u == 1) = 0; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (pow (infsup (5, 6), infsup (2, 3)) == infsup (25, 216)); %!# correct use of signed zeros %!test %! x = pow (infsup (0), infsup (1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.pow; %! for testcase = [testcases]' %! assert (isequaln (... %! pow (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.pow; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (pow (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.pow; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pow (in1, in2), out)); interval-3.2.0/inst/@infsup/pow10.m0000644000000000000000000000520013316017127015171 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} pow10 (@var{X}) ## ## Compute @code{10^x} for all numbers in @var{X}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## pow10 (infsup (5)) ## @result{} ans = [1e+05] ## @end group ## @end example ## @seealso{@@infsup/log10, @@infsup/pow, @@infsup/pow2, @@infsup/exp} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = pow10 (x) if (nargin ~= 1) print_usage (); return endif ## pow10 is monotonically increasing from (-inf, 0) to (inf, inf) l = mpfr_function_d ('pow10', -inf, x.inf); # this works for empty intervals u = mpfr_function_d ('pow10', +inf, x.sup); # ... this does not l(l == 0) = -0; u(isempty (x)) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %! assert (pow10 (infsup (5)) == infsup (100000)); %!# correct use of signed zeros %!test %! x = pow10 (infsup (-inf, -realmax)); %! assert (signbit (inf (x))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.exp10; %! for testcase = [testcases]' %! assert (isequaln (... %! pow10 (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.exp10; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (pow10 (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.exp10; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pow10 (in1), out)); interval-3.2.0/inst/@infsup/pow2.m0000644000000000000000000000515213316017127015120 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} pow2 (@var{X}) ## ## Compute @code{2^x} for all numbers in @var{X}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## pow2 (infsup (5)) ## @result{} ans = [32] ## @end group ## @end example ## @seealso{@@infsup/log2, @@infsup/pow, @@infsup/pow10, @@infsup/exp} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function x = pow2 (x) if (nargin ~= 1) print_usage (); return endif ## pow2 is monotonically increasing from (-inf, 0) to (inf, inf) l = mpfr_function_d ('pow2', -inf, x.inf); # this works for empty intervals u = mpfr_function_d ('pow2', +inf, x.sup); # ... this does not l(l == 0) = -0; u(isempty (x)) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %! assert (pow2 (infsup (5)) == infsup (32)); %!# correct use of signed zeros %!test %! x = pow2 (infsup (-inf, -realmax)); %! assert (signbit (inf (x))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.exp2; %! for testcase = [testcases]' %! assert (isequaln (... %! pow2 (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.exp2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (pow2 (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.exp2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pow2 (in1), out)); interval-3.2.0/inst/@infsup/power.m0000644000000000000000000002464613316017127015376 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} power (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} .^ @var{Y}} ## ## Compute the general power function on intervals, which is defined for ## (1) any positive base @var{X}; (2) @code{@var{X} = 0} when @var{Y} is ## positive; (3) negative base @var{X} together with integral exponent @var{Y}. ## ## This definition complies with the common complex valued power function, ## restricted to the domain where results are real, plus limit values where ## @var{X} is zero. The complex power function is defined by ## @code{exp (@var{Y} * log (@var{X}))} with initial branch of complex ## logarithm and complex exponential function. ## ## Warning: This function is not defined by IEEE Std 1788-2015. However, it ## has been published as “pow2” in O. Heimlich, M. Nehmeier, J. Wolff von ## Gudenberg. 2013. “Variants of the general interval power function.” ## Soft Computing. Volume 17, Issue 8, pp 1357–1366. ## Springer Berlin Heidelberg. DOI 10.1007/s00500-013-1008-8. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## infsup (-5, 6) .^ infsup (2, 3) ## @result{} ans = [-125, +216] ## @end group ## @end example ## @seealso{@@infsup/pow, @@infsup/pown, @@infsup/pow2, @@infsup/pow10, @@infsup/exp} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2011 function z = power (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); elseif (isa (y, "infsupdec")) ## Workaround for bug #42735 z = power (x, y); return endif ## Short circuit integral powers, e.g., x.^2 if (any ((y.inf == 0)(:))) ## can't use pown, because 0^0 must evaluate to [Empty] elseif (any ((y.inf ~= y.sup)(:)) || ... any ((not (isfinite (y.inf)))(:)) || ... any ((fix (y.inf) ~= y.inf))(:)) ## can't use pown, because y is no integer else z = pown (x, y.inf); return endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, y.inf))) x.inf = ones (size (y.inf)) .* x.inf; x.sup = ones (size (y.inf)) .* x.sup; y.inf = ones (size (x.inf)) .* y.inf; y.sup = ones (size (x.inf)) .* y.sup; endif idx.type = "()"; emptyresult = x.inf == inf | y.inf == inf | ... (x.inf == 0 & x.sup == 0 & y.sup <= 0); zPlus = pow (x, y); # pow is only defined for x > 0 zContainsZero = y.inf > 0 & x.inf <= 0 & x.sup >= 0; zMinus = repmat (infsup (), size (x.inf)); xMinusWithIntegerY = not (emptyresult) & x.inf < 0 & ... not (isfinite (y.inf) & isfinite (y.sup) & ... ceil (y.inf) > floor (y.sup)); if (any (xMinusWithIntegerY(:))) ySingleInteger = isfinite (y.inf) & isfinite (y.sup) & ... ceil (y.inf) == floor (y.sup); ## y contains a single integer idx.subs = {xMinusWithIntegerY & ySingleInteger}; if (any (idx.subs{1}(:))) xMinus = intersect (subsref (x, idx), ... # intersect to infsup (-inf, 0)); # speed up computation zMinus = subsasgn (zMinus, idx, ... pown (xMinus, ceil (subsref (y.inf, idx)))); endif ## y contains several integers idx.subs = {xMinusWithIntegerY & not(ySingleInteger)}; if (any (idx.subs{1}(:))) zMinus = subsasgn (zMinus, idx, ... multipleintegers (subsref (x, idx), ... subsref (y, idx))); endif endif z = union (zMinus, zPlus); idx.subs = {zContainsZero}; z = subsasgn (z, idx, union (subsref (z, idx), 0)); z.inf(emptyresult) = inf; z.sup(emptyresult) = -inf; endfunction function z = multipleintegers (x, y) ## Value of power on NEGATIVE base and multiple integral exponents ## Intersect to simplify computation x = intersect (x, infsup (-inf, 0)); y = intersect (ceil (y), floor (y)); assert (all (all (y.inf < y.sup & x.inf < 0))); ## Implements Table 3.4 in ## Heimlich, Oliver. 2011. “The General Interval Power Function.” ## Diplomarbeit, Institute for Computer Science, University of Würzburg. ## http://exp.ln0.de/heimlich-power-2011.htm. z = repmat (infsup (), size (x.inf)); idx.type = "()"; idx.subs = {(x.sup <= -1 & y.sup <= 0)}; if (any (idx.subs{1}(:))) xsup_idx = subsref (x.sup, idx); y_idx = subsref (y, idx); z = subsasgn (z, idx, twointegers (xsup_idx, goe (y_idx), gee (y_idx))); endif idx.subs = {(-1 <= x.inf & 0 <= y.inf)}; if (any (idx.subs{1}(:))) xinf_idx = subsref (x.inf, idx); y_idx = subsref (y, idx); z = subsasgn (z, idx, twointegers (xinf_idx, loe (y_idx), lee (y_idx))); endif idx.subs = {((x.sup <= -1 | (x.inf < -1 & -1 < x.sup)) & ... ((0 <= y.inf & not (-1 <= x.inf)) | (y.inf <= -1 & 1 <= y.sup)))}; if (any (idx.subs{1}(:))) xinf_idx = subsref (x.inf, idx); y_idx = subsref (y, idx); z = subsasgn (z, idx, twointegers (xinf_idx, goe (y_idx), gee (y_idx))); endif idx.subs = {(((x.inf < -1 & -1 < x.sup) | -1 <= x.inf) & ... ((y.inf <= -1 & 1 <= y.sup) | (y.sup <= 0 & not (x.sup <= -1))))}; if (any (idx.subs{1}(:))) xsup_idx = subsref (x.sup, idx); y_idx = subsref (y, idx); z = subsasgn (z, idx, union (subsref (z, idx), ... twointegers (xsup_idx, loe (y_idx), ... lee (y_idx)))); endif endfunction function z = twointegers (base, oddexponent, evenexponent) ## Range of power on single NEGATIVE base and two integral exponents ## ## twointegers (base, oddexponent, evenexponent) returns the interval ## [-abs(base) ^ oddexponent, abs(base) ^ evenexponent] with correctly ## rounded boundaries. ## ## twointegers (0, oddexponent, evenexponent) returns the limit value of ## [-abs(base) ^ oddexponent, abs(base) ^ evenexponent] for base -> 0. ## ## twointegers (-inf, oddexponent, evenexponent) returns the limit value of ## [-abs(base) ^ oddexponent, abs(base) ^ evenexponent] for base -> -inf. ## ## Note: oddexponent must not necessarily be odd, since it can be an ## overestimation of an actual odd exponent, if its magnitude is > 2^53. assert (all (all (oddexponent ~= 0))); assert (all (all (not (isfinite (oddexponent) & isfinite (evenexponent)) | ... abs (oddexponent - evenexponent) <= 1))); base = abs (base); z = infsup (zeros (size (base))); z.inf(base == 0 & oddexponent < 0) = -inf; z.sup(base == 0 & evenexponent < 0) = inf; z.sup(base == 0 & evenexponent == 0) = 1; z.inf(base == inf & oddexponent > 0) = -inf; z.sup(base == inf & evenexponent > 0) = inf; z.sup(base == inf & evenexponent == 0) = 1; z.sup(base == 1) = 1; z.sup(0 < base & base < 1 & evenexponent <= 0) = inf; z.sup(1 < base & base < inf & evenexponent >= 0) = inf; select = 0 < base & base < inf & isfinite (evenexponent); if (any (select(:))) z.sup(select) = sup (pown (infsup (base(select)), evenexponent(select))); endif z.inf(base == 1) = -1; z.inf(0 < base & base < 1 & oddexponent <= 0) = -inf; z.inf(1 < base & base < inf & oddexponent >= 0) = -inf; bigexponent = oddexponent == evenexponent; select = 0 < base & base < inf & bigexponent; z.inf(select) = -z.sup(select); select = 0 < base & base < inf & isfinite (oddexponent) & not (bigexponent); if (any (select(:))) z.inf(select) = -sup (pown (infsup (base(select)), oddexponent(select))); endif endfunction function e = goe (y) ## GOE Greatest odd exponent in interval y e = floor (y.sup); even = rem (e, 2) == 0; e(even) = mpfr_function_d ('minus', +inf, e(even), 1); e(e < y.inf) = nan (); # no odd number in interval endfunction function e = gee (y) ## GEE Greatest even exponent in interval y e = floor (y.sup); odd = rem (e, 2) ~= 0; e(odd) = mpfr_function_d ('minus', +inf, e(odd), 1); e(e < y.inf) = nan (); # no even number in interval endfunction function e = loe (y) ## LOE Least odd exponent in interval y e = ceil (y.inf); even = rem (e, 2) == 0; e(even) = mpfr_function_d ('plus', -inf, e(even), 1); e(e > y.sup) = nan (); # no odd number in interval endfunction function e = lee (y) ## LOE Least even exponent in interval y e = ceil (y.inf); odd = rem (e, 2) ~= 0; e(odd) = mpfr_function_d ('plus', -inf, e(odd), 1); e(e > y.sup) = nan (); # no odd number in interval endfunction %!# from the documentation string %!assert (infsup (-5, 6) .^ infsup (2, 3) == infsup (-125, 216)); %!assert (infsup (-10, 0) .^ infsup (0, 1:8) == infsup ([-1e1, -1e1, -1e3, -1e3, -1e5, -1e5, -1e7, -1e7], [1e0, 1e2, 1e2, 1e4, 1e4, 1e6, 1e6, 1e8])); %!# correct use of signed zeros %!test %! x = power (infsup (0), infsup (1)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sqr; %! for testcase = [testcases]' %! assert (isequaln (... %! power (testcase.in{1}, 2), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sqr; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (power (in1, 2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sqr; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (power (in1, 2), out)); interval-3.2.0/inst/@infsup/pown.m0000644000000000000000000001264513316017127015221 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} pown (@var{X}, @var{P}) ## ## Compute the monomial @code{x^@var{P}} for all numbers in @var{X}. ## ## Monomials are defined for all real numbers and the special monomial ## @code{@var{P} == 0} evaluates to @code{1} everywhere. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## pown (infsup (5, 6), 2) ## @result{} ans = [25, 36] ## @end group ## @end example ## @seealso{@@infsup/pow, @@infsup/pow2, @@infsup/pow10, @@infsup/exp} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function result = pown (x, p) if (nargin ~= 2) print_usage (); return endif if (not (isnumeric (p)) || any ((fix (p) ~= p)(:))) error ("interval:InvalidOperand", "pown: exponent is not an integer"); endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, p))) x.inf = ones (size (p)) .* x.inf; x.sup = ones (size (p)) .* x.sup; p = ones (size (x.inf)) .* p; endif result = x; % already correct for p == 1 select = (p == 0 & not (isempty (x))); result.inf(select) = result.sup(select) = 1; idx.type = "()"; idx.subs = {(p == 2)}; # x^2 if (any (idx.subs{1}(:))) result = subsasgn (result, idx, sqr (subsref (x, idx))); endif idx.subs = {(p == -1)}; # x^-1 = 1./x if (any (idx.subs{1}(:))) result = subsasgn (result, idx, 1 ./ subsref (x, idx)); endif idx.subs = {(rem (p, 2) == 0 & p ~= 2 & p ~= 0)}; if (any (idx.subs{1}(:))) # p even x_mig = mig (subsref (x, idx)); x_mig(isnan (x_mig)) = inf; x_mag = mag (subsref (x, idx)); x_mag(isnan (x_mag)) = -inf; x.inf = subsasgn (x.inf, idx, x_mig); x.sup = subsasgn (x.sup, idx, x_mag); result = subsasgn (result, idx, pow (subsref (x, idx), subsref (p, idx))); endif idx.subs = {(rem (p, 2) ~= 0 & p ~= -1)}; if (any (idx.subs{1}(:))) # p odd x_idx = subsref (x, idx); p_idx = infsup (subsref (p, idx)); result = subsasgn (result, idx, ... union (pow (x_idx, p_idx), ... -pow (-x_idx, p_idx))); endif ## Special case: x = [0]. The pow function used above would be undefined. select = (p > 0 & x.inf == 0 & x.sup == 0); result.inf(select) = -0; result.sup(select) = +0; endfunction function x = sqr (x) ## Compute the square for each entry in @var{X}. ## ## Accuracy: The result is a tight enclosure. l = mpfr_function_d ('sqr', -inf, mig (x)); u = mpfr_function_d ('sqr', +inf, mag (x)); emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (pown (infsup (5, 6), 2) == infsup (25, 36)); %!assert (pown (infsup (-2, 1), 2) == infsup (0, 4)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sqr; %! for testcase = [testcases]' %! assert (isequaln (... %! pown (testcase.in{1}, 2), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sqr; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (pown (in1, 2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sqr; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pown (in1, 2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.pown; %! for testcase = [testcases]' %! assert (isequaln (... %! pown (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.pown; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (pown (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.pown; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pown (in1, in2), out)); interval-3.2.0/inst/@infsup/pownrev.m0000644000000000000000000001414113316017127015727 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} pownrev (@var{C}, @var{X}, @var{P}) ## @deftypemethodx {@@infsup} {@var{X} =} pownrev (@var{C}, @var{P}) ## ## Compute the reverse monomial @code{x^@var{P}}. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{pown (x, @var{P}) ∈ @var{C}}. ## ## Accuracy: The result is a valid enclosure. The result is a tight ## enclosure for @var{P} ≥ -2. The result also is a tight enclosure if the ## reciprocal of @var{P} can be computed exactly in double-precision. ## ## @seealso{@@infsup/pown} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = pownrev (c, x, p) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) p = x; x = infsup (-inf, inf); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isnumeric (p)) || any ((fix (p) ~= p)(:))) error ("interval:InvalidOperand", "pownrev: exponent is not an integer"); endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, c.inf))) x.inf = ones (size (c.inf)) .* x.inf; x.sup = ones (size (c.inf)) .* x.sup; c.inf = ones (size (x.inf)) .* c.inf; c.sup = ones (size (x.inf)) .* c.sup; endif if (not (size_equal (x.inf, p))) x.inf = ones (size (p)) .* x.inf; x.sup = ones (size (p)) .* x.sup; c.inf = ones (size (p)) .* c.inf; c.sup = ones (size (p)) .* c.sup; p = ones (size (x.inf)) .* p; endif even = mod (p, 2) == 0; odd = not (even); result = x; ## x^0 == 1 result.inf(p == 0 & (c.inf > 1 | c.sup < 1)) = inf; result.sup(p == 0 & (c.inf > 1 | c.sup < 1)) = -inf; even = not (p == 0) & even; idx.type = "()"; idx.subs = {even}; result = subsasgn (result, idx, ... union (intersect (subsref (x, idx), ... nthroot (intersect (subsref (c, idx), ... infsup (0, inf)), p(even))), ... intersect (subsref (x, idx), ... -nthroot (intersect (subsref (c, idx), ... infsup (0, inf)), p(even))))); idx.subs = {odd}; result = subsasgn (result, idx, ... union (intersect (subsref (x, idx), ... nthroot (intersect (subsref (c, idx), ... infsup (0, inf)), p(odd))), ... intersect (subsref (x, idx), ... nthroot (intersect (subsref (c, idx), ... infsup (-inf, 0)), p(odd))))); endfunction %!assert (pownrev (infsup (25, 36), infsup (0, inf), 2) == infsup (5, 6)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.pownRev; %! for testcase = [testcases]' %! assert (isequaln (... %! pownrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.pownRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (pownrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.pownRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pownrev (in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.pownRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! pownrev (testcase.in{1}, testcase.in{2}, testcase.in{3}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.pownRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! assert (isequaln (pownrev (in1, in2, in3), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.pownRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! in3 = reshape ([in3; in3(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pownrev (in1, in2, in3), out)); interval-3.2.0/inst/@infsup/powrev1.m0000644000000000000000000002007413316017127015634 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} powrev1 (@var{B}, @var{C}, @var{X}) ## @deftypemethodx {@@infsup} {@var{X} =} powrev1 (@var{B}, @var{C}) ## ## Compute the reverse power function for the first parameter. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{pow (x, b) ∈ @var{C}} for any @code{b ∈ @var{B}}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## powrev1 (infsup (2, 5), infsup (3, 6)) ## @result{} ans ⊂ [1.2457, 2.4495] ## @end group ## @end example ## @seealso{@@infsup/pow} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2011 function x = powrev1 (b, c, x) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) x = infsup (-inf, inf); endif if (not (isa (b, "infsup"))) b = infsup (b); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (x, "infsup"))) x = infsup (x); endif x = intersect (x, infsup (0, inf)); c = intersect (c, infsup (0, inf)); ## Resize, if broadcasting is needed if (not (size_equal (b.inf, c.inf))) b.inf = ones (size (c.inf)) .* b.inf; b.sup = ones (size (c.inf)) .* b.sup; c.inf = ones (size (b.inf)) .* c.inf; c.sup = ones (size (b.inf)) .* c.sup; endif if (not (size_equal (b.inf, x.inf))) b.inf = ones (size (x.inf)) .* b.inf; b.sup = ones (size (x.inf)) .* b.sup; c.inf = ones (size (x.inf)) .* c.inf; c.sup = ones (size (x.inf)) .* c.sup; x.inf = ones (size (b.inf)) .* x.inf; x.sup = ones (size (b.inf)) .* x.sup; endif l = x.inf; u = x.sup; emptyresult = isempty (b) | isempty (c) | (x.sup == 0 & b.sup <= 0) ... | (b.sup <= 0 & ((x.sup <= 1 & c.sup < 1) | ... (x.inf >= 1 & c.inf > 1))) ... | (b.inf >= 0 & ((x.sup <= 1 & c.inf > 1) | ... (x.inf >= 1 & c.sup < 1))); l(emptyresult) = inf; u(emptyresult) = -inf; ## Implements Table B.1 in ## Heimlich, Oliver. 2011. “The General Interval Power Function.” ## Diplomarbeit, Institute for Computer Science, University of Würzburg. ## http://exp.ln0.de/heimlich-power-2011.htm. ## y before [0, 0] =========================================================== y = b.sup < 0; z = c.sup < 1; select = y & z & l < inf; if (any (select(:))) l(select) = max (l(select), ... powrev1rounded (c.sup(select), b.inf(select), -inf)); endif z = c.sup == 1; select = y & z & l < 1; l(select) = 1; z = c.sup > 1 & c.sup < inf; select = y & z & l < 1; if (any (select(:))) l(select) = max (l(select), ... powrev1rounded (c.sup(select), b.sup(select), -inf)); endif z = c.inf > 0 & c.inf < 1; select = y & z & u > 1; if (any (select(:))) u(select) = min (u(select), ... powrev1rounded (c.inf(select), b.sup(select), +inf)); endif z = c.inf == 1; select = y & z & u > 1; u(select) = 1; z = c.inf > 1; select = y & z & u > 0; if (any (select(:))) u(select) = min (u(select), ... powrev1rounded (c.inf(select), b.inf(select), +inf)); endif ## ismember (0, y) =========================================================== y = b.inf <= 0 & b.sup >= 0; gap.inf = -inf (size (l)); gap.sup = +inf (size (u)); z = c.sup < 1; select = y & z & b.sup > 0; if (any (select(:))) gap.inf(select) = powrev1rounded (c.sup(select), b.sup(select), +inf); endif select = y & z & b.inf < 0; if (any (select(:))) gap.sup(select) = powrev1rounded (c.sup(select), b.inf(select), -inf); endif z = c.inf > 1; select = y & z & b.inf < 0; if (any (select(:))) gap.inf(select) = powrev1rounded (c.inf(select), b.inf(select), +inf); endif select = y & z & b.sup > 0; if (any (select(:))) gap.sup(select) = powrev1rounded (c.inf(select), b.sup(select), -inf); endif z = c.sup < 1 | c.inf > 1; select = y & z & (l > gap.inf | (gap.inf == 1 & l == 1)); l(select) = max (l(select), gap.sup(select)); select = y & z & (u < gap.sup | gap.sup == inf | (gap.sup == 1 & u == 1)); u(select) = min (u(select), gap.inf(select)); ## y after [0, 0] ============================================================ y = b.inf > 0; z = c.sup < 1; select = y & z & u > 0; if (any (select(:))) u(select) = min (u(select), ... powrev1rounded (c.sup(select), b.sup(select), +inf)); endif z = c.sup == 1; select = y & z & u > 1; u(select) = 1; z = c.sup > 1 & c.sup < inf; select = y & z & u > 1; if (any (select(:))) u(select) = min (u(select), ... powrev1rounded (c.sup(select), b.inf(select), +inf)); endif z = c.inf > 0 & c.inf < 1; select = y & z & l < 1; if (any (select(:))) l(select) = max (l(select), ... powrev1rounded (c.inf(select), b.inf(select), -inf)); endif z = c.inf == 1; select = y & z & l < 1; l(select) = 1; z = c.inf > 1; select = y & z & l < inf; if (any (select(:))) l(select) = max (l(select), ... powrev1rounded (c.inf(select), b.sup(select), -inf)); endif ## =========================================================================== emptyresult = l > u | l == inf | u == -inf; l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction function x = powrev1rounded (z, y, direction) ## Return x = z ^ (1 / y) with directed rounding and limit values x = ones (size (z)); x((z == inf & y < 0) | (z == 0 & y > 0)) = 0; x((z == inf & y > 0) | (z == 0 & y < 0)) = inf; select = z > 1 & z < inf & isfinite (y); y(select) = mpfr_function_d ('rdivide', direction, 1, y(select)); select = z < 1 & z > 0 & isfinite (y); y(select) = mpfr_function_d ('rdivide', -direction, 1, y(select)); select = isfinite (y) & z > 0 & z ~= 1 & z < inf; x(select) = mpfr_function_d ('pow', direction, z(select), y(select)); endfunction %!# from the documentation string %!assert (powrev1 (infsup (2, 5), infsup (3, 6)) == "[0x1.3EE8390D43955, 0x1.3988E1409212Fp1]"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.powRev1; %! for testcase = [testcases]' %! assert (isequaln (... %! powrev1 (testcase.in{1}, testcase.in{2}, testcase.in{3}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.powRev1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! assert (isequaln (powrev1 (in1, in2, in3), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.powRev1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! in3 = reshape ([in3; in3(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (powrev1 (in1, in2, in3), out)); interval-3.2.0/inst/@infsup/powrev2.m0000644000000000000000000002270413316017127015637 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{Y} =} powrev2 (@var{A}, @var{C}, @var{Y}) ## @deftypemethodx {@@infsup} {@var{Y} =} powrev2 (@var{A}, @var{C}) ## ## Compute the reverse power function for the second parameter. ## ## That is, an enclosure of all @code{y ∈ @var{Y}} where ## @code{pow (a, y) ∈ @var{C}} for any @code{a ∈ @var{A}}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## powrev2 (infsup (2, 5), infsup (3, 6)) ## @result{} ans ⊂ [0.6826, 2.585] ## @end group ## @end example ## @seealso{@@infsup/pow} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2011 function y = powrev2 (a, c, y) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) y = infsup (-inf, inf); endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (y, "infsup"))) y = infsup (y); endif a = intersect (a, infsup (0, inf)); c = intersect (c, infsup (0, inf)); ## Resize, if broadcasting is needed if (not (size_equal (a.inf, c.inf))) a.inf = ones (size (c.inf)) .* a.inf; a.sup = ones (size (c.inf)) .* a.sup; c.inf = ones (size (a.inf)) .* c.inf; c.sup = ones (size (a.inf)) .* c.sup; endif if (not (size_equal (a.inf, y.inf))) a.inf = ones (size (y.inf)) .* a.inf; a.sup = ones (size (y.inf)) .* a.sup; c.inf = ones (size (y.inf)) .* c.inf; c.sup = ones (size (y.inf)) .* c.sup; y.inf = ones (size (a.inf)) .* y.inf; y.sup = ones (size (a.inf)) .* y.sup; endif l = y.inf; u = y.sup; emptyresult = isempty (a) | isempty (c) ... | (a.sup == 0 & (y.sup <= 0 | c.inf > 0)) ... | (y.sup <= 0 & ((a.sup <= 1 & c.sup < 1) | ... (a.inf > 1 & c.inf > 1))) ... | (y.inf >= 0 & ((a.sup <= 1 & c.inf > 1) | ... (a.inf > 1 & c.sup < 1))) ... | (((a.inf == 1 & a.sup == 1) | (y.inf == 0 & y.sup == 0)) ... & (c.sup < 1 | c.inf > 1)); l(emptyresult) = inf; u(emptyresult) = -inf; ## Implements Table B.2 in ## Heimlich, Oliver. 2011. “The General Interval Power Function.” ## Diplomarbeit, Institute for Computer Science, University of Würzburg. ## http://exp.ln0.de/heimlich-power-2011.htm. ## x overlaps/starts/containedBy [0, 1] ====================================== x = a.sup < 1; select = a.sup == 0 & l < 0; l(select) = 0; z = c.sup <= 1; select = x & z & (a.inf == 0 | c.sup == 1) & l < 0; l(select) = 0; z = c.sup > 1 & c.sup < inf; select = x & z & l < 0; if (any (select(:))) l(select) = max (l(select), ... powrev2rounded (a.sup(select), c.sup(select), -inf)); endif z = c.inf >= 1; select = x & z & (a.inf == 0 | c.inf == 1) & u > 0; u(select) = 0; z = c.inf > 0 & c.inf < 1; select = x & z & u > 0; if (any (select(:))) u (select) = min (u (select), powrev2rounded (a.sup, c.inf, +inf)(select)); endif ## x containedBy/finishes [0, 1] ============================================= x = a.inf > 0 & a.inf < 1 & a.sup <= 1; z = c.sup < 1 & c.sup > 0; select = x & z & l < inf; if (any (select(:))) l(select) = max (l(select), ... powrev2rounded (a.inf(select), c.sup(select), -inf)); endif z = c.inf > 1 & c.sup < inf; select = x & z & u > -inf; if (any (select(:))) u(select) = min (u(select), ... powrev2rounded (a.inf(select), c.inf (select), +inf)); endif ## ismember (1, x) =========================================================== x = a.sup >= 1 & a.inf <= 1; z = c.inf == 0 & c.sup == 0; select = x & z & l < 0; l(select) = 0; z = c.sup == inf & c.inf > 1; select = x & z & u > 0 & a.sup <= 1; u(select) = 0; gap.inf = -inf (size (l)); gap.sup = +inf (size (u)); z = c.sup < 1; select = x & z & a.inf == 0; gap.sup(select) = 0; select = x & z & a.sup > 1; if (any (select(:))) gap.inf(select) = powrev2rounded (a.sup(select), c.sup(select), +inf); endif select = x & z & a.inf > 0 & a.inf < 1 & a.sup > 1; if (any (select(:))) gap.sup(select) = powrev2rounded(a.inf(select), c.sup(select), -inf); endif z = c.inf > 1; select = x & z & a.inf == 0; gap.inf(select) = 0; select = x & z & a.sup > 1; if (any (select(:))) gap.sup(select) = powrev2rounded (a.sup(select), c.inf(select), -inf); endif select = x & z & a.inf > 0 & a.inf < 1 & a.sup > 1; if (any (select(:))) gap.inf(select) = powrev2rounded (a.inf(select), c.inf(select), +inf); endif z = c.sup < 1 | c.inf > 1; select = x & z & (l > gap.inf | gap.inf == -inf | (gap.inf == 0 & l == 0)) ... & (a.inf >= 1 | a.sup > 1 | a.inf <= 0); l(select) = max (l(select), gap.sup(select)); select = x & z & (u < gap.sup | gap.sup == inf | (gap.sup == 0 & u == 0)) ... & (a.inf >= 1 | a.sup > 1 | a.inf <= 0); u(select) = min (u(select), gap.inf(select)); ## x after [0, 1] ============================================================ x = a.inf > 1; z = c.sup < 1; select = x & z & u > -inf; if (any (select(:))) u(select) = min (u(select), ... powrev2rounded (a.sup(select), c.sup(select), +inf)); endif z = c.inf > 0 & c.inf < 1; select = x & z & l < 0; if (any (select(:))) l(select) = max (l(select), ... powrev2rounded (a.inf(select), c.inf(select), -inf)); endif z = c.inf == 1; select = x & z & l < 0; l(select) = 0; z = c.inf > 1; select = x & z & l < inf; if (any (select(:))) l(select) = max (l(select), ... powrev2rounded (a.sup(select), c.inf(select), -inf)); endif z = c.sup == 1; select = x & z & u > 0; u(select) = 0; z = c.sup > 1 & c.sup < inf; select = x & z & u > 0; if (any (select(:))) u(select) = min (u(select), ... powrev2rounded (a.inf(select), c.sup(select), +inf)); endif ## =========================================================================== emptyresult = l > u | l == inf | u == -inf; l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; y.inf = l; y.sup = u; endfunction function y = powrev2rounded (x, z, direction) ## Return y = log z / log x with directed rounding and limit values y = nominator = denominator = zeros (size (x)); y(z == inf & x < 1) = -inf; y(z == inf & x > 1 & x < inf) = inf; ## We do not use log here, because log2 is able to produce some ## results without rounding errors. rnd_log_numerator_up = (direction > 0) == (sign (x - 1) == sign (z - 1)); select = isfinite (x) & isfinite (z) & rnd_log_numerator_up; if (any (select(:))) denominator(select) = mpfr_function_d ('log2', -inf, x(select)); nominator(select) = mpfr_function_d ('log2', +inf, z(select)); endif select = isfinite (x) & isfinite (z) & not (rnd_log_numerator_up); if (any (select(:))) denominator(select) = mpfr_function_d ('log2', +inf, x(select)); nominator(select) = mpfr_function_d ('log2', -inf, z(select)); endif select = isfinite (x) & isfinite (z); if (any (select(:))) y(select) = mpfr_function_d ('rdivide', direction, ... nominator(select), ... denominator(select)); endif endfunction %!# from the documentation string %!assert (powrev2 (infsup (2, 5), infsup (3, 6)) == "[0x1.5D7E8F22BA886p-1, 0x1.4AE00D1CFDEB5p1]"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.powRev2; %! for testcase = [testcases]' %! assert (isequaln (... %! powrev2 (testcase.in{1}, testcase.in{2}, testcase.in{3}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.powRev2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! assert (isequaln (powrev2 (in1, in2, in3), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.powRev2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! in3 = reshape ([in3; in3(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (powrev2 (in1, in2, in3), out)); interval-3.2.0/inst/@infsup/precedes.m0000644000000000000000000000547113316017127016027 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} precedes (@var{A}, @var{B}) ## ## Evaluate precedes comparison on intervals. ## ## True, if @var{A} is left of @var{B}. The intervals may touch. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/le, @@infsup/lt, @@infsup/gt, @@infsup/strictprecedes, @@infsup/subset, @@infsup/interior, @@infsup/disjoint} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function result = precedes (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); endif ## This comparison also works for empty intervels, where the comparison must ## always return true. result = (a.sup <= b.inf); endfunction %!assert (precedes (infsup (1, 2), infsup (2, 3))); %!assert (not (precedes (infsup (1, 2.1), infsup (1.9, 3)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.precedes; %! for testcase = [testcases]' %! assert (isequaln (... %! precedes (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.precedes; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (precedes (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.precedes; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (precedes (in1, in2), out)); interval-3.2.0/inst/@infsup/prepad.m0000644000000000000000000000566713316017127015517 0ustar 00000000000000## Copyright 2015-2017 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} prepad (@var{X}, @var{L}) ## @defmethodx {@@infsup} prepad (@var{X}, @var{L}, @var{C}) ## @defmethodx {@@infsup} prepad (@var{X}, @var{L}, @var{C}, @var{DIM}) ## ## Prepend the scalar interval value @var{C} to the interval vector @var{X} ## until it is of length @var{L}. If @var{C} is not given, a value of 0 is ## used. ## ## If @code{length (@var{X}) > L}, elements from the beginning of @var{X} are ## removed until an interval vector of length @var{L} is obtained. ## ## If @var{X} is an interval matrix, elements are prepended or removed from ## each row or column. ## ## If the optional argument DIM is given, operate along this dimension. ## ## If DIM is larger than the dimension of X, the result will have DIM ## dimensions. ## ## @example ## @group ## prepad (infsup (1 : 3), 5, 42) ## @result{} ans = 1×5 interval vector ## [42] [42] [1] [2] [3] ## @end group ## @end example ## @seealso{@@infsup/reshape, @@infsup/cat, @@infsup/postpad, @@infsup/resize} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-19 function x = prepad (x, len, c, dim) if (nargin < 2 || nargin > 4) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (isa (len, "infsup")) error ("interval:InvalidOperand", "prepad: len must not be an interval"); endif if (nargin < 3) c = infsup (0); elseif (not (isa (c, "infsup"))) c = infsup (c); endif if (nargin < 4) dim = find (size (x.inf) ~= 1, 1); if (isempty (dim)) dim = 1; endif elseif (isa (dim, "infsup")) error ("interval:InvalidOperand", "prepad: dim must not be an interval"); endif x.inf = prepad (x.inf, len, c.inf, dim); x.sup = prepad (x.sup, len, c.sup, dim); endfunction %!assert (prepad (infsup (2:4), 4, 1) == infsup (1:4)); %!assert (prepad (infsup (0:2), 2, 1) == infsup (1:2)); %!test %! if (compare_versions (OCTAVE_VERSION (), "4.0.0", ">=")) %! assert (prepad (infsup (0), 10, 0, 3) == infsup (zeros (1, 1, 10))) %! else %! # In Octave 3.8.x it is not possible to increase the number of dimensions. %! endif %!assert (prepad (infsup (zeros (1, 2, 2)), 3) == infsup (zeros (1, 3, 2))); interval-3.2.0/inst/@infsup/printf.m0000644000000000000000000000413713316017127015535 0ustar 00000000000000## Copyright 2018 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} printf (@var{template}, @var{X}) ## ## Print interval @var{X} under the control of a template string ## @var{template} to the stream @code{stdout} and return the number of ## characters printed. ## ## See @command{help intervaltotext} for the syntax of the template string. ## ## @example ## @group ## printf ("The result lies within the box %[4g].\n", infsup (2, 3)) ## @result{} The result lies within the box [ 2, 3]. ## @end group ## @end example ## ## When @var{X} is a vector, matrix, or array of intervals, this function ## cycles through the format template until all the values have been printed. ## ## @example ## @group ## printf ("%5:[g] %5:[g]\n", infsup (pascal (2))) ## @result{} [ 1 ] [ 1 ] ## [ 1 ] [ 2 ] ## @end group ## @end example ## @seealso{intervaltotext, @@infsup/fprintf, @@infsup/sprintf} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2018-06-30 function chars_printed = printf (template, x) if (nargin ~= 2) print_usage (); return endif [template, literals] = printf_prepare (template, x); if (nargout >= 1) chars_printed = printf (template, literals{:}); else printf (template, literals{:}); endif endfunction %!test %! if (compare_versions (OCTAVE_VERSION, "4.2", ">=")) %! assert (evalc ("n = printf ('%g', infsup ('pi'));"), "3.14159 3.1416"); %! assert (n, 14); %! endif interval-3.2.0/inst/@infsup/private/__loosespacing__.m0000644000000000000000000000500213316017127021157 0ustar 00000000000000## Copyright 2017 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deffun __loosespacing__ () ## ## Query the current format's spacing configuration. ## ## This function supports a wide range of Octave versions. The API to query ## the current format settings has undergone several incompatible ## modifications in the 4.0, 4.2 and 4.4 releases. ## ## @example ## @group ## format compact ## __loosespacing__ ## @result{} ans = 0 ## @end group ## @group ## format loose ## __loosespacing__ ## @result{} ans = 1 ## @end group ## @end example ## @seealso{format} ## @end deffun ## Author: Oliver Heimlich ## Created: 2017-08-15 function result = __loosespacing__ () if (compare_versions (OCTAVE_VERSION (), "4.4.0", ">=")) ## Starting with changeset f84aa17075d4 it is possible ## to query the format function without breaking ## current format settings. [~, spacing] = format (); elseif (exist ("__compactformat__", "builtin")) ## An internal function has been introduced by Octave 4.0.0. result = not (__compactformat__ ()); return elseif (compare_versions (OCTAVE_VERSION (), "4.2.0", ">=")) ## Abovementioned changeset has removed the internal function. ## Development versions of Octave (4.3.0+) should already have ## support for the 2-output format function. ## TODO: This case can be removed after the 4.4.0 release. [~, spacing] = format (); else ## In older versions, we use this kludgy workaround to ## detect the current settings. ## Note: The deprecated root property "FormatSpacing", ## which has been removed in Octave 4.2.0, always returns "loose" ## in Octave < 4.0.0 and is of no use. compact_spacing = isempty (strfind (disp (zeros ([1 2 2])), "\n\n")); result = not (compact_spacing); return endif result = strcmp ("loose", spacing); endfunction interval-3.2.0/inst/@infsup/private/decimaladd.m0000644000000000000000000000604113316017127017750 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {@var{DECIMAL} =} decimaladd (@var{DECIMAL}, @var{ADDEND}) ## ## Add two decimal numbers. ## ## @end deftypefun ## Author: Oliver Heimlich ## Created: 2014-10-21 function [decimal] = decimaladd (decimal, addend) ## Align mantissas if (addend.e < decimal.e) addend.m = [zeros(decimal.e - addend.e, 1); ... addend.m]; addend.e = decimal.e; elseif (addend.e > decimal.e) decimal.m = [zeros(addend.e - decimal.e, 1); ... decimal.m]; decimal.e = addend.e; endif if (length (decimal.m) > length (addend.m)) addend.m = [addend.m; ... zeros(length (decimal.m) - ... length (addend.m), 1)]; elseif (length (decimal.m) < length (addend.m)) decimal.m = [decimal.m; ... zeros(length (addend.m) - ... length (decimal.m), 1)]; endif assert (length (decimal.m) == length (addend.m)); assert (decimal.e == addend.e); ## Add if (decimal.s == addend.s) decimal.m += addend.m; else decimal.m -= addend.m; endif ## Carry while (not (isempty (find (decimal.m >= 10)))) decimal.m = [0; rem(decimal.m, 10)] ... + [(decimal.m >= 10); 0]; if (decimal.m(1) == 0) decimal.m(1) = []; else decimal.e ++; endif endwhile ## Resolve negative decimal digits while (1) highestnegative = find (decimal.m < 0, 1); if (isempty (highestnegative)) break; endif highestpositive = find (decimal.m > 0, 1); if (isempty (highestpositive) || ... highestnegative < highestpositive) ## Flip sign decimal.s = not (decimal.s); decimal.m *= -1; else assert (decimal.m(1) >= 0); decimal.m += 10 * (decimal.m < 0) ... - [(decimal.m(2:end) < 0); 0]; endif endwhile clear highestnegative highestpositive; ## Normalize mantissa: remove leading zeroes firstnonzerodigit = find (decimal.m ~= 0, 1, "first"); if (firstnonzerodigit > 1) decimal.m = decimal.m(firstnonzerodigit:end); decimal.e -= firstnonzerodigit - 1; elseif (isempty (firstnonzerodigit)) # all digits are zero decimal.s = false; decimal.m = []; decimal.e = int64 (0); return endif ## Remove trailing zeros decimal.m = decimal.m(1 : find (decimal.m ~= 0, 1, "last")); endfunction interval-3.2.0/inst/@infsup/private/decimalcompare.m0000644000000000000000000000373313316017127020653 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deffun decimalcompare (@var{X}, @var{Y}) ## ## Compare two decimal floating point numbers. ## ## The result is a negative number, if @code{@var{X} < @var{Y}}; ## zero, if @code{@var{X} == @var{Y}}; a positive number, ## if @code{@var{X} > @var{Y}}. ## ## @seealso{str2decimal, double2decimal} ## @end deffun ## Author: Oliver Heimlich ## Created: 2014-09-29 function result = decimalcompare (x, y) ## Comparison with zero if (isempty (x.m) ~= isempty (y.m)) if (y.s || ... # Y < 0 not (x.s || isempty (x.m))) # X > 0 result = 1; else result = -1; endif return endif ## Different signs if (x.s ~= y.s) result = y.s - x.s; return endif ## Different exponents if (x.e ~= y.e) result = x.e - y.e; if (x.s) result .*= -1; endif return endif ## Compare common mantissa places for i = 1 : min (length (x.m), length (y.m)) if (x.m(i) ~= y.m(i)) result = x.m(i) - y.m(i); if (x.s) result .*= -1; endif return endif endfor ## Compare mantissa length. There is no need to inspect the digits, because the ## mantissa is normalized (no trailing zeroes). result = length (x.m) - length (y.m); if (x.s) result .*= -1; endif endfunction interval-3.2.0/inst/@infsup/private/decimaldivide.m0000644000000000000000000000420113316017127020460 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{QUOTIENT}, @var{REMAINDER}] =} decimaldivide (@var{DIVIDEND}, @var{DIVISOR}, @var{PRECISION}) ## ## Divide two decimal numbers. The parameter @var{PRECISION} limits the ## maximum significand places in the @var{QUOTIENT}. ## ## @end deftypefun ## Author: Oliver Heimlich ## Created: 2014-10-22 function [quotient, remainder] = decimaldivide (dividend, divisor, precision) assert (not (isempty (divisor.m)), "division by zero"); if (isempty (dividend.m)) # 0 / divisor quotient = dividend; remainder = dividend; return endif ## Compute exponent and sign of the result quotient.e = dividend.e - divisor.e + 1; divisor.e = dividend.e; quotient.s = xor (dividend.s, divisor.s); divisor.s = dividend.s; quotient.m = zeros (precision, 1); ## Perform long division remainder = dividend; i = 1; while (i <= length (quotient.m)) if (isempty (remainder.m)) break endif while (sign (decimalcompare (divisor, remainder)) ~= (-1) ^ remainder.s) quotient.m (i) ++; ## Subtract divisor from remainder divisor.s = not (remainder.s); remainder = decimaladd (remainder, divisor); divisor.s = remainder.s; endwhile divisor.e --; if (i == 1 && quotient.m (i) == 0) quotient.e --; else i++; endif endwhile ## Remove trailing zeros quotient.m = quotient.m(1 : find (quotient.m ~= 0, 1, "last")); endfunction interval-3.2.0/inst/@infsup/private/double2decimal.m0000644000000000000000000000712613316017127020561 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deffun double2decimal (@var{X}) ## ## Convert a binary floating point number @var{X} in double precision to a ## decimal floating point number with arbitrary precision. The number must be ## a finite number and must not be NaN. ## ## Conversion is exact, because @code{rem (10, 2) == 0}. ## ## Sign: true (-) or false (+) ## ## Mantissa: Vector that holds the decimal digits after the decimal point. The ## first digit is not zero. Trailing zeroes are removed. ## ## Exponent: Integral exponent (base 10). ## ## @example ## @group ## x = double2decimal (-200) ## @result{} ## x.s = 1 ## x.m = [2] ## x.e = 2 ## y = double2decimal (0.125) ## @result{} ## y.s = 0 ## y.m = [1 2 5]' ## y.e = 0 ## z = double2decimal (0) ## @result{} ## z.s = 0 ## z.m = [] ## z.e = 0 ## @end group ## @end example ## @seealso{str2decimal} ## @end deffun ## Author: Oliver Heimlich ## Created: 2014-09-29 function decimal = double2decimal (binary) [decimal.s, exponent, fraction] = parsedouble (binary); if (sum (fraction) == 0) # this number equals zero decimal.s = false; # normalize: remove sign from -0 decimal.m = []; decimal.e = int64 (0); return endif ## Remove trailing zeroes if this might reduce the number of loop cycles below if (exponent < length (fraction)) fraction = fraction(1:find (fraction, 1, "last")); endif ## Move the point to the end of the mantissa and interpret mantissa ## as a binary integer number that is now in front of the ## point. Convert binary integer to decimal. exponent -= length (fraction); decimal.m = zeros (); for i = 1 : length(fraction) ## Multiply by 2 decimal.m .*= 2; ## Add 1 if necessary decimal.m(end) += fraction(i); ## Carry decimal.m = [0; rem(decimal.m, 10)] ... + [(decimal.m >= 10); 0]; endfor clear fraction; ## Normalize: Remove leading zeroes (for performance reasons not in loop) decimal.m = decimal.m(find (decimal.m ~= 0, 1, "first"):end); assert (length (decimal.m) > 0, "number must not equal zero at this point"); decimal.e = int64 (length (decimal.m)); ## Multiply decimal integer with 2 ^ exponent while (exponent > 0) decimal.m .*= 2; decimal.m = [0; rem(decimal.m, 10)] ... + [(decimal.m >= 10); 0]; if (decimal.m(1) == 0) decimal.m(1) = []; else decimal.e ++; endif exponent --; endwhile while (exponent < 0) ## Instead of division by 2 we devide by 10 and multiply by 5 decimal.e --; # cheap division by 10 decimal.m .*= 5; decimal.m = [0; rem(decimal.m, 10)] ... + [floor(decimal.m ./ 10); 0]; if (decimal.m(1) == 0) decimal.m(1) = []; else decimal.e ++; endif exponent ++; endwhile ## Normalize mantissa: remove trailing zeroes; decimal.m = decimal.m(1 : find (decimal.m ~= 0, 1, "last")); endfunction interval-3.2.0/inst/@infsup/private/hex2double.m0000644000000000000000000001304413316017127017743 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{X}, @var{ISEXACT}] =} hex2double (@var{S}, @var{DIRECTION}) ## ## Convert a hexadecimal floating point number @var{S} to double precision with ## directed rounding. ## ## The input number format is [+-]0xh[,.]h[[pP][+-]d]. ## ## @seealso{str2decimal} ## @end deftypefun ## Author: Oliver Heimlich ## Created: 2014-10-20 function [binary, isexact] = hex2double (string, direction) ## Strip Sign if (isempty (string)) hex.s = false; else hex.s = (string (1) == "-"); if (strfind("+-", string(1))) string = string (2:end); endif endif ## Strip hex indicator if (strncmpi ("0x", string, 2)) string = string (3:end); else error ("interval:InvalidOperand", ... ["invalid hex number does not start with 0x: " string]); endif ## Split mantissa & exponent [hex.m, hex.e] = strtok (string, "pP"); ## Convert exponent from string to number if (isempty (hex.e)) hex.e = int64(0); # 2 ^ 0 = 1 else if (strfind (hex.e, ".") || strfind (hex.e, ",")) error ("interval:InvalidOperand", ... ["invalid hex number with rational exponent: " string]); endif hex.e = str2double (hex.e(2:end)); # remove “p” and convert if (isnan (hex.e) || ... # greater than realmax or illegal format abs(hex.e) >= pow2 (53)) # possibly lost precision error ("interval:InvalidOperand", ... ["invalid hex number with big/invalid exponent: " string]); endif hex.e = int64 (hex.e); endif ## Split Mantissa at point hex.m = strsplit (hex.m, {".",","}); switch length(hex.m) case 0 hex.m = {"", ""}; case 1 hex.m{2} = ""; case 2 # nothing to do otherwise error ("interval:InvalidOperand", ... ["invalid hex number with multiple points: " string]); endswitch ## Normalize mantissa string: move point to the right if (hex.e - length (hex.m{2}) * 4 <= intmin (class (hex.e))) error ("interval:InvalidOperand", ... ["exponent overflow during normalization: " string ]); endif hex.e -= length (hex.m{2}) * 4; hex.m = strcat (hex.m{1}, hex.m{2}); hexvalues = rem (uint8 (hex.m) - 47, 39); # 1 .. 16 lookup = [0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1;... 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1;... 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1;... 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]; hex.m = (logical (lookup (:, hexvalues))) (:)'; ## Normalize mantissa: remove leading zeroes firstnonzerodigit = find (hex.m, 1, "first"); if (firstnonzerodigit > 1) hex.m = hex.m (firstnonzerodigit:end); elseif (isempty (firstnonzerodigit)) ## All digits are zero isexact = true (); if (hex.s) binary = -0; else binary = 0; endif return endif ## Move point to the left, right after the first significand binary digit if (length (hex.m) > 1) if (hex.e + (length (hex.m) - 1) >= intmax (class (hex.e))) error ("interval:InvalidOperand", ... ["exponent overflow during normalization: " string ]); endif hex.e += length (hex.m) - 1; endif ## Overflow if (hex.e > 1023) isexact = false (); if (hex.s && direction < 0) binary = -inf; elseif (hex.s) binary = -realmax (); elseif (direction > 0) binary = inf; else binary = realmax (); endif return endif ## Underflow if (hex.e < -1074) isexact = false (); if (hex.s && direction < 0) binary = -pow2 (-1074); elseif (hex.s) binary = -0; elseif (direction > 0) binary = pow2 (-1074); else binary = 0; endif return endif if (hex.e < -1022) ## Subnormal numbers hex.m = [zeros(1, -1022 - hex.e), hex.m]; ieee754exponent = -1023; else ## Normal numbers ieee754exponent = hex.e; endif ## Only the most significand 53 bits are relevant. significand = postpad (hex.m, 53, 0, 2); isexact = length (hex.m) <= length (significand) || ... isempty (find (hex.m (54:end), 1)); ## The first bit can be omitted (normalization). significand (1) = []; ## The remaining 52 bits can be converted to 13 hex digits ieee754mantissa = dec2hex (pow2 (51 : -1 : 0) * significand', 13); if (not (hex.s)) ieee754signandexponent = ieee754exponent + 1023; else ieee754signandexponent = ieee754exponent + 1023 + pow2 (11); endif ieee754double = strcat (dec2hex (ieee754signandexponent, 3), ieee754mantissa); binary = hex2num (ieee754double); ## Last, consider the rounding direction if (isexact || ... (direction < 0 && not (hex.s)) || (direction > 0 && hex.s)) ## The number is exact or the truncation of digits above resulted in ## correct rounding direction else delta = pow2 (-1074); binary = mpfr_function_d ('plus', direction, binary, delta); endif endfunction interval-3.2.0/inst/@infsup/private/parsedouble.m0000644000000000000000000000421313316017127020205 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{SIGN}, @var{EXPONENT}, @var{MANTISSA}] =} parsedouble (@var{X}) ## ## Parse a finite binary floating point number @var{X} in double precision. ## ## The mantissa is normalized, the implicit first bit is moved after the point ## @code{@var{X} = (-1) ^ @var{SIGN} * @var{MANTISSA} (=0.XXXXX… in binary) * 2 ^ @var{EXPONENT}}. ## @end deftypefun ## Author: Oliver Heimlich ## Created: 2014-10-24 function [sign, exponent, mantissa] = parsedouble (binary) if (not (isfinite (binary)) || isnan (binary)) assert (false (), "Invalid call to parsedouble"); endif ## Decode bit representation hex = num2hex (binary); # 16 hexadecimal digits (with leading zeros) hexvalues = rem (uint8 (hex) - 47, 39); # 1 .. 16 lookup = [0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1;... 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1;... 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1;... 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]; bits = (logical (lookup (:, hexvalues))) (:)'; ## Separate sign, exponent, and mantissa bits. sign = bits(1); exponent = bits(2 : 12); fraction = bits(13 : end)'; if (sum (exponent) == 0) # denormalized numbers mantissa = fraction; else # normalized numbers mantissa = [true(); fraction]; endif ## Decode IEEE 754 exponent exponent = int64(pow2 (10 : -1 : 0) * exponent') - 1023; ## binary == (-1) ^ sign * fraction (=X.XXXXX… in binary) * 2 ^ exponent exponent ++; endfunction interval-3.2.0/inst/@infsup/private/printf_prepare.m0000644000000000000000000000470313316017127020724 0ustar 00000000000000## Copyright 2018 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{template}, @var{literals}] =} printf_prepare (@var{template}, @var{X}) ## ## Convert interval @var{X} under the control of a template string ## @var{template} to an interval literal. The format @var{TEMPLATE} is ## modified to be used by Octave's formatted output functions @command{printf}, ## @command{fprintf}, and @command{sprintf}. That is, syntax for interval ## literals is replaced by @code{%s}. ## ## @seealso{intervaltotext} ## @end deftypefun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2018-06-30 function [template, literals] = printf_prepare (template, x) if (nargin ~= 2) print_usage (); return endif if (not (ischar (template))) error ("format TEMPLATE must be a string"); return endif if (not (isa (x, "infsup"))) error ("X must be an interval") return endif ## Split templates to process each template individually template = strsplit (template, "%", "collapsedelimiters", false); ## Undo splitting of escaped '%' n = 2; while (n < numel (template)) if (isempty (template{n})) template{n - 1} = cstrcat (template{n - 1}, "%%", template{n + 1}); template([n, (n + 1)]) = []; else n ++; endif endwhile ## Format interval literals and replace corresponding templates by %s template_parts = numel (template) - 1; literals = cell (size (x)); for n = 1 : template_parts part_idx = colon (n, template_parts, numel (x)); [literals_part, ~, template_part_suffix] = intervaltotext ( subsref (x, substruct ("()", {part_idx})), template{n + 1}); literals(part_idx) = literals_part; template{n + 1} = cstrcat ("s", template_part_suffix); endfor template = strjoin (template, "%"); endfunction interval-3.2.0/inst/@infsup/private/str2decimal.m0000644000000000000000000001132413316017127020112 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deffun str2decimal (@var{S}) ## ## Parse a decimal number string @var{S} and split the sign, the mantissa and ## the exponent information. ## ## The input number format is [+-]d[,.]d[[eE][+-]d] (cf. str2double). ## ## Limitations: The decimal exponent of the input format must be a number ## between -2^53 (exclusive) and +2^53 (exclusive). ## The number itself either must equal zero or its absolute value must be ## between 10^(-2^62) (inclusive) and 10^(2^63 - 1) (exclusive). ## ## Sign: true (-) or false (+) ## ## Mantissa: Vector that holds the decimal digits after the decimal point. The ## first digit is not zero. Trailing zeroes are removed. ## ## Exponent: Integral exponent (base 10). ## ## @example ## @group ## x = str2decimal ("-12.3e14") ## @result{} ## x.s = 1 ## x.m = [1 2 3]' ## x.e = 16 ## y = str2decimal ("0.00123e-14") ## @result{} ## y.s = 0 ## y.m = [1 2 3]' ## y.e = -12 ## z = str2decimal ("0") ## @result{} ## z.s = 0 ## z.m = [] ## z.e = 0 ## @end group ## @end example ## @seealso{double2decimal} ## @end deffun ## Author: Oliver Heimlich ## Created: 2014-09-27 function decimal = str2decimal (string) ## Strip Sign if (isempty (string)) decimal.s = false; else decimal.s = (string(1) == "-"); if (strfind("+-", string(1))) string = string (2:end); endif endif ## Split mantissa & exponent [decimal.m, decimal.e] = strtok (string, "eE"); ## Convert exponent from string to number if (isempty (decimal.e)) decimal.e = int64(0); # 10 ^ 0 = 1 else if (strfind (decimal.e, ".") || strfind (decimal.e, ",")) error ("interval:InvalidOperand", ... ["invalid decimal number with rational exponent: " string]); endif decimal.e = str2double (decimal.e(2:end)); # remove “e” and convert if (isnan (decimal.e) || ... # greater than realmax or illegal format abs(decimal.e) >= pow2 (53)) # possibly lost precision error ("interval:InvalidOperand", ... ["invalid decimal number with big/invalid exponent: " string]); endif decimal.e = int64 (decimal.e); endif ## Normalize mantissa: remove leading zeroes within string representation ## before decimal point. This does not affect the exponent and is therefore ## preferred over the normalization below, which might produce overflow errors. decimal.m = decimal.m(find(decimal.m ~= "0", 1):end); ## Split Mantissa at decimal point decimal.m = strsplit (decimal.m, {".",","}); switch length(decimal.m) case 0 decimal.m = {"", ""}; case 1 decimal.m{2} = ""; case 2 # nothing to do otherwise error ("interval:InvalidOperand", ... ["invalid decimal number with multiple decimal points: " ... string]); endswitch ## Normalize mantissa string: move decimal point to the left if (decimal.e + length (decimal.m{1}) >= intmax (class (decimal.e))) error ("interval:InvalidOperand", ... ["exponent overflow during normalization: " string ]); endif decimal.e += length (decimal.m{1}); decimal.m = strcat (decimal.m{1}, decimal.m{2}); ## Convert mantissa to numeric vector with decimal digits decimal.m = str2num (decimal.m'); ## Normalize mantissa: remove leading zeroes firstnonzerodigit = find (decimal.m ~= 0, 1, "first"); if (firstnonzerodigit > 1) decimal.m = decimal.m(firstnonzerodigit:end); if (decimal.e - (firstnonzerodigit - 1) <= intmin (class (decimal.e))) error ("interval:InvalidOperand", ... ["exponent overflow during normalization: " string ]); endif decimal.e -= firstnonzerodigit - 1; elseif (isempty (firstnonzerodigit)) # all digits are zero decimal.s = false; decimal.m = []; decimal.e = int64 (0); return endif ## Normalize mantissa: remove trailing zeroes; lastnonzerodigit = find (decimal.m ~= 0, 1, "last"); if (lastnonzerodigit < length (decimal.m)) decimal.m = decimal.m(1:lastnonzerodigit); endif endfunction interval-3.2.0/inst/@infsup/private/uncertainsplit.m0000644000000000000000000000540313316017127020746 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{BOUNDARY}, @var{UNCERTAIN}] =} uncertainsplit (@var{BOUNDARY}) ## ## The the decimal number itself and the decimal number that represents the ## uncertainty for the number. ## @end deftypefun ## Author: Oliver Heimlich ## Created: 2014-10-21 function [boundary, uncertain] = uncertainsplit (boundary) uncertainseparator = find (boundary == "?", 1); assert (not (isempty (uncertainseparator))); exponentseparator = find (lower (boundary) == "e", 1); if (isempty (exponentseparator)) exponentfield = ""; if (uncertainseparator == length (boundary)) ulpcount = ""; else ulpcount = boundary ((uncertainseparator + 1) : end); endif else exponentfield = boundary (exponentseparator : end); ulpcount = boundary ((uncertainseparator + 1) : (exponentseparator - 1)); endif ## Strip uncertain information from the boundary literal = boundary (1 : (uncertainseparator - 1)); boundary = strcat (literal, exponentfield); ## Make a decimal number that represents the uncertainty decimalseparator = find ((literal == ".") + (literal == ","), 1); if (isempty (ulpcount)) ## Half-ULP if (isempty (decimalseparator)) uncertain = "0.5"; else uncertain = strcat (regexprep (literal, "[0-9]", "0"), "5"); endif else uncertain = ulpcount; if (not (isempty (decimalseparator))) ## Insert decimal point in ulp number placesafterpoint = length (literal) - decimalseparator; if (length (uncertain) < length (literal)) uncertain = prepad (uncertain, length (literal), "0", 2); endif uncertain = strcat (uncertain (1 : ... (length (uncertain) - ... placesafterpoint)), ... ".", ... uncertain ((length (uncertain) - ... placesafterpoint + 1) ... : length (uncertain))); endif endif uncertain = strcat (uncertain, exponentfield); endfunction interval-3.2.0/inst/@infsup/prod.m0000644000000000000000000000447713316017127015206 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} prod (@var{X}) ## @defmethodx {@@infsup} prod (@var{X}, @var{DIM}) ## ## Product of elements along dimension @var{DIM}. If @var{DIM} is omitted, it ## defaults to the first non-singleton dimension. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## prod (infsup (1 : 4)) ## @result{} ans = [24] ## @end group ## @end example ## @seealso{@@infsup/sum} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-10-23 function [result] = prod (x, dim) if (nargin > 2) print_usage (); return endif if (nargin < 2) ## Try to find non-singleton dimension dim = find (size (x.inf) ~= 1, 1); if (isempty (dim)) dim = 1; endif endif if (dim > ndims (x)) ## Nothing to do result = x; return endif if (ndims (x) == 2 && size (x) == [0 0]) ## Inconsistency: prod ([]) = 1 x = infsup(ones (0, 1)); endif resultsize = size (x); resultsize (dim) = 1; result = infsup (ones (resultsize)); idx.type = "()"; idx.subs = repmat ({":"}, ndims (x)); for i = 1:size (x, dim) idx.subs{dim} = i; result = result .* subsref (x, idx); endfor endfunction %!# from the documentation string %!assert (prod (infsup (1 : 4)) == 24); %!assert (prod (infsup ([])) == 1); %!assert (prod (infsup (magic (3))) == [96, 45, 84]); %!assert (prod (infsup (magic (3)), 2) == [48; 105; 72]); %!assert (prod (infsup (magic (3)), 3) == magic (3)); %!assert (prod (prod (reshape (infsup (1:24), 1, 2, 3, 4))) == reshape ([720, 665280, 13366080, 96909120], 1, 1, 1, 4)) interval-3.2.0/inst/@infsup/psi.m0000644000000000000000000000567113316017127015032 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} psi (@var{X}) ## ## Compute the digamma function, also known as the psi function. ## ## @tex ## $$ ## {\rm psi} (x) = \int_0^\infty \left( {{\exp(-t)} \over t} - {{\exp (-xt)} \over {1 - \exp (-t)}} \right) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## ∞ ## / exp (-t) exp (-xt) ## psi (x) = | ---------- - -------------- dt ## / t 1 - exp (-t) ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## psi (infsup (1)) ## @result{} ans ⊂ [-0.57722, -0.57721] ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-28 function x = psi (x) if (nargin ~= 1) print_usage (); return endif u = inf (size (x.inf)); l = -u; ## psi is monotonically increasing, but not defined for non-positive integers. nosingularity = x.inf >= 0 | ceil (x.inf) > floor (x.sup) | ... (ceil (x.inf) == floor (x.sup) & ... (fix (x.inf) == x.inf | fix (x.sup) == x.sup)); if (any (nosingularity(:))) x.inf(x.inf == 0) = 0; # fix negative zero l(nosingularity & (x.inf > 0 | fix (x.inf) ~= x.inf)) = ... mpfr_function_d ('psi', -inf, x.inf(nosingularity)); u(nosingularity & (x.sup > 0 | fix (x.sup) ~= x.sup)) = ... mpfr_function_d ('psi', +inf, x.sup(nosingularity)); endif emptyresult = x.inf == x.sup & fix (x.inf) == x.inf & x.inf <= 0; l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!assert (isempty (psi (infsup (0)))); %!assert (isempty (psi (infsup (-1)))); %!assert (isempty (psi (infsup (-2)))); %!assert (isempty (psi (infsup (-3)))); %!assert (isentire (psi (infsup (-inf, -42.23)))); %!assert (isentire (psi (infsup (0, inf)))); %!assert (isentire (psi (infsup (-1, 0)))); %!assert (isentire (psi (infsup (-2, -1)))); %!assert (isentire (psi (infsup (-eps, eps)))); %!assert (isentire (psi (infsup (-1-eps, -1+eps)))); %!assert (isentire (psi (infsup (-4.1, -3.9)))); %!# from the documentation string %!assert (psi (infsup (1)) == "[-0x1.2788CFC6FB619p-1, -0x1.2788CFC6FB618p-1]"); interval-3.2.0/inst/@infsup/qr.m0000644000000000000000000001253713316017127014660 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {[@var{Q}, @var{R}] =} qr (@var{A}) ## @deftypemethodx {@@infsup} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A}) ## Compute the QR decomposition of @var{A}. ## ## @var{A} will be a subset of @var{Q} * @var{R} with orthogonal matrix @var{Q} ## and triangular matrix @var{R}. ## ## The columns of @var{Q} are orthogonal unit vectors, that is, @code{Q' * Q} ## equals the identity. @var{R} is an upper triangular matrix with positive ## diagonal elements. ## ## The result is returned in a permuted form, according to the optional return ## value @var{P}. ## ## Accuracy: The result is a valid enclosure. ## @seealso{@@infsup/lu, @@infsup/chol} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-06-26 function [Q, R, P] = qr (A) ## We use the Gram-Schmidt process, since Householder reflections would ## introduce a much larger overestimation for Q in most cases. n = length (A); Q = resize (A, n); R = zeros (n); P = eye (columns (A)); warning ("off", "Octave:broadcast", "local"); for i = 1 : n iColIdx = substruct ("()", {":", i}); if (nargout >= 3 && i < columns (A)) ## Swap columns of Q, choose the column with maximum norm as next pivot B = subsref (Q, substruct ("()", {":", i : n})); [~, j] = max (mig (sumsq (B, 1))); j += i - 1; if (j != i) swapIdx = 1 : n; swapIdx([i j]) = [j i]; swap = @(X) subsref (X, substruct ("()", {":", swapIdx})); Q = swap (Q); R = swap (R); P = P(:, swapIdx(1 : columns (A))); endif endif iCol = subsref (Q, iColIdx); d = norm (iCol, 2); iCol = mulrev (d, iCol, "[-1, +1]"); Q = subsasgn (Q, iColIdx, iCol); R = subsasgn (R, substruct ("()", {i, i}), d); if (i < n) otherColsIdx = substruct ("()", {":", (i + 1) : n}); otherCols = subsref (Q, otherColsIdx); d = dot (otherCols, iCol, 1); otherCols -= d .* iCol; Q = subsasgn (Q, otherColsIdx, otherCols); R = subsasgn (R, substruct ("()", {i, (i + 1) : n}), d); endif endfor Q = resize (Q, rows (A)); R = resize (R, size (A)); P = inv (P); endfunction %!test %! A = infsup ([1 2 3; 4 5 6]); %! [Q, R] = qr (A); %! assert (all (all (subset (A, Q * R)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q))) < 1e-14); %!test %! A = infsup ([1 2; 3 4; 5 6]); %! [Q, R] = qr (A); %! assert (all (all (subset (A, Q * R)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q (:, [1 2])))) < 1e-14); %!test %! A = infsup ([1 2 3; 4 9 6; 9 8 7]); %! [Q, R] = qr (A); %! assert (all (all (subset (A, Q * R)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q))) < 1e-13); %!test %! for n = 3 : 2 : 10 %! A = infsup (magic (n)); %! [Q, R] = qr (A); %! assert (all (all (subset (A, Q * R)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q))) < 1e-10); %! endfor %!test %! A = infsup (magic (3)) + "[2, 2.2]"; %! [Q, R] = qr (A); %! assert (all (all (subset (A, Q * R)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q))) < 1.5); %!function result = is_permutation_matrix (P) %! result = isequal (P, eye (length (P))) || ... %! isequal (typeinfo (P), "permutation matrix"); %!endfunction %!test %! A = infsup ([1 2 3; 4 5 6]); %! [Q, R, P] = qr (A); %! assert (all (all (subset (A, Q * R * P)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q))) < 1e-14); %! assert (is_permutation_matrix (P)); %!test %! A = infsup ([1 2; 3 4; 5 6]); %! [Q, R, P] = qr (A); %! assert (all (all (subset (A, Q * R * P)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q (:, [1 2])))) < 1e-14); %! assert (is_permutation_matrix (P)); %!test %! A = infsup ([1 2 3; 4 9 6; 9 8 7]); %! [Q, R, P] = qr (A); %! assert (all (all (subset (A, Q * R * P)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q))) < 1e-13); %! assert (is_permutation_matrix (P)); %!test %! for n = 3 : 2 : 10 %! A = infsup (magic (n)); %! [Q, R, P] = qr (A); %! assert (all (all (subset (A, Q * R * P)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q))) < 1e-10); %! assert (is_permutation_matrix (P)); %! endfor %!test %! A = infsup (magic (3)) + "[2, 2.2]"; %! [Q, R, P] = qr (A); %! assert (all (all (subset (A, Q * R * P)))); %! assert (all (all (subset (eye (length (Q)), Q' * Q)))); %! assert (max (max (wid (Q))) < 1.5); %! assert (is_permutation_matrix (P)); interval-3.2.0/inst/@infsup/rad.m0000644000000000000000000000753213316017127015003 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{R} =} rad (@var{X}) ## @deftypemethodx {@@infsup} {[@var{M}, @var{R}] =} rad (@var{X}) ## ## Get the radius (and midpoint) of interval @var{X}. ## ## If @var{X} is empty, @code{rad (@var{X})} is NaN. ## If @var{X} is unbounded in one or both directions, @code{rad (@var{X})} is ## positive infinity. ## ## With two output parameters the midpoint and radius are computed. ## ## Accuracy: The radius @var{R} will make a tight enclosure of the interval ## together with midpoint @var{M}. ## ## @example ## @group ## rad (infsup (2.5, 3.5)) ## @result{} ans = 0.50000 ## @end group ## @end example ## @seealso{@@infsup/inf, @@infsup/sup, @@infsup/mid, @@infsup/wid} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-05 function [out1, out2] = rad (x) if (nargin ~= 1) print_usage (); return endif m = mid (x); ## The midpoint is rounded to nearest and the radius must cover both boundaries r1 = mpfr_function_d ('minus', +inf, m, x.inf); r2 = mpfr_function_d ('minus', +inf, x.sup, m); r = max (r1, r2); r (isempty (x)) = nan (); if (nargout >= 2) out1 = m; out2 = r; else out1 = r; endif endfunction %!test; %! [m, r] = rad (infsup (2.5, 3.5)); %! assert (m, 3); %! assert (r, .5); %!# from the documentation string %!assert (rad (infsup (2.5, 3.5)), .5); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.rad; %! for testcase = [testcases]' %! assert (isequaln (... %! rad (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.rad; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (rad (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.rad; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (rad (in1), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.rad; %! for testcase = [testcases]' %! assert (isequaln (... %! rad (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.rad; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (rad (in1), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.rad; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (rad (in1), out)); interval-3.2.0/inst/@infsup/rdivide.m0000644000000000000000000001657013316017127015665 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} rdivide (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} ./ @var{Y}} ## ## Divide all numbers of interval @var{X} by all numbers of @var{Y}. ## ## For @var{X} = 1 compute the reciprocal of @var{Y}. Thus this function can ## compute @code{recip} as defined by IEEE Std 1788-2015. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (2, 3); ## y = infsup (1, 2); ## x ./ y ## @result{} ans = [1, 3] ## @end group ## @end example ## @seealso{@@infsup/times} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function result = rdivide (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); elseif (isa (y, "infsupdec")) ## Workaround for bug #42735 result = rdivide (x, y); return endif ## Short-circuit evaluation for 1 ./ x if (all (vec (x.inf == 1 & x.sup == 1))) result = recip (y); ## Resize, if broadcasting is needed if (not (size_equal (x.inf, y.inf))) result.inf = ones (size (x.inf)) .* result.inf; result.sup = ones (size (x.inf)) .* result.sup; endif return endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, y.inf))) x.inf = ones (size (y.inf)) .* x.inf; x.sup = ones (size (y.inf)) .* x.sup; y.inf = ones (size (x.inf)) .* y.inf; y.sup = ones (size (x.inf)) .* y.sup; endif ## Partitionize the function's domain q1 = x.sup <= 0 & y.sup < 0; q2 = x.sup <= 0 & y.inf > 0; q3 = x.sup <= 0 & y.sup == 0; q4 = x.sup <= 0 & y.sup > 0 & y.inf == 0; q5 = x.inf >= 0 & x.sup > 0 & y.sup < 0; q6 = x.inf >= 0 & x.sup > 0 & y.inf > 0; q7 = x.inf >= 0 & x.sup > 0 & y.sup == 0; q8 = x.inf >= 0 & x.sup > 0 & y.sup > 0 & y.inf == 0; q9 = x.inf < 0 & 0 < x.sup & y.sup < 0; q10 = x.inf < 0 & 0 < x.sup & y.inf > 0; l = u = zeros (size (x.inf)); l (q1) = mpfr_function_d ('rdivide', -inf, x.sup(q1), y.inf(q1)); l (q2) = mpfr_function_d ('rdivide', -inf, x.inf(q2), y.inf(q2)); l (q3) = mpfr_function_d ('rdivide', -inf, x.sup(q3), y.inf(q3)); l (q4) = -inf; l (q5) = mpfr_function_d ('rdivide', -inf, x.sup(q5), y.sup(q5)); l (q6) = mpfr_function_d ('rdivide', -inf, x.inf(q6), y.sup(q6)); l (q7) = -inf; l (q8) = mpfr_function_d ('rdivide', -inf, x.inf(q8), y.sup(q8)); l (q9) = mpfr_function_d ('rdivide', -inf, x.sup(q9), y.sup(q9)); l (q10) = mpfr_function_d ('rdivide', -inf, x.inf(q10), y.inf(q10)); u (q1) = mpfr_function_d ('rdivide', +inf, x.inf(q1), y.sup(q1)); u (q2) = mpfr_function_d ('rdivide', +inf, x.sup(q2), y.sup(q2)); u (q3) = inf; u (q4) = mpfr_function_d ('rdivide', +inf, x.sup(q4), y.sup(q4)); u (q5) = mpfr_function_d ('rdivide', +inf, x.inf(q5), y.inf(q5)); u (q6) = mpfr_function_d ('rdivide', +inf, x.sup(q6), y.inf(q6)); u (q7) = mpfr_function_d ('rdivide', +inf, x.inf(q7), y.inf(q7)); u (q8) = inf; u (q9) = mpfr_function_d ('rdivide', +inf, x.inf(q9), y.sup(q9)); u (q10) = mpfr_function_d ('rdivide', +inf, x.sup(q10), y.inf(q10)); entireresult = (y.inf < 0 & y.sup > 0) | (x.inf < 0 & x.sup > 0 & ... (y.inf == 0 | y.sup == 0)); l(entireresult) = -inf; u(entireresult) = inf; zeroresult = x.inf == 0 & x.sup == 0; l(zeroresult) = u(zeroresult) = 0; l(l == 0) = -0; emptyresult = isempty (x) | isempty (y) | (y.inf == 0 & y.sup == 0); l(emptyresult) = inf; u(emptyresult) = -inf; result = infsup (); result.inf = l; result.sup = u; endfunction function result = recip (x) ## Compute the reciprocal of @var{X}. ## ## The result is equivalent to @code{1 ./ @var{X}}, but is computed more ## efficiently. ## ## Accuracy: The result is a tight enclosure. l = inf (size (x.inf)); u = -l; ## Fix signs to make use of limit values for 1 ./ x. x.inf(x.inf == 0) = +0; x.sup(x.sup == 0) = -0; select = (x.inf >= 0 | x.sup <= 0) & ... # undefined for x = [0, 0] not (x.inf == 0 & x.sup == 0) & ... # x is not empty x.inf < inf; if (any (select(:))) ## recip is monotonically decreasing l(select) = mpfr_function_d ('rdivide', -inf, 1, x.sup(select)); u(select) = mpfr_function_d ('rdivide', +inf, 1, x.inf(select)); endif ## singularity at x = 0 select = x.inf < 0 & x.sup > 0; if (any (select(:))) l(select) = -inf; u(select) = +inf; endif l(l == 0) = -0; result = infsup (); result.inf = l; result.sup = u; endfunction %!# from the documentation string %!assert (infsup (2, 3) ./ infsup (1, 2) == infsup (1, 3)); %!assert (1 ./ infsup (1, 4) == infsup (0.25, 1)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.div; %! for testcase = [testcases]' %! assert (isequaln (... %! rdivide (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.div; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (rdivide (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.div; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (rdivide (in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.recip; %! for testcase = [testcases]' %! assert (isequaln (... %! rdivide (1, testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.recip; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (rdivide (1, in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.recip; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (rdivide (1, in1), out)); interval-3.2.0/inst/@infsup/realsqrt.m0000644000000000000000000000527013316017127016067 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} realsqrt (@var{X}) ## ## Compute the square root (for all non-negative numbers). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## realsqrt (infsup (-6, 4)) ## @result{} ans = [0, 2] ## @end group ## @end example ## @seealso{@@infsup/sqr, @@infsup/rsqrt, @@infsup/pow, @@infsup/cbrt, @@infsup/nthroot} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-01 function x = realsqrt (x) l = mpfr_function_d ('realsqrt', -inf, max (0, x.inf)); u = mpfr_function_d ('realsqrt', +inf, max (0, x.sup)); emptyresult = isempty (x) | x.sup < 0; l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (realsqrt (infsup (-6, 4)) == infsup (0, 2)); %!# correct use of signed zeros %!test %! x = realsqrt (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = realsqrt (infsup (0, 2)); %! assert (signbit (inf (x))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sqrt; %! for testcase = [testcases]' %! assert (isequaln (... %! realsqrt (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sqrt; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (realsqrt (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sqrt; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (realsqrt (in1), out)); interval-3.2.0/inst/@infsup/rem.m0000644000000000000000000002235413316017127015017 0ustar 00000000000000## Copyright 2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} rem (@var{X}, @var{Y}) ## ## Compute the remainder of the division @var{X} by @var{Y}. ## ## Conceptionally, it is given by the expression ## @code{@var{X} - @var{Y} .* fix (@var{X} ./ @var{Y})}. For negative @var{X}, ## the remainder will be either zero or negative. This function is undefined ## for @var{Y} = 0. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## rem (infsup (3), infsup (2)) ## @result{} ans = [1] ## rem (infsup (-3), infsup (2)) ## @result{} ans = [-1] ## @end group ## @end example ## ## @seealso{@@infsup/rdivide, @@infsup/mod} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2017-09-02 function [result, d] = rem (x, y) if (nargin ~= 2) print_usage (); return endif ## Usually, the implementation of an interval arithmetic function is cleanly ## split into a bare and a decorated version. This function's decoration is ## quite complicated to be computed and depends on intermediate values that ## are used to compute the bare interval result. Thus, we also compute ## decoration information as a second output parameter for @infsupdec. if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif ## We can exploit the function's symmetric properties and ## compute each quadrant by projection into the first quadrant. x_p = intersect (x, infsup (0, inf)); x_n = intersect (x, infsup (-inf, 0)); y_p = intersect (y, infsup (0, inf)); y_n = intersect (y, infsup (-inf, 0)); [l1, u1, d1] = rem_quadrant_I (x_p, y_p); [l2, u2, d2] = rem_quadrant_I (x_p, -y_n); [l3, u3, d3] = rem_quadrant_I (-x_n, y_p); [l3, u3] = deal (-u3, -l3); [l4, u4, d4] = rem_quadrant_I (-x_n, -y_n); [l4, u4] = deal (-u4, -l4); l = min (min (l1, l2), min (l3, l4)); u = max (max (u1, u2), max (u3, u4)); warning ("off", "interval:UndefinedOperation", "local"); result = infsup (l, u); d = min (min (d1, d2), min (d3, d4)); endfunction function [l, u, d] = rem_quadrant_I (x, y) ## Compute fractions x ./ y at three corners of the interval box to detect ## cases with y = x ./ n inside the area, where the function is noncontinuous ## and takes extreme values. ## ## ^ y .* y = x / 1 ## | .* ## | q--------.*-r ## | | .* | ## | +----.*-----s y = x / 2 ## | .* ..** ## | .* ..** ## | .* ..** ## | .* ..** ## |.*.** (and so on) ## +---------------------> x q = mpfr_function_d ("rdivide", -inf, x.inf, y.sup); r = mpfr_function_d ("rdivide", +inf, x.sup, y.sup); s = mpfr_function_d ("rdivide", +inf, x.sup, y.inf); ## Fix limit values for corner cases unbound_x_idx = (x.sup == inf & true (size (y.sup))); r(unbound_x_idx) = s(unbound_x_idx) = inf; div_by_zero_idx = (y.inf == 0 & true (size (x.sup))); s(div_by_zero_idx) = inf; # Cases where rem (x, y) == 0 q_zero_idx = (q == fix (q) & (q >= 1 | x.sup == 0) & q < inf); s_zero_idx = (s == fix (s) & s >= 1); inner_zero_idx = (q < s & ceil (q) <= floor (s) & s >= 1); zero_idx = (q_zero_idx | s_zero_idx | inner_zero_idx); l = u = zeros (size (q)); d = _com ()(ones (size (q))); d(s_zero_idx | (q_zero_idx & q > 1)) = _dac (); d(inner_zero_idx) = _def (); d(div_by_zero_idx) = _trv (); ## If the interval box contains no cases with y = x ./ n, the minimum is ## located at (x.inf, y.sup). Otherwise the minimum is zero. select = not (zero_idx); l(select) = mpfr_function_d ("rem", -inf, x.inf(select), y.sup(select)); ## Consider the maximum for y = x ./ n, with the smallest such n. q(q_zero_idx) = mpfr_function_d ("plus", -inf, q(q_zero_idx), 1); q = ceil (q); ## Case 1: y > x select = (q <= 0); u(select) = min (y.sup (select), x.sup(select)); ## Case 2: y.sup = x ./ n select = ((q > 0) & (q <= r)); u(select) = y.sup(select); ## Case 3: y = x.sup ./ n select = ((q > r) & (q <= s)); u(select) = mpfr_function_d ("rdivide", +inf, x.sup(select), q(select)); ## Case 4: The maximum is located at (x.sup, y.inf) select = (q > s); u(select) = mpfr_function_d ("rem", +inf, x.sup(select), y.inf(select)); empty_result_idx = x.sup < 0 | y.sup <= 0; l(empty_result_idx) = inf; u(empty_result_idx) = -inf; endfunction function d = _com () d = uint8 (16); endfunction function d = _dac () d = uint8 (12); endfunction function d = _def () d = uint8 (8); endfunction function d = _trv () d = uint8 (4); endfunction %!assert (rem (infsup (), infsup ()) == infsup ()); %!assert (rem (infsup (0), infsup ()) == infsup ()); %!assert (rem (infsup (), infsup (0)) == infsup ()); %!assert (rem (infsup (0), infsup (0)) == infsup ()); %!assert (rem (infsup (1), infsup (0)) == infsup ()); %!assert (rem (infsup (0, 1), infsup (0)) == infsup ()); %!assert (rem (infsup (1, 2), infsup (0)) == infsup ()); %!assert (rem (infsup (0, inf), infsup (0)) == infsup ()); %!assert (rem (infsup (1, inf), infsup (0)) == infsup ()); %!assert (rem (infsup (realmax, inf), infsup (0)) == infsup ()); %!assert (rem (infsup (0), infsup (1)) == infsup (0)); %!assert (rem (infsup (0), infsup (0, 1)) == infsup (0)); %!assert (rem (infsup (0), infsup (1, 2)) == infsup (0)); %!assert (rem (infsup (0), infsup (0, inf)) == infsup (0)); %!assert (rem (infsup (0), infsup (1, inf)) == infsup (0)); %!assert (rem (infsup (0), infsup (realmax, inf)) == infsup (0)); %!assert (rem (infsup (1), infsup (1)) == infsup (0)); %!assert (rem (infsup (2), infsup (1)) == infsup (0)); %!assert (rem (infsup (4), infsup (2)) == infsup (0)); %!assert (rem (infsup (6), infsup (3)) == infsup (0)); %!assert (rem (infsup (8), infsup (2)) == infsup (0)); %!assert (rem (infsup (9), infsup (3)) == infsup (0)); %!assert (rem (infsup (realmax), infsup (realmax)) == infsup (0)); %!assert (rem (infsup (realmax), infsup (realmax / 2)) == infsup (0)); %!assert (rem (infsup (realmax), infsup (realmax / 4)) == infsup (0)); %!assert (rem (infsup (realmax), infsup (realmax / 8)) == infsup (0)); %!assert (rem (infsup (realmax), infsup (realmax / 16)) == infsup (0)); %!assert (rem (infsup (realmax), infsup (realmax / 32)) == infsup (0)); %!assert (rem (infsup (0.1), infsup (0.1)) == infsup (0)); %!assert (rem (infsup (0.1 * 2), infsup (0.1)) == infsup (0)); %!assert (rem (infsup (0.1 * 4), infsup (0.1)) == infsup (0)); %!assert (rem (infsup (pi), infsup (pi)) == infsup (0)); %!assert (rem (infsup (pi), infsup (pi / 2)) == infsup (0)); %!assert (rem (infsup (pi), infsup (pi / 4)) == infsup (0)); %!assert (rem (infsup (pow2 (-1074)), infsup (pow2 (-1074))) == infsup (0)); %!assert (rem (infsup (pow2 (-1073)), infsup (pow2 (-1074))) == infsup (0)); %!assert (rem (infsup (pow2 (-1072)), infsup (pow2 (-1074))) == infsup (0)); %!assert (rem (infsup (1), infsup (2)) == infsup (1)); %!assert (rem (infsup (0.5), infsup (1)) == infsup (0.5)); %!assert (rem (infsup (pi), infsup (3.15)) == infsup (pi)); %!assert (rem (infsup (1), infsup (2, 3)) == infsup (1)); %!assert (rem (infsup (1), infsup (2, inf)) == infsup (1)); %!assert (rem (infsup (0.5), infsup (1, 2)) == infsup (0.5)); %!assert (rem (infsup (0.5), infsup (1, inf)) == infsup (0.5)); %!assert (rem (infsup (pi), infsup (3.15)) == infsup (pi)); %!assert (rem (infsup (pi), infsup (3.15, inf)) == infsup (pi)); %!assert (rem (infsup (0, 1), infsup (0, 1)) == infsup (0, 1)); %!assert (rem (infsup (0, 2), infsup (0, 1)) == infsup (0, 1)); %!assert (rem (infsup (0, 1), infsup (0, 2)) == infsup (0, 1)); %!assert (rem (infsup (0, realmax), infsup (0, realmax)) == infsup (0, realmax)); %!assert (rem (infsup (realmax, inf), infsup (realmax, inf)) == infsup (0, inf)); %!assert (rem (infsup (0, inf), infsup (0, inf)) == infsup (0, inf)); %!assert (rem (infsup (0), infsup (1)) == infsup (0)); %!assert (rem (infsup (1), infsup (1)) == infsup (0)); %!assert (rem (infsup (0, 1), infsup (1)) == infsup (0, 1)); %!assert (rem (infsup (1, 2), infsup (1)) == infsup (0, 1)); %!assert (rem (infsup (0, inf), infsup (1)) == infsup (0, 1)); %!assert (rem (infsup (1, inf), infsup (1)) == infsup (0, 1)); %!assert (rem (infsup (realmax, inf), infsup (1)) == infsup (0, 1)); %!assert (rem (infsup (1), infsup (1)) == infsup (0)); %!assert (rem (infsup (1), infsup (0, 1)) == infsup (0, 0.5)); %!assert (rem (infsup (1), infsup (1, 2)) == infsup (0, 1)); %!assert (rem (infsup (1), infsup (0, inf)) == infsup (0, 1)); %!assert (rem (infsup (1), infsup (1, inf)) == infsup (0, 1)); %!assert (rem (infsup (1), infsup (2, inf)) == infsup (1)); %!assert (rem (infsup (1), infsup (realmax, inf)) == infsup (1)); interval-3.2.0/inst/@infsup/reshape.m0000644000000000000000000000440313316017127015656 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} reshape (@var{A}, @var{M}, @var{N}, ...) ## @defmethodx {@@infsup} reshape (@var{X}, [@var{M} @var{N}, ...]) ## @defmethodx {@@infsup} reshape (@var{X}, ..., @var{[]}, ...) ## ## Return an interval matrix with the specified dimensions (M, N, ...) whose ## elements are taken from the interval matrix @var{A}. The elements of the ## matrix are accessed in column-major order (like Fortran arrays are stored). ## ## Note that the total number of elements in the original matrix ## (@code{prod (size (@var{A}))}) must match the total number of elements in ## the new matrix (@code{prod ([@var{M} @var{N}])}). ## ## A single dimension of the return matrix may be left unspecified and ## Octave will determine its size automatically. An empty matrix ([]) ## is used to flag the unspecified dimension. ## ## @example ## @group ## reshape (infsup (1 : 6), 2, 3) ## @result{} ans = 2×3 interval matrix ## [1] [3] [5] ## [2] [4] [6] ## @end group ## @end example ## @seealso{@@infsup/resize, @@infsup/cat, @@infsup/postpad, @@infsup/prepad} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-19 function a = reshape (a, varargin) if (not (isa (a, "infsup"))) print_usage (); return endif a.inf = reshape (a.inf, varargin{:}); a.sup = reshape (a.sup, varargin{:}); endfunction %!assert (reshape (infsup (1 : 6), 2, 3) == infsup (reshape (1 : 6, 2, 3))); %!assert (reshape (infsup (1 : 24), 2, [], 4) == infsup (reshape (1 : 24, 2, 3, 4))); interval-3.2.0/inst/@infsup/resize.m0000644000000000000000000000471413316017127015535 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} resize (@var{X}, @var{M}) ## @defmethodx {@@infsup} resize (@var{X}, @var{M}, @var{N}, ...) ## @defmethodx {@@infsup} resize (@var{X}, [@var{M} @var{N}, ...]) ## ## Resize interval array @var{X} cutting off elements as necessary. ## ## In the result, element with certain indices is equal to the corresponding ## element of @var{X} if the indices are within the bounds of @var{X}; ## otherwise, the element is set to zero. ## ## If only @var{M} is supplied, and it is a scalar, the dimension of the result ## is @var{M}-by-@var{M}. If @var{M}, @var{N}, ... are all scalars, then the ## dimensions of the result are @var{M}-by-@var{N}-by-.... If given a vector as ## input, then the dimensions of the result are given by the elements of that ## vector. ## ## An object can be resized to more dimensions than it has; in such ## case the missing dimensions are assumed to be 1. Resizing an ## object to fewer dimensions is not possible. ## ## @example ## @group ## resize (infsup (magic (3)), 4, 2) ## @result{} ans = 4×2 interval matrix ## [8] [1] ## [3] [5] ## [4] [9] ## [0] [0] ## @end group ## @end example ## @seealso{@@infsup/reshape, @@infsup/cat, @@infsup/postpad, @@infsup/prepad} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-19 function x = resize (x, varargin) if (not (isa (x, "infsup"))) print_usage (); return endif x.inf = resize (x.inf, varargin{:}); x.sup = resize (x.sup, varargin{:}); x.inf(x.inf == 0) = -0; endfunction %!assert (resize (infsup (magic (3)), 4, 2) == infsup ([8, 1; 3, 5; 4, 9; 0, 0])); %!assert (resize (infsup (ones (2, 2, 2)), 4, 1, 2) == infsup (resize (ones (2, 2, 2), 4, 1, 2))) interval-3.2.0/inst/@infsup/round.m0000644000000000000000000000741713316017127015366 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} round (@var{X}) ## ## Round each number in interval @var{X} to the nearest integer. Ties are ## rounded away from zero (towards +Inf or -Inf depending on the sign). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## round (infsup (2.5, 3.5)) ## @result{} ans = [3, 4] ## round (infsup (-0.5, 5)) ## @result{} ans = [-1, +5] ## @end group ## @end example ## @seealso{@@infsup/floor, @@infsup/ceil, @@infsup/roundb, @@infsup/fix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = round (x) if (nargin ~= 1) print_usage (); return endif x.inf = round (x.inf); x.sup = round (x.sup); x.inf(x.inf == 0) = -0; x.sup(x.sup == 0) = +0; endfunction %!# Empty interval %!assert (round (infsup ()) == infsup ()); %!# Singleton intervals %!assert (round (infsup (0)) == infsup (0)); %!assert (round (infsup (0.5)) == infsup (1)); %!assert (round (infsup (0.25)) == infsup (0)); %!assert (round (infsup (0.75)) == infsup (1)); %!assert (round (infsup (-0.5)) == infsup (-1)); %!# Bounded intervals %!assert (round (infsup (-0.5, 0)) == infsup (-1, 0)); %!assert (round (infsup (0, 0.5)) == infsup (0, 1)); %!assert (round (infsup (0.25, 0.5)) == infsup (0, 1)); %!assert (round (infsup (-1, 0)) == infsup (-1, 0)); %!assert (round (infsup (-1, 1)) == infsup (-1, 1)); %!assert (round (infsup (-realmin, realmin)) == infsup (0)); %!assert (round (infsup (-realmax, realmax)) == infsup (-realmax, realmax)); %!# Unbounded intervals %!assert (round (infsup (-realmin, inf)) == infsup (0, inf)); %!assert (round (infsup (-realmax, inf)) == infsup (-realmax, inf)); %!assert (round (infsup (-inf, realmin)) == infsup (-inf, 0)); %!assert (round (infsup (-inf, realmax)) == infsup (-inf, realmax)); %!assert (round (infsup (-inf, inf)) == infsup (-inf, inf)); %!# correct use of signed zeros %!test %! x = round (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = round (infsup (-0.25, 0.25)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.roundTiesToAway; %! for testcase = [testcases]' %! assert (isequaln (... %! round (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.roundTiesToAway; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (round (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.roundTiesToAway; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (round (in1), out)); interval-3.2.0/inst/@infsup/roundb.m0000644000000000000000000000754713316017127015534 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} roundb (@var{X}) ## ## Round each number in interval @var{X} to the nearest integer. Ties are ## rounded towards the nearest even integer. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## roundb (infsup (2.5, 3.5)) ## @result{} ans = [2, 4] ## roundb (infsup (-0.5, 5.5)) ## @result{} ans = [0, 6] ## @end group ## @end example ## @seealso{@@infsup/floor, @@infsup/ceil, @@infsup/round, @@infsup/fix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = roundb (x) if (nargin ~= 1) print_usage (); return endif x.inf = roundb (x.inf); x.sup = roundb (x.sup); x.inf(x.inf == 0) = -0; x.sup(x.sup == 0) = +0; endfunction %!# Empty interval %!assert (roundb (infsup ()) == infsup ()); %!# Singleton intervals %!assert (roundb (infsup (0)) == infsup (0)); %!assert (roundb (infsup (0.5)) == infsup (0)); %!assert (roundb (infsup (0.25)) == infsup (0)); %!assert (roundb (infsup (0.75)) == infsup (1)); %!assert (roundb (infsup (1.5)) == infsup (2)); %!assert (roundb (infsup (-0.5)) == infsup (0)); %!assert (roundb (infsup (-1.5)) == infsup (-2)); %!# Bounded intervals %!assert (roundb (infsup (-0.5, 0)) == infsup (0)); %!assert (roundb (infsup (0, 0.5)) == infsup (0)); %!assert (roundb (infsup (0.25, 0.5)) == infsup (0)); %!assert (roundb (infsup (-1, 0)) == infsup (-1, 0)); %!assert (roundb (infsup (-1, 1)) == infsup (-1, 1)); %!assert (roundb (infsup (-realmin, realmin)) == infsup (0)); %!assert (roundb (infsup (-realmax, realmax)) == infsup (-realmax, realmax)); %!# Unbounded intervals %!assert (roundb (infsup (-realmin, inf)) == infsup (0, inf)); %!assert (roundb (infsup (-realmax, inf)) == infsup (-realmax, inf)); %!assert (roundb (infsup (-inf, realmin)) == infsup (-inf, 0)); %!assert (roundb (infsup (-inf, realmax)) == infsup (-inf, realmax)); %!assert (roundb (infsup (-inf, inf)) == infsup (-inf, inf)); %!# correct use of signed zeros %!test %! x = roundb (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!test %! x = roundb (infsup (-0.25, 0.25)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.roundTiesToEven; %! for testcase = [testcases]' %! assert (isequaln (... %! roundb (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.roundTiesToEven; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (roundb (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.roundTiesToEven; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (roundb (in1), out)); interval-3.2.0/inst/@infsup/rows.m0000644000000000000000000000222413316017127015220 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} rows (@var{A}) ## ## Return the number of rows of @var{A}. ## @seealso{@@infsup/numel, @@infsup/size, @@infsup/length, @@infsup/columns, @@infsup/end} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function result = rows (a) if (nargin ~= 1) print_usage (); return endif result = rows (a.inf); endfunction %!assert (rows (infsup (zeros (3, 4))), 3); interval-3.2.0/inst/@infsup/rsqrt.m0000644000000000000000000000310713316017127015402 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} rsqrt (@var{X}) ## ## Compute the reciprocal square root (for all positive numbers). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## rsqrt (infsup (-6, 4)) ## @result{} ans = [0.5, inf] ## @end group ## @end example ## @seealso{@@infsup/realsqrt} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function x = rsqrt (x) l = mpfr_function_d ('rsqrt', -inf, max (0, x.sup)); u = mpfr_function_d ('rsqrt', +inf, max (0, x.inf)); emptyresult = isempty (x) | x.sup <= 0; l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (rsqrt (infsup (-6, 4)) == infsup (.5, inf)); %!# correct use of signed zeros %!test %! x = rsqrt (infsup (0, inf)); %! assert (signbit (inf (x))); interval-3.2.0/inst/@infsup/sdist.m0000644000000000000000000000552613316017127015364 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sdist (@var{X}, @var{Y}) ## ## Compute the signed distance between two intervals as sets. ## ## The signed distance for closed real intervals is the minimum distance ## between each pair of numbers, where the result's sign indicates whether ## @var{x} precedes @var{y} (negative), @var{y} precedes @var{x} (positive), or ## @var{x} intersects @var{y} (zero). That is, the signed distance equals zero ## if a number can be found in both intervals. Otherwise the signed distance ## is the positive or negative size of the gap between both intervals on the ## real number lane. ## ## If any interval is empty, the result is NaN. For interval arrays the ## result is computed entry-wise. ## ## Accuracy: The result is correctly-rounded (away from zero). ## ## @example ## @group ## sdist (infsup (0, 6), infsup (7, 20)) ## @result{} ans = -1 ## sdist (infsup (3, 5), infsup (0, 1)) ## @result{} ans = 2 ## @end group ## @end example ## @seealso{@@infsup/idist, @@infsup/hdist} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-06-11 function result = sdist (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); endif ## Resize, if broadcasting is needed if (not (size_equal (x.inf, y.inf))) x.inf = ones (size (y.inf)) .* x.inf; x.sup = ones (size (y.inf)) .* x.sup; y.inf = ones (size (x.inf)) .* y.inf; y.sup = ones (size (x.inf)) .* y.sup; endif result = zeros (size (x.inf)); select = x.sup < y.inf; if (any (select(:))) result(select) = ... mpfr_function_d ('minus', -inf, x.sup(select), y.inf(select)); endif select = x.inf > y.sup; if (any (select(:))) result(select) = max (result(select), ... mpfr_function_d ('minus', +inf, x.inf(select), y.sup(select))); endif result(isempty (x) | isempty (y)) = nan (); endfunction %!# from the documentation string %!assert (sdist (infsup (0, 6), infsup (7, 20)), -1); %!assert (sdist (infsup (3, 5), infsup (0, 1)), 2); interval-3.2.0/inst/@infsup/sec.m0000644000000000000000000000745013316017127015006 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sec (@var{X}) ## ## Compute the secant in radians, that is the reciprocal cosine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sec (infsup (1)) ## @result{} ans ⊂ [1.8508, 1.8509] ## @end group ## @end example ## @seealso{@@infsup/cos, @@infsup/csc, @@infsup/cot} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function x = sec (x) if (nargin ~= 1) print_usage (); return endif l = u = derivl = derivu = zeros (size (x.inf)); ## Check, if wid (x) is certainly greater than 2*pi. This can save the ## computation if some values. width = mpfr_function_d ('minus', -inf, x.sup, x.inf); persistent pi = infsup ("pi"); certainlysingularity = width >= sup (pi); ## We simply compute the secant for both endpoints. select = not (certainlysingularity); l(select) = min (... mpfr_function_d ('sec', -inf, x.inf(select)), ... mpfr_function_d ('sec', -inf, x.sup(select))); u(select) = max (... mpfr_function_d ('sec', inf, x.inf(select)), ... mpfr_function_d ('sec', inf, x.sup(select))); ## A change of sign is a sufficient singularity indicator certainlysingularity = certainlysingularity | (select & sign (l) ~= sign (u)); l(certainlysingularity) = -inf; u(certainlysingularity) = inf; ## Check, whether the interval contains a local extremum using the derivative select = not (certainlysingularity); derivl(select) = mpfr_function_d ('sec', 0, x.inf(select)) .* ... mpfr_function_d ('tan', 0, x.inf(select)); derivu(select) = mpfr_function_d ('sec', 0, x.sup(select)) .* ... mpfr_function_d ('tan', 0, x.sup(select)); hasextremum = select & ((derivl <= 0 & derivu >= 0) | ... (derivl >= 0 & derivu <= 0)); l(hasextremum & l > 0) = 1; u(hasextremum & u < 0) = -1; emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (sec (infsup (1)) == "[0x1.D9CF0F125CC29, 0x1.D9CF0F125CC2A]"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sec; %! for testcase = [testcases]' %! assert (isequaln (... %! sec (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sec; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sec (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sec; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sec (in1), out)); interval-3.2.0/inst/@infsup/sech.m0000644000000000000000000000514213316017127015152 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sech (@var{X}) ## ## Compute the hyperbolic secant, that is the reciprocal hyperbolic cosine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sech (infsup (1)) ## @result{} ans ⊂ [0.64805, 0.64806] ## @end group ## @end example ## @seealso{@@infsup/cosh, @@infsup/csch, @@infsup/coth} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function x = sech (x) if (nargin ~= 1) print_usage (); return endif l = mpfr_function_d ('sech', -inf, mag (x)); u = mpfr_function_d ('sech', +inf, mig (x)); emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (sech (infsup (1)) == "[0x1.4BCDC50ED6BE7p-1, 0x1.4BCDC50ED6BE8p-1]"); %!# correct use of signed zeros %!test %! x = sech (infsup (0, inf)); %! assert (signbit (inf (x))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sech; %! for testcase = [testcases]' %! assert (isequaln (... %! sech (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sech; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sech (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sech; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sech (in1), out)); interval-3.2.0/inst/@infsup/setdiff.m0000644000000000000000000000467013316017127015661 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} setdiff (@var{A}, @var{B}) ## ## Build the relative complement of interval @var{B} in interval @var{A}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (1, 3); ## y = infsup (2, 4); ## setdiff (x, y) ## @result{} ans = [1, 2] ## @end group ## @end example ## @seealso{@@infsup/intersect, @@infsup/union, @@infsup/setxor} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-03 function a = setdiff (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); endif ## Resize, if broadcasting is needed if (not (size_equal (a.inf, b.inf))) a.inf = ones (size (b.inf)) .* a.inf; a.sup = ones (size (b.inf)) .* a.sup; b.inf = ones (size (a.inf)) .* b.inf; b.sup = ones (size (a.inf)) .* b.sup; endif l = a.inf; u = a.sup; select = b.sup >= a.sup & b.inf > a.inf; u(select) = min (u(select), b.inf(select)); select = b.inf <= a.inf & b.sup < a.sup; l(select) = max (l(select), b.sup(select)); emptyresult = b.inf <= a.inf & b.sup >= a.sup; l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; u(u == 0) = +0; a.inf = l; a.sup = u; endfunction %!assert (isempty (setdiff (infsup (), infsup (1, 4)))); %!assert (setdiff (infsup (1, 3), infsup ()) == infsup (1, 3)); %!assert (isempty (setdiff (infsup (1, 3), infsup (-inf, inf)))); %!assert (isempty (setdiff (infsup (1, 3), infsup (1, 4)))); %!assert (setdiff (infsup (-inf, inf), infsup (1, 4)) == infsup (-inf, inf)); %!# from the documentation string %! assert (setdiff (infsup (1, 3), infsup (2, 4)) == infsup (1, 2)); interval-3.2.0/inst/@infsup/setxor.m0000644000000000000000000001021713316017127015553 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {} setxor (@var{A}, @var{B}) ## @deftypemethodx {@@infsup} {[@var{C}, @var{C1}, @var{C2}] =} setxor (@var{A}, @var{B}) ## ## Build the symmetric difference of intervals @var{A} and @var{B}. ## ## With three output arguments, return intervals @var{C1} and @var{C2} such ## that @var{C1} and @var{C2} are enclosures of disjoint sets whose union is ## enclosed by interval @var{C}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (1, 3); ## y = infsup (2, 4); ## [z, z1, z2] = setxor (x, y) ## @result{} ## z = [1, 4] ## z1 = [1, 2] ## z2 = [3, 4] ## @end group ## @end example ## @seealso{@@infsup/intersect, @@infsup/union, @@infsup/setdiff} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-03 function [c, c1, c2] = setxor (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); endif ## Resize, if broadcasting is needed if (not (size_equal (a.inf, b.inf))) a.inf = ones (size (b.inf)) .* a.inf; a.sup = ones (size (b.inf)) .* a.sup; b.inf = ones (size (a.inf)) .* b.inf; b.sup = ones (size (a.inf)) .* b.sup; endif ## Sort the four boundaries in ascending order b1 <= b2 <= b3 <= b4, ## if only one empty interval is present, then [b2, b3] = [Empty], ## with two empty intervals we also have [b1, b4] = [Empty]. b1 = min (a.inf, b.inf); b2 = max (a.inf, b.inf); b3 = min (a.sup, b.sup); b4 = max (a.sup, b.sup); [b2, b3] = deal (min (b2, b3), max (b2, b3)); l = b1; u = b4; select = a.inf == b.inf; l(select) = b3(select); select = a.sup == b.sup; u(select) = b2(select); select = a.inf == b.inf & a.sup == b.sup; l(select) = inf; u(select) = -inf; l(l == 0) = -0; u(u == 0) = +0; c = infsup (); c.inf = l; c.sup = u; if (nargout > 1) select = isempty (a) | isempty (b); b1(select) = a.inf(select); b2(select) = a.sup(select); b3(select) = b.inf(select); b4(select) = b.sup(select); l1 = b1; u1 = b2; select = a.inf == b.inf; l1(select) = inf; u1(select) = -inf; l1(l1 == 0) = -0; u1(u1 == 0) = +0; c1 = infsup (); c1.inf = l1; c1.sup = u1; l2 = b3; u2 = b4; select = a.sup == b.sup; l2(select) = inf; u2(select) = -inf; l2(l2 == 0) = -0; u2(u2 == 0) = +0; c2 = infsup (); c2.inf = l2; c2.sup = u2; endif endfunction %!test %! [z, z1, z2] = setxor (infsup (), infsup ()); %! assert (isempty (z)); %! assert (isempty (z1)); %! assert (isempty (z2)); %!test %! [z, z1, z2] = setxor (infsup (-inf, inf), infsup ()); %! assert (isentire (z)); %! assert (isentire (z1)); %! assert (isempty (z2)); %!test %! [z, z1, z2] = setxor (infsup (-inf, inf), infsup (2)); %! assert (isentire (z)); %! assert (z1 == infsup (-inf, 2)); %! assert (z2 == infsup (2, inf)); %!test %! [z, z1, z2] = setxor (infsup (2, 3), infsup (2)); %! assert (z == infsup (2, 3)); %! assert (z1 == infsup ()); %! assert (z2 == infsup (2, 3)); %!test %! [z, z1, z2] = setxor (infsup (2, 3), infsup (2, 2.5)); %! assert (z == infsup (2.5, 3)); %! assert (z1 == infsup ()); %! assert (z2 == infsup (2.5, 3)); %!# from the documentation string %!test %! [z, z1, z2] = setxor (infsup (1, 3), infsup (2, 4)); %! assert (z == infsup (1, 4)); %! assert (z1 == infsup (1, 2)); %! assert (z2 == infsup (3, 4)); interval-3.2.0/inst/@infsup/sign.m0000644000000000000000000000524213316017127015171 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sign (@var{X}) ## ## Compute the signum function for each number in interval @var{X}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sign (infsup (2, 3)) ## @result{} ans = [1] ## sign (infsup (0, 5)) ## @result{} ans = [0, 1] ## sign (infsup (-17)) ## @result{} ans = [-1] ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function x = sign (x) if (nargin ~= 1) print_usage (); return endif l = sign (x.inf); u = sign (x.sup); emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (sign (infsup (2, 3)) == infsup (1)); %!assert (sign (infsup (0, 5)) == infsup (0, 1)); %!assert (sign (infsup (-17)) == infsup (-1)); %!# correct use of signed zeros %!test %! x = sign (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sign; %! for testcase = [testcases]' %! assert (isequaln (... %! sign (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sign; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sign (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sign; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sign (in1), out)); interval-3.2.0/inst/@infsup/sin.m0000644000000000000000000001345113316017127015023 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sin (@var{X}) ## ## Compute the sine in radians. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sin (infsup (1)) ## @result{} ans ⊂ [0.84147, 0.84148] ## @end group ## @end example ## @seealso{@@infsup/asin, @@infsup/csc, @@infsup/sinh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-05 function x = sin (x) if (nargin ~= 1) print_usage (); return endif l = u = cossignl = cossignu = zeros (size (x.inf)); ## Check, if wid (x) is certainly greater than 2*pi. This can save the ## computation if some sine values. width = mpfr_function_d ('minus', -inf, x.sup, x.inf); persistent pi = infsup ("pi"); persistent twopi = 2 .* pi; certainlyfullperiod = width >= sup (twopi); l(certainlyfullperiod) = -1; u(certainlyfullperiod) = 1; possiblynotfullperiod = not (certainlyfullperiod); if (__check_crlibm__ ()) l(possiblynotfullperiod) = min (crlibm_function ('sin', -inf, ... x.inf(possiblynotfullperiod)), ... crlibm_function ('sin', -inf, ... x.sup(possiblynotfullperiod))); u(possiblynotfullperiod) = max (crlibm_function ('sin', inf, ... x.inf(possiblynotfullperiod)), ... crlibm_function ('sin', inf, ... x.sup(possiblynotfullperiod))); ## We use sign (cos) to know the gradient at the boundaries. cossignl(possiblynotfullperiod) = sign (crlibm_function ('cos', .5, ... x.inf(possiblynotfullperiod))); cossignu(possiblynotfullperiod) = sign (crlibm_function ('cos', .5, ... x.sup(possiblynotfullperiod))); else l(possiblynotfullperiod) = min (mpfr_function_d ('sin', -inf, ... x.inf(possiblynotfullperiod)), ... mpfr_function_d ('sin', -inf, ... x.sup(possiblynotfullperiod))); u(possiblynotfullperiod) = max (mpfr_function_d ('sin', inf, ... x.inf(possiblynotfullperiod)), ... mpfr_function_d ('sin', inf, ... x.sup(possiblynotfullperiod))); ## We use sign (cos) to know the gradient at the boundaries. cossignl(possiblynotfullperiod) = sign (mpfr_function_d ('cos', .5, ... x.inf(possiblynotfullperiod))); cossignu(possiblynotfullperiod) = sign (mpfr_function_d ('cos', .5, ... x.sup(possiblynotfullperiod))); endif ## In case of sign (cos) == 0, we conservatively use sign (cos) of nextout. cossignl(cossignl == 0) = sign (l(cossignl == 0)); cossignu(cossignu == 0) = (-1) * sign (u(cossignu == 0)); containsinf = possiblynotfullperiod & ((cossignl == -1 & cossignu == 1) | ... (cossignl == cossignu & ... width >= sup (pi))); l(containsinf) = -1; containssup = possiblynotfullperiod & ((cossignl == 1 & cossignu == -1) | ... (cossignl == cossignu & ... width >= sup (pi))); u(containssup) = 1; emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; u(u == 0) = +0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (sin (infsup (1)) == "[0x1.AED548F090CEEp-1, 0x1.AED548F090CEFp-1]"); %!# correct use of signed zeros %!test %! x = sin (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!# test fix for bug #51283 %!test %! x = sin (infsup ([0, 0])); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sin; %! for testcase = [testcases]' %! assert (isequaln (... %! sin (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sin (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sin (in1), out)); interval-3.2.0/inst/@infsup/sinh.m0000644000000000000000000000534613316017127015177 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sinh (@var{X}) ## ## Compute the hyperbolic sine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sinh (infsup (1)) ## @result{} ans ⊂ [1.1752, 1.1753] ## @end group ## @end example ## @seealso{@@infsup/asinh, @@infsup/csch, @@infsup/cosh, @@infsup/tanh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-06 function x = sinh (x) if (nargin ~= 1) print_usage (); return endif if (__check_crlibm__ ()) l = crlibm_function ('sinh', -inf, x.inf); u = crlibm_function ('sinh', +inf, x.sup); else l = mpfr_function_d ('sinh', -inf, x.inf); u = mpfr_function_d ('sinh', +inf, x.sup); endif emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (sinh (infsup (1)) == "[0x1.2CD9FC44EB982, 0x1.2CD9FC44EB983]"); %!# correct use of signed zeros %!test %! x = sinh (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sinh; %! for testcase = [testcases]' %! assert (isequaln (... %! sinh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sinh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sinh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sinh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sinh (in1), out)); interval-3.2.0/inst/@infsup/sinrev.m0000644000000000000000000001636113316017127015543 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} sinrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsup} {@var{X} =} sinrev (@var{C}) ## ## Compute the reverse sine function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{sin (x) ∈ @var{C}}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## sinrev (infsup (-1), infsup (0, 6)) ## @result{} ans ⊂ [4.7123, 4.7124] ## @end group ## @end example ## @seealso{@@infsup/sin} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = sinrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsup (-inf, inf); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (x, "infsup"))) x = infsup (x); endif arcsine = asin (c); result = x; ## Resize, if broadcasting is needed if (not (size_equal (arcsine.inf, result.inf))) arcsine.inf = ones (size (result.inf)) .* arcsine.inf; arcsine.sup = ones (size (result.inf)) .* arcsine.sup; result.inf = ones (size (arcsine.inf)) .* result.inf; result.sup = ones (size (arcsine.inf)) .* result.sup; endif result.inf(isempty (arcsine)) = inf; result.sup(isempty (arcsine)) = -inf; idx.type = '()'; persistent pi = infsup ("pi"); select = not (isempty (result)) ... & not (subset (infsup (-pi.sup / 2, pi.sup / 2), arcsine)); if (any (select(:))) ## Find a smaller upper bound for x, if the restriction from c allows it u = inf (size (result.inf)); select_u = select & result.sup < inf; ## Find n, such that result.sup is within a distance of pi/2 around n * pi. n = result.sup; n(select_u) = ceil (floor (sup (n(select_u) ./ (pi ./ 2))) ./ 2); arcsineshifted = arcsine; idx.subs = {(select_u & rem (n, 2) == 0)}; arcsineshifted = subsasgn (arcsineshifted, idx, ... subsref (arcsineshifted, idx) + ... subsref (n, idx) .* pi); idx.subs = {(select_u & rem (n, 2) ~= 0)}; arcsineshifted = subsasgn (arcsineshifted, idx, ... subsref (n, idx) .* pi - ... subsref (arcsineshifted, idx)); overlapping = not (isempty (intersect (result, arcsineshifted))); u(select_u & overlapping) = ... min (result.sup(select_u & overlapping), ... arcsineshifted.sup(select_u & overlapping)); m = n; m(select_u & ~overlapping) = ... mpfr_function_d ('minus', +inf, m(select_u & ~overlapping), 1); idx.subs = {(select_u & ~overlapping & rem (n, 2) == 0)}; u(idx.subs{1}) = ... sup (subsref (m, idx) .* pi - subsref (arcsine, idx)); idx.subs = {(select_u & ~overlapping & rem (n, 2) ~= 0)}; u(idx.subs{1}) = ... sup (subsref (arcsine, idx) + subsref (m, idx) .* pi); ## Find a larger lower bound for x, if the restriction from c allows it l = -inf (size (result.inf)); select_l = select & result.inf > -inf; ## Find n, such that result.inf is within a distance of pi/2 around n * pi. n = result.inf; n(select_l) = floor (ceil (inf (n(select_l) ./ (pi ./ 2))) ./ 2); arcsineshifted = arcsine; idx.subs = {(select_l & rem (n, 2) == 0)}; arcsineshifted = subsasgn (arcsineshifted, idx, ... subsref (arcsineshifted, idx) + ... subsref (n, idx) .* pi); idx.subs = {(select_l & rem (n, 2) ~= 0)}; arcsineshifted = subsasgn (arcsineshifted, idx, ... subsref (n, idx) .* pi - ... subsref (arcsineshifted, idx)); overlapping = not (isempty (intersect (result, arcsineshifted))); l(select_l & overlapping) = ... max (result.inf(select_l & overlapping), ... arcsineshifted.inf(select_l & overlapping)); m = n; m(select_l & ~overlapping) = ... mpfr_function_d ('plus', -inf, m(select_l & ~overlapping), 1); idx.subs = {(select_l & ~overlapping & rem (n, 2) == 0)}; l(idx.subs {1}) = ... inf (subsref (m, idx) .* pi - subsref (arcsine, idx)); idx.subs = {(select_l & ~overlapping & rem (n, 2) ~= 0)}; l(idx.subs {1}) = ... inf (subsref (arcsine, idx) + subsref (m, idx) .* pi); result.inf(select) = max (l(select), result.inf(select)); result.sup(select) = min (u(select), result.sup(select)); result.inf(result.inf > result.sup) = inf; result.sup(result.inf > result.sup) = -inf; endif endfunction %!# from the documentation string %!assert (sinrev (infsup (-1), infsup (0, 6)) == "[0x1.2D97C7F3321D2p2, 0x1.2D97C7F3321D3p2]"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sinRev; %! for testcase = [testcases]' %! assert (isequaln (... %! sinrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sinRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sinrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sinRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sinrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sinRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! sinrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sinRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (sinrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sinRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sinrev (in1, in2), out)); interval-3.2.0/inst/@infsup/size.m0000644000000000000000000000462313316017127015205 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{SZ} =} size (@var{A}) ## @deftypemethodx {@@infsup} {@var{DIM_SZ} =} size (@var{A}, @var{DIM}) ## @deftypemethodx {@@infsup} {[@var{ROWS, COLS, ..., DIM_N_SZ}] =} size (...) ## ## Return a row vector with the size (number of elements) of each ## dimension for the interval array @var{A}. ## ## When given a second argument, @var{DIM}, return the size of the ## corresponding dimension. ## ## With a single output argument, @command{size} returns a row vector. When ## called with multiple output arguments, @command{size} returns the size of ## dimension N in the Nth argument. The number of rows, dimension 1, ## is returned in the first argument, the number of columns, dimension ## 2, is returned in the second argument, etc. If there are more ## dimensions in A then there are output arguments, @command{size} returns the ## total number of elements in the remaining dimensions in the final ## output argument. ## ## @seealso{@@infsup/length, @@infsup/numel, @@infsup/rows, @@infsup/columns, @@infsup/end} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function varargout = size (a, dim) if (nargin == 0 || nargin > 2) print_usage (); return endif if (nargin == 1) varargout = cell (1, max (1, nargout)); [varargout{:}] = size (a.inf); else if (nargout > 1) print_usage (); return endif varargout{1} = size (a.inf, dim); endif endfunction %!assert (size (infsup (zeros (3, 4))), [3 4]); %!assert (size (infsup (zeros (2, 3, 4))), [2, 3, 4]); %!test %! [x y z] = size (infsup (magic (3))); %! assert (x, 3); %! assert (y, 3); %! assert (z, 1); interval-3.2.0/inst/@infsup/smig.m0000644000000000000000000000310113316017127015160 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} smig (@var{X}) ## ## Get the signed mignitude of numbers in interval @var{X}, that is the unique ## number closest to zero for each element. ## ## If @var{X} is empty, @code{smig (@var{X})} is NaN. ## ## Accuracy: The result is exact. ## ## @example ## @group ## smig (infsup (-2, -1)) ## @result{} ans = -1 ## @end group ## @end example ## @seealso{@@infsup/mig, @@infsup/mag, @@infsup/inf, @@infsup/sup} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-06-13 function result = smig (x) if (nargin ~= 1) print_usage (); return endif result = zeros (size (x.inf)); result(x.inf > 0) = x.inf; result(x.sup < 0) = x.sup; result(isempty (x)) = nan (); endfunction %!assert (smig (infsup (-1, 2)), 0); %!assert (smig (infsup (-42, -23)), -23); %!assert (smig (infsup (23, 42)), 23); interval-3.2.0/inst/@infsup/sprintf.m0000644000000000000000000000310413316017127015711 0ustar 00000000000000## Copyright 2018 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sprintf (@var{template}, @var{X}) ## ## Convert interval @var{X} under the control of a template string ## @var{template} to a string with interval literals. ## ## See @command{help intervaltotext} for the syntax of the template string. ## ## @example ## @group ## sprintf ("The result lies within the box %[4g].\n", infsup (2, 3)) ## @result{} ans = The result lies within the box [ 2, 3]. ## @end group ## @end example ## ## @seealso{intervaltotext, @@infsup/printf, @@infsup/fprintf} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2018-06-30 function s = sprintf (template, x) if (nargin ~= 2) print_usage (); return endif [template, literals] = printf_prepare (template, x); s = sprintf (template, literals{:}); endfunction %!assert (sprintf ("%g", infsup ("pi")), "3.14159 3.1416"); interval-3.2.0/inst/@infsup/sqrrev.m0000644000000000000000000000720713316017127015556 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} sqrrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsup} {@var{X} =} sqrrev (@var{C}) ## ## Compute the reverse square function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{x .^ 2 ∈ @var{C}}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sqrrev (infsup (-2, 1)) ## @result{} ans = [-1, +1] ## @end group ## @end example ## @seealso{@@infsup/sqr} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = sqrrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsup (-inf, inf); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (x, "infsup"))) x = infsup (x); endif p = sqrt (c); n = -p; result = union (intersect (p, x), intersect (n, x)); endfunction %!# from the documentation string %!assert (sqrrev (infsup (-2, 1)) == infsup (-1, 1)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sqrRev; %! for testcase = [testcases]' %! assert (isequaln (... %! sqrrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sqrRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sqrrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sqrRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sqrrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sqrRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! sqrrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sqrRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (sqrrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sqrRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sqrrev (in1, in2), out)); interval-3.2.0/inst/@infsup/sqrt.m0000644000000000000000000000270713316017127015225 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sqrt (@var{X}) ## ## Compute the square root (for all non-negative numbers). ## ## Since intervals are only defined for real numbers, this function and ## @code{realsqrt} are equivalent. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sqrt (infsup (-6, 4)) ## @result{} ans = [0, 2] ## @end group ## @end example ## @seealso{@@infsup/sqr, @@infsup/pow, @@infsup/nthroot, @@infsup/cbrt} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function result = sqrt (x) if (nargin ~= 1) print_usage (); return endif result = realsqrt (x); endfunction %!# from the documentation string %!assert (sqrt (infsup (-6, 4)) == infsup (0, 2)); interval-3.2.0/inst/@infsup/strictprecedes.m0000644000000000000000000000551213316017127017254 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} strictprecedes (@var{A}, @var{B}) ## ## Evaluate strict precedes comparison on intervals. ## ## True, if @var{A} is strictly left of @var{B}. The intervals may not touch. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/le, @@infsup/lt, @@infsup/gt, @@infsup/precedes, @@infsup/subset, @@infsup/interior, @@infsup/disjoint} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function result = strictprecedes (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); endif result = (a.sup < b.inf); result(isempty (a) | isempty (b)) = true (); endfunction %!assert (strictprecedes (infsup (1, 1.9), infsup (2.1, 3))); %!assert (not (strictprecedes (infsup (1, 2), infsup (2, 3)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.strictPrecedes; %! for testcase = [testcases]' %! assert (isequaln (... %! strictprecedes (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.strictPrecedes; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (strictprecedes (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.strictPrecedes; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (strictprecedes (in1, in2), out)); interval-3.2.0/inst/@infsup/strictsubset.m0000644000000000000000000000433113316017127016765 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} strictsubset (@var{A}, @var{B}) ## ## Evaluate strict subset comparison on intervals. ## ## True, if all numbers from @var{A} are also contained in @var{B} and @var{B} ## contains a number that is not in @var{A}. ## False, if @var{A} contains a number which is not a member in @var{B} or if ## @var{A} and @var{B} are equal. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/subset, @@infsup/eq, @@infsup/interior} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-05-16 function result = strictsubset (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); endif result = (b.inf <= a.inf & a.sup <= b.sup) ... & (b.inf != a.inf | a.sup != b.sup); endfunction %!assert (strictsubset (infsup (1, 2), infsup (1, 3))); %!assert (strictsubset (infsup (2, 3), infsup (1, 3))); %!assert (not (strictsubset (infsup (1, 2), infsup (1, 2)))); %!assert (not (strictsubset (infsup (1, 3), infsup (1, 2)))); %!assert (strictsubset (infsup (), infsup (1, 3))); %!assert (not (strictsubset (infsup (), infsup ()))); %!assert (strictsubset (infsup (), infsup (-inf, inf))); %!assert (strictsubset (infsup (0, inf), infsup (-inf, inf))); %!assert (strictsubset (infsup (-inf, 0), infsup (-inf, inf))); %!assert (not (strictsubset (infsup (-inf, inf), infsup (-inf, inf)))); interval-3.2.0/inst/@infsup/subsasgn.m0000644000000000000000000000402113316017127016050 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} subsasgn (@var{A}, @var{IDX}, @var{RHS}) ## @defopx Operator {@@infsup} {@var{A}(@var{SUBS}) = @var{RHS}} ## ## Perform the subscripted assignment operation according to the subscript ## specified by @var{IDX}. ## ## The subscript @var{IDX} is expected to be a structure array with fields ## @code{type} and @code{subs}. Only valid value for @var{type} is ## @code{"()"}. The @code{subs} field may be either @code{":"} or a cell array ## of index values. ## @seealso{@@infsup/subsref, @@infsup/end} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function A = subsasgn (A, S, B) if (nargin ~= 3) print_usage (); return endif if (not (isa (A, "infsup"))) A = infsup (A); endif if (not (isa (B, "infsup"))) B = infsup (B); elseif (isa (B, "infsupdec")) ## Workaround for bug #42735 A = subsasgn (A, S, B); return endif assert (strcmp (S.type, "()"), "only subscripts with parenthesis allowed"); A.inf = subsasgn (A.inf, S, B.inf); A.sup = subsasgn (A.sup, S, B.sup); A.inf(A.inf == 0) = -0; # any new elements are stored as [-0, +0] internally endfunction %!test %! A = infsup (magic (3)); %! A(4, 4) = 42; %! assert (inf (A), [magic(3),[0;0;0];0,0,0,42]); %! assert (sup (A), [magic(3),[0;0;0];0,0,0,42]); interval-3.2.0/inst/@infsup/subset.m0000644000000000000000000000521313316017127015534 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} subset (@var{A}, @var{B}) ## ## Evaluate subset comparison on intervals. ## ## True, if all numbers from @var{A} are also contained in @var{B}. ## False, if @var{A} contains a number which is not a member in @var{B}. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsup/eq, @@infsup/interior, @@infsup/disjoint} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function result = subset (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsup"))) a = infsup (a); endif if (not (isa (b, "infsup"))) b = infsup (b); endif result = (b.inf <= a.inf & a.sup <= b.sup); endfunction %!assert (subset (infsup (1, 2), infsup (1, 3))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.subset; %! for testcase = [testcases]' %! assert (isequaln (... %! subset (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.subset; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (subset (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.subset; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (subset (in1, in2), out)); interval-3.2.0/inst/@infsup/subsref.m0000644000000000000000000000560613316017127015706 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} subsref (@var{A}, @var{IDX}) ## @defopx Operator {@@infsup} {@var{A}(@var{I})} ## @defopx Operator {@@infsup} {@var{A}(@var{I1}, @var{I2})} ## @defopx Operator {@@infsup} {@var{A}.@var{P}} ## ## Select property @var{P} or elements @var{I} from interval array @var{A}. ## ## The index @var{I} may be either @code{:} or an index array. ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## The property @var{P} may correspond to any unary method of the interval's ## class, but usually is either @code{inf} or @code{sup}. ## ## @example ## @group ## x = infsup (magic (3), magic (3) + 1); ## x (1) ## @result{} ans = [8, 9] ## x (:, 2) ## @result{} ans = 3×1 interval vector ## [1, 2] ## [5, 6] ## [9, 10] ## x.inf ## @result{} ans = ## 8 1 6 ## 3 5 7 ## 4 9 2 ## @end group ## @end example ## @seealso{@@infsup/subsasgn, @@infsup/end} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function A = subsref (A, S) if (nargin ~= 2) print_usage (); return endif switch S(1).type case "()" A.inf = subsref (A.inf, S(1)); A.sup = subsref (A.sup, S(1)); case "{}" error ("interval cannot be indexed with {}") case "." if (not (any (strcmp (S(1).subs, methods (A))))) error (["interval property ‘", S(1).subs, "’ is unknown"]) endif functionname = ["@infsup", filesep(), S(1).subs]; if (nargin (functionname) ~= 1) error (["‘", S(1).subs, "’ is not a valid interval property"]) endif A = feval (S(1).subs, A); otherwise error ("invalid subscript type") endswitch if (numel (S) > 1) A = subsref (A, S(2 : end)); endif endfunction %!assert (infsup (magic (3))([1, 2, 3]) == magic (3)([1, 2, 3])); %!# from the documentation string %!test %! x = infsup (magic (3), magic (3) + 1); %! assert (x(1) == infsup (8, 9)); %! assert (x(:, 2) == infsup ([1; 5; 9], [2; 6; 10])); %! assert (x.inf, magic (3)); %!assert (reshape (infsup (1:16), 2, 2, 2, 2)(2, 7) == infsup (14)) %!assert (reshape (infsup (1:16), 2, 2, 2, 2)(:, 2, 2, 2) == infsup ([15; 16])) interval-3.2.0/inst/@infsup/sum.m0000644000000000000000000000436113316017127015036 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sum (@var{X}) ## @defmethodx {@@infsup} sum (@var{X}, @var{DIM}) ## ## Sum of elements along dimension @var{DIM}. If @var{DIM} is omitted, it ## defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sum ([infsup(1), pow2(-1074), -1]) ## @result{} ans ⊂ [4.9406e-324, 4.9407e-324] ## infsup (1) + pow2 (-1074) - 1 ## @result{} ans ⊂ [0, 2.2205e-16] ## @end group ## @end example ## @seealso{@@infsup/plus, @@infsup/prod} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-26 function result = sum (x, dim) if (nargin > 2) print_usage (); return endif if (nargin < 2) ## Try to find non-singleton dimension dim = find (size (x.inf) ~= 1, 1); if (isempty (dim)) dim = 1; endif endif ## Short-circuit if (size (x.inf, dim) == 1) result = x; return endif l = mpfr_vector_sum_d (-inf, x.inf, dim); u = mpfr_vector_sum_d (+inf, x.sup, dim); result = infsup (); result.inf = l; result.sup = u; endfunction %!# from the documentation string %!assert (sum ([infsup(1), pow2(-1074), -1]) == infsup (pow2 (-1074))); %!assert (sum (infsup ([])) == 0); %!# correct use of signed zeros %!test %! x = sum (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!# N-dimensional arrays %!assert (sum (infsup (ones (1, 1, 10))) == infsup (10)); %!assert (sum (infsup (ones (1, 1, 10))) == infsup (10)); interval-3.2.0/inst/@infsup/sumabs.m0000644000000000000000000000335713316017127015530 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sumabs (@var{X}) ## @defmethodx {@@infsup} sumabs (@var{X}, @var{DIM}) ## ## Sum of absolute values along dimension @var{DIM}. If @var{DIM} is omitted, ## it defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sumabs ([infsup(1), pow2(-1074), -1]) ## @result{} ans ⊂ [2, 2.0001] ## @end group ## @end example ## @seealso{@@infsup/sum, @@infsup/plus, @@infsup/abs} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-26 function result = sumabs (x, dim) if (nargin > 2) print_usage (); return endif if (nargin < 2) result = sum (abs (x)); else result = sum (abs (x), dim); endif endfunction %!# from the documentation string %!assert (sumabs ([infsup(1), pow2(-1074), -1]) == infsup (2, 2+eps*2)); %!assert (sumabs (infsup ([])) == 0); %!# correct use of signed zeros %!test %! x = sumabs (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); interval-3.2.0/inst/@infsup/sumsq.m0000644000000000000000000000341013316017127015374 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sumsq (@var{X}) ## @defmethodx {@@infsup} sumsq (@var{X}, @var{DIM}) ## ## Sum of squares along dimension @var{DIM}. If @var{DIM} is omitted, ## it defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sumsq ([infsup(1), pow2(-1074), -1]) ## @result{} ans ⊂ [2, 2.0001] ## @end group ## @end example ## @seealso{@@infsup/plus, @@infsup/sum, @@infsup/sumabs} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-26 function result = sumsq (x, dim) if (nargin > 2) print_usage (); return endif x = abs (x); if (nargin < 2) result = dot (x, x); else result = dot (x, x, dim); endif endfunction %!# from the documentation string %!assert (sumsq ([infsup(1), pow2(-1074), -1]) == infsup (2, 2+eps*2)); %!assert (sumsq (infsup ([])) == 0); %!# correct use of signed zeros %!test %! x = sumsq (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); interval-3.2.0/inst/@infsup/sup.m0000644000000000000000000000453113316017127015040 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} sup (@var{X}) ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## ## Get the (least) upper boundary for all numbers of interval @var{X}. ## ## If @var{X} is empty, @code{sup (@var{X})} is negative infinity. ## ## Accuracy: The result is exact. ## ## @example ## @group ## sup (infsup (2.5, 3.5)) ## @result{} ans = 3.5000 ## @end group ## @end example ## @seealso{@@infsup/inf, @@infsup/mid} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-27 function result = sup (x) if (nargin ~= 1) print_usage (); return endif result = x.sup; endfunction %!# from the documentation string %!assert (sup (infsup (2.5, 3.5)), 3.5); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.sup; %! for testcase = [testcases]' %! assert (isequaln (... %! sup (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.sup; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sup (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sup; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sup (in1), out)); interval-3.2.0/inst/@infsup/tan.m0000644000000000000000000000726313316017127015020 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} tan (@var{X}) ## ## Compute the tangent in radians. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## tan (infsup (1)) ## @result{} ans ⊂ [1.5574, 1.5575] ## @end group ## @end example ## @seealso{@@infsup/atan, @@infsup/tanh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-06 function x = tan (x) if (nargin ~= 1) print_usage (); return endif l = u = zeros (size (x)); ## Check, if wid (x) is certainly greater than pi. This may save ## computation of some tangent values. width = mpfr_function_d ('minus', -inf, x.sup, x.inf); persistent pi = infsup ("pi"); certainlyfullperiod = width >= sup (pi); possiblynotfullperiod = not (certainlyfullperiod); if (__check_crlibm__ ()) l(possiblynotfullperiod) = crlibm_function ('tan', -inf, ... x.inf(possiblynotfullperiod)); u(possiblynotfullperiod) = crlibm_function ('tan', inf, ... x.sup(possiblynotfullperiod)); else l(possiblynotfullperiod) = mpfr_function_d ('tan', -inf, ... x.inf(possiblynotfullperiod)); u(possiblynotfullperiod) = mpfr_function_d ('tan', inf, ... x.sup(possiblynotfullperiod)); endif singularity = certainlyfullperiod | ... l > u | (... width > 2 & (... sign (l) == sign (u) | ... max (abs (l), abs (u)) < 1)); l(singularity) = -inf; u(singularity) = inf; emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (tan (infsup (1)) == "[0x1.8EB245CBEE3A5, 0x1.8EB245CBEE3A6]"); %!# correct use of signed zeros %!test %! x = tan (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.tan; %! for testcase = [testcases]' %! assert (isequaln (... %! tan (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.tan; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (tan (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.tan; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (tan (in1), out)); interval-3.2.0/inst/@infsup/tanh.m0000644000000000000000000000524613316017127015167 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} tanh (@var{X}) ## ## Compute the hyperbolic tangent. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## tanh (infsup (1)) ## @result{} ans ⊂ [0.76159, 0.7616] ## @end group ## @end example ## @seealso{@@infsup/atanh, @@infsup/coth, @@infsup/sinh, @@infsup/cosh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-07 function x = tanh (x) if (nargin ~= 1) print_usage (); return endif ## tanh is monotonically increasing from (-inf, -1) to (inf, 1) l = mpfr_function_d ('tanh', -inf, x.inf); u = mpfr_function_d ('tanh', +inf, x.sup); emptyresult = isempty (x); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (tanh (infsup (1)) == "[0x1.85EFAB514F394p-1, 0x1.85EFAB514F395p-1]"); %!# correct use of signed zeros %!test %! x = tanh (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.tanh; %! for testcase = [testcases]' %! assert (isequaln (... %! tanh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.tanh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (tanh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.tanh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (tanh (in1), out)); interval-3.2.0/inst/@infsup/tanrev.m0000644000000000000000000001473413316017127015536 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsup} {@var{X} =} tanrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsup} {@var{X} =} tanrev (@var{C}) ## ## Compute the reverse tangent function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{tan (x) ∈ @var{C}}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## tanrev (infsup (0), infsup (2, 4)) ## @result{} ans ⊂ [3.1415, 3.1416] ## @end group ## @end example ## @seealso{@@infsup/tan} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = tanrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsup (-inf, inf); endif if (not (isa (c, "infsup"))) c = infsup (c); endif if (not (isa (x, "infsup"))) x = infsup (x); endif arctangent = atan (c); result = x; ## Resize, if broadcasting is needed if (not (size_equal (arctangent.inf, result.inf))) arctangent.inf = ones (size (result.inf)) .* arctangent.inf; arctangent.sup = ones (size (result.inf)) .* arctangent.sup; result.inf = ones (size (arctangent.inf)) .* result.inf; result.sup = ones (size (arctangent.inf)) .* result.sup; endif result.inf(isempty (arctangent)) = inf; result.sup(isempty (arctangent)) = -inf; idx.type = '()'; persistent pi = infsup ("pi"); select = not (isempty (result)) ... & not (subset (infsup (-pi.sup / 2, pi.sup / 2), arctangent)); if (any (select(:))) ## Find a smaller upper bound for x, if the restriction from c allows it u = inf (size (result.inf)); select_u = select & result.sup < inf; ## Find n, such that result.sup is within a distance of pi/2 around n * pi. n = result.sup; n(select_u) = ceil (floor (sup (n(select_u) ./ (pi ./ 2))) ./ 2); arctangentshifted = arctangent; idx.subs = {select_u}; arctangentshifted = subsasgn (arctangentshifted, idx, ... subsref (arctangentshifted, idx) + ... n(select_u) .* pi); overlapping = not (isempty (intersect (result, arctangentshifted))); u(select_u & overlapping) = ... min (result.sup(select_u & overlapping), ... arctangentshifted.sup(select_u & overlapping)); n(select_u & ~overlapping) = ... mpfr_function_d ('minus', +inf, n(select_u & ~overlapping), 1); idx.subs = {(select_u & ~overlapping)}; u(idx.subs{1}) = ... sup (subsref (arctangent, idx) + subsref (n, idx) .* pi); ## Find a larger lower bound for x, if the restriction from c allows it l = -inf (size (result.inf)); select_l = select & result.inf > -inf; ## Find n, such that result.inf is within a distance of pi/2 around n * pi. n = result.inf; n(select_l) = floor (ceil (inf (n(select_l) ./ (pi ./ 2))) ./ 2); arctangentshifted = arctangent; idx.subs = {select_l}; arctangentshifted = subsasgn (arctangentshifted, idx, ... subsref (arctangentshifted, idx) + ... n(select_l) .* pi); overlapping = not (isempty (intersect (result, arctangentshifted))); l(select_l & overlapping) = ... max (result.inf (select_l & overlapping), ... arctangentshifted.inf(select_l & overlapping)); n(select_l & ~overlapping) = ... mpfr_function_d ('plus', -inf, n(select_l & ~overlapping), 1); idx.subs = {(select_l & ~overlapping)}; l(idx.subs {1}) = ... inf (subsref (arctangent, idx) + subsref (n, idx) .* pi); result.inf(select) = max (l(select), result.inf(select)); result.sup(select) = min (u(select), result.sup(select)); result.inf(result.inf > result.sup) = inf; result.sup(result.inf > result.sup) = -inf; endif endfunction %!# from the documentation string %!assert (tanrev (infsup (0), infsup (2, 4)) == infsup ("pi")); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.tanRev; %! for testcase = [testcases]' %! assert (isequaln (... %! tanrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.tanRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (tanrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.tanRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (tanrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.tanRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! tanrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.tanRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (tanrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.tanRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (tanrev (in1, in2), out)); interval-3.2.0/inst/@infsup/times.m0000644000000000000000000001040513316017127015347 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} times (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} .* @var{Y}} ## ## Multiply all numbers of interval @var{X} by all numbers of @var{Y}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsup (2, 3); ## y = infsup (1, 2); ## x .* y ## @result{} ans = [2, 6] ## @end group ## @end example ## @seealso{@@infsup/rdivide} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function x = times (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsup"))) x = infsup (x); endif if (not (isa (y, "infsup"))) y = infsup (y); elseif (isa (y, "infsupdec")) ## Workaround for bug #42735 result = times (x, y); return endif ## At least one case of interval multiplication is complicated: when zero is an ## inner point of both interval factors. In all other cases it would suffice ## to compute a single product for each product boundary. ## ## It is not significandly faster to do a case by case analysis in order to ## save some calls to the times function with directed rounding. Therefore, we ## simply compute the product for each pair of boundaries where the min/max ## could be located. l = min (min (min (... mpfr_function_d ('times', -inf, x.inf, y.inf), ... mpfr_function_d ('times', -inf, x.inf, y.sup)), ... mpfr_function_d ('times', -inf, x.sup, y.inf)), ... mpfr_function_d ('times', -inf, x.sup, y.sup)); u = max (max (max (... mpfr_function_d ('times', +inf, x.inf, y.inf), ... mpfr_function_d ('times', +inf, x.inf, y.sup)), ... mpfr_function_d ('times', +inf, x.sup, y.inf)), ... mpfr_function_d ('times', +inf, x.sup, y.sup)); ## [0] × anything = [0] × [0] ## [Entire] × anything but [0] = [Entire] × [Entire] ## This prevents the cases where 0 × inf would produce NaNs. entireproduct = isentire (x) | isentire (y); l(entireproduct) = -inf; u(entireproduct) = inf; zeroproduct = (x.inf == 0 & x.sup == 0) | (y.inf == 0 & y.sup == 0); l(zeroproduct) = -0; u(zeroproduct) = +0; emptyresult = isempty (x) | isempty (y); l(emptyresult) = inf; u(emptyresult) = -inf; l(l == 0) = -0; x.inf = l; x.sup = u; endfunction %!# from the documentation string %!assert (infsup (2, 3) .* infsup (1, 2) == infsup (2, 6)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.mul; %! for testcase = [testcases]' %! assert (isequaln (... %! times (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.mul; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (times (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.mul; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (times (in1, in2), out)); interval-3.2.0/inst/@infsup/transpose.m0000644000000000000000000000302013316017127016237 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} transpose (@var{X}) ## @defopx Operator {@@infsup} {@var{X}.'} ## ## Return the transpose of interval matrix or vector @var{X}. ## ## @example ## @group ## infsup (zeros (1, 3), ones (1, 3)) .' ## @result{} ans = 3×1 interval vector ## [0, 1] ## [0, 1] ## [0, 1] ## @end group ## @end example ## @seealso{@@infsup/ctranspose} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function x = transpose (x) if (nargin ~= 1) print_usage (); return endif x.inf = transpose (x.inf); x.sup = transpose (x.sup); endfunction %!assert (transpose (infsup (magic (3))) == infsup (magic (3).')); %!# from the documentation string %!assert (transpose (infsup (zeros (1, 3), ones (1, 3))) == infsup (zeros (3, 1), ones (3, 1))); interval-3.2.0/inst/@infsup/tril.m0000644000000000000000000000414013316017127015177 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} tril (@var{A}) ## @defmethodx {@@infsup} tril (@var{A}, @var{k}) ## @defmethodx {@@infsup} tril (@var{A}, @var{k}, "pack") ## Return a new matrix formed by extracting the lower triangular part of the ## matrix @var{A}, and setting all other elements to zero. ## ## The second argument is optional, and specifies how many diagonals above or ## below the main diagonal should also be set to zero. ## ## If the option @option{pack} is given as third argument, the extracted ## elements are not inserted into a matrix, but rather stacked column-wise one ## above other. ## ## @seealso{@@infsup/triu, @@infsup/diag} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-08-04 function A = tril (A, varargin) if (nargin >= 2 && isa (varargin{1}, 'infsup')) error ('tril: invalid second argument; it must not be an interval'); endif if (nargin >= 3 && isa (varargin{2}, 'infsup')) error ('tril: invalid third argument; it must not be an interval'); endif A.inf = tril (A.inf, varargin{:}); A.sup = tril (A.sup, varargin{:}); A.inf(A.inf == 0) = -0; endfunction %!assert (tril (infsup (magic (10))) == tril (magic (10))); %!assert (tril (infsup (magic (10)), 1) == tril (magic (10), 1)); %!assert (tril (infsup (magic (10)), -1) == tril (magic (10), -1)); %!assert (tril (infsup (magic (10)), 0, "pack") == tril (magic (10), 0, "pack")); interval-3.2.0/inst/@infsup/triu.m0000644000000000000000000000414013316017127015210 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} triu (@var{A}) ## @defmethodx {@@infsup} triu (@var{A}, @var{k}) ## @defmethodx {@@infsup} triu (@var{A}, @var{k}, "pack") ## Return a new matrix formed by extracting the upper triangular part of the ## matrix @var{A}, and setting all other elements to zero. ## ## The second argument is optional, and specifies how many diagonals above or ## below the main diagonal should also be set to zero. ## ## If the option @option{pack} is given as third argument, the extracted ## elements are not inserted into a matrix, but rather stacked column-wise one ## above other. ## ## @seealso{@@infsup/tril, @@infsup/diag} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-08-04 function A = triu (A, varargin) if (nargin >= 2 && isa (varargin{1}, 'infsup')) error ('triu: invalid second argument; it must not be an interval'); endif if (nargin >= 3 && isa (varargin{2}, 'infsup')) error ('triu: invalid third argument; it must not be an interval'); endif A.inf = triu (A.inf, varargin{:}); A.sup = triu (A.sup, varargin{:}); A.inf(A.inf == 0) = -0; endfunction %!assert (triu (infsup (magic (10))) == triu (magic (10))); %!assert (triu (infsup (magic (10)), 1) == triu (magic (10), 1)); %!assert (triu (infsup (magic (10)), -1) == triu (magic (10), -1)); %!assert (triu (infsup (magic (10)), 0, "pack") == triu (magic (10), 0, "pack")); interval-3.2.0/inst/@infsup/uminus.m0000644000000000000000000000470013316017127015547 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} uminus (@var{X}) ## @defopx Operator {@@infsup} {-@var{X}} ## ## Negate all numbers in the interval. ## ## Accuracy: The result is exact. ## ## @example ## @group ## x = infsup (2, 3); ## -x ## @result{} ans = [-3, -2] ## @end group ## @end example ## @seealso{@@infsup/uplus} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function x = uminus (x) if (nargin ~= 1) print_usage (); return endif ## This also works for empty / entire intervals [x.inf, x.sup] = deal (-x.sup, -x.inf); endfunction %!# from the documentation string %!assert (-infsup (2, 3) == infsup (-3, -2)); %!# correct use of signed zeros %!test %! x = uminus (infsup (0)); %! assert (signbit (inf (x))); %! assert (not (signbit (sup (x)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.neg; %! for testcase = [testcases]' %! assert (isequaln (... %! uminus (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.neg; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (uminus (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.neg; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (uminus (in1), out)); interval-3.2.0/inst/@infsup/union.m0000644000000000000000000000637013316017127015364 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} union (@var{A}) ## @defmethodx {@@infsup} union (@var{A}, @var{B}) ## @defmethodx {@@infsup} union (@var{A}, [], @var{DIM}) ## ## Build the interval hull of the union of intervals. ## ## With two arguments the union is built pair-wise. Otherwise the union is ## computed for all interval members along dimension @var{DIM}, which defaults ## to the first non-singleton dimension. ## ## Accuracy: The result is exact. ## ## @example ## @group ## x = infsup (1, 3); ## y = infsup (2, 4); ## union (x, y) ## @result{} ans = [1, 4] ## @end group ## @end example ## @seealso{@@infsup/intersect, @@infsup/setdiff, @@infsup/setxor} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-02 function a = union (a, b, dim) if (not (isa (a, "infsup"))) a = infsup (a); endif switch (nargin) case 1 l = min (a.inf); u = max (a.sup); case 2 if (not (isa (b, "infsup"))) b = infsup (b); endif l = min (a.inf, b.inf); u = max (a.sup, b.sup); case 3 if (not (builtin ("isempty", b))) warning ("union: second argument is ignored"); endif l = min (a.inf, [], dim); u = max (a.sup, [], dim); otherwise print_usage (); return endswitch a.inf = l; a.sup = u; endfunction %!# from the documentation string %!assert (union (infsup (1, 3), infsup (2, 4)) == infsup (1, 4)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.convexHull; %! for testcase = [testcases]' %! assert (isequaln (... %! union (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.convexHull; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (union (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.convexHull; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (union (in1, in2), out)); interval-3.2.0/inst/@infsup/uplus.m0000644000000000000000000000606013316017127015400 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} uplus (@var{X}) ## @defopx Operator {@@infsup} {+@var{X}} ## ## Return the interval itself. ## ## Accuracy: The result is exact. ## ## @example ## @group ## x = infsup (2, 3); ## + x ## @result{} ans = [2, 3] ## @end group ## @end example ## @seealso{@@infsup/uminus} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-30 function x = uplus (x) if (nargin ~= 1) print_usage (); return endif endfunction %!# from the documentation string %!assert (+infsup (2, 3) == infsup (2, 3)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.pos; %! for testcase = [testcases]' %! assert (isequaln (... %! uplus (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.pos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (uplus (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.pos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (uplus (in1), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.pos; %! for testcase = [testcases]' %! assert (isequaln (... %! uplus (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.pos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (uplus (in1), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.pos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (uplus (in1), out)); interval-3.2.0/inst/@infsup/vertcat.m0000644000000000000000000000301313316017127015673 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} vertcat (@var{ARRAY1}, @var{ARRAY2}, @dots{}) ## @defopx Operator {@@infsup} {[@var{ARRAY1}; @var{ARRAY2}; @dots{}]} ## ## Return the vertical concatenation of interval array objects along ## dimension 1. ## ## @example ## @group ## a = infsup (2, 5); ## [a; a; a] ## @result{} ans = 3×1 interval vector ## [2, 5] ## [2, 5] ## [2, 5] ## @end group ## @end example ## @seealso{@@infsup/horzcat} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-29 function result = vertcat (varargin) result = cat (1, varargin{:}); endfunction %!assert (vertcat (infsup (1), infsup (2)) == infsup (vertcat (1, 2))); %!test %! # from the documentation string %! a = infsup (2, 5); %! assert (vertcat (a, a, a) == infsup ([2; 2; 2], [5; 5; 5])); interval-3.2.0/inst/@infsup/wid.m0000644000000000000000000000646513316017127015024 0ustar 00000000000000## Copyright 2014-2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} wid (@var{X}) ## ## Get the width of interval @var{X}. ## ## If @var{X} is empty, @code{wid (@var{X})} is NaN. ## If @var{X} is unbounded in one or both directions, @code{wid (@var{X})} is ## positive infinity. ## ## Accuracy: The result is a tight enclosure of the interval's actual width. ## ## @example ## @group ## wid (infsup (2.5, 3.5)) ## @result{} ans = 1 ## @end group ## @end example ## @seealso{@@infsup/inf, @@infsup/sup, @@infsup/rad} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-05 function result = wid (x) if (nargin ~= 1) print_usage (); return endif result = mpfr_function_d ('minus', +inf, x.sup, x.inf); result(x.inf > x.sup) = nan (); endfunction %!# from the documentation string %!assert (wid (infsup (2.5, 3.5)), 1); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.wid; %! for testcase = [testcases]' %! assert (isequaln (... %! wid (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.wid; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (wid (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.wid; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (wid (in1), out)); %!test %! # Decorated scalar evaluation %! testcases = testdata.NoSignal.infsupdec.wid; %! for testcase = [testcases]' %! assert (isequaln (... %! wid (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Decorated vector evaluation %! testcases = testdata.NoSignal.infsupdec.wid; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (wid (in1), out)); %!test %! # Decorated N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.wid; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (wid (in1), out)); interval-3.2.0/inst/@infsupdec/abs.m0000644000000000000000000000754713316017127015464 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} abs (@var{X}) ## ## Compute the absolute value of numbers. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## abs (infsupdec (2.5, 3.5)) ## @result{} ans = [2.5, 3.5]_com ## abs (infsupdec (-0.5, 5.5)) ## @result{} ans = [0, 5.5]_com ## @end group ## @end example ## @seealso{@@infsupdec/mag, @@infsupdec/mig} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = abs (x) if (nargin ~= 1) print_usage (); return endif result = newdec (abs (x.infsup)); ## abs is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# Empty interval %!assert (isequal (abs (infsupdec ()), infsupdec ())); %!# Singleton intervals %!assert (isequal (abs (infsupdec (1)), infsupdec (1))); %!assert (isequal (abs (infsupdec (0)), infsupdec (0))); %!assert (isequal (abs (infsupdec (-1)), infsupdec (1))); %!assert (isequal (abs (infsupdec (realmax)), infsupdec (realmax))); %!assert (isequal (abs (infsupdec (realmin)), infsupdec (realmin))); %!assert (isequal (abs (infsupdec (-realmin)), infsupdec (realmin))); %!assert (isequal (abs (infsupdec (-realmax)), infsupdec (realmax))); %!# Bounded intervals %!assert (isequal (abs (infsupdec (1, 2)), infsupdec (1, 2))); %!assert (isequal (abs (infsupdec (0, 1)), infsupdec (0, 1))); %!assert (isequal (abs (infsupdec (-1, 1)), infsupdec (0, 1))); %!assert (isequal (abs (infsupdec (-1, 0)), infsupdec (0, 1))); %!assert (isequal (abs (infsupdec (-2, -1)), infsupdec (1, 2))); %!# Unbounded intervals %!assert (isequal (abs (infsupdec (0, inf)), infsupdec (0, inf))); %!assert (isequal (abs (infsupdec (-inf, inf)), infsupdec (0, inf))); %!assert (isequal (abs (infsupdec (-inf, 0)), infsupdec (0, inf))); %!assert (isequal (abs (infsupdec (1, inf)), infsupdec (1, inf))); %!assert (isequal (abs (infsupdec (-1, inf)), infsupdec (0, inf))); %!assert (isequal (abs (infsupdec (-inf, -1)), infsupdec (1, inf))); %!assert (isequal (abs (infsupdec (-inf, 1)), infsupdec (0, inf))); %!# from the documentation string %!assert (isequal (abs (infsupdec (2.5, 3.5)), infsupdec (2.5, 3.5))); %!assert (isequal (abs (infsupdec (-0.5, 5.5)), infsupdec (0, 5.5))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.abs; %! for testcase = [testcases]' %! assert (isequaln (... %! abs (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.abs; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (abs (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.abs; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (abs (in1), out)); interval-3.2.0/inst/@infsupdec/absrev.m0000644000000000000000000001363513316017127016174 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} absrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsupdec} {@var{X} =} absrev (@var{C}) ## ## Compute the reverse absolute value function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{abs (x) ∈ @var{C}}. ## ## Accuracy: The result is a tight enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## absrev (infsupdec (-2, 1)) ## @result{} ans = [-1, +1]_trv ## @end group ## @end example ## @seealso{@@infsupdec/abs} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = absrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsupdec (-inf, inf); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif result = infsupdec (absrev (c.infsup, x.infsup), "trv"); result.dec(isnai (c) | isnai (x)) = _ill (); endfunction %!# Empty interval %!assert (isequal (absrev (infsupdec ()), infsupdec ())); %!assert (isequal (absrev (infsupdec (0, 1), infsupdec ()), infsupdec ())); %!assert (isequal (absrev (infsupdec (0, 1), infsupdec (7, 9)), infsupdec ())); %!assert (isequal (absrev (infsupdec (), infsupdec (0, 1)), infsupdec ())); %!assert (isequal (absrev (infsupdec (-2, -1)), infsupdec ())); %!# Singleton intervals %!assert (isequal (absrev (infsupdec (1)), infsupdec (-1, 1, "trv"))); %!assert (isequal (absrev (infsupdec (0)), infsupdec (0, "trv"))); %!assert (isequal (absrev (infsupdec (-1)), infsupdec ())); %!assert (isequal (absrev (infsupdec (realmax)), infsupdec (-realmax, realmax, "trv"))); %!assert (isequal (absrev (infsupdec (realmin)), infsupdec (-realmin, realmin, "trv"))); %!assert (isequal (absrev (infsupdec (-realmin)), infsupdec ())); %!assert (isequal (absrev (infsupdec (-realmax)), infsupdec ())); %!# Bound intervals %!assert (isequal (absrev (infsupdec (1, 2)), infsupdec (-2, 2, "trv"))); %!assert (isequal (absrev (infsupdec (1, 2), infsupdec (0, 2)), infsupdec (1, 2, "trv"))); %!assert (isequal (absrev (infsupdec (0, 1), infsupdec (-0.5, 2)), infsupdec (-0.5, 1, "trv"))); %!assert (isequal (absrev (infsupdec (-1, 1)), infsupdec (-1, 1, "trv"))); %!assert (isequal (absrev (infsupdec (-1, 0)), infsupdec (0, "trv"))); %!# Unbound intervals %!assert (isequal (absrev (infsupdec (0, inf)), infsupdec (-inf, inf, "trv"))); %!assert (isequal (absrev (infsupdec (-inf, inf)), infsupdec (-inf, inf, "trv"))); %!assert (isequal (absrev (infsupdec (-inf, 0)), infsupdec (0, "trv"))); %!assert (isequal (absrev (infsupdec (1, inf), infsupdec (-inf, 0)), infsupdec (-inf, -1, "trv"))); %!assert (isequal (absrev (infsupdec (-1, inf)), infsupdec (-inf, inf, "trv"))); %!assert (isequal (absrev (infsupdec (-inf, -1)), infsupdec ())); %!assert (isequal (absrev (infsupdec (-inf, 1)), infsupdec (-1, 1, "trv"))); %!# from the documentation string %!assert (isequal (absrev (infsupdec (-2, 1)), infsupdec (-1, 1, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation with one argument %! testcases = testdata.NoSignal.infsupdec.absRev; %! for testcase = [testcases]' %! assert (isequaln (... %! absrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation with one argument %! testcases = testdata.NoSignal.infsupdec.absRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (absrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.absRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (absrev (in1), out)); %!test %! # Scalar evaluation with two arguments %! testcases = testdata.NoSignal.infsupdec.absRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! absrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation with two arguments %! testcases = testdata.NoSignal.infsupdec.absRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (absrev (in1, in2), out)); %!test %! # N-dimensional array evaluation with two arguments %! testcases = testdata.NoSignal.infsupdec.absRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (absrev (in1, in2), out)); interval-3.2.0/inst/@infsupdec/acos.m0000644000000000000000000000500413316017127015626 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} acos (@var{X}) ## ## Compute the inverse cosine in radians (arccosine). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## acos (infsupdec (.5)) ## @result{} ans ⊂ [1.0471, 1.0472]_com ## @end group ## @end example ## @seealso{@@infsupdec/cos} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = acos (x) if (nargin ~= 1) print_usage (); return endif result = newdec (acos (x.infsup)); ## acos is continuous everywhere, but defined for [-1, 1] only persistent domain = infsup (-1, 1); result.dec(not (subset (x.infsup, domain))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (acos (infsupdec (.5)), infsupdec ("[0x1.0C152382D7365, 0x1.0C152382D7366]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.acos; %! for testcase = [testcases]' %! assert (isequaln (... %! acos (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.acos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (acos (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.acos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (acos (in1), out)); interval-3.2.0/inst/@infsupdec/acosh.m0000644000000000000000000000500413316017127015776 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} acosh (@var{X}) ## ## Compute the inverse hyperbolic cosine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## acosh (infsupdec (2)) ## @result{} ans ⊂ [1.3169, 1.317]_com ## @end group ## @end example ## @seealso{@@infsupdec/cosh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = acosh (x) if (nargin ~= 1) print_usage (); return endif result = newdec (acosh (x.infsup)); ## acosh is continuous everywhere, but defined for [1, Inf] only persistent domain = infsup (1, inf); result.dec(not (subset (x.infsup, domain))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (acosh (infsupdec (2)), infsupdec ("[0x1.5124271980434, 0x1.5124271980435]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.acosh; %! for testcase = [testcases]' %! assert (isequaln (... %! acosh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.acosh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (acosh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.acosh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (acosh (in1), out)); interval-3.2.0/inst/@infsupdec/asin.m0000644000000000000000000000500713316017127015636 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} asin (@var{X}) ## ## Compute the inverse sine in radians (arcsine). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## asin (infsupdec (.5)) ## @result{} ans ⊂ [0.52359, 0.5236]_com ## @end group ## @end example ## @seealso{@@infsupdec/sin} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = asin (x) if (nargin ~= 1) print_usage (); return endif result = newdec (asin (x.infsup)); ## asin is continuous everywhere, but defined for [-1, 1] only persistent domain = infsup (-1, 1); result.dec(not (subset (x.infsup, domain))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (asin (infsupdec (.5)), infsupdec ("[0x1.0C152382D7365p-1, 0x1.0C152382D7366p-1]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.asin; %! for testcase = [testcases]' %! assert (isequaln (... %! asin (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.asin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (asin (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.asin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (asin (in1), out)); interval-3.2.0/inst/@infsupdec/asinh.m0000644000000000000000000000462613316017127016014 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} asinh (@var{X}) ## ## Compute the inverse hyperbolic sine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## asinh (infsupdec (1)) ## @result{} ans ⊂ [0.88137, 0.88138]_com ## @end group ## @end example ## @seealso{@@infsupdec/sinh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = asinh (x) if (nargin ~= 1) print_usage (); return endif result = newdec (asinh (x.infsup)); ## asinh is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (asinh (infsupdec (1)), infsupdec ("[0x1.C34366179D426p-1, 0x1.C34366179D427p-1]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.asinh; %! for testcase = [testcases]' %! assert (isequaln (... %! asinh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.asinh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (asinh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.asinh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (asinh (in1), out)); interval-3.2.0/inst/@infsupdec/atan.m0000644000000000000000000000463613316017127015636 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} atan (@var{X}) ## ## Compute the inverse tangent in radians. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## atan (infsupdec (1)) ## @result{} ans ⊂ [0.78539, 0.7854]_com ## @end group ## @end example ## @seealso{@@infsupdec/tan, @@infsupdec/atan2} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = atan (x) if (nargin ~= 1) print_usage (); return endif result = newdec (atan (x.infsup)); ## atan is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (atan (infsupdec (1)), infsupdec ("[0x1.921FB54442D18p-1, 0x1.921FB54442D19p-1]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.atan; %! for testcase = [testcases]' %! assert (isequaln (... %! atan (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.atan; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (atan (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.atan; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (atan (in1), out)); interval-3.2.0/inst/@infsupdec/atan2.m0000644000000000000000000000636613316017127015722 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} atan2 (@var{Y}, @var{X}) ## ## Compute the inverse tangent with two arguments. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## atan2 (infsupdec (1), infsupdec (-1)) ## @result{} ans ⊂ [2.3561, 2.3562]_com ## @end group ## @end example ## @seealso{@@infsupdec/tan} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = atan2 (y, x) if (nargin ~= 2) print_usage (); return endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif result = newdec (atan2 (y.infsup, x.infsup)); ## The function is discontinuous for x <= 0 and y == 0 discontinuos = inf (y) < 0 & sup (y) >= 0 & inf (x) < 0; result.dec(discontinuos) = min (result.dec(discontinuos), _def ()); ## For y = [0, y.sup] the function is discontinuous, but its ## restriction is not onlyrestrictioncontinuous = inf (y) == 0 & inf (x) < 0; result.dec(onlyrestrictioncontinuous) = ... min (result.dec(onlyrestrictioncontinuous), _dac ()); ## The only undefined input is <0,0> result.dec(ismember (0, y) & ismember (0, x)) = _trv (); result.dec = min (result.dec, min (y.dec, x.dec)); endfunction %!# from the documentation string %!assert (isequal (atan2 (infsupdec (1), infsupdec (-1)), infsupdec ("[0x1.2D97C7F3321D2p1, 0x1.2D97C7F3321D3p1]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.atan2; %! for testcase = [testcases]' %! assert (isequaln (... %! atan2 (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.atan2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (atan2 (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.atan2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (atan2 (in1, in2), out)); interval-3.2.0/inst/@infsupdec/atan2rev1.m0000644000000000000000000000445313316017127016513 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{Y} =} atan2rev1 (@var{B}, @var{C}, @var{Y}) ## @deftypemethodx {@@infsupdec} {@var{Y} =} atan2rev1 (@var{B}, @var{C}) ## ## Compute the reverse atan2 function for the first parameter. ## ## That is, an enclosure of all @code{y ∈ @var{Y}} where ## @code{atan2 (y, b) ∈ @var{C}} for any @code{b ∈ @var{B}}. ## ## Accuracy: The result is a valid enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## atan2rev1 (infsupdec (1, 2), infsupdec ("pi") / 4) ## @result{} ans ⊂ [0.99999, 2.0001]_trv ## @end group ## @end example ## @seealso{@@infsupdec/atan2} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = atan2rev1 (b, c, y) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) y = infsupdec (-inf, inf); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif ## inverse atan2 is not a point function result = infsupdec (atan2rev1 (b.infsup, c.infsup, y.infsup), "trv"); result.dec(isnai (y) | isnai (b) | isnai (c)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (atan2rev1 (infsupdec (1, 2), infsupdec ("pi") / 4), infsupdec ("[0x1.FFFFFFFFFFFFFp-1, 0x1.0000000000001p1]_trv"))); interval-3.2.0/inst/@infsupdec/atan2rev2.m0000644000000000000000000000445413316017127016515 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} atan2rev2 (@var{A}, @var{C}, @var{X}) ## @deftypemethodx {@@infsupdec} {@var{X} =} atan2rev2 (@var{A}, @var{C}) ## ## Compute the reverse atan2 function for the second parameter. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{atan2 (a, x) ∈ @var{C}} for any @code{a ∈ @var{A}}. ## ## Accuracy: The result is a valid enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## atan2rev2 (infsupdec (1, 2), infsupdec ("pi") / 4) ## @result{} ans ⊂ [0.99999, 2.0001]_trv ## @end group ## @end example ## @seealso{@@infsupdec/atan2} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = atan2rev2 (a, c, x) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) x = infsupdec (-inf, inf); endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif ## inverse atan2 is not a point function result = infsupdec (atan2rev2 (a.infsup, c.infsup, x.infsup), "trv"); result.dec(isnai (x) | isnai (a) | isnai (c)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (atan2rev2 (infsupdec (1, 2), infsupdec ("pi") / 4), infsupdec ("[0x1.FFFFFFFFFFFFEp-1, 0x1.0000000000001p1]_trv"))); interval-3.2.0/inst/@infsupdec/atanh.m0000644000000000000000000000503113316017127015774 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} atanh (@var{X}) ## ## Compute the inverse hyperbolic tangent. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## atanh (infsupdec (.5)) ## @result{} ans ⊂ [0.5493, 0.54931]_com ## @end group ## @end example ## @seealso{@@infsupdec/tanh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = atanh (x) if (nargin ~= 1) print_usage (); return endif result = newdec (atanh (x.infsup)); ## atanh is continuous everywhere, but defined for ]-1, 1[ only persistent domain_hull = infsup (-1, 1); result.dec(not (interior (x.infsup, domain_hull))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (atanh (infsupdec (.5)), infsupdec ("[0x1.193EA7AAD030Ap-1, 0x1.193EA7AAD030Bp-1]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.atanh; %! for testcase = [testcases]' %! assert (isequaln (... %! atanh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.atanh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (atanh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.atanh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (atanh (in1), out)); interval-3.2.0/inst/@infsupdec/bisect.m0000644000000000000000000000445313316017127016161 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {[@var{A}, @var{B}] =} bisect (@var{X}) ## ## Bisect an interval into two intervals, which contain half the amount of ## binary64 numbers each. ## ## Instead of bisecting the values of numbers in the interval at ## @code{mid (@var{X})}, this function bisects a function that counts them. In ## a bisect method this eliminates exactly half of the solutions and avoids ## slow convergence speeds in extreme cases. ## ## If all numbers in interval @var{X} are of equal sign, the pivot element used ## for bisection is @code{pow2 (mid (log2 (abs (@var{X}))))}. If @var{X} is no ## empty interval, the intervals @var{A} and @var{B} are non-empty and satisfy ## @code{@var{A}.sup == @var{B}.inf}. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## The function is a set operation and the result carries the @code{trv} ## decoration at best. ## ## @example ## @group ## [a, b] = bisect (infsupdec (2, 32)) ## @result{} ## a = [2, 8]_trv ## b = [8, 32]_trv ## @end group ## @end example ## @seealso{@@infsupdec/nextout} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-05-25 function [a, b] = bisect (x) if (nargin > 1) print_usage (); return endif ## bisect must not retain any useful decoration [a, b] = bisect (x.infsup); a = infsupdec (a, "trv"); b = infsupdec (b, "trv"); a.dec(isnai (x)) = b.dec(isnai (x)) = _ill (); endfunction %!# from the documentation string %!test %! [a, b] = bisect (infsupdec (2, 32)); %! assert (a == infsupdec (2, 8, "trv")); %! assert (b == infsupdec (8, 32, "trv")); interval-3.2.0/inst/@infsupdec/bitunpack.m0000644000000000000000000000522013316017127016661 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} bitunpack (@var{X}) ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## ## Encode decorated interval @var{X} in interchange format. ## ## The result is a raw bit pattern of length 136 that derive from two binary64 ## numbers plus 8 bit for the decoration. Bits are in increasing order. ## Byte order depends on the system's endianness. First 8 bytes come from the ## lower interval boundary, next 8 bytes come from the upper interval boundary, ## last byte comes from the decoration. ## ## The result is a row vector if @var{X} is a row vector; otherwise, it is a ## column vector. ## ## For all scalar intervals the following equation holds: ## @code{@var{X} == interval_bitpack (bitunpack (@var{X}))}. ## ## @seealso{interval_bitpack} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-12-23 function result = bitunpack (x) if (nargin ~= 1) print_usage (); return endif bare = bitunpack (x.infsup); d = bitunpack (x.dec); ## The exchange representation of [NaI] is (NaN, NaN, ill). if (any (isnai (x)(:))) bare(vec (1:128) + 128 .* vec (find (isnai (x)) - 1, 2)) = ... [bitunpack(nan (sum (isnai (x)), 2))]; endif ## Initialize result vector result = zeros (1, length (bare) + length (d), 'logical'); if (not (isrow (bare))) result = result'; endif ## Merge alternating 128 bit blocks from bare and 8 bit blocks from d together ## into result. target_bare = reshape (1 : length (result), 8, length (result) / 8); target_d = target_bare (:, 17 : 17 : size (target_bare, 2)); target_bare(:, 17 : 17 : size (target_bare, 2)) = []; result(target_bare) = bare; result(target_d) = d; endfunction %!test %! littleendian = bitunpack (uint16 (1))(1); %! b = zeros (1, 136); %! if (littleendian) %! b([52, 63, 117, 127, 133]) = 1; %! else %! b([7, 12, 71, 77, 133]) = 1; %! endif %! assert (bitunpack (infsupdec (3, 4)), logical (b)); interval-3.2.0/inst/@infsupdec/cancelminus.m0000644000000000000000000000614413316017127017210 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{Z} =} cancelminus (@var{X}, @var{Y}) ## ## Recover interval @var{Z} from intervals @var{X} and @var{Y}, given that one ## knows @var{X} was obtained as the sum @var{Y} + @var{Z}. ## ## Accuracy: The result is a tight enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## cancelminus (infsupdec (2, 3), infsupdec (1, 1.5)) ## @result{} ans = [1, 1.5]_trv ## @end group ## @end example ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = cancelminus (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif ## cancelMinus must not retain any useful decoration result = infsupdec (cancelminus (x.infsup, y.infsup), "trv"); result.dec(isnai (x) | isnai (y)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (cancelminus (infsupdec (2, 3), infsupdec (1, 1.5)), infsupdec (1, 1.5, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.cancelMinus; %! for testcase = [testcases]' %! assert (isequaln (... %! cancelminus (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.cancelMinus; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (cancelminus (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.cancelMinus; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cancelminus (in1, in2), out)); interval-3.2.0/inst/@infsupdec/cat.m0000644000000000000000000000567513316017127015466 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} cat (@var{DIM}, @var{ARRAY1}, @var{ARRAY2}, @dots{}) ## ## Return the concatenation of N-D interval arrays @var{ARRAY1}, @var{ARRAY2}, ## … along dimension @var{DIM}. ## ## @example ## @group ## cat (2, infsupdec (magic (3)), infsupdec (pascal (3))) ## @result{} 3×6 interval matrix ## ## [8]_com [1]_com [6]_com [1]_com [1]_com [1]_com ## [3]_com [5]_com [7]_com [1]_com [2]_com [3]_com ## [4]_com [9]_com [2]_com [1]_com [3]_com [6]_com ## @end group ## @end example ## @seealso{@@infsup/horzcat, @@infsup/vertcat} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-10-09 function result = cat (dim, varargin) if (isa (dim, "infsup")) print_usage (); return endif ## Conversion of non-interval and undecorated parameters to decorated intervals decorated_interval_idx = cellfun ("isclass", varargin, "infsupdec"); to_convert_idx = not (decorated_interval_idx); varargin(to_convert_idx) = cellfun (@infsupdec, ... varargin(to_convert_idx), ... "UniformOutput", false); ## Stack intervals along dimension dim s = cellfun ("struct", varargin); # struct array result = infsupdec (); result.infsup = cat (dim, s.infsup); result.dec = cat (dim, s.dec); endfunction %!assert (size (cat (1, infsupdec ([]), infsupdec ([]))), [0 0]); %!assert (isequal (cat (1, infsupdec (1), infsupdec (2)), infsupdec (cat (1, 1, 2)))); %!assert (isequal (cat (2, infsupdec (1), infsupdec (2)), infsupdec (cat (2, 1, 2)))); %!assert (isequal (horzcat (infsupdec (1), infsupdec (2)), infsupdec (horzcat (1, 2)))); %!test %! a = infsupdec (2, 5); %! assert (isequal (horzcat (a, a, a), infsupdec ([2, 2, 2], [5, 5, 5]))); %!assert (isequal (vertcat (infsupdec (1), infsupdec (2)), infsupdec (vertcat (1, 2)))); %!test %! a = infsupdec (2, 5); %! assert (isequal (vertcat (a, a, a), infsupdec ([2; 2; 2], [5; 5; 5]))); %!assert (isequal (cat (5, infsupdec (1), infsupdec (2)), infsupdec (cat (5, 1, 2)))); %!assert (isequal (cat (1, infsupdec (zeros (2, 2, 2)), infsupdec (ones (2, 2, 2))), infsupdec (cat (1, zeros (2, 2, 2), ones (2, 2, 2))))); interval-3.2.0/inst/@infsupdec/cbrt.m0000644000000000000000000000257113316017127015641 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} cbrt (@var{X}) ## ## Compute the cube root. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cbrt (infsupdec (-27, 27)) ## @result{} ans = [-3, +3]_com ## @end group ## @end example ## @seealso{@@infsupdec/realsqrt, @@infsupdec/nthroot} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function result = cbrt (x) if (nargin ~= 1) print_usage (); return endif result = newdec (cbrt (x.infsup)); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (cbrt (infsupdec (-27, 27)), infsupdec (-3, 3))); interval-3.2.0/inst/@infsupdec/ceil.m0000644000000000000000000000557613316017127015633 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} ceil (@var{X}) ## ## Round each number in interval @var{X} towards +Inf. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## ceil (infsupdec (2.5, 3.5)) ## @result{} ans = [3, 4]_def ## ceil (infsupdec (-0.5, 5)) ## @result{} ans = [0, 5]_def ## @end group ## @end example ## @seealso{@@infsupdec/floor, @@infsupdec/round, @@infsupdec/roundb, @@infsupdec/fix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = ceil (x) if (nargin ~= 1) print_usage (); return endif result = newdec (ceil (x.infsup)); ## Between two integral numbers the function is constant, thus continuous discontinuos = not (issingleton (result)); result.dec(discontinuos) = min (result.dec(discontinuos), _def ()); onlyrestrictioncontinuous = issingleton (result) & fix (sup (x)) == sup (x); result.dec(onlyrestrictioncontinuous) = ... min (result.dec(onlyrestrictioncontinuous), _dac ()); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (ceil (infsupdec (2.5, 3.5)), infsupdec (3, 4, "def"))); %!assert (isequal (ceil (infsupdec (-.5, 5)), infsupdec (0, 5, "def"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.ceil; %! for testcase = [testcases]' %! assert (isequaln (... %! ceil (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.ceil; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (ceil (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.ceil; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (ceil (in1), out)); interval-3.2.0/inst/@infsupdec/cos.m0000644000000000000000000000463213316017127015473 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} cos (@var{X}) ## ## Compute the cosine in radians. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cos (infsupdec (1)) ## @result{} ans ⊂ [0.5403, 0.54031]_com ## @end group ## @end example ## @seealso{@@infsupdec/acos, @@infsupdec/sec, @@infsupdec/cosh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = cos (x) if (nargin ~= 1) print_usage (); return endif result = newdec (cos (x.infsup)); ## cos is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (cos (infsupdec (1)), infsupdec ("[0x1.14A280FB5068Bp-1, 0x1.14A280FB5068Cp-1]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.cos; %! for testcase = [testcases]' %! assert (isequaln (... %! cos (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.cos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (cos (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.cos; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cos (in1), out)); interval-3.2.0/inst/@infsupdec/cosh.m0000644000000000000000000000466113316017127015645 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} cosh (@var{X}) ## ## Compute the hyperbolic cosine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cosh (infsupdec (1)) ## @result{} ans ⊂ [1.543, 1.5431]_com ## @end group ## @end example ## @seealso{@@infsupdec/acosh, @@infsupdec/sech, @@infsupdec/sinh, @@infsupdec/tanh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = cosh (x) if (nargin ~= 1) print_usage (); return endif result = newdec (cosh (x.infsup)); ## cosh is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (cosh (infsupdec (1)), infsupdec ("[0x1.8B07551D9F55, 0x1.8B07551D9F551]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.cosh; %! for testcase = [testcases]' %! assert (isequaln (... %! cosh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.cosh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (cosh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.cosh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cosh (in1), out)); interval-3.2.0/inst/@infsupdec/coshrev.m0000644000000000000000000000771713316017127016367 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} coshrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsupdec} {@var{X} =} coshrev (@var{C}) ## ## Compute the reverse hyperbolic cosine function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{cosh (x) ∈ @var{C}}. ## ## Accuracy: The result is a tight enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## coshrev (infsupdec (-2, 1)) ## @result{} ans = [0]_trv ## @end group ## @end example ## @seealso{@@infsupdec/cosh} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = coshrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsupdec (-inf, inf); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif result = infsupdec (coshrev (c.infsup, x.infsup), "trv"); result.dec(isnai (c) | isnai (x)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (coshrev (infsupdec (-2, 1)), infsupdec (0, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.coshRev; %! for testcase = [testcases]' %! assert (isequaln (... %! coshrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.coshRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (coshrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.coshRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (coshrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.coshRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! coshrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.coshRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (coshrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.coshRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (coshrev (in1, in2), out)); interval-3.2.0/inst/@infsupdec/cosrev.m0000644000000000000000000000776513316017127016222 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} cosrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsupdec} {@var{X} =} cosrev (@var{C}) ## ## Compute the reverse cosine function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{cos (x) ∈ @var{C}}. ## ## Accuracy: The result is a valid enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## cosrev (infsupdec (0), infsupdec (6, 9)) ## @result{} ans ⊂ [7.8539, 7.854]_trv ## @end group ## @end example ## @seealso{@@infsupdec/cos} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = cosrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsupdec (-inf, inf); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif result = infsupdec (cosrev (c.infsup, x.infsup), "trv"); result.dec(isnai (c) | isnai (x)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (cosrev (0, infsupdec (6, 9)), infsupdec ("[0x1.F6A7A2955385Ep2, 0x1.F6A7A2955386p2]_trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.cosRev; %! for testcase = [testcases]' %! assert (isequaln (... %! cosrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.cosRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (cosrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.cosRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cosrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.cosRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! cosrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.cosRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (cosrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.cosRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (cosrev (in1, in2), out)); interval-3.2.0/inst/@infsupdec/cot.m0000644000000000000000000000330213316017127015465 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} cot (@var{X}) ## ## Compute the cotangent in radians, that is the reciprocal tangent. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## cot (infsupdec (1)) ## @result{} ans ⊂ [0.64209, 0.6421]_com ## @end group ## @end example ## @seealso{@@infsupdec/tan, @@infsupdec/csc, @@infsupdec/sec} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function result = cot (x) if (nargin ~= 1) print_usage (); return endif result = newdec (cot (x.infsup)); ## Because tan (nextdown (pi)) < realmax, we can simple check for ## a singularity by comparing the result with entire for x ~= 0. domain = not (isentire (result)) | (inf (x) <= 0 & sup (x) >= 0); result.dec(not (domain)) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (cot (infsupdec (1)), infsupdec ("[0x1.48C05D04E1CFDp-1, 0x1.48C05D04E1CFEp-1]"))); interval-3.2.0/inst/@infsupdec/coth.m0000644000000000000000000000310413316017127015635 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} coth (@var{X}) ## ## Compute the hyperbolic cotangent, that is the reciprocal hyperbolic tangent. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## coth (infsupdec (1)) ## @result{} ans ⊂ [1.313, 1.3131]_com ## @end group ## @end example ## @seealso{@@infsupdec/tanh, @@infsupdec/csch, @@infsupdec/sech} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function result = coth (x) if (nargin ~= 1) print_usage (); return endif result = newdec (coth (x.infsup)); ## coth is defined and continuous for x ~= 0 result.dec (inf (x) <= 0 & sup (x) >= 0) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (coth (infsupdec (1)), infsupdec ("[0x1.50231499B6B1D, 0x1.50231499B6B1E]_com"))); interval-3.2.0/inst/@infsupdec/csc.m0000644000000000000000000000327313316017127015457 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} csc (@var{X}) ## ## Compute the cosecant in radians, that is the reciprocal sine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## csc (infsupdec (1)) ## @result{} ans ⊂ [1.1883, 1.1884]_com ## @end group ## @end example ## @seealso{@@infsupdec/sin, @@infsupdec/sec, @@infsupdec/cot} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function result = csc (x) if (nargin ~= 1) print_usage (); return endif result = newdec (csc (x.infsup)); ## Because csc (nextdown (pi)) < realmax, we can simple check for ## a singularity by comparing the result with entire for x ~= 0. domain = not (isentire (result)) | (inf (x) <= 0 & sup (x) >= 0); result.dec(not (domain)) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (csc (infsupdec (1)), infsupdec ("[0x1.303AA9620B223, 0x1.303AA9620B224]_com"))); interval-3.2.0/inst/@infsupdec/csch.m0000644000000000000000000000317513316017127015630 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} csch (@var{X}) ## ## Compute the hyperbolic cosecant, that is the reciprocal hyperbolic sine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## csch (infsupdec (1)) ## @result{} ans ⊂ [0.85091, 0.85092]_com ## @end group ## @end example ## @seealso{@@infsupdec/sinh, @@infsupdec/sech, @@infsupdec/coth} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function result = csch (x) if (nargin ~= 1) print_usage (); return endif if (isnai (x)) result = x; return endif result = newdec (csch (x.infsup)); ## csch is defined and continuous for x ~= 0 result.dec (inf (x) <= 0 & sup (x) >= 0) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (csch (infsupdec (1)), infsupdec ("[0x1.B3AB8A78B90Cp-1, 0x1.B3AB8A78B90C1p-1]_com"))); interval-3.2.0/inst/@infsupdec/decorationpart.m0000644000000000000000000001120513316017127017717 0ustar 00000000000000## Copyright 2014-2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} decorationpart (@var{X}) ## @defmethodx {@@infsupdec} decorationpart (@var{X}, @var{TYPE}) ## ## Return the decoration of the decorated interval @var{X}. ## ## The returned value depends on the requested @var{TYPE}. ## @table @asis ## @item @option{char} (default) ## The decoration is a cell array of character strings and its size equals the ## size of its interval part. Possible values: @option{ill}, @option{trv}, ## @option{def}, @option{dac}, @option{com}. ## @item @option{uint8} ## The decoration is an array of uint8 numbers and its size equals the size of ## its interval part. Possible values: @option{0}, @option{4}, @option{8}, ## @option{12}, @option{16} as defined by IEEE Std 1788-2015, 14.4 Interchange ## representations and encodings. ## @end table ## ## @example ## @group ## x = infsupdec ("[0, 1] [1, inf] [-1, 1]_def [empty]"); ## decorationpart (x) ## @result{} ans = ## @{ ## [1,1] = com ## [1,2] = dac ## [1,3] = def ## [1,4] = trv ## @} ## decorationpart (x, "uint8") ## @result{} ans = ## ## 16 12 8 4 ## ## @end group ## @end example ## @seealso{@@infsupdec/intervalpart} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-12 function dec = decorationpart (x, type) if (nargin > 2) print_usage (); return endif if (nargin < 2) type = "char"; endif switch (type) case "char" # see below case "uint8" dec = x.dec; return otherwise error ("decorationpart: illegal value for parameter TYPE") endswitch persistent dec_translation = {... # 0 = ill "ill", [], [], [], ... # 4 = trv "trv", [], [], [], ... # 8 = def "def", [], [], [], ... # 12 = dac "dac", [], [], [], ... # 16 = com "com"}; dec = cell (size (x.dec)); dec(:) = dec_translation(x.dec(:) + 1); endfunction %!assert (decorationpart (infsupdec (3, 4)), {"com"}); %!assert (decorationpart (infsupdec (3, inf)), {"dac"}); %!assert (decorationpart (infsupdec ("[3, 4]_def")), {"def"}); %!assert (decorationpart (infsupdec ()), {"trv"}); %!assert (decorationpart (nai), {"ill"}); %!assert (decorationpart (nai, "uint8") ... %! < decorationpart (infsupdec ("[3, 4]_trv"), "uint8")); %!assert (decorationpart (infsupdec ("[3, 4]_trv"), "uint8") ... %! < decorationpart (infsupdec ("[3, 4]_def"), "uint8")); %!assert (decorationpart (infsupdec ("[3, 4]_def"), "uint8") ... %! < decorationpart (infsupdec ("[3, 4]_dac"), "uint8")); %!assert (decorationpart (infsupdec ("[3, 4]_dac"), "uint8") ... %! < decorationpart (infsupdec ("[3, 4]_com"), "uint8")); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.decorationPart; %! for testcase = [testcases]' %! assert (isequaln (... %! decorationpart (testcase.in{1}), ... %! {testcase.out})); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.decorationPart; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = {testcases.out}'; %! assert (isequaln (decorationpart (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.decorationPart; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = {testcases.out}'; %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (decorationpart (in1), out)); interval-3.2.0/inst/@infsupdec/det.m0000644000000000000000000000276213316017127015465 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} det (@var{A}) ## ## Compute the determinant of matrix @var{A}. ## ## The determinant for matrices of size 3×3 or greater is computed via L-U ## decomposition and may be affected by overestimation due to the dependency ## problem. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## det (infsupdec (magic (3))) ## @result{} ans = [-360]_com ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-10-24 function result = det (x) if (nargin ~= 1) print_usage (); return endif result = newdec (det (x.infsup)); result.dec = min (result.dec, min (min (x.dec))); endfunction %!# from the documentation string %!assert (det (infsupdec (magic (3))) == -360); interval-3.2.0/inst/@infsupdec/diag.m0000644000000000000000000000460313316017127015611 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {M =} diag (@var{V}) ## @deftypemethodx {@@infsupdec} {V =} diag (@var{M}) ## @deftypemethodx {@@infsupdec} {M =} diag (@var{V}, @var{K}) ## @deftypemethodx {@@infsupdec} {M =} diag (@var{V}, @var{M}, @var{N}) ## @deftypemethodx {@@infsupdec} {V =} diag (@var{M}, @var{K}) ## ## Create a diagonal matrix @var{M} with vector @var{V} on diagonal @var{K} or ## extract a vector @var{V} from the @var{K}-th diagonal of matrix @var{M}. ## ## With three arguments, create a matrix of size @var{M}×@var{N}. ## ## @example ## @group ## diag (infsupdec (1 : 3)) ## @result{} ans = 3×3 interval matrix ## ## [1]_com [0]_com [0]_com ## [0]_com [2]_com [0]_com ## [0]_com [0]_com [3]_com ## @end group ## @end example ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-10-24 function x = diag (x, varargin) if (nargin > 3) print_usage (); return endif if ((nargin >= 2 && isa (varargin{1}, 'infsup')) || ... (nargin >= 3 && isa (varargin{2}, 'infsup'))) error ('diag: invalid argument; only the first may be an interval'); endif x.dec(x.dec == 0) = uint8 (255); x.infsup = diag (x.infsup, varargin{:}); x.dec = diag (x.dec, varargin{:}); x.dec(x.dec == uint8 (0)) = _com (); # any new elements are [0]_com x.dec(x.dec == uint8 (255)) = uint8 (0); endfunction %!assert (diag (infsupdec (-inf, inf)) == "[Entire]"); %!assert (diag (infsupdec ()) == "[Empty]"); %!assert (numel (diag (infsupdec ([]))), 0); %!assert (isequal (diag (infsupdec (magic (3))), infsupdec ([8; 5; 2]))); %!assert (isequal (diag (infsupdec ([8 5 3])), infsupdec ([8 0 0; 0 5 0; 0 0 3]))); interval-3.2.0/inst/@infsupdec/dilog.m0000644000000000000000000000354513316017127016007 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} dilog (@var{X}) ## ## Compute the real part of the dilogarithm function. ## ## @tex ## $$ ## {\rm dilog} (x) = -\Re \int_0^x {{\log (1-t)} \over t} dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## x ## / log (1 - t) ## dilog (x) = - Re | ------------- dt ## / t ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## dilog (infsupdec (1)) ## @result{} ans ⊂ [1.6449, 1.645]_com ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-29 function result = dilog (x) if (nargin ~= 1) print_usage (); return endif result = newdec (dilog (x.infsup)); ## dilog is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!assert (isequal (dilog (infsupdec (-inf, inf)), infsupdec ("[-Inf, +0x1.3BD3CC9BE45DFp1]_dac"))); %!# from the documentation string %!assert (isequal (dilog (infsupdec (1)), infsupdec ("[0x1.A51A6625307D3, 0x1.A51A6625307D4]_com"))); interval-3.2.0/inst/@infsupdec/disjoint.m0000644000000000000000000000547113316017127016534 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} disjoint (@var{A}, @var{B}) ## ## Evaluate disjoint comparison on intervals. ## ## True, if all numbers from @var{A} are not contained in @var{B} and vice ## versa. False, if @var{A} and @var{B} have at least one element in common. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsupdec/eq, @@infsupdec/subset, @@infsupdec/interior} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = disjoint (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = disjoint (a.infsup, b.infsup); result(isnai (a) | isnai (b)) = false (); endfunction %!assert (disjoint (infsupdec (3, 4), infsupdec (5, 6))); %!assert (not (disjoint (infsupdec (3, 4), infsupdec (4, 5)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.disjoint; %! for testcase = [testcases]' %! assert (isequaln (... %! disjoint (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.disjoint; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (disjoint (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.disjoint; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (disjoint (in1, in2), out)); interval-3.2.0/inst/@infsupdec/dot.m0000644000000000000000000001410113316017127015465 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} dot (@var{X}, @var{Y}) ## @defmethodx {@@infsupdec} dot (@var{X}, @var{Y}, @var{DIM}) ## ## Compute the dot product of two interval vectors. ## ## If @var{X} and @var{Y} are arrays, calculate the dot products along the ## first non-singleton dimension. If the optional argument @var{DIM} is given, ## calculate the dot products along this dimension. ## ## Conceptually this is equivalent to @code{sum (@var{X} .* @var{Y})} ## but it is computed in such a way that no intermediate round-off ## errors are introduced. ## ## Broadcasting is performed along all dimensions except if @var{X} ## and @var{Y} are both vectors and @var{DIM} is not specified, in ## which case they are aligned along dimension 1. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## dot ([infsupdec(1), 2, 3], [infsupdec(2), 3, 4]) ## @result{} ans = [20]_com ## @end group ## @group ## dot (infsupdec ([realmax; realmin; realmax]), [1; -1; -1], 1) ## @result{} ans ⊂ [-2.2251e-308, -2.225e-308]_com ## @end group ## @end example ## @seealso{@@infsupdec/plus, @@infsupdec/sum, @@infsupdec/times} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-01-31 function result = dot (x, y, dim) if (nargin < 2 || nargin > 3) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif if (nargin < 3) if (isvector (x.dec) && isvector (y.dec)) ## Align vectors along common dimension dim = 1; x = vec (x, dim); y = vec (y, dim); else ## Try to find non-singleton dimension xsize = size (x.dec); ysize = size (y.dec); xsize(end+1:ndims (y)) = 1; ysize(end+1:ndims (x)) = 1; dim = find (and (xsize ~= 1, ysize ~= 1), 1); if (isempty (dim)) dim = 1; endif endif endif result = newdec (dot (x.infsup, y.infsup, dim)); warning ("off", "Octave:broadcast", "local"); if (size (x, dim) > 0 && size (y, dim) > 0) result.dec = min (result.dec, ... min (min (x.dec, [], dim), min (y.dec, [], dim))); endif if (isequal (x, infsupdec ([])) && isequal (y, infsupdec ([]))) ## Inconsistency, dot (infsupdec ([]), []) = [0]_com ## Needs to be handled here for the decoration to work correctly result = newdec (result.infsup); endif endfunction %!# matrix × matrix %!assert (isequal (dot (infsupdec (magic (3)), magic (3)), infsupdec([89, 107, 89]))); %!assert (isequal (dot (infsupdec (magic (3)), magic (3), 1), infsupdec([89, 107, 89]))); %!assert (isequal (dot (infsupdec (magic (3)), magic (3), 2), infsupdec([101; 83; 101]))); %!# matrix × vector %!assert (isequal (dot (infsupdec (magic (3)), [1, 2, 3]), infsupdec([28; 34; 28]))); %!assert (isequal (dot (infsupdec (magic (3)), [1, 2, 3], 1), infsupdec([15, 30, 45]))); %!assert (isequal (dot (infsupdec (magic (3)), [1, 2, 3], 2), infsupdec([28; 34; 28]))); %!assert (isequal (dot (infsupdec (magic (3)), [1; 2; 3]), infsupdec([26, 38, 26]))); %!assert (isequal (dot (infsupdec (magic (3)), [1; 2; 3], 1), infsupdec([26, 38, 26]))); %!assert (isequal (dot (infsupdec (magic (3)), [1; 2; 3], 2), infsupdec([15; 30; 45]))); %!# matrix × scalar %!assert (isequal (dot (infsupdec (magic (3)), 42), infsupdec([630, 630, 630]))); %!assert (isequal (dot (infsupdec (magic (3)), 42, 1), infsupdec([630, 630, 630]))); %!assert (isequal (dot (infsupdec (magic (3)), 42, 2), infsupdec([630; 630; 630]))); %!# vector x vector %!assert (isequal (dot (infsupdec([1, 2, 3]), [4, 5, 6]), infsupdec(32))); %!assert (isequal (dot (infsupdec([1, 2, 3]), [4, 5, 6], 1), infsupdec([4, 10, 18]))); %!assert (isequal (dot (infsupdec([1, 2, 3]), [4, 5, 6], 2), infsupdec(32))); %!assert (isequal (dot (infsupdec([1; 2; 3]), [4; 5; 6]), infsupdec(32))); %!assert (isequal (dot (infsupdec([1; 2; 3]), [4; 5; 6], 1), infsupdec(32))); %!assert (isequal (dot (infsupdec([1; 2; 3]), [4; 5; 6], 2), infsupdec([4; 10; 18]))); %!# vector × scalar %!assert (isequal (dot (infsupdec ([1, 2, 3]), 42), infsupdec(252))); %!assert (isequal (dot (infsupdec ([1, 2, 3]), 42, 1), infsupdec([42, 84, 126]))); %!assert (isequal (dot (infsupdec ([1, 2, 3]), 42, 2), infsupdec(252))); %!assert (isequal (dot (infsupdec ([1; 2; 3]), 42), infsupdec(252))); %!assert (isequal (dot (infsupdec ([1; 2; 3]), 42, 1), infsupdec(252))); %!assert (isequal (dot (infsupdec ([1; 2; 3]), 42, 2), infsupdec([42; 84; 126]))); %!# empty matrix x empty matrix %!assert (isequal (dot (infsupdec (ones (0, 2)), infsupdec (ones (0, 2))), infsupdec ([0, 0]))); %!# N-dimensional arrays %!test %! x = infsupdec (reshape (1:24, 2, 3, 4)); %! y = infsupdec (2.*ones (2, 3, 4)); %! assert (isequal (dot (x, y, 3), infsupdec ([80, 96, 112; 88, 104, 120]))) %!test %! x = infsupdec (ones (2, 2, 2, 2)); %! y = infsupdec (1); %! assert (size (dot (x, y)), [1, 2, 2, 2]); %! assert (size (dot (x, y, 1)), [1, 2, 2, 2]); %! assert (size (dot (x, y, 2)), [2, 1, 2, 2]); %! assert (size (dot (x, y, 3)), [2, 2, 1, 2]); %! assert (size (dot (x, y, 4)), [2, 2, 2]); %! assert (size (dot (x, y, 5)), [2, 2, 2, 2]); %!# from the documentation string %!assert (isequal (dot ([infsupdec(1), 2, 3], [infsupdec(2), 3, 4]), infsupdec (20))); %!assert (isequal (dot (infsupdec ([realmax; realmin; realmax]), [1; -1; -1], 1), infsupdec (-realmin))); interval-3.2.0/inst/@infsupdec/ei.m0000644000000000000000000000407613316017127015306 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} ei (@var{X}) ## ## Compute the exponential integral for positive arguments. ## ## @tex ## $$ ## {\rm ei} (x) = \int_{-\infty}^x {{\exp t} \over t} dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## x ## / exp (t) ## ei (x) = | --------- dt ## / t ## -∞ ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## ei (infsupdec (1)) ## @result{} ans ⊂ [1.8951, 1.8952]_com ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-29 function result = ei (x) if (nargin ~= 1) print_usage (); return endif result = newdec (ei (x.infsup)); ## ei is continuous everywhere, but defined for x > 0 only persistent domain_hull = infsup (0, inf); result.dec (not (interior (x.infsup, domain_hull))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!assert (isempty (ei (infsupdec (0)))); %!assert (isempty (ei (infsupdec (-inf, -2)))); %!assert (isequal (ei (infsupdec (0, inf)), infsupdec ("[Entire]_trv"))); %!assert (isequal (ei (infsupdec (1, inf)), infsupdec ("[0x1.E52670F350D08, Inf]_dac"))); %!# from the documentation string %!assert (isequal (ei (infsupdec (1)), infsupdec ("[0x1.E52670F350D08, 0x1.E52670F350D09]_com"))); interval-3.2.0/inst/@infsupdec/eq.m0000644000000000000000000000747013316017127015317 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} eq (@var{A}, @var{B}) ## @defopx Operator {@@infsupdec} {@var{A} == @var{B}} ## ## Compare intervals @var{A} and @var{B} for equality. ## ## True, if all numbers from @var{A} are also contained in @var{B} and vice ## versa. False, if @var{A} contains a number which is not a member in @var{B} ## or vice versa. ## ## @example ## @group ## x = infsupdec (2, 3); ## y = infsupdec (1, 2); ## x == y ## @result{} ans = 0 ## @end group ## @end example ## @seealso{@@infsupdec/subset, @@infsupdec/interior, @@infsupdec/disjoint} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = eq (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = eq (a.infsup, b.infsup); result(isnai (a) | isnai (b)) = false (); endfunction %!# Empty interval %!assert (eq (infsupdec (), infsupdec ()) == true); %!assert (eq (infsupdec (), infsupdec (1)) == false); %!assert (eq (infsupdec (0), infsupdec ()) == false); %!assert (eq (infsupdec (-inf, inf), infsupdec ()) == false); %!# Singleton intervals %!assert (eq (infsupdec (0), infsupdec (1)) == false); %!assert (eq (infsupdec (0), infsupdec (0)) == true); %!# Bounded intervals %!assert (eq (infsupdec (1, 2), infsupdec (3, 4)) == false); %!assert (eq (infsupdec (1, 2), infsupdec (2, 3)) == false); %!assert (eq (infsupdec (1, 2), infsupdec (1.5, 2.5)) == false); %!assert (eq (infsupdec (1, 2), infsupdec (1, 2)) == true); %!# Unbounded intervals %!assert (eq (infsupdec (0, inf), infsupdec (-inf, 0)) == false); %!assert (eq (infsupdec (0, inf), infsupdec (0, inf)) == true); %!assert (eq (infsupdec (-inf, 0), infsupdec (-inf, 0)) == true); %!assert (eq (infsupdec (-inf, inf), infsupdec (42)) == false); %!assert (eq (infsupdec (-inf, 0), infsupdec (-inf, inf)) == false); %!assert (eq (infsupdec (-inf, inf), infsupdec (-inf, inf)) == true); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.equal; %! for testcase = [testcases]' %! assert (isequaln (... %! eq (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.equal; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (eq (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.equal; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (eq (in1, in2), out)); interval-3.2.0/inst/@infsupdec/erf.m0000644000000000000000000000332313316017127015457 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} erf (@var{X}) ## ## Compute the error function. ## ## @tex ## $$ ## {\rm erf} (x) = {2 \over \sqrt{\pi}}\int_0^x \exp (-t^2) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## x ## 2 / ## erf (x) = ----- | exp (-t²) dt ## √π / ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## erf (infsupdec (1)) ## @result{} ans ⊂ [0.8427, 0.84271]_com ## @end group ## @end example ## @seealso{@@infsupdec/erfc} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-28 function result = erf (x) if (nargin ~= 1) print_usage (); return endif result = newdec (erf (x.infsup)); ## erf is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (erf (infsupdec (1)) == "[0x1.AF767A741088Ap-1, 0x1.AF767A741088Bp-1]"); interval-3.2.0/inst/@infsupdec/erfc.m0000644000000000000000000000341113316017127015620 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} erfc (@var{X}) ## ## Compute the complementary error function @code{1 - erf (@var{X})}. ## ## @tex ## $$ ## {\rm erfc} (x) = {2 \over \sqrt{\pi}}\int_x^\infty \exp (-t^2) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## ∞ ## 2 / ## erfc (x) = ----- | exp (-t²) dt ## √π / ## x ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## erfc (infsupdec (1)) ## @result{} ans ⊂ [0.15729, 0.1573]_com ## @end group ## @end example ## @seealso{@@infsup/erf} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-28 function result = erfc (x) if (nargin ~= 1) print_usage (); return endif result = newdec (erfc (x.infsup)); ## erfc is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (erfc (infsupdec (1)) == "[0x1.4226162FBDDD4p-3, 0x1.4226162FBDDD5p-3]"); interval-3.2.0/inst/@infsupdec/exp.m0000644000000000000000000000453613316017127015506 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} exp (@var{X}) ## ## Compute the exponential function. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## exp (infsupdec (1)) ## @result{} ans ⊂ [2.7182, 2.7183]_com ## @end group ## @end example ## @seealso{@@infsupdec/log, @@infsupdec/pow} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = exp (x) if (nargin ~= 1) print_usage (); return endif result = newdec (exp (x.infsup)); ## exp is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (exp (infsupdec (1)), infsupdec ("e"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.exp; %! for testcase = [testcases]' %! assert (isequaln (... %! exp (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.exp; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (exp (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.exp; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (exp (in1), out)); interval-3.2.0/inst/@infsupdec/expm1.m0000644000000000000000000000277213316017127015744 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} expm1 (@var{X}) ## ## Compute @code{exp (@var{X}) - 1} accurately in the neighborhood of zero. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## expm1 (infsupdec (eps)) ## @result{} ans ⊂ [2.2204e-16, 2.2205e-16]_com ## @end group ## @end example ## @seealso{@@infsup/exp, @@infsup/log1p} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-20 function result = expm1 (x) if (nargin ~= 1) print_usage (); return endif result = newdec (expm1 (x.infsup)); ## expm1 is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (expm1 (infsupdec (eps)), infsupdec ("[0x1p-52, 0x1.0000000000001p-52]"))); interval-3.2.0/inst/@infsupdec/factorial.m0000644000000000000000000000513513316017127016652 0ustar 00000000000000## Copyright 2017 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} factorial (@var{N}) ## ## Compute the factorial of @var{N} where @var{N} is a non-negative integer. ## ## If @var{N} is a scalar, this is equivalent to ## @display ## factorial (@var{N}) = 1 * 2 * @dots{} * @var{N}. ## @end display ## For vector, matrix or array arguments, return the factorial of each ## element in the array. ## ## For non-integers see the generalized factorial function @command{gamma}. ## Note that the factorial function grows large quite quickly, and the result ## cannot be represented exactly in binary64 for @var{N} ≥ 23 and will overflow ## for @var{N} ≥ 171. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## factorial (infsupdec (6)) ## @result{} ans = [720]_com ## @end group ## @end example ## @seealso{@@infsupdec/prod, @@infsupdec/gamma, @@infsupdec/gammaln} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-01-31 function result = factorial (x) if (nargin ~= 1) print_usage (); return endif result = newdec (factorial (x.infsup)); ## The function is defined for non-negative integrals only defined = issingleton (x) & fix (sup (x)) == sup (x); result.dec(not (defined)) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (factorial (infsupdec (6)), infsupdec (720))); %!assert (isequal (factorial (infsupdec (0)), infsupdec (1))); %!assert (isequal (factorial (infsupdec ("[0, 1.99]")), infsupdec (1, "trv"))); %!assert (isequal (factorial (infsupdec ("[0, 2]")), infsupdec (1, 2, "trv"))); %!assert (isequal (factorial (infsupdec ("[1.4, 1.6]")), empty ())); %!assert (isequal (factorial (infsupdec (23)), infsupdec ("[0x1.5e5c335f8a4cdp+74, 0x1.5e5c335f8a4cep+74]_com"))); %!assert (isequal (factorial (infsupdec (171)), infsupdec ("[0x1.fffffffffffffp+1023, Inf]_dac"))); interval-3.2.0/inst/@infsupdec/fix.m0000644000000000000000000000615113316017127015473 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} fix (@var{X}) ## ## Truncate fractional portion of each number in interval @var{X}. This is ## equivalent to rounding towards zero. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## fix (infsupdec (2.5, 3.5)) ## @result{} ans = [2, 3]_def ## fix (infsupdec (-0.5, 5)) ## @result{} ans = [0, 5]_def ## @end group ## @end example ## @seealso{@@infsupdec/floor, @@infsupdec/ceil, @@infsupdec/round, @@infsupdec/roundb} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = fix (x) if (nargin ~= 1) print_usage (); return endif result = newdec (fix (x.infsup)); ## Between two integral numbers the function is constant, thus continuous ## At x == 0 the function is continuous. discontinuous = not (issingleton (result)); result.dec(discontinuous) = min (result.dec(discontinuous), _def ()); onlyrestrictioncontinuous = issingleton (result) & ... ((sup (x) < 0 & fix (sup (x)) == sup (x)) | ... (inf (x) > 0 & fix (inf (x)) == inf (x))); result.dec(onlyrestrictioncontinuous) = ... min (result.dec(onlyrestrictioncontinuous), _dac ()); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (fix (infsupdec (2.5, 3.5)), infsupdec (2, 3, "def"))); %!assert (isequal (fix (infsupdec (-0.5, 5)), infsupdec (0, 5, "def"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.trunc; %! for testcase = [testcases]' %! assert (isequaln (... %! fix (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.trunc; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (fix (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.trunc; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (fix (in1), out)); interval-3.2.0/inst/@infsupdec/floor.m0000644000000000000000000000576113316017127016034 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} floor (@var{X}) ## ## Round each number in interval @var{X} towards -Inf. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## floor (infsupdec (2.5, 3.5)) ## @result{} ans = [2, 3]_def ## floor (infsupdec (-0.5, 5)) ## @result{} ans = [-1, +5]_def ## @end group ## @end example ## @seealso{@@infsupdec/ceil, @@infsupdec/round, @@infsupdec/roundb, @@infsupdec/fix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = floor (x) if (nargin ~= 1) print_usage (); return endif result = newdec (floor (x.infsup)); ## Between two integral numbers the function is constant, thus continuous discontinuous = not (issingleton (result)); result.dec(discontinuous) = min (result.dec(discontinuous), _def ()); onlyrestrictioncontinuous = issingleton (result) & fix (inf (x)) == inf (x); result.dec(onlyrestrictioncontinuous) = ... min (result.dec(onlyrestrictioncontinuous), _dac ()); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (floor (infsupdec (2.5, 3.5)), infsupdec (2, 3, "def"))); %!assert (isequal (floor (infsupdec (-0.5, 5)), infsupdec (-1, 5, "def"))); %!warning %! _ = @infsupdec; %! assert (isequal (... %! floor (_ ("jansen")), nai)) #ghtwish %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.floor; %! for testcase = [testcases]' %! assert (isequaln (... %! floor (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.floor; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (floor (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.floor; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (floor (in1), out)); interval-3.2.0/inst/@infsupdec/fma.m0000644000000000000000000000666013316017127015455 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} fma (@var{X}, @var{Y}, @var{Z}) ## ## Fused multiply and add @code{@var{X} * @var{Y} + @var{Z}}. ## ## This function is semantically equivalent to evaluating multiplication and ## addition separately, but in addition guarantees a tight enclosure of the ## result. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## output_precision (16, 'local') ## fma (infsupdec (1+eps), infsupdec (7), infsupdec ("0.1")) ## @result{} ans ⊂ [7.100000000000001, 7.100000000000003]_com ## infsupdec (1+eps) * infsupdec (7) + infsupdec ("0.1") ## @result{} ans ⊂ [7.1, 7.100000000000003]_com ## @end group ## @end example ## @seealso{@@infsupdec/plus, @@infsupdec/mtimes} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = fma (x, y, z) if (nargin ~= 3) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif if (not (isa (z, "infsupdec"))) z = infsupdec (z); endif result = newdec (fma (x.infsup, y.infsup, z.infsup)); ## fma is defined and continuous everywhere result.dec = min (result.dec, min (x.dec, min (y.dec, z.dec))); endfunction %!# from the documentation string %!assert (isequal (fma (infsupdec (1+eps), infsupdec (7), infsupdec ("0.1")), infsupdec ("[0x1.C666666666668p2, 0x1.C666666666669p2]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.fma; %! for testcase = [testcases]' %! assert (isequaln (... %! fma (testcase.in{1}, testcase.in{2}, testcase.in{3}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.fma; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! assert (isequaln (fma (in1, in2, in3), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.fma; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2 | i == numel (in1)) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! in3 = reshape ([in3; in3(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (fma (in1, in2, in3), out)); interval-3.2.0/inst/@infsupdec/gamma.m0000644000000000000000000000404313316017127015765 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} gamma (@var{X}) ## ## Compute the gamma function. ## ## @tex ## $$ ## {\rm gamma} (x) = \int_0^\infty t^(x-1) \exp (-t) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## ∞ ## / ## gamma (x) = | t^(x - 1) * exp (-t) dt ## / ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a valid enclosure. The result is tightest for ## @var{X} >= -10. ## ## @example ## @group ## gamma (infsupdec (1.5)) ## @result{} ans ⊂ [0.88622, 0.88623]_com ## @end group ## @end example ## @seealso{@@infsupdec/psi, @@infsupdec/gammaln, @@infsupdec/factorial} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-01 function result = gamma (x) if (nargin ~= 1) print_usage (); return endif result = newdec (gamma (x.infsup)); ## gamma is continuous where it is defined undefined = (inf (x) <= 0 & fix (inf (x)) == inf (x)) | ... (sup (x) <= 0 & fix (sup (x)) == sup (x)) | ... (inf (x) < 0 & ceil (inf (x)) <= floor (sup (x))); result.dec(undefined) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (gamma (infsupdec (1.5)), infsupdec ("[0x1.C5BF891B4EF6Ap-1, 0x1.C5BF891B4EF6Bp-1]_com"))); interval-3.2.0/inst/@infsupdec/gammaln.m0000644000000000000000000000412213316017127016315 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} gammaln (@var{X}) ## ## Compute the logarithm of the gamma function for positive arguments. ## ## @tex ## $$ ## {\rm gammaln} (x) = \log \int_0^\infty t^{x-1} \exp (-t) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## ∞ ## / ## gammaln (x) = log | t^(x-1) exp (-t) dt ## / ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## gammaln (infsupdec (1.5)) ## @result{} ans ⊂ [-0.12079, -0.12078]_com ## @end group ## @end example ## @seealso{@@infsupdec/psi, @@infsupdec/gamma, @@infsupdec/factorial} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-28 function result = gammaln (x) if (nargin ~= 1) print_usage (); return endif result = newdec (gammaln (x.infsup)); ## gammaln is continuous everywhere, but defined for x > 0 only persistent domain_hull = infsup (0, inf); result.dec(not (interior (x.infsup, domain_hull))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!assert (isequal (gammaln (infsupdec (-inf, inf)), infsupdec ("[-0x1.F19B9BCC38A42p-4, +Inf]_trv"))); %!# from the documentation string %!assert (isequal (gammaln (infsupdec (1.5)), infsupdec ("[-0x1.EEB95B094C192p-4, -0x1.EEB95B094C191p-4]_com"))); interval-3.2.0/inst/@infsupdec/gauss.m0000644000000000000000000000421613316017127016027 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{x} =} gauss (@var{A}, @var{b}) ## ## Solve a linear interval system @var{A} * @var{x} = @var{b} using Gaussian ## elimination. ## ## The found enclosure is improved with the help of the Gauß-Seidel-method. ## ## Note: This algorithm is very inaccurate and slow for matrices of a dimension ## greater than 3. A better solver is provided by @code{mldivide}. The ## inaccuracy mainly comes from the dependency problem of interval arithmetic ## during back-substitution of the solution's enclosure. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## gauss (infsupdec ([1, 0; 0, 2]), [2, 0; 0, 4]) ## @result{} ans = 2×2 interval matrix ## [2]_trv [0]_trv ## [0]_trv [2]_trv ## @end group ## @end example ## @seealso{@@infsupdec/mldivide} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-18 function result = gauss (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif result = infsupdec (gauss (x.infsup, y.infsup), "trv"); warning ("off", "Octave:broadcast", "local"); result.dec = min (result.dec, min (vec (min (x.dec, y.dec)))); endfunction %!# from the documentation string %!assert (isequal (gauss (infsupdec ([1, 0; 0, 2]), [2, 0; 0, 4]), infsupdec ([2, 0; 0, 2], "trv"))); interval-3.2.0/inst/@infsupdec/hypot.m0000644000000000000000000000331113316017127016043 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} hypot (@var{X}, @var{Y}) ## ## Compute the euclidean norm. ## ## @code{hypot (@var{x}, @var{y}) = sqrt (@var{x}^2 + @var{y}^2)} ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsupdec (2, 3); ## y = infsupdec (1, 2); ## hypot (x, y) ## @result{} ans ⊂ [2.236, 3.6056]_com ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-20 function result = hypot (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif result = newdec (hypot (x.infsup, y.infsup)); ## hypot is continuous and defined everywhere result.dec = min (result.dec, min (x.dec, y.dec)); endfunction %!# from the documentation string %!assert (isequal (hypot (infsupdec (2, 3), infsupdec (1, 2)), infsupdec ("[0x1.1E3779B97F4A7p1, 0x1.CD82B446159F4p1]"))); interval-3.2.0/inst/@infsupdec/inf.m0000644000000000000000000000510113316017127015453 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} inf (@var{X}) ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## ## Get the (greatest) lower boundary for all numbers of interval @var{X}. ## ## If @var{X} is empty, @code{inf (@var{X})} is positive infinity. If @var{X} ## is NaI, @code{inf (@var{X})} is NaN. ## ## Accuracy: The result is exact. ## ## @example ## @group ## inf (infsupdec (2.5, 3.5)) ## @result{} ans = 2.5000 ## @end group ## @end example ## @seealso{@@infsupdec/sup, @@infsup/mid} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-09-18 function result = inf (x) if (nargin ~= 1) print_usage (); return endif result = inf (x.infsup); result(isnai (x)) = nan; endfunction %!assert (inf (infsupdec (2.5, 3.5)), 2.5); %!assert (inf (infsupdec ()), +inf); %!assert (inf (infsupdec ("[nai]")), nan); %!warning id=interval:UndefinedOperation %! assert (inf (infsupdec (2, 1)), nan); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.inf; %! for testcase = [testcases]' %! assert (isequaln (... %! inf (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.inf; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (inf (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.inf; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (inf (in1), out)); interval-3.2.0/inst/@infsupdec/infsupdec.m0000644000000000000000000005244013316017127016667 0ustar 00000000000000## Copyright 2014-2017 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypeop Constructor {@@infsupdec} {[@var{X}, @var{ISEXACT}] =} infsupdec () ## @deftypeopx Constructor {@@infsupdec} {[@var{X}, @var{ISEXACT}] =} infsupdec (@var{M}) ## @deftypeopx Constructor {@@infsupdec} {[@var{X}, @var{ISEXACT}] =} infsupdec (@var{M}, @var{D}) ## @deftypeopx Constructor {@@infsupdec} {[@var{X}, @var{ISEXACT}] =} infsupdec (@var{S}) ## @deftypeopx Constructor {@@infsupdec} {[@var{X}, @var{ISEXACT}] =} infsupdec (@var{L}, @var{U}) ## @deftypeopx Constructor {@@infsupdec} {[@var{X}, @var{ISEXACT}] =} infsupdec (@var{L}, @var{U}, @var{D}) ## @deftypeopx Constructor {@@infsupdec} {[@var{X}, @var{ISEXACT}] =} infsupdec (@var{I}, @var{D}) ## ## Create a decorated interval from boundaries. Convert boundaries to double ## precision. ## ## The syntax without parameters creates an (exact) empty interval. The syntax ## with a single parameter @code{infsupdec (@var{M})} equals ## @code{infsupdec (@var{M}, @var{M})}. The syntax ## @code{infsupdec (@var{M}, @var{D})} equals ## @code{infsupdec (@var{M}, @var{M}, @var{D})}. The syntax ## @code{infsupdec (@var{S})} parses a possibly decorated interval literal in ## inf-sup form or as a special value, where @code{infsupdec ("[S1, S2]")} is ## equivalent to @code{infsupdec ("S1", "S2")} and, if [S1, S2]_D is a valid ## interval literal, ## @code{infsupdec ("[S1, S2]_D")} is equivalent to ## @code{infsupdec ("S1", "S2", "D")}. The syntax ## @code{infsupdec (@var{I}, @var{D})} overrides an interval @var{I}'s ## decoration with a new decoration @var{D}. A second, logical output ## @var{ISEXACT} indicates if @var{X}'s boundaries both have been converted ## without precision loss and without changes to the optional, desired ## decoration. ## ## If construction fails, the special value NaI, “not an interval,” will be ## returned and a warning message will be raised. NaI is equivalent to ## [Empty] together with an ill-formed decoration. ## ## Each boundary can be provided in the following formats: literal constants ## [+-]inf[inity], e, pi; scalar real numeric data types, i. e., double, ## single, [u]int[8,16,32,64]; or decimal numbers as strings of the form ## [+-]d[,.]d[[eE][+-]d]; or hexadecimal numbers as string of the form ## [+-]0xh[,.]h[[pP][+-]d]; or decimal numbers in rational form ## [+-]d/d. ## ## Also it is possible, to construct intervals from the uncertain form in the ## form @code{m?ruE}, where @code{m} is a decimal mantissa, ## @code{r} is empty (= half ULP) or a decimal integer ULP count or a ## second @code{?} character for unbounded intervals, @code{u} is ## empty or a direction character (u: up, d: down), and @code{E} is an ## exponential field. ## ## If decimal or hexadecimal numbers are no binary64 floating point numbers, a ## tight enclosure will be computed. int64 and uint64 numbers of high ## magnitude (> 2^53) can also be affected from precision loss. ## ## The decoration @var{D} must be any of @code{com}, @code{dac}, @code{def}, ## @code{trv}, or @code{ill}. Illegal decorations within interval literals ## will produce NaIs, whereas illegal decorations provided as an additional ## function parameter will be automatically adjusted. ## ## For the creation of interval arrays, arguments may be provided as (1) cell ## arrays with arbitrary/mixed types, (2) numeric arrays, or for matrices (3) ## strings. Scalar values do broadcast. ## ## Non-standard behavior: This class constructor is not described by IEEE Std ## 1788-2015, however it implements the standard functions setDec, ## numsToInterval, and textToInterval. ## ## @example ## @group ## v = infsupdec () ## @result{} v = [Empty]_trv ## w = infsupdec (1) ## @result{} w = [1]_com ## x = infsupdec (2, 3) ## @result{} x = [2, 3]_com ## y = infsupdec ("0.1") ## @result{} y ⊂ [0.099999, 0.10001]_com ## z = infsupdec ("0.1", "0.2") ## @result{} z ⊂ [0.099999, 0.20001]_com ## @end group ## @end example ## @seealso{exacttointerval, hull, midrad, @@infsup/newdec} ## @end deftypeop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-12 function [x, isexact] = infsupdec (varargin) persistent scalar_empty_interval = class (struct ("dec", _trv), ... "infsupdec", infsup ()); ## Enable all mixed mode functions to use decorated variants with implicit ## conversion from bare to decorated intervals. ## ## There is bug #42735 in GNU Octave core, which makes this a little ## complicated: When [infsup] [operator] [infsupdec] syntax is used, the ## decoration from the second argument would be lost, because the bare ## implementation for the operator is evaluated. However, sufficient runtime ## checks have been placed in the overloaded class operator implementations of ## the infsup class as a workaround. ## ## The workaround is necessary, because otherwise this could lead to wrong ## results, which is catastrophic for a verified computation package. superiorto ("infsup"); if (nargin == 0) x = scalar_empty_interval; isexact = true; return endif if (nargin == 1 && isa (varargin{1}, "infsupdec")) x = varargin{1}; isexact = true; return endif warning ("off", "Octave:broadcast", "local"); for i = 1 : numel (varargin) if (ischar (varargin{i})) varargin{i} = __split_interval_literals__ (varargin{i}); endif endfor if (nargin >= 1 && ... iscellstr (varargin{end}) && ... not (isempty (varargin{end})) && ... any (strcmpi (varargin{end}{1}, ... {"com", "dac", "def", "trv", "ill"}))) ## The decoration information has been passed as the last parameter decstr = varargin{end}; varargin = varargin(1 : end - 1); ## The setDec function, as described by IEEE Std 1788-2015, ## may fix decorations fix_illegal_decorations = true; elseif (nargin == 1 && iscell (varargin{1})) ## Extract decorations from possibly decorated interval literals char_idx = cellfun ("ischar", varargin{1}); ## Split bare interval literal and decoration literal_and_decoration = cellfun ("strsplit", ... varargin{1}(char_idx), {"_"}, ... "UniformOutput", false); number_of_parts = cellfun ("numel", literal_and_decoration); illegal_local_idx = number_of_parts > 2; if (any (illegal_local_idx(:))) ## More than 2 underscores in any literal warning ("interval:UndefinedOperation", ... "illegal decorated interval literal") literal_and_decoration(illegal_local_idx) = {"[nai]"}; endif ## Ignore strings without decoration has_decoration_local_idx = (number_of_parts == 2); literal_and_decoration = literal_and_decoration(has_decoration_local_idx); char_idx(char_idx) = has_decoration_local_idx; ## Extract decoration decstr = cell (size (varargin{1})); decstr(char_idx) = vertcat ({}, ... cellindexmat (literal_and_decoration, 2){:}); varargin{1}(char_idx) = vertcat({}, ... cellindexmat (literal_and_decoration, ... 1){:}); ## Interval literals must not carry illegal decorations fix_illegal_decorations = false; else ## Undecorated interval boundaries decstr = {""}; ## No need to fix illegal decorations fix_illegal_decorations = false; endif switch numel (varargin) case 0 [bare, isexact] = infsup (); isnai = overflow = false; case 1 switch class (varargin{1}) case "infsup" bare = varargin{1}; isexact = true; isnai = overflow = false (size (bare)); if (nargin == 1 && any (not (isempty (bare)(:)))) warning ("interval:ImplicitPromote", ... ["Implicitly decorated bare interval; ", ... "resulting decoration may be wrong"]); endif case "infsupdec" ## setDec and newDec replace the current decoration ## with a new one bare = struct (varargin{1}).infsup; isexact = true; isnai = overflow = false (size (bare)); case "cell" ## [nai] is a legal literal, but not allowed in the infsup ## constructor. Create a silent nai in these cases. char_idx = cellfun ("ischar", varargin{1}); nai_literal_local_idx = not (cellfun ("isempty", ... regexp (varargin{1}(char_idx), ... '^\s*\[\s*nai\s*\]\s*$', ... "ignorecase"))); nai_literal_idx = find (char_idx)(nai_literal_local_idx); varargin{1}(nai_literal_idx) = "[]"; [bare, isexact, overflow, isnai] = infsup (varargin{1}); isnai(nai_literal_idx) = true; ## There is no version of [nai], which may carry decoration. if (any (not (cellfun ("isempty", decstr))(nai_literal_idx)(:))) warning ("interval:UndefinedOperation", ... "the [NaI] literal may not carry decoration") decstr(nai_literal_idx) = ""; endif otherwise [bare, isexact, overflow, isnai] = infsup (varargin{1}); endswitch case 2 [bare, isexact, overflow, isnai] = infsup (varargin{1}, varargin{2}); otherwise print_usage (); return endswitch ## Convert decoration strings into decoration matrix. ## Initialize the matrix with the ill decoration, which is not allowed to ## be used explicitly as a parameter to this function. dec = repmat (_ill, size (decstr)); ## Missing decorations will later be assigned their final value missingdecoration_value = uint8 (1); # magic value, not used otherwise dec(cellfun ("isempty", decstr)) = missingdecoration_value; dec(strcmpi (decstr, "com")) = _com; dec(strcmpi (decstr, "dac")) = _dac; dec(strcmpi (decstr, "def")) = _def; dec(strcmpi (decstr, "trv")) = _trv; if (any ((dec == _ill)(:))) warning ("interval:UndefinedOperation", "illegal decoration"); endif ## Broadcast decoration and bare interval if (not (isequal (size (bare), size (dec)))) for dim = 1 : max (ndims (bare), ndims (dec)) if (size (bare, dim) != 1 && size (dec, dim) != 1 && ... size (bare, dim) != size (dec, dim)) warning ("interval:InvalidOperand", ... ["infsupdec: Dimensions of decoration and interval ", ... "are not compatible"]); ## Unable to recover from this kind of error x = scalar_empty_interval; isexact = false; return endif endfor dec = dec + zeros (size (bare), "uint8"); bare = bare + zeros (size (dec)); endif ## If creation failed in infsup constructor, make an illegal interval dec(isnai) = _ill; ## Silently fix decoration when overflow occurred dec(overflow & (dec == _com)) = _dac; ## Add missing decoration missingdecoration = (dec == missingdecoration_value); dec(missingdecoration) = _dac; dec(missingdecoration & isempty (bare)) = _trv; dec(missingdecoration & iscommoninterval (bare)) = _com; ## Check decoration empty_not_trv = isempty (bare) & (dec ~= _trv) & (dec ~= _ill); if (any (empty_not_trv(:))) if (not (fix_illegal_decorations)) warning ("interval:UndefinedOperation", ... "illegal decorated empty interval literal") dec(empty_not_trv) = _ill; else dec(empty_not_trv) = _trv; endif isexact = false (); endif uncommon_com = not (iscommoninterval (bare)) & (dec == _com); if (any (uncommon_com(:))) if (not (fix_illegal_decorations)) warning ("interval:UndefinedOperation", ... "illegal decorated uncommon interval literal") dec(uncommon_com) = _ill; else dec(uncommon_com) = _dac; endif isexact = false (); endif ## Illegal intervals must be empty illegal = (dec == _ill); if (any (illegal(:))) bare(illegal) = infsup (); isexact = false (); endif x = class (struct ("dec", dec), "infsupdec", bare); endfunction %!# [NaI]s %!assert (isnai (infsupdec ("[nai]"))); # quiet [NaI] %!assert (isnai (infsupdec (" [ nai ] "))); # quiet [NaI] %!assert (isnai (infsupdec ({0, "[nai]"})), [false, true]); # quiet [NaI] %!warning id=interval:UndefinedOperation %! assert (isnai (infsupdec (3, 2))); # illegal boundaries %!warning id=interval:UndefinedOperation %! assert (isnai (infsupdec (inf, -inf))); # illegal boundaries %!warning id=interval:UndefinedOperation %! assert (isnai (infsupdec ("Flugeldufel"))); # illegal literal %!warning id=interval:UndefinedOperation %! assert (isnai (infsupdec ("[1, Inf]_com"))); # illegal decorated literal %!warning id=interval:UndefinedOperation %! assert (isnai (infsupdec ("[Empty]_def"))); # illegal decorated literal %!# decoration adjustments, setDec function %!test %! x = infsupdec (42, inf, "com"); %! assert (inf (x), 42); %! assert (sup (x), inf); %! assert (decorationpart (x), {"dac"}); %!test %! x = infsupdec (-inf, inf, {"com"}); %! assert (inf (x), -inf); %! assert (sup (x), inf); %! assert (decorationpart (x), {"dac"}); %!test %! x = infsupdec ("def"); %! assert (inf (x), inf); %! assert (sup (x), -inf); %! assert (decorationpart (x), {"trv"}); %!# overflow %!test %! x = infsupdec ("[1, 1e999]_com"); %! assert (inf (x), 1); %! assert (sup (x), inf); %! assert (decorationpart (x), {"dac"}); %!# decorated interval literal %!test %! x = infsupdec ("[2, 3]_def"); %! assert (inf (x), 2); %! assert (sup (x), 3); %! assert (decorationpart (x), {"def"}); %!test %! x = infsupdec ("[1, 5]_dac"); %! assert (inf (x), 1); %! assert (sup (x), 5); %! assert (decorationpart (x), {"dac"}); %!test %! x = infsupdec ("[1, Infinity]_dac"); %! assert (inf (x), 1); %! assert (sup (x), inf); %! assert (decorationpart (x), {"dac"}); %!test %! x = infsupdec ("[Empty]_trv"); %! assert (inf (x), inf); %! assert (sup (x), -inf); %! assert (decorationpart (x), {"trv"}); %!# automatic decoration / undecorated interval literal / newDec function %!test %! x = infsupdec ("[2, 3]"); %! assert (inf (x), 2); %! assert (sup (x), 3); %! assert (decorationpart (x), {"com"}); %!test %! x = infsupdec ("[Empty]"); %! assert (inf (x), inf); %! assert (sup (x), -inf); %! assert (decorationpart (x), {"trv"}); %!test %! x = infsupdec ("[Entire]"); %! assert (inf (x), -inf); %! assert (sup (x), inf); %! assert (decorationpart (x), {"dac"}); %!test %! x = infsupdec (""); %! assert (inf (x), -inf); %! assert (sup (x), inf); %! assert (decorationpart (x), {"dac"}); %!# separate decoration information %!test %! x = infsupdec ("[2, 3]", "def"); %! assert (inf (x), 2); %! assert (sup (x), 3); %! assert (decorationpart (x), {"def"}); %!# cell array with decorated interval literals %!test %! x = infsupdec ({"[2, 3]_def", "[4, 5]_dac"}); %! assert (inf (x), [2, 4]); %! assert (sup (x), [3, 5]); %! assert (decorationpart (x), {"def", "dac"}); %!#cell array with separate decoration cell array %!test %! x = infsupdec ({"[2, 3]", "[4, 5]"}, {"def", "dac"}); %! assert (inf (x), [2, 4]); %! assert (sup (x), [3, 5]); %! assert (decorationpart (x), {"def", "dac"}); %!# cell array with separate decoration vector %!test %! x = infsupdec ({"[2, 3]"; "[4, 5]"}, ["def"; "dac"]); %! assert (inf (x), [2; 4]); %! assert (sup (x), [3; 5]); %! assert (decorationpart (x), {"def"; "dac"}); %!# cell array with broadcasting decoration %!test %! x = infsupdec ({"[2, 3]", "[4, 5]"}, "def"); %! assert (inf (x), [2, 4]); %! assert (sup (x), [3, 5]); %! assert (decorationpart (x), {"def", "def"}); %!test %! x = infsupdec ({"[2, 3]", "[4, 5]"}, "def; dac"); %! assert (inf (x), [2, 4; 2, 4]); %! assert (sup (x), [3, 5; 3, 5]); %! assert (decorationpart (x), {"def", "def"; "dac", "dac"}); %!# separate boundaries with decoration %!test %! x = infsupdec (2, 3, "def"); %! assert (inf (x), 2); %! assert (sup (x), 3); %! assert (decorationpart (x), {"def"}); %!# matrix boundaries with decoration %!test %! x = infsupdec ([3, 16], {"def", "trv"}); %! assert (inf (x), [3, 16]); %! assert (sup (x), [3, 16]); %! assert (decorationpart (x), {"def", "trv"}); %!# separate matrix boundaries with broadcasting decoration %!test %! x = infsupdec (magic (3), magic (3) + 1, "def"); %! assert (inf (x), magic (3)); %! assert (sup (x), magic (3) + 1); %! assert (decorationpart (x), {"def", "def", "def"; "def", "def", "def"; "def", "def", "def"}); %!# N-dimensional arrays %!test %! x = infsupdec (zeros (2, 2, 2)); %! assert (x.inf, zeros (2, 2, 2)); %! assert (x.sup, zeros (2, 2, 2)); %! assert (decorationpart (x), repmat ({"com"}, [2, 2, 2])); %!test %! x = infsupdec (zeros (2, 2, 2), ones (2, 2, 2), repmat ({"trv"}, [2, 2, 2])); %! assert (x.inf, zeros (2, 2, 2)); %! assert (x.sup, ones (2, 2, 2)); %! assert (decorationpart (x), repmat ({"trv"}, [2, 2, 2])); %!test %! x = infsupdec (zeros (1, 1, 2), ones (1, 2, 1), {"trv"; "trv"}); %! assert (x.inf, zeros (2, 2, 2)); %! assert (x.sup, ones (2, 2, 2)); %! assert (decorationpart (x), repmat ({"trv"}, [2, 2, 2])); %!test %! c1 = reshape ({1, 2, 3, 4, 5, 6, 7, 8}, 2, 2, 2); %! c2 = reshape ({2, 3, 4, 5, 6, 7, 8, 9}, 2, 2, 2); %! decpart = reshape ({"trv", "def", "dac", "com", "trv", "def", "dac", "com"}, 2, 2, 2); %! x = infsupdec (c1, c2, decpart); %! assert (x.inf, reshape (1:8, 2, 2, 2)); %! assert (x.sup, reshape (2:9, 2, 2, 2)); %! assert (decorationpart (x), decpart) %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsup.setDec; %! for testcase = [testcases]' %! assert (isequaln (... %! infsupdec (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsup.setDec; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (infsupdec (in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.("d-numsToInterval"); %! for testcase = [testcases]' %! assert (isequaln (... %! infsupdec (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.("d-numsToInterval"); %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (infsupdec (in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.("d-textToInterval"); %! for testcase = [testcases]' %! assert (isequaln (... %! infsupdec (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.("d-textToInterval"); %! in1 = vertcat (testcases.in); %! out = vertcat (testcases.out); %! assert (isequaln (infsupdec (in1), out)); %!warning %! testcases = testdata.PossiblyUndefinedOperation.infsupdec.("d-textToInterval"); %! for testcase = [testcases]' %! lastwarn ("", ""); %! assert (isequaln (... %! infsupdec (testcase.in{1}), ... %! testcase.out)); %! assert (nthargout (2, @lastwarn), "interval:PossiblyUndefinedOperation"); %! endfor %!warning %! testcases = testdata.UndefinedOperation.infsupdec.("d-textToInterval"); %! for testcase = [testcases]' %! lastwarn ("", ""); %! assert (isequaln (... %! infsupdec (testcase.in{1}), ... %! testcase.out)); %! assert (nthargout (2, @lastwarn), "interval:UndefinedOperation"); %! endfor %!warning %! testcases = testdata.UndefinedOperation.infsupdec.("d-numsToInterval"); %! for testcase = [testcases]' %! lastwarn ("", ""); %! assert (isequaln (... %! infsupdec (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! assert (nthargout (2, @lastwarn), "interval:UndefinedOperation"); %! endfor %!warning %! testcases = testdata.UndefinedOperation.infsup.setDec; %! for testcase = [testcases]' %! lastwarn ("", ""); %! assert (isequaln (... %! infsupdec (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! assert (nthargout (2, @lastwarn), "interval:UndefinedOperation"); %! endfor %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.("d-numsToInterval"); %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (infsupdec (in1, in2), out)); interval-3.2.0/inst/@infsupdec/interior.m0000644000000000000000000000546213316017127016544 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} interior (@var{A}, @var{B}) ## ## Evaluate interior comparison on intervals. ## ## True, if all numbers from @var{A} are also contained in @var{B}, but are no ## boundaries of @var{B}. False, if @var{A} contains a number which is not a ## member in @var{B} or which is a boundary of @var{B}. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsupdec/eq, @@infsupdec/subset, @@infsupdec/disjoint} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = interior (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = interior (a.infsup, b.infsup); result(isnai (a) | isnai (b)) = false; endfunction %!assert (interior (infsupdec (1, 2), infsupdec (0, 3))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.interior; %! for testcase = [testcases]' %! assert (isequaln (... %! interior (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.interior; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (interior (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.interior; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (interior (in1, in2), out)); interval-3.2.0/inst/@infsupdec/intersect.m0000644000000000000000000000732413316017127016710 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} intersect (@var{A}) ## @defmethodx {@@infsupdec} intersect (@var{A}, @var{B}) ## @defmethodx {@@infsupdec} intersect (@var{A}, [], @var{DIM}) ## ## Intersect intervals. ## ## With two arguments the intersection is built pair-wise. Otherwise the ## intersection is computed for all interval members along dimension @var{DIM}, ## which defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## The function is a set operation and the result carries the @code{trv} ## decoration at best. ## ## @example ## @group ## x = infsupdec (1, 3); ## y = infsupdec (2, 4); ## intersect (x, y) ## @result{} ans = [2, 3]_trv ## @end group ## @end example ## @seealso{@@infsupdec/union, @@infsupdec/setdiff, @@infsupdec/setxor} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = intersect (a, b, dim) if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif switch (nargin) case 1 result = infsupdec (intersect (a.infsup), "trv"); result.dec = min (result.dec, min (a.dec)); case 2 if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = infsupdec (intersect (a.infsup, b.infsup), "trv"); warning ("off", "Octave:broadcast", "local"); result.dec = min (result.dec, min (a.dec, b.dec)); case 3 if (not (builtin ("isempty", b))) warning ("intersect: second argument is ignored"); endif result = infsupdec (intersect (a.infsup, [], dim), "trv"); result.dec = min (result.dec, min (a.dec, [], dim)); otherwise print_usage (); return endswitch endfunction %!# from the documentation string %!assert (isequal (intersect (infsupdec (1, 3), infsupdec (2, 4)), infsupdec (2, 3, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.intersection; %! for testcase = [testcases]' %! assert (isequaln (... %! intersect (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.intersection; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (intersect (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.intersection; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (intersect (in1, in2), out)); interval-3.2.0/inst/@infsupdec/intervalpart.m0000644000000000000000000000524613316017127017424 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{S} =} intervalpart (@var{X}) ## ## Return the bare interval for the decorated interval @var{X}. ## ## @seealso{@@infsupdec/decorationpart} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-12 function bare = intervalpart (x) if (nargin ~= 1) print_usage (); return endif if (any (isnai (x)(:))) warning ("interval:IntvlPartOfNaI", ... "intervalpart: NaI has no interval part") endif bare = x.infsup; endfunction %!warning id=interval:IntvlPartOfNaI %! assert (intervalpart (nai ()) == infsup ()); %!assert (intervalpart (infsupdec (2, 3)) == infsup (2, 3)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.intervalPart; %! for testcase = [testcases]' %! assert (isequaln (... %! intervalpart (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.intervalPart; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (intervalpart (in1), out)); %!warning %! testcases = testdata.IntvlPartOfNaI.infsupdec.intervalPart; %! for testcase = [testcases]' %! lastwarn ("", ""); %! assert (isequaln (... %! intervalpart (testcase.in{1}), ... %! testcase.out)); %! assert (nthargout (2, @lastwarn), "interval:IntvlPartOfNaI"); %! endfor %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.intervalPart; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (intervalpart (in1), out)); interval-3.2.0/inst/@infsupdec/isempty.m0000644000000000000000000000457313316017127016405 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} isempty (@var{X}) ## ## Check if the interval represents the empty set. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## Warning: This function is not compatible with the builtin @code{isempty} ## function. ## ## @seealso{@@infsupdec/eq, @@infsupdec/isentire, @@infsupdec/issingleton} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = isempty (x) if (nargin ~= 1) print_usage (); return endif result = isempty (x.infsup); result(isnai (x)) = false; endfunction %!assert (isempty (infsupdec ())); %!assert (not (isempty (infsupdec (1, 2)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.isEmpty; %! for testcase = [testcases]' %! assert (isequaln (... %! isempty (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.isEmpty; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (isempty (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.isEmpty; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (isempty (in1), out)); interval-3.2.0/inst/@infsupdec/isnai.m0000644000000000000000000000453713316017127016016 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} isnai (@var{X}) ## ## Check if the interval is the result of a failed interval construction. ## ## @seealso{@@infsupdec/eq, @@infsupdec/isentire, @@infsupdec/issingleton, @@infsupdec/isempty} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = isnai (interval) if (nargin ~= 1) print_usage (); return endif ## NaI is internally stored as an empty interval with ill decoration. result = (interval.dec == _ill ()); endfunction %!assert (isnai (infsupdec ("[nai]"))); %!assert (not (isnai (infsupdec (2, 3)))); %!warning assert (isnai (infsupdec ("happy 42 hacking")), logical ([1 0 1])); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.isNaI; %! for testcase = [testcases]' %! assert (isequaln (... %! isnai (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.isNaI; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (isnai (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.isNaI; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (isnai (in1), out)); interval-3.2.0/inst/@infsupdec/le.m0000644000000000000000000000552013316017127015304 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} le (@var{A}, @var{B}) ## @defopx Operator {@@infsupdec} {@var{A} <= @var{B}} ## ## Compare intervals @var{A} and @var{B} for weakly less. ## ## True, if all numbers from @var{A} are weakly less than any number in ## @var{B}. False, if @var{A} contains a number which is strictly greater than ## all numbers in @var{B}. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsupdec/eq, @@infsupdec/lt, @@infsupdec/ge, @@infsupdec/subset, @@infsupdec/interior, @@infsupdec/disjoint} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = le (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = le (a.infsup, b.infsup); result (isnai (a) | isnai (b)) = false; endfunction %!assert (le (infsupdec (1, 3), infsupdec (3))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.less; %! for testcase = [testcases]' %! assert (isequaln (... %! le (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.less; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (le (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.less; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (le (in1, in2), out)); interval-3.2.0/inst/@infsupdec/linspace.m0000644000000000000000000000426613316017127016510 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} linspace (@var{BASE}, @var{LIMIT}) ## @defmethodx {@@infsupdec} linspace (@var{BASE}, @var{LIMIT}, @var{N}) ## ## Return a row vector of @var{N} linearly spaced members between @var{BASE} ## and @var{LIMIT}. ## ## If @var{BASE} is greater than @var{LIMIT}, members are returned in ## decreasing order. The default value for @var{N} is 100. ## ## If either @var{BASE} or @var{LIMIT} is not a scalar, the result is a matrix. ## ## Accuracy: The result is an accurate enclosure. ## ## @example ## @group ## transpose (linspace (infsupdec (0), infsupdec (10), 4)) ## @result{} ans ⊂ 4×1 interval vector ## ## [0]_com ## [3.3333, 3.3334]_com ## [6.6666, 6.6667]_com ## [10]_com ## @end group ## @end example ## @seealso{linspace} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-07-19 function result = linspace (base, limit, n) if (nargin < 2 || nargin > 3) print_usage (); return endif if (not (isa (base, "infsupdec"))) base = infsupdec (base); endif if (not (isa (limit, "infsupdec"))) limit = infsupdec (limit); endif if (nargin < 3) n = 100; endif result = newdec (linspace (base.infsup, limit.infsup, n)); ## linspace is defined and continuous everywhere result.dec = min (result.dec, min (base.dec, limit.dec)); endfunction %!assert (isequal (linspace (infsupdec (0), infsupdec (10), 9), infsupdec (linspace (0, 10, 9)))); interval-3.2.0/inst/@infsupdec/log.m0000644000000000000000000000512713316017127015470 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} log (@var{X}) ## ## Compute the natural logarithm. ## ## The function is only defined where @var{X} is positive. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## log (infsupdec (2)) ## @result{} ans ⊂ [0.69314, 0.69315]_com ## @end group ## @end example ## @seealso{@@infsupdec/exp, @@infsupdec/log2, @@infsupdec/log10} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = log (x) if (nargin ~= 1) print_usage (); return endif result = newdec (log (x.infsup)); ## log is continuous everywhere, but defined for x > 0 only persistent domain_hull = infsup (0, inf); result.dec(not (interior (x.infsup, domain_hull))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (log (infsupdec (2)), infsupdec ("[0x1.62E42FEFA39EFp-1, 0x1.62E42FEFA39Fp-1]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.log; %! for testcase = [testcases]' %! assert (isequaln (... %! log (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.log; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (log (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.log; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (log (in1), out)); interval-3.2.0/inst/@infsupdec/log10.m0000644000000000000000000000517213316017127015631 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} log10 (@var{X}) ## ## Compute the decimal (base-10) logarithm. ## ## The function is only defined where @var{X} is positive. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## log10 (infsupdec (2)) ## @result{} ans ⊂ [0.30102, 0.30103]_com ## @end group ## @end example ## @seealso{@@infsupdec/pow10, @@infsupdec/log, @@infsupdec/log2} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = log10 (x) if (nargin ~= 1) print_usage (); return endif result = newdec (log10 (x.infsup)); ## log10 is continuous everywhere, but defined for x > 0 only persistent domain_hull = infsup (0, inf); result.dec(not (interior (x.infsup, domain_hull))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (log10 (infsupdec (2)), infsupdec ("[0x1.34413509F79FEp-2, 0x1.34413509F79FFp-2]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.log10; %! for testcase = [testcases]' %! assert (isequaln (... %! log10 (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.log10; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (log10 (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.log10; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (log10 (in1), out)); interval-3.2.0/inst/@infsupdec/log1p.m0000644000000000000000000000327513316017127015733 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} log1p (@var{X}) ## ## Compute @code{log (1 + @var{X})} accurately in the neighborhood of zero. ## ## The function is only defined where @var{X} is greater than -1. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## log1p (infsupdec (eps)) ## @result{} ans ⊂ [2.2204e-16, 2.2205e-16]_com ## @end group ## @end example ## @seealso{@@infsup/exp, @@infsup/log} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-20 function result = log1p (x) if (nargin ~= 1) print_usage (); return endif result = newdec (log1p (x.infsup)); ## log1p is continuous everywhere, but defined for x > -1 only persistent domain_hull = infsup (-1, inf); result.dec(not (interior (x.infsup, domain_hull))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (log1p (infsupdec (eps)), infsupdec ("[0x1.FFFFFFFFFFFFFp-53, 0x1p-52]"))); interval-3.2.0/inst/@infsupdec/log2.m0000644000000000000000000000505613316017127015553 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} log2 (@var{X}) ## ## Compute the binary (base-2) logarithm. ## ## The function is only defined where @var{X} is positive. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## log2 (infsupdec (2)) ## @result{} ans = [1]_com ## @end group ## @end example ## @seealso{@@infsupdec/pow2, @@infsupdec/log, @@infsupdec/log10} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-04 function result = log2 (x) if (nargin ~= 1) print_usage (); return endif result = newdec (log2 (x.infsup)); ## log2 is continuous everywhere, but defined for x > 0 only persistent domain_hull = infsup (0, inf); result.dec(not (interior (x.infsup, domain_hull))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (log2 (infsupdec (2)), infsupdec (1))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.log2; %! for testcase = [testcases]' %! assert (isequaln (... %! log2 (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.log2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (log2 (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.log2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (log2 (in1), out)); interval-3.2.0/inst/@infsupdec/lt.m0000644000000000000000000000571113316017127015325 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} lt (@var{A}, @var{B}) ## @defopx Operator {@@infsupdec} {@var{A} < @var{B}} ## ## Compare intervals @var{A} and @var{B} for strictly less. ## ## True, if all numbers from @var{A} are strict less than at least one number ## in @var{B}. False, if @var{A} contains a number which is greater than all ## numbers in @var{B} or is equal to the greatest number of @var{B}. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsupdec/eq, @@infsupdec/le, @@infsupdec/gt, @@infsupdec/subset, @@infsupdec/interior, @@infsupdec/disjoint} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = lt (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = lt (a.infsup, b.infsup); result(isnai (a) | isnai (b)) = false; endfunction %!assert (not (lt (infsupdec (1, 3), infsupdec (3)))); %!assert (lt (infsupdec (1, 3), infsupdec (3.1))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.strictLess; %! for testcase = [testcases]' %! assert (isequaln (... %! lt (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.strictLess; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (lt (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.strictLess; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (lt (in1, in2), out)); interval-3.2.0/inst/@infsupdec/lu.m0000644000000000000000000000462113316017127015325 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {[@var{L}, @var{U}] = } lu (@var{A}) ## @deftypemethodx {@@infsupdec} {[@var{L}, @var{U}, @var{P}] = } lu (@var{A}) ## ## Compute the LU decomposition of @var{A}. ## ## @var{A} will be a subset of @var{L} * @var{U} with lower triangular matrix ## @var{L} and upper triangular matrix @var{U}. ## ## The result is returned in a permuted form, according to the optional return ## value @var{P}. ## ## Accuracy: The result is a valid enclosure. ## @seealso{@infsup/qr} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-18 function [L, U, P] = lu (x) if (nargin ~= 1) print_usage (); return endif P = eye (size (x.dec)); if (isnai (x)) L = U = nai (); return endif if (nargout >= 3) [L, U, P] = lu (x.infsup); else [L, U] = lu (x.infsup); endif ## Reverse operations should not carry decoration L = infsupdec (L, "trv"); U = infsupdec (U, "trv"); endfunction %!test %! [l, u] = lu (infsupdec (magic (3))); %! assert (isequal (l, infsupdec ({1, 0, 0; .375, 1, 0; .5, "68/37", 1}, "trv")));, ... %! assert (subset (u, infsupdec ({8, 1, 6; 0, 4.625, 4.75; 0, 0, "-0x1.3759F2298375Bp3"}, ... %! {8, 1, 6; 0, 4.625, 4.75; 0, 0, "-0x1.3759F22983759p3"}))); %! A = magic (3); %! A ([1, 5, 9]) = 0; %! [l, u, p] = lu (infsupdec (A)); %! assert (p, [0, 0, 1; 1, 0, 0; 0, 1, 0]); %! assert (isequal (l, infsupdec ({1, 0, 0; "4/3", 1, 0; 0, "1/9", 1}, "trv"))); %! assert (subset (u, infsupdec ({3, 0, 7; 0, 9, "-0x1.2AAAAAAAAAAACp3"; 0, 0, "0x1.C25ED097B425Ep2"}, ... %! {3, 0, 7; 0, 9, "-0x1.2AAAAAAAAAAAAp3"; 0, 0, "0x1.C25ED097B426p2"}))); interval-3.2.0/inst/@infsupdec/max.m0000644000000000000000000000735113316017127015475 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} max (@var{X}) ## @defmethodx {@@infsupdec} max (@var{X}, @var{Y}) ## @defmethodx {@@infsupdec} max (@var{X}, [], @var{DIM}) ## ## Compute the maximum value chosen from intervals. ## ## This function does not return the greatest element of the interval (see ## @code{sup}), but returns an interval enclosure of the function: ## @display ## max (@var{x}, @var{y}) = ( (x + y) + abs (x - y) ) / 2 ## @end display ## ## With two arguments the function is applied element-wise. Otherwise the ## maximum is computed for all interval members along dimension @var{DIM}, ## which defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsupdec (2, 3); ## y = infsupdec (1, 2); ## max (x, y) ## @result{} ans = [2, 3]_com ## @end group ## @end example ## @seealso{@@infsupdec/min} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = max (x, y, dim) if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif switch (nargin) case 1 bare = max (x.infsup); case 2 if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif bare = max (x.infsup, y.infsup); case 3 if (not (builtin ("isempty", y))) warning ("max: second argument is ignored"); endif bare = max (x.infsup, [], dim); otherwise print_usage (); return endswitch result = newdec (bare); ## max is defined and continuous everywhere switch (nargin) case 1 result.dec = min (result.dec, min (x.dec)); case 2 warning ("off", "Octave:broadcast", "local"); result.dec = min (result.dec, min (x.dec, y.dec)); case 3 result.dec = min (result.dec, min (x.dec, [], dim)); endswitch endfunction %!# from the documentation string %!assert (isequal (max (infsupdec (2, 3), infsupdec (1, 2)), infsupdec (2, 3))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.max; %! for testcase = [testcases]' %! assert (isequaln (... %! max (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.max; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (max (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.max; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (max (in1, in2), out)); interval-3.2.0/inst/@infsupdec/min.m0000644000000000000000000000734613316017127015477 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} min (@var{X}) ## @defmethodx {@@infsupdec} min (@var{X}, @var{Y}) ## @defmethodx {@@infsupdec} min (@var{X}, [], @var{DIM}) ## ## Compute the minimum value chosen from intervals. ## ## This function does not return the least element of the interval (see ## @code{inf}), but returns an interval enclosure of the function: ## @display ## min (@var{x}, @var{y}) = ( (x + y) - abs (x - y) ) / 2 ## @end display ## ## With two arguments the function is applied element-wise. Otherwise the ## minimum is computed for all interval members along dimension @var{DIM}, ## which defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsupdec (2, 3); ## y = infsupdec (1, 2); ## min (x, y) ## @result{} ans = [1, 2]_com ## @end group ## @end example ## @seealso{@@infsupdec/max} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = min (x, y, dim) if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif switch (nargin) case 1 bare = min (x.infsup); case 2 if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif bare = min (x.infsup, y.infsup); case 3 if (not (builtin ("isempty", y))) warning ("min: second argument is ignored"); endif bare = min (x.infsup, [], dim); otherwise print_usage (); return endswitch result = newdec (bare); ## min is defined and continuous everywhere switch (nargin) case 1 result.dec = min (result.dec, min (x.dec)); case 2 warning ("off", "Octave:broadcast", "local"); result.dec = min (result.dec, min (x.dec, y.dec)); case 3 result.dec = min (result.dec, min (x.dec, [], dim)); endswitch endfunction %!# from the documentation string %!assert (isequal (min (infsupdec (2, 3), infsupdec (1, 2)), infsupdec (1, 2))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.min; %! for testcase = [testcases]' %! assert (isequaln (... %! min (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.min; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (min (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.min; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (min (in1, in2), out)); interval-3.2.0/inst/@infsupdec/mince.m0000644000000000000000000000356313316017127016004 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} mince (@var{X}) ## @defmethodx {@@infsupdec} mince (@var{X}, @var{N}) ## ## Mince interval @var{X} into a row vector of @var{N} sub-intervals of equal ## size. ## ## The sub-intervals are returned in ascending order and may overlap due to ## round-off errors. ## ## If @var{X} is not a scalar, the result is a matrix. The default value for ## @var{N} is 100. ## ## Accuracy: The result is an accurate enclosure. ## ## @example ## @group ## mince (infsupdec (0, 10), 4) ## @result{} ans = 1×4 interval vector ## ## [0, 2.5]_trv [2.5, 5]_trv [5, 7.5]_trv [7.5, 10]_trv ## @end group ## @end example ## @seealso{@@infsupdec/linspace, @@infsupdec/bisect} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-07-19 function result = mince (x, n) if (nargin > 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (nargin < 2) n = 100; endif result = infsupdec (mince (x.infsup, n), "trv"); result.dec = min (result.dec, x.dec); endfunction %!assert (isequal (mince (infsupdec (0, 10), 10), infsupdec (0 : 9, 1 : 10, "trv"))); interval-3.2.0/inst/@infsupdec/minus.m0000644000000000000000000000546113316017127016043 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} minus (@var{X}, @var{Y}) ## @defopx Operator {@@infsupdec} {@var{X} - @var{Y}} ## ## Subtract all numbers of interval @var{Y} from all numbers of @var{X}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsupdec (2, 3); ## y = infsupdec (1, 2); ## x - y ## @result{} ans = [0, 2]_com ## @end group ## @end example ## @seealso{@@infsupdec/plus} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = minus (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif result = newdec (minus (x.infsup, y.infsup)); ## minus is defined and continuous everywhere result.dec = min (result.dec, min (x.dec, y.dec)); endfunction %!# from the documentation string %!assert (isequal (infsupdec (2, 3) - infsupdec (1, 2), infsupdec (0, 2))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sub; %! for testcase = [testcases]' %! assert (isequaln (... %! minus (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sub; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (minus (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.sub; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (minus (in1, in2), out)); interval-3.2.0/inst/@infsupdec/mldivide.m0000644000000000000000000000400413316017127016475 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} mldivide (@var{X}, @var{Y}) ## @defopx Operator {@@infsupdec} {@var{X} \ @var{Y}} ## ## Return the interval matrix left division of @var{X} and @var{Y}. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## infsupdec ([1, 0; 0, 2]) \ [2, 0; 0, 4] ## @result{} ans = 2×2 interval matrix ## [2]_trv [0]_trv ## [0]_trv [2]_trv ## @end group ## @end example ## @seealso{@@infsupdec/mtimes} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-01-31 function result = mldivide (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif ## Reverse operations should not carry decoration result = infsupdec (mldivide (x.infsup, y.infsup), "trv"); warning ("off", "Octave:broadcast", "local"); result.dec = min (result.dec, min (vec (min (x.dec, y.dec)))); endfunction %!# unique solution %!assert (isequal (infsupdec ([1, 0; 0, 2]) \ [2, 0; 0, 4], infsupdec ([2, 0; 0 2], "trv"))); %!# no solution %!assert (all (isempty (infsupdec ([1, 0; 2, 0]) \ [3; 0]))); %!# many solutions %!assert (isequal (infsupdec ([1, 0; 2, 0]) \ [4; 8], infsupdec ([4; -inf], [4; inf], "trv"))); interval-3.2.0/inst/@infsupdec/mod.m0000644000000000000000000001702513316017127015466 0ustar 00000000000000## Copyright 2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} mod (@var{X}, @var{Y}) ## ## Compute the modulus of @var{X} and @var{Y}. ## ## Conceptionally, it is given by the expression ## @code{@var{X} - @var{Y} .* floor (@var{X} ./ @var{Y})}. This function is ## undefined for @var{Y} = 0. ## ## @example ## @group ## mod (infsupdec (3), infsupdec (2)) ## @result{} ans = [1]_com ## mod (infsupdec (-3), infsupdec (2)) ## @result{} ans = [1]_com ## @end group ## @end example ## ## Accuracy: The result is a valid enclosure. ## ## @seealso{@@infsupdec/rdivide, @@infsupdec/rem} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2017-10-15 function result = mod (x, y) if (nargin ~= 2) print_usage (); return endif ## Usually, the implementation of an interval arithmetic function is cleanly ## split into a bare and a decorated version. This function's decoration is ## quite complicated to be computed and depends on intermediate values that ## are used to compute the bare interval result. Thus, we get most of the ## decoration information as a second output parameter from @infsup. if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif [bare, d] = mod (x.infsup, y.infsup); result = newdec (bare); result.dec = min (result.dec, min (d, min (x.dec, y.dec))); endfunction %!assert (isequal (mod (infsupdec (), infsupdec ()), infsupdec ())); %!assert (isequal (mod (infsupdec (0), infsupdec ()), infsupdec ())); %!assert (isequal (mod (infsupdec (), infsupdec (0)), infsupdec ())); %!assert (isequal (mod (infsupdec (0), infsupdec (0)), infsupdec ())); %!assert (isequal (mod (infsupdec (1), infsupdec (0)), infsupdec ())); %!assert (isequal (mod (infsupdec (0, 1), infsupdec (0)), infsupdec ())); %!assert (isequal (mod (infsupdec (1, 2), infsupdec (0)), infsupdec ())); %!assert (isequal (mod (infsupdec (0, inf), infsupdec (0)), infsupdec ())); %!assert (isequal (mod (infsupdec (1, inf), infsupdec (0)), infsupdec ())); %!assert (isequal (mod (infsupdec (realmax, inf), infsupdec (0)), infsupdec ())); %!assert (isequal (mod (infsupdec (0), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (0), infsupdec (0, 1)), infsupdec (0, "trv"))); %!assert (isequal (mod (infsupdec (0), infsupdec (1, 2)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (0), infsupdec (0, inf)), infsupdec (0, "trv"))); %!assert (isequal (mod (infsupdec (0), infsupdec (1, inf)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (0), infsupdec (realmax, inf)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (1), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (2), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (4), infsupdec (2)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (6), infsupdec (3)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (8), infsupdec (2)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (9), infsupdec (3)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (realmax), infsupdec (realmax)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (realmax), infsupdec (realmax / 2)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (realmax), infsupdec (realmax / 4)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (realmax), infsupdec (realmax / 8)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (realmax), infsupdec (realmax / 16)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (realmax), infsupdec (realmax / 32)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (0.1), infsupdec (0.1)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (0.1 * 2), infsupdec (0.1)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (0.1 * 4), infsupdec (0.1)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (pi), infsupdec (pi)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (pi), infsupdec (pi / 2)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (pi), infsupdec (pi / 4)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (pow2 (-1074)), infsupdec (pow2 (-1074))), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (pow2 (-1073)), infsupdec (pow2 (-1074))), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (pow2 (-1072)), infsupdec (pow2 (-1074))), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (1), infsupdec (2)), infsupdec (1))); %!assert (isequal (mod (infsupdec (0.5), infsupdec (1)), infsupdec (0.5))); %!assert (isequal (mod (infsupdec (pi), infsupdec (3.15)), infsupdec (pi))); %!assert (isequal (mod (infsupdec (1), infsupdec (2, 3)), infsupdec (1))); %!assert (isequal (mod (infsupdec (1), infsupdec (2, inf)), infsupdec (1, "dac"))); %!assert (isequal (mod (infsupdec (0.5), infsupdec (1, 2)), infsupdec (0.5))); %!assert (isequal (mod (infsupdec (0.5), infsupdec (1, inf)), infsupdec (0.5, "dac"))); %!assert (isequal (mod (infsupdec (pi), infsupdec (3.15)), infsupdec (pi))); %!assert (isequal (mod (infsupdec (pi), infsupdec (3.15, inf)), infsupdec (pi, "dac"))); %!assert (isequal (mod (infsupdec (0, 1), infsupdec (0, 1)), infsupdec (0, 1, "trv"))); %!assert (isequal (mod (infsupdec (0, 2), infsupdec (0, 1)), infsupdec (0, 1, "trv"))); %!assert (isequal (mod (infsupdec (0, 1), infsupdec (0, 2)), infsupdec (0, 1, "trv"))); %!assert (isequal (mod (infsupdec (0, realmax), infsupdec (0, realmax)), infsupdec (0, realmax, "trv"))); %!assert (isequal (mod (infsupdec (realmax, inf), infsupdec (realmax, inf)), infsupdec (0, inf, "def"))); %!assert (isequal (mod (infsupdec (0, inf), infsupdec (0, inf)), infsupdec (0, inf, "trv"))); %!assert (isequal (mod (infsupdec (0), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (1), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (0, 1), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (mod (infsupdec (1, 2), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (mod (infsupdec (0, inf), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (mod (infsupdec (1, inf), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (mod (infsupdec (realmax, inf), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (mod (infsupdec (1), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (mod (infsupdec (1), infsupdec (0, 1)), infsupdec (0, 0.5, "trv"))); %!assert (isequal (mod (infsupdec (1), infsupdec (1, 2)), infsupdec (0, 1, "def"))); %!assert (isequal (mod (infsupdec (1), infsupdec (0, inf)), infsupdec (0, 1, "trv"))); %!assert (isequal (mod (infsupdec (1), infsupdec (1, inf)), infsupdec (0, 1, "def"))); %!assert (isequal (mod (infsupdec (1), infsupdec (2, inf)), infsupdec (1, "dac"))); %!assert (isequal (mod (infsupdec (1), infsupdec (realmax, inf)), infsupdec (1, "dac"))); interval-3.2.0/inst/@infsupdec/mpower.m0000644000000000000000000000506513316017127016221 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsup} mpower (@var{X}, @var{Y}) ## @defopx Operator {@@infsup} {@var{X} ^ @var{Y}} ## ## Return the matrix power operation of @var{X} raised to the @var{Y} power. ## ## If @var{X} is a scalar, this function and @code{power} are equivalent. ## Otherwise, @var{X} must be a square matrix and @var{Y} must be a single ## integer. ## ## Warning: This function is not defined by IEEE Std 1788-2015. ## ## Accuracy: The result is a valid enclosure. The result is tightest for ## @var{Y} in @{0, 1, 2@}. ## ## @example ## @group ## infsupdec (magic (3)) ^ 2 ## @result{} ans = 3×3 interval matrix ## [91]_com [67]_com [67]_com ## [67]_com [91]_com [67]_com ## [67]_com [67]_com [91]_com ## @end group ## @end example ## @seealso{@@infsupdec/pow, @@infsupdec/pown, @@infsupdec/pow2, @@infsupdec/pow10, @@infsupdec/exp} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-01-24 function result = mpower (x, y) if (nargin != 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (isscalar (x.dec)) ## Short-circuit for scalars result = power (x, y); return endif if (not (isreal (y)) || fix (y) ~= y) error ("interval:InvalidOperand", ... "mpower: only integral powers can be computed"); endif result = newdec (mpower (x.infsup, y)); if (y < 0) result.dec(:) = _trv (); elseif (y < 2) result.dec = x.dec; elseif (y == 2) warning ('off', 'Octave:broadcast', 'local'); result.dec = min (result.dec, min (min (x.dec, [], 1), ... min (x.dec, [], 2))); elseif (y > 2) result.dec = min (result.dec, min (vec (x.dec))); endif endfunction %!# from the documentation string %!assert (isequal (infsupdec (magic (3)) ^ 2, infsupdec (magic (3) ^ 2))); interval-3.2.0/inst/@infsupdec/mtimes.m0000644000000000000000000000616613316017127016211 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} mtimes (@var{X}, @var{Y}) ## @defopx Method {@@infsupdec} mtimes (@var{X}, @var{Y}, @var{ACCURACY}) ## @defopx Operator {@@infsupdec} {@var{X} * @var{Y}} ## ## Compute the interval matrix multiplication. ## ## The @var{ACCURACY} can be set to @code{tight} (default) or @code{valid}. ## With @code{valid} accuracy an algorithm for fast matrix multiplication based ## on BLAS routines is used. The latter is published by ## Siegried M. Rump (2012), “Fast interval matrix multiplication,” ## Numerical Algorithms 61(1), 1-34. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsupdec ([1, 2; 7, 15], [2, 2; 7.5, 15]); ## y = infsupdec ([3, 3; 0, 1], [3, 3.25; 0, 2]); ## x * y ## @result{} ans = 2×2 interval matrix ## [3, 6]_com [5, 10.5]_com ## [21, 22.5]_com [36, 54.375]_com ## @end group ## @end example ## @seealso{@@infsupdec/mrdivide} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-21 function result = mtimes (x, y, accuracy) if (nargin < 2 || nargin > 3 || (nargin == 3 && not (ischar (accuracy)))) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif ## null matrix input -> null matrix output if (isempty (x.dec) || isempty (y.dec)) if (size (x.dec, 2) ~= size (y.dec, 1)) error ("interval:InvalidOperand", ... "operator *: nonconformant arguments"); endif result = infsupdec (zeros (rows (x.dec), columns (y.dec))); return endif if (isscalar (x) || isscalar (y)) result = times (x, y); return endif if (nargin == 2) result = newdec (mtimes (x.infsup, y.infsup)); else result = newdec (mtimes (x.infsup, y.infsup, accuracy)); endif dec_x = min (x.dec, [], 2); dec_y = min (y.dec, [], 1); warning ('off', 'Octave:broadcast', 'local'); result.dec = min (result.dec, min (dec_x, dec_y)); endfunction %!assert (isequal (infsupdec ([1, 2; 7, 15], [2, 2; 7.5, 15], {"com", "def"; "dac", "com"}) * infsupdec ([3, 3; 0, 1], [3, 3.25; 0, 2]), infsupdec ([3, 5; 21, 36], [6, 10.5; 22.5, 54.375], {"def", "def"; "dac", "dac"}))); %!# from the documentation string %!assert (isequal (infsupdec ([1, 2; 7, 15], [2, 2; 7.5, 15]) * infsupdec ([3, 3; 0, 1], [3, 3.25; 0, 2]), infsupdec ([3, 5; 21, 36], [6, 10.5; 22.5, 54.375]))); interval-3.2.0/inst/@infsupdec/mulrev.m0000644000000000000000000002055513316017127016223 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} mulrev (@var{B}, @var{C}, @var{X}) ## @deftypemethodx {@@infsupdec} {@var{X} =} mulrev (@var{B}, @var{C}) ## @deftypemethodx {@@infsupdec} {[@var{U}, @var{V}] =} mulrev (@var{B}, @var{C}) ## @deftypemethodx {@@infsupdec} {[@var{U}, @var{V}] =} mulrev (@var{B}, @var{C}, @var{X}) ## ## Compute the reverse multiplication function or the two-output division. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{x .* b ∈ @var{C}} for any @code{b ∈ @var{B}}. ## ## This function is similar to interval division @code{@var{C} ./ @var{B}}. ## However, it treats the case 0/0 as “any real number” instead of “undefined”. ## ## Interval division, considered as a set, can have zero, one or two disjoint ## connected components as a result. If called with two output parameters, ## this function returns the components separately. @var{U} contains the ## negative or unique component, whereas @var{V} contains the positive ## component in cases with two components. ## ## Accuracy: The result is a tight enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## c = infsupdec (1); ## b = infsupdec (-inf, inf); ## [u, v] = mulrev (b, c) ## @result{} ## u = [-inf, 0]_trv ## v = [0, inf]_trv ## @end group ## @end example ## @seealso{@@infsupdec/times} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function [u, v] = mulrev (b, c, x) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) x = infsupdec (-inf, inf); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (nargout < 2) u = mulrev (b.infsup, c.infsup, x.infsup); u = infsupdec (u, "trv"); u.dec(isnai (x) | isnai (b) | isnai (c)) = _ill (); else [u, v] = mulrev (b.infsup, c.infsup, x.infsup); u = newdec (u); u.dec(isempty (b) | isempty (c) | ismember (0, b)) = _trv (); u.dec = min (u.dec, min (b.dec, c.dec)); u.dec(isnai (x)) = _ill (); v = infsupdec (v, "trv"); v.dec(isnai (x) | isnai (b) | isnai (c)) = _ill (); endif endfunction %!# IEEE Std 1788-2015 mulRevToPair examples %!test %! [u, v] = mulrev (infsupdec (0), infsupdec (1, 2)); %! assert (isempty (u) & isempty (v)); %!test %! [u, v] = mulrev (infsupdec (0), infsupdec (0, 1)); %! assert (isentire (u) & isempty (v)); %!test %! [u, v] = mulrev (infsupdec (1), infsupdec (1, 2)); %! assert (isequal (u, infsupdec (1, 2)) & isempty (v)); %!test %! [u, v] = mulrev (infsupdec (1, inf), infsupdec (1)); %! assert (isequal (u, infsupdec (0, 1, "dac")) & isempty (v)); %!test %! [u, v] = mulrev (infsupdec (-1, 1), infsupdec (1, 2)); %! assert (isequal (u, infsupdec (-inf, -1, "trv")) & isequal (v, infsupdec (1, inf, "trv"))); %!test %! [u, v] = mulrev (infsupdec (-inf, inf), infsupdec (1)); %! assert (isequal (u, infsupdec (-inf, 0, "trv")) & isequal (v, infsupdec (0, inf, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.mulRevToPair1; %! for testcase = [testcases]' %! assert (isequaln (... %! nthargout (1, 2, @mulrev, testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.mulRevToPair1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (nthargout (1, 2, @mulrev, in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.mulRevToPair1; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (nthargout (1, 2, @mulrev, in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.mulRevToPair2; %! for testcase = [testcases]' %! assert (isequaln (... %! nthargout (2, @mulrev, testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.mulRevToPair2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (nthargout (2, @mulrev, in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.mulRevToPair2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (nthargout (2, @mulrev, in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.mulRev; %! for testcase = [testcases]' %! assert (isequaln (... %! mulrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.mulRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (mulrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.mulRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mulrev (in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.mulRevTen; %! for testcase = [testcases]' %! assert (isequaln (... %! mulrev (testcase.in{1}, testcase.in{2}, testcase.in{3}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.mulRevTen; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! assert (isequaln (mulrev (in1, in2, in3), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.mulRevTen; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! in3 = reshape ([in3; in3(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (mulrev (in1, in2, in3), out)); interval-3.2.0/inst/@infsupdec/nextout.m0000644000000000000000000000323613316017127016414 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} nextout (@var{X}) ## ## Increases the interval's boundaries in each direction to the next number. ## ## This is the equivalent function to IEEE 754's nextDown and nextUp. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## The function is a set operation and the result carries the @code{trv} ## decoration at best. ## ## @example ## @group ## x = infsupdec (1); ## nextout (x) == infsupdec (1 - eps / 2, 1 + eps) ## @result{} ans = 1 ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-03 function result = nextout (x) if (nargin ~= 1) print_usage (); return endif result = infsupdec (nextout (x.infsup), "trv"); result.dec(isnai (x)) = _ill (); endfunction %!# from the documentation string %!test %! x = nextout (infsupdec (1)); %! assert (inf (x), 1 - eps / 2); %! assert (sup (x), 1 + eps); %! assert (decorationpart (x), {"trv"}); interval-3.2.0/inst/@infsupdec/nthroot.m0000644000000000000000000000421513316017127016401 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} nthroot (@var{X}, @var{N}) ## ## Compute the real n-th root of @var{X}. ## ## Accuracy: The result is a valid enclosure. The result is a tight ## enclosure for @var{n} ≥ -2. The result also is a tight enclosure if the ## reciprocal of @var{n} can be computed exactly in double-precision. ## @seealso{@@infsupdec/pown, @@infsupdec/pownrev, @@infsupdec/realsqrt, @@infsupdec/cbrt} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-20 function result = nthroot (x, n) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif result = newdec (nthroot (intervalpart (x), n)); ## nthroot is continuous everywhere, but not defined everywhere even = mod (n, 2) == 0; defined = (not (even) & (n > 0 | inf (x) > 0 | sup (x) < 0)) ... | (even & ((n > 0 & inf (x) >= 0)| (n < 0 & inf (x) > 0))); result.dec(not (defined)) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!assert (isequal (nthroot (infsupdec (25, 36), 2), infsupdec (5, 6))); %!assert (isequal (nthroot (infsupdec (-1, 1), 2), infsupdec (0, 1, "trv"))); %!assert (isequal (nthroot (infsupdec (-1, 1), 3), infsupdec (-1, 1))); %!assert (isequal (nthroot (infsupdec (-1, 1), -2), infsupdec (1, inf, "trv"))); %!assert (isequal (nthroot (infsupdec (-1, 1), -3), infsupdec (-inf, inf, "trv"))); interval-3.2.0/inst/@infsupdec/overlap.m0000644000000000000000000001072713316017127016361 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {[@var{STATE}, @var{BITMASK}] =} overlap(@var{A}, @var{B}) ## ## Extensively compare the positions of intervals @var{A} and @var{B} on the ## real number line. ## ## Return the @var{STATE} as a string and the @var{BITMASK} of the state as an ## uint16 number, which represents one of the 16 possible states by taking a ## value 2^i (i = 0 … 15). ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @table @asis ## @item @code{bothEmpty}, 2^0 ## Both intervals are empty ## @item @code{firstEmpty}, 2^1 ## Interval @var{A} is empty and @var{B} is not ## @item @code{secondEmpty}, 2^2 ## Interval @var{A} is not empty, but @var{B} is ## @item @code{before}, 2^3 ## [- - - @var{A} - - -]@ @ @ [- - - @var{B} - - -] ## @item @code{meets}, 2^4 ## [- - - @var{A} - - -][- - - @var{B} - - -] ## @*Interval @var{A}'s upper boundary equals interval @var{B}'s lower boundary ## and neither consists of a single point only. ## @item @code{overlaps}, 2^5 ## [- - - @var{A} - - - [= = =] - - - @var{B} - - -] ## @item @code{starts}, 2^6 ## [[= = = @var{A} = = =] - - - @var{B} - - -] ## @item @code{containedBy}, 2^7 ## [- - - @var{B} - - - [= = = @var{A} = = =] - - -] ## @item @code{finishes}, 2^8 ## [- - - @var{B} - - - [= = = @var{A} = = =]] ## @item @code{equals}, 2^9 ## Both intervals are equal (and not empty) ## @item @code{finishedBy}, 2^10 ## [- - - @var{A} - - - [= = = @var{B} = = =]] ## @item @code{contains}, 2^11 ## [- - - @var{A} - - - [= = = @var{B} = = =] - - -] ## @item @code{startedBy}, 2^12 ## [[= = = @var{B} = = =] - - - @var{A} - - -] ## @item @code{overlappedBy}, 2^13 ## [- - - @var{B} - - - [= = =] - - - @var{A} - - -] ## @item @code{metBy}, 2^14 ## [- - - @var{B} - - -][- - - @var{A} - - -] ## @*Interval @var{A}'s lower boundary equals interval @var{B}'s upper boundary ## and neither consists of a single point only. ## @item @code{after}, 2^15 ## [- - - @var{B} - - -]@ @ @ [- - - @var{A} - - -] ## @end table ## ## @seealso{@@infsupdec/eq, @@infsupdec/subset, @@infsupdec/interior, @@infsupdec/disjoint} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function [state, bitmask] = overlap (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif if (isnai (a) || isnai (b)) error ("interval:InvalidOperand", "interval comparison with NaI") endif [state, bitmask] = overlap (a.infsup, b.infsup); endfunction %!assert (overlap (infsupdec (1, 2), infsupdec (3, 4)), "before"); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.overlap; %! for testcase = [testcases]' %! assert (isequaln (... %! overlap (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.overlap; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = {testcases.out}'; %! assert (isequaln (overlap (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.overlap; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = {testcases.out}'; %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (overlap (in1, in2), out)); interval-3.2.0/inst/@infsupdec/plus.m0000644000000000000000000000544413316017127015674 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} plus (@var{X}, @var{Y}) ## @defopx Operator {@@infsupdec} {@var{X} + @var{Y}} ## ## Add all numbers of interval @var{X} to all numbers of @var{Y}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsupdec (2, 3); ## y = infsupdec (1, 2); ## x + y ## @result{} ans = [3, 5]_com ## @end group ## @end example ## @seealso{@@infsupdec/minus} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = plus (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif result = newdec (plus (x.infsup, y.infsup)); ## plus is continuous and defined everywhere result.dec = min (result.dec, min (x.dec, y.dec)); endfunction %!# from the documentation string %!assert (isequal (infsupdec (2, 3) + infsupdec (1, 2), infsupdec (3, 5))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.add; %! for testcase = [testcases]' %! assert (isequaln (... %! plus (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.add; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (plus (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.add; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (plus (in1, in2), out)); interval-3.2.0/inst/@infsupdec/polyval.m0000644000000000000000000000402013316017127016364 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} polyval (@var{P}, @var{X}) ## ## Evaluate polynomial @var{P} with argument @var{X}. ## ## Horner's scheme is used to evaluate a first approximation. The result is ## improved with iterative refinement. ## ## Accuracy: The result is a tight enclosure for polynomials of degree 1 or ## less. For polynomials of higher degree the result is a valid enclosure. ## For @var{X} being no singleton interval, the algorithm suffers from the ## dependency problem. ## ## @example ## @group ## output_precision (16, 'local') ## polyval (infsupdec ([3 4 2 1]), 42) # 3x^3 + 4x^2 + 2x^1 + 1 | x = 42 ## @result{} [229405]_com ## polyval (infsupdec ([3 4 2 1]), "42?") # ... | x = 41.5 .. 42.5 ## @result{} [221393.125, 237607.875]_com ## @end group ## @end example ## @seealso{@@infsup/fzero} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-05-30 function result = polyval (p, x) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (p, "infsupdec"))) p = infsupdec (p); endif result = newdec (polyval (p.infsup, x.infsup)); result.dec = min (result.dec, min (min (p.dec), x.dec)); endfunction %!assert (isequal (polyval (infsupdec (3, "trv"), 0), infsupdec (3, "trv"))); interval-3.2.0/inst/@infsupdec/postpad.m0000644000000000000000000000552413316017127016362 0ustar 00000000000000## Copyright 2015-2017 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} postpad (@var{X}, @var{L}) ## @defmethodx {@@infsupdec} postpad (@var{X}, @var{L}, @var{C}) ## @defmethodx {@@infsupdec} postpad (@var{X}, @var{L}, @var{C}, @var{DIM}) ## ## Append the scalar interval value @var{C} to the interval vector @var{X} ## until it is of length @var{L}. If @var{C} is not given, a value of 0 is ## used. ## ## If @code{length (@var{X}) > L}, elements from the end of @var{X} are removed ## until an interval vector of length @var{L} is obtained. ## ## If @var{X} is an interval matrix, elements are appended or removed from each ## row or column. ## ## If the optional argument DIM is given, operate along this dimension. ## ## If DIM is larger than the dimension of X, the result will have DIM ## dimensions. ## ## @example ## @group ## postpad (infsupdec (1 : 3), 5, 42) ## @result{} ans = 1×5 interval vector ## [1]_com [2]_com [3]_com [42]_com [42]_com ## @end group ## @end example ## @seealso{@@infsupdec/reshape, @@infsup/cat, @@infsupdec/prepad, @@infsupdec/resize} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-19 function x = postpad (x, len, c, dim) if (nargin < 2 || nargin > 4) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (nargin < 3) c = infsupdec (0); elseif (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (nargin < 4) dim = find (size (x.dec) ~= 1, 1); if (isempty (dim)) dim = 1; endif endif x.infsup = postpad (x.infsup, len, c.infsup, dim); x.dec = postpad (x.dec, len, c.dec, dim); endfunction %!assert (isequal (postpad (infsupdec (1:3), 4, 4), infsupdec (1:4))); %!assert (isequal (postpad (infsupdec (1:3), 2, 4), infsupdec (1:2))); %!test %! if (compare_versions (OCTAVE_VERSION (), "4.0.0", ">=")) %! assert (isequal (postpad (infsupdec (0), 10, 0, 3), infsupdec (zeros (1, 1, 10)))); %! else %! # In Octave 3.8.x it is not possible to increase the number of dimensions. %! endif %!assert (isequal (postpad (infsupdec (zeros (1, 2, 2)), 3), infsupdec (zeros (1, 3, 2)))); interval-3.2.0/inst/@infsupdec/pow.m0000644000000000000000000000633213316017127015513 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} pow (@var{X}, @var{Y}) ## ## Compute the simple power function on intervals defined by ## @code{exp (@var{Y} * log (@var{X}))}. ## ## The function is only defined where @var{X} is positive or where @var{X} is ## zero and @var{Y} is positive. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## pow (infsupdec (5, 6), infsupdec (2, 3)) ## @result{} ans = [25, 216]_com ## @end group ## @end example ## @seealso{@@infsupdec/pown, @@infsupdec/pow2, @@infsupdec/pow10, @@infsupdec/exp, @@infsupdec/mpower} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = pow (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif result = newdec (pow (x.infsup, y.infsup)); ## pow is continuous everywhere (where it is defined), ## but defined for x > 0 or (x = 0 and y > 0) only persistent nonnegative = infsup (0, inf); domain = interior (x.infsup, nonnegative) | ... (subset (x.infsup, nonnegative) & interior (y.infsup, nonnegative)); result.dec(not (domain)) = _trv (); result.dec = min (result.dec, min (x.dec, y.dec)); endfunction %!# from the documentation string %!assert (isequal (pow (infsupdec (5, 6), infsupdec (2, 3)), infsupdec (25, 216))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.pow; %! for testcase = [testcases]' %! assert (isequaln (... %! pow (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.pow; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (pow (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.pow; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pow (in1, in2), out)); interval-3.2.0/inst/@infsupdec/pow10.m0000644000000000000000000000467013316017127015657 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} pow10 (@var{X}) ## ## Compute @code{10^x} for all numbers in @var{X}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## pow10 (infsupdec (5)) ## @result{} ans = [1e+05]_com ## @end group ## @end example ## @seealso{@@infsupdec/log10, @@infsupdec/pow, @@infsupdec/pow2, @@infsupdec/exp} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = pow10 (x) if (nargin ~= 1) print_usage (); return endif result = newdec (pow10 (x.infsup)); ## pow10 is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (pow10 (infsupdec (5)), infsupdec (100000))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.exp10; %! for testcase = [testcases]' %! assert (isequaln (... %! pow10 (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.exp10; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (pow10 (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.exp10; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2 || i == numel (in1)) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pow10 (in1), out)); interval-3.2.0/inst/@infsupdec/pow2.m0000644000000000000000000000464313316017127015600 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} pow2 (@var{X}) ## ## Compute @code{2^x} for all numbers in @var{X}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## pow2 (infsupdec (5)) ## @result{} ans = [32]_com ## @end group ## @end example ## @seealso{@@infsupdec/log2, @@infsupdec/pow, @@infsupdec/pow10, @@infsupdec/exp} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = pow2 (x) if (nargin ~= 1) print_usage (); return endif result = newdec (pow2 (x.infsup)); ## pow2 is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (pow2 (infsupdec (5)), infsupdec (32))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.exp2; %! for testcase = [testcases]' %! assert (isequaln (... %! pow2 (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.exp2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (pow2 (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.exp2; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2 | i == numel (in1)) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pow2 (in1), out)); interval-3.2.0/inst/@infsupdec/power.m0000644000000000000000000000772113316017127016045 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} power (@var{X}, @var{Y}) ## @defopx Operator {@@infsupdec} {@var{X} .^ @var{Y}} ## ## Compute the general power function on intervals, which is defined for ## (1) any positive base @var{X}; (2) @code{@var{X} = 0} when @var{Y} is ## positive; (3) negative base @var{X} together with integral exponent @var{Y}. ## ## This definition complies with the common complex valued power function, ## restricted to the domain where results are real, plus limit values where ## @var{X} is zero. The complex power function is defined by ## @code{exp (@var{Y} * log (@var{X}))} with initial branch of complex ## logarithm and complex exponential function. ## ## Warning: This function is not defined by IEEE Std 1788-2015. However, it ## has been published as “pow2” in O. Heimlich, M. Nehmeier, J. Wolff von ## Gudenberg. 2013. “Variants of the general interval power function.” ## Soft Computing. Volume 17, Issue 8, pp 1357–1366. ## Springer Berlin Heidelberg. DOI 10.1007/s00500-013-1008-8. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## infsupdec (-5, 6) .^ infsupdec (2, 3) ## @result{} ans = [-125, +216]_trv ## @end group ## @end example ## @seealso{@@infsupdec/pow, @@infsupdec/pown, @@infsupdec/pow2, @@infsupdec/pow10, @@infsupdec/exp} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-15 function result = power (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif result = newdec (power (x.infsup, y.infsup)); ## The general power function is continuous where it is defined domain = not (isempty (result)) & ... (inf (x) > 0 | ... # defined for all x > 0 (inf (x) == 0 & inf (y) > 0) | ... # defined for x = 0 if y > 0 # defined for x < 0 only where y is integral (issingleton (y) & fix (inf (y)) == inf (y) & ... (inf (y) > 0 | not (ismember (0, x))))); # not defined for 0^0 result.dec(not (domain)) = _trv (); result.dec = min (result.dec, min (x.dec, y.dec)); endfunction %!# from the documentation string %!assert (isequal (infsupdec (-5, 6) .^ infsupdec (2, 3), infsupdec (-125, 216, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sqr; %! for testcase = [testcases]' %! assert (isequaln (... %! power (testcase.in{1}, 2), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sqr; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (power (in1, 2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sqr; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (power (in1, 2), out)); interval-3.2.0/inst/@infsupdec/pown.m0000644000000000000000000000731613316017127015674 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} pown (@var{X}, @var{P}) ## ## Compute the monomial @code{x^@var{P}} for all numbers in @var{X}. ## ## Monomials are defined for all real numbers and the special monomial ## @code{@var{P} == 0} evaluates to @code{1} everywhere. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## pown (infsupdec (5, 6), 2) ## @result{} ans = [25, 36]_com ## @end group ## @end example ## @seealso{@@infsupdec/pow, @@infsupdec/pow2, @@infsupdec/pow10, @@infsupdec/exp} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = pown (x, p) if (nargin ~= 2) print_usage (); return endif result = newdec (pown (x.infsup, p)); ## x^P is undefined for x == 0 and P < 0 domain = p >= 0 | not (ismember (0, x)); result.dec(not (domain)) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (pown (infsupdec (5, 6), 2), infsupdec (25, 36))); %!assert (pown (infsupdec (-2, 1), 2) == infsupdec (0, 4)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sqr; %! for testcase = [testcases]' %! assert (isequaln (... %! pown (testcase.in{1}, 2), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sqr; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (pown (in1, 2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.sqr; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pown (in1, 2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.pown; %! for testcase = [testcases]' %! assert (isequaln (... %! pown (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.pown; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (pown (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.pown; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pown (in1, in2), out)); interval-3.2.0/inst/@infsupdec/pownrev.m0000644000000000000000000001065513316017127016411 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} pownrev (@var{C}, @var{X}, @var{P}) ## @deftypemethodx {@@infsupdec} {@var{X} =} pownrev (@var{C}, @var{P}) ## ## Compute the reverse monomial @code{x^@var{P}}. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{pown (x, @var{P}) ∈ @var{C}}. ## ## Accuracy: The result is a valid enclosure. The result is a tight ## enclosure for @var{P} ≥ -2. The result also is a tight enclosure if the ## reciprocal of @var{P} can be computed exactly in double-precision. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @seealso{@@infsupdec/pown} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = pownrev (c, x, p) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) p = x; x = infsupdec (-inf, inf); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif result = infsupdec (pownrev (c.infsup, x.infsup, p), "trv"); result.dec(isnai (c) | isnai (x)) = _ill (); endfunction %!assert (isequal (pownrev (infsupdec (25, 36), infsupdec (0, inf), 2), infsupdec (5, 6, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.pownRev; %! for testcase = [testcases]' %! assert (isequaln (... %! pownrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.pownRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (pownrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.pownRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pownrev (in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.pownRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! pownrev (testcase.in{1}, testcase.in{2}, testcase.in{3}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.pownRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! assert (isequaln (pownrev (in1, in2, in3), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.pownRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! in3 = vertcat (vertcat (testcases.in){:, 3}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! in3 = reshape ([in3; in3(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (pownrev (in1, in2, in3), out)); interval-3.2.0/inst/@infsupdec/powrev1.m0000644000000000000000000000441313316017127016307 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} powrev1 (@var{B}, @var{C}, @var{X}) ## @deftypemethodx {@@infsupdec} {@var{X} =} powrev1 (@var{B}, @var{C}) ## ## Compute the reverse power function for the first parameter. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{pow (x, b) ∈ @var{C}} for any @code{b ∈ @var{B}}. ## ## Accuracy: The result is a valid enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## powrev1 (infsupdec (2, 5), infsupdec (3, 6)) ## @result{} ans ⊂ [1.2457, 2.4495]_trv ## @end group ## @end example ## @seealso{@@infsupdec/pow} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = powrev1 (b, c, x) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) x = infsupdec (-inf, inf); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif if (not (isa (c, "infsup"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif ## inverse power is not a point function result = infsupdec (powrev1 (b.infsup, c.infsup, x.infsup), "trv"); result.dec(isnai (x) | isnai (b) | isnai (c)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (powrev1 (infsupdec (2, 5), infsupdec (3, 6)), infsupdec ("[0x1.3EE8390D43955, 0x1.3988E1409212Fp1]_trv"))); interval-3.2.0/inst/@infsupdec/powrev2.m0000644000000000000000000000442113316017127016307 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{Y} =} powrev2 (@var{A}, @var{C}, @var{Y}) ## @deftypemethodx {@@infsupdec} {@var{Y} =} powrev2 (@var{A}, @var{C}) ## ## Compute the reverse power function for the second parameter. ## ## That is, an enclosure of all @code{y ∈ @var{Y}} where ## @code{pow (a, y) ∈ @var{C}} for any @code{a ∈ @var{A}}. ## ## Accuracy: The result is a valid enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## powrev2 (infsupdec (2, 5), infsupdec (3, 6)) ## @result{} ans ⊂ [0.6826, 2.585]_trv ## @end group ## @end example ## @seealso{@@infsupdec/pow} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = powrev2 (a, c, y) if (nargin < 2 || nargin > 3) print_usage (); return endif if (nargin < 3) y = infsupdec (-inf, inf); endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif ## inverse power is not a point function result = infsupdec (powrev2 (a.infsup, c.infsup, y.infsup), "trv"); result.dec(isnai (y) | isnai (a) | isnai (c)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (powrev2 (infsupdec (2, 5), infsupdec (3, 6)), infsupdec ("[0x1.5D7E8F22BA886p-1, 0x1.4AE00D1CFDEB5p1]_trv"))); interval-3.2.0/inst/@infsupdec/precedes.m0000644000000000000000000000550413316017127016500 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} precedes (@var{A}, @var{B}) ## ## Evaluate precedes comparison on intervals. ## ## True, if @var{A} is left of @var{B}. The intervals may touch. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsupdec/eq, @@infsupdec/le, @@infsupdec/lt, @@infsupdec/gt, @@infsupdec/strictprecedes, @@infsupdec/subset, @@infsupdec/interior, @@infsupdec/disjoint} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = precedes (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = precedes (a.infsup, b.infsup); result(isnai (a) | isnai (b)) = false; endfunction %!assert (precedes (infsupdec (1, 2), infsupdec (2, 3))); %!assert (not (precedes (infsupdec (1, 2.1), infsupdec (1.9, 3)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.precedes; %! for testcase = [testcases]' %! assert (isequaln (... %! precedes (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.precedes; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (precedes (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.precedes; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (precedes (in1, in2), out)); interval-3.2.0/inst/@infsupdec/prepad.m0000644000000000000000000000552213316017127016161 0ustar 00000000000000## Copyright 2015-2017 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} prepad (@var{X}, @var{L}) ## @defmethodx {@@infsupdec} prepad (@var{X}, @var{L}, @var{C}) ## @defmethodx {@@infsupdec} prepad (@var{X}, @var{L}, @var{C}, @var{DIM}) ## ## Prepend the scalar interval value @var{C} to the interval vector @var{X} ## until it is of length @var{L}. If @var{C} is not given, a value of 0 is ## used. ## ## If @code{length (@var{X}) > L}, elements from the beginning of @var{X} are ## removed until an interval vector of length @var{L} is obtained. ## ## If @var{X} is an interval matrix, elements are prepended or removed from ## each row or column. ## ## If the optional argument DIM is given, operate along this dimension. ## ## If DIM is larger than the dimension of X, the result will have DIM ## dimensions. ## ## @example ## @group ## prepad (infsupdec (1 : 3), 5, 42) ## @result{} ans = 1×5 interval vector ## [42]_com [42]_com [1]_com [2]_com [3]_com ## @end group ## @end example ## @seealso{@@infsupdec/reshape, @@infsup/cat, @@infsupdec/postpad, @@infsupdec/resize} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-19 function x = prepad (x, len, c, dim) if (nargin < 2 || nargin > 4) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (nargin < 3) c = infsupdec (0); elseif (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (nargin < 4) dim = find (size (x.dec) ~= 1, 1); if (isempty (dim)) dim = 1; endif endif x.infsup = prepad (x.infsup, len, c.infsup, dim); x.dec = prepad (x.dec, len, c.dec, dim); endfunction %!assert (isequal (prepad (infsupdec (2:4), 4, 1), infsupdec (1:4))); %!assert (isequal (prepad (infsupdec (0:2), 2, 1), infsupdec (1:2))); %!test %! if (compare_versions (OCTAVE_VERSION (), "4.0.0", ">=")) %! assert (isequal (prepad (infsupdec (0), 10, 0, 3), infsupdec (zeros (1, 1, 10)))); %! else %! # In Octave 3.8.x it is not possible to increase the number of dimensions. %! endif %!assert (isequal (prepad (infsupdec (zeros (1, 2, 2)), 3), infsupdec (zeros (1, 3, 2)))); interval-3.2.0/inst/@infsupdec/private/_com.m0000644000000000000000000000200613316017127017267 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defvr Constant _com ## Return numeric representation of the common decoration ## @end defvr ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-18 function d = _com () ## See IEEE Std 1788-2015 14.4 Interchange representations and encodings d = uint8 (16); endfunction interval-3.2.0/inst/@infsupdec/private/_dac.m0000644000000000000000000000202613316017127017242 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defvr Constant _dac ## Return numeric representation of the defined-and-continuous decoration ## @end defvr ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-18 function d = _dac () ## See IEEE Std 1788-2015 14.4 Interchange representations and encodings d = uint8 (12); endfunction interval-3.2.0/inst/@infsupdec/private/_def.m0000644000000000000000000000200613316017127017247 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defvr Constant _def ## Return numeric representation of the defined decoration ## @end defvr ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-18 function d = _def () ## See IEEE Std 1788-2015 14.4 Interchange representations and encodings d = uint8 (8); endfunction interval-3.2.0/inst/@infsupdec/private/_ill.m0000644000000000000000000000201113316017127017265 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defvr Constant _ill ## Return numeric representation of the ill-formed decoration ## @end defvr ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-18 function d = _ill () ## See IEEE Std 1788-2015 14.4 Interchange representations and encodings d = uint8 (0); endfunction interval-3.2.0/inst/@infsupdec/private/_trv.m0000644000000000000000000000200613316017127017324 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defvr Constant _trv ## Return numeric representation of the trivial decoration ## @end defvr ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-18 function d = _trv () ## See IEEE Std 1788-2015 14.4 Interchange representations and encodings d = uint8 (4); endfunction interval-3.2.0/inst/@infsupdec/prod.m0000644000000000000000000000425013316017127015647 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} prod (@var{X}) ## @defmethodx {@@infsupdec} prod (@var{X}, @var{DIM}) ## ## Product of elements along dimension @var{DIM}. If @var{DIM} is omitted, it ## defaults to the first non-singleton dimension. ## ## Accuracy: The result is a valid enclosure. ## ## @example ## @group ## prod (infsupdec (1 : 4)) ## @result{} ans = [24]_com ## @end group ## @end example ## @seealso{@@infsupdec/sum} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-10-24 function result = prod (x, dim) if (nargin > 2) print_usage (); return endif if (nargin < 2) ## Try to find non-singleton dimension dim = find (size (x.dec) ~= 1, 1); if (isempty (dim)) dim = 1; endif endif result = newdec (prod (x.infsup, dim)); if (not (isempty (x.dec))) warning ("off", "Octave:broadcast", "local"); result.dec = min (result.dec, min (x.dec, [], dim)); endif endfunction %!# from the documentation string %!assert (prod (infsupdec (1 : 4)) == 24); %!assert (prod (infsupdec ([])) == 1); %!assert (isequal (prod (infsupdec (magic (3))), infsupdec ([96, 45, 84]))); %!assert (isequal (prod (infsupdec (magic (3)), 2), infsupdec ([48; 105; 72]))); %!assert (isequal (prod (infsupdec (magic (3)), 3), infsupdec (magic (3)))); %!assert (isequal (prod (prod (reshape (infsup (1:24), 1, 2, 3, 4))), infsup (reshape ([720, 665280, 13366080, 96909120], 1, 1, 1, 4)))); interval-3.2.0/inst/@infsupdec/psi.m0000644000000000000000000000560713316017127015505 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} psi (@var{X}) ## ## Compute the digamma function, also known as the psi function. ## ## @tex ## $$ ## {\rm psi} (x) = \int_0^\infty \left( {{\exp(-t)} \over t} - {{\exp (-xt)} \over {1 - \exp (-t)}} \right) dt ## $$ ## @end tex ## @ifnottex ## @group ## @verbatim ## ∞ ## / exp (-t) exp (-xt) ## psi (x) = | ---------- - -------------- dt ## / t 1 - exp (-t) ## 0 ## @end verbatim ## @end group ## @end ifnottex ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## psi (infsupdec (1)) ## @result{} ans ⊂ [-0.57722, -0.57721]_com ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-28 function result = psi (x) if (nargin ~= 1) print_usage (); return endif if (isnai (x)) result = x; return endif result = newdec (psi (x.infsup)); ## psi is continuous where it is defined undefined = (inf (x) <= 0 & fix (inf (x)) == inf (x)) | ... (sup (x) <= 0 & fix (sup (x)) == sup (x)) | ... (inf (x) < 0 & ceil (inf (x)) <= floor (sup (x))); result.dec(undefined) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!assert (isempty (psi (infsupdec (0)))); %!assert (isempty (psi (infsupdec (-1)))); %!assert (isempty (psi (infsupdec (-2)))); %!assert (isempty (psi (infsupdec (-3)))); %!assert (isequal (psi (infsupdec (pow2 (-1074), inf)), infsupdec ("[Entire]_dac"))); %!assert (isequal (psi (infsupdec (0, inf)), infsupdec ("[Entire]_trv"))); %!assert (isequal (psi (infsupdec (-inf, -43.23)), infsupdec ("[Entire]_trv"))); %!assert (isequal (psi (infsupdec (-1, 0)), infsupdec ("[Entire]_trv"))); %!assert (isequal (psi (infsupdec (-2, -1)), infsupdec ("[Entire]_trv"))); %!assert (isequal (psi (infsupdec (-eps, eps)), infsupdec ("[Entire]_trv"))); %!assert (isequal (psi (infsupdec (-1-eps, -1+eps)), infsupdec ("[Entire]_trv"))); %!assert (isequal (psi (infsupdec (-4.1, -3.9)), infsupdec ("[Entire]_trv"))); %!# from the documentation string %!assert (isequal (psi (infsupdec (1)), infsupdec ("[-0x1.2788CFC6FB619p-1, -0x1.2788CFC6FB618p-1]_com"))); interval-3.2.0/inst/@infsupdec/rdivide.m0000644000000000000000000000775113316017127016342 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} rdivide (@var{X}, @var{Y}) ## @defopx Operator {@@infsupdec} {@var{X} ./ @var{Y}} ## ## Divide all numbers of interval @var{X} by all numbers of @var{Y}. ## ## For @var{X} = 1 compute the reciprocal of @var{Y}. Thus this function can ## compute @code{recip} as defined by IEEE Std 1788-2015. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsupdec (2, 3); ## y = infsupdec (1, 2); ## x ./ y ## @result{} ans = [1, 3]_com ## @end group ## @end example ## @seealso{@@infsupdec/mtimes} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = rdivide (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif result = newdec (rdivide (x.infsup, y.infsup)); divisionbyzero = ismember (0, y); if (not (size_equal (x.dec, y.dec))) divisionbyzero = divisionbyzero & true (size (x.dec)); endif result.dec(divisionbyzero) = _trv (); result.dec = min (result.dec, min (x.dec, y.dec)); endfunction %!# from the documentation string %!assert (isequal (infsupdec (2, 3) ./ infsupdec (1, 2), infsupdec (1, 3))); %!assert (1 ./ infsupdec (1, 4) == infsupdec (0.25, 1)); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.div; %! for testcase = [testcases]' %! assert (isequaln (... %! rdivide (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.div; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (rdivide (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.div; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (rdivide (in1, in2), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.recip; %! for testcase = [testcases]' %! assert (isequaln (... %! rdivide (1, testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.recip; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (rdivide (1, in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.recip; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (rdivide (1, in1), out)); interval-3.2.0/inst/@infsupdec/realsqrt.m0000644000000000000000000000515213316017127016542 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} realsqrt (@var{X}) ## ## Compute the square root (for all non-negative numbers). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## realsqrt (infsupdec (-6, 4)) ## @result{} ans = [0, 2]_trv ## @end group ## @end example ## @seealso{@@infsupdec/sqr, @@infsupdec/rsqrt, @@infsupdec/pow, @@infsupdec/cbrt, @@infsupdec/nthroot} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = realsqrt (x) if (nargin ~= 1) print_usage (); return endif result = newdec (realsqrt (x.infsup)); ## realsqrt is continuous everywhere, but defined for x >= 0 only persistent domain = infsup (0, inf); defined = subset (x.infsup, domain); result.dec(not (defined)) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (realsqrt (infsupdec (-6, 4)), infsupdec (0, 2, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sqrt; %! for testcase = [testcases]' %! assert (isequaln (... %! realsqrt (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sqrt; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (realsqrt (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sqrt; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (realsqrt (in1), out)); interval-3.2.0/inst/@infsupdec/rem.m0000644000000000000000000001712613316017127015474 0ustar 00000000000000## Copyright 2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} rem (@var{X}, @var{Y}) ## ## Compute the remainder of the division @var{X} by @var{Y}. ## ## Conceptionally, it is given by the expression ## @code{@var{X} - @var{Y} .* fix (@var{X} ./ @var{Y})}. For negative @var{X}, ## the remainder will be either zero or negative. This function is undefined ## for @var{Y} = 0. ## ## @example ## @group ## rem (infsupdec (3), infsupdec (2)) ## @result{} ans = [1]_com ## rem (infsupdec (-3), infsupdec (2)) ## @result{} ans = [-1]_com ## @end group ## @end example ## ## Accuracy: The result is a valid enclosure. ## ## @seealso{@@infsupdec/rdivide, @@infsupdec/mod} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2017-09-24 function result = rem (x, y) if (nargin ~= 2) print_usage (); return endif ## Usually, the implementation of an interval arithmetic function is cleanly ## split into a bare and a decorated version. This function's decoration is ## quite complicated to be computed and depends on intermediate values that ## are used to compute the bare interval result. Thus, we get most of the ## decoration information as a second output parameter from @infsup. if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif [bare, d] = rem (x.infsup, y.infsup); result = newdec (bare); result.dec = min (result.dec, min (d, min (x.dec, y.dec))); endfunction %!assert (isequal (rem (infsupdec (), infsupdec ()), infsupdec ())); %!assert (isequal (rem (infsupdec (0), infsupdec ()), infsupdec ())); %!assert (isequal (rem (infsupdec (), infsupdec (0)), infsupdec ())); %!assert (isequal (rem (infsupdec (0), infsupdec (0)), infsupdec ())); %!assert (isequal (rem (infsupdec (1), infsupdec (0)), infsupdec ())); %!assert (isequal (rem (infsupdec (0, 1), infsupdec (0)), infsupdec ())); %!assert (isequal (rem (infsupdec (1, 2), infsupdec (0)), infsupdec ())); %!assert (isequal (rem (infsupdec (0, inf), infsupdec (0)), infsupdec ())); %!assert (isequal (rem (infsupdec (1, inf), infsupdec (0)), infsupdec ())); %!assert (isequal (rem (infsupdec (realmax, inf), infsupdec (0)), infsupdec ())); %!assert (isequal (rem (infsupdec (0), infsupdec (1)), infsupdec (0))); %!assert (isequal (rem (infsupdec (0), infsupdec (0, 1)), infsupdec (0, "trv"))); %!assert (isequal (rem (infsupdec (0), infsupdec (1, 2)), infsupdec (0))); %!assert (isequal (rem (infsupdec (0), infsupdec (0, inf)), infsupdec (0, "trv"))); %!assert (isequal (rem (infsupdec (0), infsupdec (1, inf)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (0), infsupdec (realmax, inf)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (1), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (2), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (4), infsupdec (2)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (6), infsupdec (3)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (8), infsupdec (2)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (9), infsupdec (3)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (realmax), infsupdec (realmax)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (realmax), infsupdec (realmax / 2)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (realmax), infsupdec (realmax / 4)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (realmax), infsupdec (realmax / 8)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (realmax), infsupdec (realmax / 16)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (realmax), infsupdec (realmax / 32)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (0.1), infsupdec (0.1)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (0.1 * 2), infsupdec (0.1)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (0.1 * 4), infsupdec (0.1)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (pi), infsupdec (pi)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (pi), infsupdec (pi / 2)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (pi), infsupdec (pi / 4)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (pow2 (-1074)), infsupdec (pow2 (-1074))), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (pow2 (-1073)), infsupdec (pow2 (-1074))), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (pow2 (-1072)), infsupdec (pow2 (-1074))), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (1), infsupdec (2)), infsupdec (1))); %!assert (isequal (rem (infsupdec (0.5), infsupdec (1)), infsupdec (0.5))); %!assert (isequal (rem (infsupdec (pi), infsupdec (3.15)), infsupdec (pi))); %!assert (isequal (rem (infsupdec (1), infsupdec (2, 3)), infsupdec (1))); %!assert (isequal (rem (infsupdec (1), infsupdec (2, inf)), infsupdec (1, "dac"))); %!assert (isequal (rem (infsupdec (0.5), infsupdec (1, 2)), infsupdec (0.5))); %!assert (isequal (rem (infsupdec (0.5), infsupdec (1, inf)), infsupdec (0.5, "dac"))); %!assert (isequal (rem (infsupdec (pi), infsupdec (3.15)), infsupdec (pi))); %!assert (isequal (rem (infsupdec (pi), infsupdec (3.15, inf)), infsupdec (pi, "dac"))); %!assert (isequal (rem (infsupdec (0, 1), infsupdec (0, 1)), infsupdec (0, 1, "trv"))); %!assert (isequal (rem (infsupdec (0, 2), infsupdec (0, 1)), infsupdec (0, 1, "trv"))); %!assert (isequal (rem (infsupdec (0, 1), infsupdec (0, 2)), infsupdec (0, 1, "trv"))); %!assert (isequal (rem (infsupdec (0, realmax), infsupdec (0, realmax)), infsupdec (0, realmax, "trv"))); %!assert (isequal (rem (infsupdec (realmax, inf), infsupdec (realmax, inf)), infsupdec (0, inf, "def"))); %!assert (isequal (rem (infsupdec (0, inf), infsupdec (0, inf)), infsupdec (0, inf, "trv"))); %!assert (isequal (rem (infsupdec (0), infsupdec (1)), infsupdec (0))); %!assert (isequal (rem (infsupdec (1), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (0, 1), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (rem (infsupdec (1, 2), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (rem (infsupdec (0, inf), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (rem (infsupdec (1, inf), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (rem (infsupdec (realmax, inf), infsupdec (1)), infsupdec (0, 1, "def"))); %!assert (isequal (rem (infsupdec (1), infsupdec (1)), infsupdec (0, "dac"))); %!assert (isequal (rem (infsupdec (1), infsupdec (0, 1)), infsupdec (0, 0.5, "trv"))); %!assert (isequal (rem (infsupdec (1), infsupdec (1, 2)), infsupdec (0, 1, "def"))); %!assert (isequal (rem (infsupdec (1), infsupdec (0, inf)), infsupdec (0, 1, "trv"))); %!assert (isequal (rem (infsupdec (1), infsupdec (1, inf)), infsupdec (0, 1, "def"))); %!assert (isequal (rem (infsupdec (1), infsupdec (2, inf)), infsupdec (1, "dac"))); %!assert (isequal (rem (infsupdec (1), infsupdec (realmax, inf)), infsupdec (1, "dac"))); interval-3.2.0/inst/@infsupdec/reshape.m0000644000000000000000000000452513316017127016337 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} reshape (@var{A}, @var{M}, @var{N}, ...) ## @defmethodx {@@infsupdec} reshape (@var{X}, [@var{M} @var{N}, ...]) ## @defmethodx {@@infsupdec} reshape (@var{X}, ..., @var{[]}, ...) ## ## Return an interval matrix with the specified dimensions (M, N, ...) whose ## elements are taken from the interval matrix @var{A}. The elements of the ## matrix are accessed in column-major order (like Fortran arrays are stored). ## ## Note that the total number of elements in the original matrix ## (@code{prod (size (@var{A}))}) must match the total number of elements in ## the new matrix (@code{prod ([@var{M} @var{N}])}). ## ## A single dimension of the return matrix may be left unspecified and ## Octave will determine its size automatically. An empty matrix ([]) ## is used to flag the unspecified dimension. ## ## @example ## @group ## reshape (infsupdec (1 : 6), 2, 3) ## @result{} ans = 2×3 interval matrix ## [1]_com [3]_com [5]_com ## [2]_com [4]_com [6]_com ## @end group ## @end example ## @seealso{@@infsupdec/resize, @@infsup/cat, @@infsupdec/postpad, @@infsupdec/prepad} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-19 function x = reshape (x, varargin) if (not (isa (x, "infsupdec"))) print_usage (); return endif x.infsup = reshape (x.infsup, varargin{:}); x.dec = reshape (x.dec, varargin{:}); endfunction %!assert (isequal (reshape (infsupdec (1 : 6), 2, 3), infsupdec (reshape (1 : 6, 2, 3)))); %!assert (isequal (reshape (infsupdec (1 : 24), 2, [], 4), infsupdec (reshape (1 : 24, 2, 3, 4)))); interval-3.2.0/inst/@infsupdec/resize.m0000644000000000000000000000523013316017127016203 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} resize (@var{X}, @var{M}) ## @defmethodx {@@infsupdec} resize (@var{X}, @var{M}, @var{N}, ...) ## @defmethodx {@@infsupdec} resize (@var{X}, [@var{M} @var{N}, ...]) ## ## Resize interval array @var{X} cutting off elements as necessary. ## ## In the result, element with certain indices is equal to the corresponding ## element of @var{X} if the indices are within the bounds of @var{X}; ## otherwise, the element is set to zero. ## ## If only @var{M} is supplied, and it is a scalar, the dimension of the result ## is @var{M}-by-@var{M}. If @var{M}, @var{N}, ... are all scalars, then the ## dimensions of the result are @var{M}-by-@var{N}-by-.... If given a vector as ## input, then the dimensions of the result are given by the elements of that ## vector. ## ## An object can be resized to more dimensions than it has; in such ## case the missing dimensions are assumed to be 1. Resizing an ## object to fewer dimensions is not possible. ## ## @example ## @group ## resize (infsupdec (magic (3)), 4, 2) ## @result{} ans = 4×2 interval matrix ## [8]_com [1]_com ## [3]_com [5]_com ## [4]_com [9]_com ## [0]_com [0]_com ## @end group ## @end example ## @seealso{@@infsupdec/reshape, @@infsup/cat, @@infsupdec/postpad, @@infsupdec/prepad} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-19 function x = resize (x, varargin) if (not (isa (x, "infsupdec"))) print_usage (); return endif x.dec(x.dec == 0) = uint8 (255); x.infsup = resize (x.infsup, varargin{:}); x.dec = resize (x.dec, varargin{:}); x.dec(x.dec == 0) = _com (); # any new elements are [0]_com x.dec(x.dec == uint8 (255)) = uint8 (0); endfunction %!assert (isequal (resize (infsupdec (magic (3)), 4, 2), infsupdec([8, 1; 3, 5; 4, 9; 0, 0]))); %!assert (isequal (resize (infsupdec (ones (2, 2, 2)), 4, 1, 2), infsupdec (resize (ones (2, 2, 2), 4, 1, 2)))) interval-3.2.0/inst/@infsupdec/round.m0000644000000000000000000001110713316017127016031 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} round (@var{X}) ## ## Round each number in interval @var{X} to the nearest integer. Ties are ## rounded away from zero (towards +Inf or -Inf depending on the sign). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## round (infsupdec (2.5, 3.5)) ## @result{} ans = [3, 4]_def ## round (infsupdec (-0.5, 5)) ## @result{} ans = [-1, +5]_def ## @end group ## @end example ## @seealso{@@infsupdec/floor, @@infsupdec/ceil, @@infsupdec/roundb, @@infsupdec/fix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = round (x) if (nargin ~= 1) print_usage (); return endif result = newdec (round (x.infsup)); ## Round is like a scaled fix function discontinuous = not (issingleton (result)); result.dec(discontinuous) = min (result.dec(discontinuous), _def ()); onlyrestrictioncontinuous = issingleton (result) & ... not ((sup (x) >= 0 | ... fix (sup (x)) == sup (x) | ... fix (sup (x) * 2) / 2 ~= sup (x)) & ... (inf (x) <= 0 | ... fix (inf (x)) == inf (x) | ... fix (inf (x) * 2) / 2 ~= inf (x))); result.dec(onlyrestrictioncontinuous) = ... min (result.dec(onlyrestrictioncontinuous), _dac ()); result.dec = min (result.dec, x.dec); endfunction %!# Empty interval %!assert (isequal (round (infsupdec ()), infsupdec ())); %!# Singleton intervals %!assert (isequal (round (infsupdec (0)), infsupdec (0))); %!assert (isequal (round (infsupdec (0.5)), infsupdec (1, "dac"))); %!assert (isequal (round (infsupdec (0.25)), infsupdec (0))); %!assert (isequal (round (infsupdec (0.75)), infsupdec (1))); %!assert (isequal (round (infsupdec (-0.5)), infsupdec (-1, "dac"))); %!# Bounded intervals %!assert (isequal (round (infsupdec (-0.5, 0)), infsupdec (-1, 0, "def"))); %!assert (isequal (round (infsupdec (0, 0.5)), infsupdec (0, 1, "def"))); %!assert (isequal (round (infsupdec (0.25, 0.5)), infsupdec (0, 1, "def"))); %!assert (isequal (round (infsupdec (-1, 0)), infsupdec (-1, 0, "def"))); %!assert (isequal (round (infsupdec (-1, 1)), infsupdec (-1, 1, "def"))); %!assert (isequal (round (infsupdec (-realmin, realmin)), infsupdec (0))); %!assert (isequal (round (infsupdec (-realmax, realmax)), infsupdec (-realmax, realmax, "def"))); %!# Unbounded intervals %!assert (isequal (round (infsupdec (-realmin, inf)), infsupdec (0, inf, "def"))); %!assert (isequal (round (infsupdec (-realmax, inf)), infsupdec (-realmax, inf, "def"))); %!assert (isequal (round (infsupdec (-inf, realmin)), infsupdec (-inf, 0, "def"))); %!assert (isequal (round (infsupdec (-inf, realmax)), infsupdec (-inf, realmax, "def"))); %!assert (isequal (round (infsupdec (-inf, inf)), infsupdec (-inf, inf, "def"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.roundTiesToAway; %! for testcase = [testcases]' %! assert (isequaln (... %! round (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.roundTiesToAway; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (round (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.roundTiesToAway; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (round (in1), out)); interval-3.2.0/inst/@infsupdec/roundb.m0000644000000000000000000001117613316017127016201 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} roundb (@var{X}) ## ## Round each number in interval @var{X} to the nearest integer. Ties are ## rounded towards the nearest even integer. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## roundb (infsupdec (2.5, 3.5)) ## @result{} ans = [2, 4]_def ## roundb (infsupdec (-0.5, 5.5)) ## @result{} ans = [0, 6]_def ## @end group ## @end example ## @seealso{@@infsupdec/floor, @@infsupdec/ceil, @@infsupdec/round, @@infsupdec/fix} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = roundb (x) if (nargin ~= 1) print_usage (); return endif result = newdec (roundb (x.infsup)); discontinuous = not (issingleton (result)); result.dec(discontinuous) = min (result.dec(discontinuous), _def ()); onlyrestrictioncontinuous = issingleton (result) & ... not ((rem (inf (result), 2) ~= 0 | ... ((fix (sup (x)) == sup (x) | ... fix (sup (x) * 2) / 2 ~= sup (x)) & ... (fix (inf (x)) == inf (x) | ... fix (inf (x) * 2) / 2 ~= inf (x))))); result.dec(onlyrestrictioncontinuous) = ... min (result.dec(onlyrestrictioncontinuous), _dac ()); result.dec = min (result.dec, x.dec); endfunction %!# Empty interval %!assert (isequal (roundb (infsupdec ()), infsupdec ())); %!# Singleton intervals %!assert (isequal (roundb (infsupdec (0)), infsupdec (0))); %!assert (isequal (roundb (infsupdec (0.5)), infsupdec (0, "dac"))); %!assert (isequal (roundb (infsupdec (0.25)), infsupdec (0))); %!assert (isequal (roundb (infsupdec (0.75)), infsupdec (1))); %!assert (isequal (roundb (infsupdec (1.5)), infsupdec (2, "dac"))); %!assert (isequal (roundb (infsupdec (-0.5)), infsupdec (0, "dac"))); %!assert (isequal (roundb (infsupdec (-1.5)), infsupdec (-2, "dac"))); %!# Bounded intervals %!assert (isequal (roundb (infsupdec (-0.5, 0)), infsupdec (0, "dac"))); %!assert (isequal (roundb (infsupdec (0, 0.5)), infsupdec (0, "dac"))); %!assert (isequal (roundb (infsupdec (0.25, 0.5)), infsupdec (0, "dac"))); %!assert (isequal (roundb (infsupdec (-1, 0)), infsupdec (-1, 0, "def"))); %!assert (isequal (roundb (infsupdec (-1, 1)), infsupdec (-1, 1, "def"))); %!assert (isequal (roundb (infsupdec (-realmin, realmin)), infsupdec (0))); %!assert (isequal (roundb (infsupdec (-realmax, realmax)), infsupdec (-realmax, realmax, "def"))); %!# Unbounded intervals %!assert (isequal (roundb (infsupdec (-realmin, inf)), infsupdec (0, inf, "def"))); %!assert (isequal (roundb (infsupdec (-realmax, inf)), infsupdec (-realmax, inf, "def"))); %!assert (isequal (roundb (infsupdec (-inf, realmin)), infsupdec (-inf, 0, "def"))); %!assert (isequal (roundb (infsupdec (-inf, realmax)), infsupdec (-inf, realmax, "def"))); %!assert (isequal (roundb (infsupdec (-inf, inf)), infsupdec (-inf, inf, "def"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.roundTiesToEven; %! for testcase = [testcases]' %! assert (isequaln (... %! roundb (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.roundTiesToEven; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (roundb (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.roundTiesToEven; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (roundb (in1), out)); interval-3.2.0/inst/@infsupdec/rsqrt.m0000644000000000000000000000310613316017127016055 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} rsqrt (@var{X}) ## ## Compute the reciprocal square root (for all positive numbers). ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## rsqrt (infsupdec (-6, 4)) ## @result{} ans = [0.5, inf]_trv ## @end group ## @end example ## @seealso{@@infsupdec/realsqrt} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function result = rsqrt (x) if (nargin ~= 1) print_usage (); return endif result = newdec (rsqrt (x.infsup)); ## rsqrt is continuous everywhere, but defined for x > 0 only persistent domain_hull = infsup (0, inf); result.dec(not (interior (x.infsup, domain_hull))) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (rsqrt (infsupdec (-6, 4)), infsupdec (.5, inf, "trv"))); interval-3.2.0/inst/@infsupdec/sec.m0000644000000000000000000000322213316017127015453 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} sec (@var{X}) ## ## Compute the secant in radians, that is the reciprocal cosine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sec (infsupdec (1)) ## @result{} ans ⊂ [1.8508, 1.8509]_com ## @end group ## @end example ## @seealso{@@infsupdec/cos, @@infsupdec/csc, @@infsupdec/cot} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function result = sec (x) if (nargin ~= 1) print_usage (); return endif result = newdec (sec (x.infsup)); ## Because sec (nextdown (pi/2)) < realmax, we can simple check for ## a singularity by comparing the result with entire. domain = not (isentire (result)); result.dec(not (domain)) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (sec (infsupdec (1)), infsupdec ("[0x1.D9CF0F125CC29, 0x1.D9CF0F125CC2A]_com"))); interval-3.2.0/inst/@infsupdec/sech.m0000644000000000000000000000302213316017127015621 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} sech (@var{X}) ## ## Compute the hyperbolic secant, that is the reciprocal hyperbolic cosine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sech (infsupdec (1)) ## @result{} ans ⊂ [0.64805, 0.64806]_com ## @end group ## @end example ## @seealso{@@infsupdec/cosh, @@infsupdec/csch, @@infsupdec/coth} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-15 function result = sech (x) if (nargin ~= 1) print_usage (); return endif result = newdec (sech (x.infsup)); ## sech is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (sech (infsupdec (1)), infsupdec ("[0x1.4BCDC50ED6BE7p-1, 0x1.4BCDC50ED6BE8p-1]_com"))); interval-3.2.0/inst/@infsupdec/setdiff.m0000644000000000000000000000423613316017127016333 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} setdiff (@var{A}, @var{B}) ## ## Build the relative complement of interval @var{B} in interval @var{A}. ## ## Accuracy: The result is a tight enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## The function is a set operation and the result carries the @code{trv} ## decoration at best. ## ## @example ## @group ## x = infsupdec (1, 3); ## y = infsupdec (2, 4); ## setdiff (x, y) ## @result{} ans = [1, 2]_trv ## @end group ## @end example ## @seealso{@@infsupdec/intersect, @@infsupdec/union, @@infsupdec/setxor} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-03 function result = setdiff (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = infsupdec (setdiff (a.infsup, b.infsup), "trv"); result.dec(isnai (a) | isnai (b)) = _ill (); endfunction %!assert (isempty (setdiff (infsupdec (), infsupdec (1, 4)))); %!assert (setdiff (infsupdec (1, 3), infsupdec ()) == infsupdec (1, 3)); %!assert (isempty (setdiff (infsupdec (1, 3), infsupdec (-inf, inf)))); %!assert (isempty (setdiff (infsupdec (1, 3), infsupdec (1, 4)))); %!assert (setdiff (infsupdec (-inf, inf), infsupdec (1, 4)) == infsupdec (-inf, inf)); %!# from the documentation string %!assert (setdiff (infsupdec (1, 3), infsupdec (2, 4)) == infsupdec (1, 2)); interval-3.2.0/inst/@infsupdec/setxor.m0000644000000000000000000000640013316017127016226 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {} setxor (@var{A}, @var{B}) ## @deftypemethodx {@@infsupdec} {[@var{C}, @var{C1}, @var{C2}] =} setxor (@var{A}, @var{B}) ## ## Build the symmetric difference of intervals @var{A} and @var{B}. ## ## With three output arguments, return intervals @var{C1} and @var{C2} such ## that @var{C1} and @var{C2} are enclosures of disjoint sets whose union is ## enclosed by interval @var{C}. ## ## Accuracy: The result is a tight enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## The function is a set operation and the result carries the @code{trv} ## decoration at best. ## ## @example ## @group ## x = infsupdec (1, 3); ## y = infsupdec (2, 4); ## [z, z1, z2] = setxor (x, y) ## @result{} ## z = [1, 4]_trv ## z1 = [1, 2]_trv ## z2 = [3, 4]_trv ## @end group ## @end example ## @seealso{@@infsupdec/intersect, @@infsupdec/union, @@infsupdec/setdiff} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-04-03 function [c, c1, c2] = setxor (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif if (nargout > 1) [c, c1, c2] = setxor (a.infsup, b.infsup); c1 = infsupdec (c1, "trv"); c2 = infsupdec (c2, "trv"); c1.dec(isnai (a) | isnai (b)) = c2.dec(isnai (a) | isnai (b)) = _ill (); else c = setxor (a.infsup, b.infsup); endif c = infsupdec (c, "trv"); c.dec(isnai (a) | isnai (b)) = _ill (); endfunction %!test %! [z, z1, z2] = setxor (infsupdec (), infsupdec ()); %! assert (isempty (z)); %! assert (isempty (z1)); %! assert (isempty (z2)); %!test %! [z, z1, z2] = setxor (infsupdec (-inf, inf), infsupdec ()); %! assert (isentire (z)); %! assert (isentire (z1)); %! assert (isempty (z2)); %!test %! [z, z1, z2] = setxor (infsupdec (-inf, inf), infsupdec (2)); %! assert (isentire (z)); %! assert (z1 == infsupdec (-inf, 2)); %! assert (z2 == infsupdec (2, inf)); %!test %! [z, z1, z2] = setxor (infsupdec (2, 3), infsupdec (2)); %! assert (z == infsupdec (2, 3)); %! assert (z1 == infsupdec ()); %! assert (z2 == infsupdec (2, 3)); %!test %! [z, z1, z2] = setxor (infsupdec (2, 3), infsupdec (2, 2.5)); %! assert (z == infsupdec (2.5, 3)); %! assert (z1 == infsupdec ()); %! assert (z2 == infsupdec (2.5, 3)); %!test %! # from the documentation string %! [z, z1, z2] = setxor (infsupdec (1, 3), infsupdec (2, 4)); %! assert (z == infsupdec (1, 4)); %! assert (z1 == infsupdec (1, 2)); %! assert (z2 == infsupdec (3, 4)); interval-3.2.0/inst/@infsupdec/sign.m0000644000000000000000000000565513316017127015655 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} sign (@var{X}) ## ## Compute the signum function for each number in interval @var{X}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sign (infsupdec (2, 3)) ## @result{} ans = [1]_com ## sign (infsupdec (0, 5)) ## @result{} ans = [0, 1]_def ## sign (infsupdec (-17)) ## @result{} ans = [-1]_com ## @end group ## @end example ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = sign (x) if (nargin ~= 1) print_usage (); return endif result = newdec (sign (x.infsup)); ## sign is defined everywhere and continuous for x ~= 0 discontinuous = not (issingleton (result)); result.dec(discontinuous) = min (result.dec(discontinuous), _def ()); onlyrestrictioncontinuous = inf (x) == 0 & sup (x) == 0; result.dec(onlyrestrictioncontinuous) = ... min (result.dec(onlyrestrictioncontinuous), _dac ()); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (sign (infsupdec (2, 3)), infsupdec (1))); %!assert (isequal (sign (infsupdec (0)), infsupdec (0, "dac"))); %!assert (isequal (sign (infsupdec (0, 5)), infsupdec (0, 1, "def"))); %!assert (isequal (sign (infsupdec (-17)), infsupdec (-1))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sign; %! for testcase = [testcases]' %! assert (isequaln (... %! sign (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sign; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sign (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sign; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sign (in1), out)); interval-3.2.0/inst/@infsupdec/sin.m0000644000000000000000000000466613316017127015507 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} sin (@var{X}) ## ## Compute the sine in radians. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sin (infsupdec (1)) ## @result{} ans ⊂ [0.84147, 0.84148]_com ## @end group ## @end example ## @seealso{@@infsupdec/asin, @@infsupdec/csc, @@infsupdec/sinh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = sin (x) if (nargin ~= 1) print_usage (); return endif result = newdec (sin (x.infsup)); ## sin is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (sin (infsupdec (1)), infsupdec ("[0x1.AED548F090CEEp-1, 0x1.AED548F090CEFp-1]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sin; %! for testcase = [testcases]' %! assert (isequaln (... %! sin (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sin (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sin (in1), out)); interval-3.2.0/inst/@infsupdec/sinh.m0000644000000000000000000000466413316017127015655 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} sinh (@var{X}) ## ## Compute the hyperbolic sine. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sinh (infsupdec (1)) ## @result{} ans ⊂ [1.1752, 1.1753]_com ## @end group ## @end example ## @seealso{@@infsupdec/asinh, @@infsupdec/csch, @@infsupdec/cosh, @@infsupdec/tanh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = sinh (x) if (nargin ~= 1) print_usage (); return endif result = newdec (sinh (x.infsup)); ## sinh is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (sinh (infsupdec (1)), infsupdec ("[0x1.2CD9FC44EB982, 0x1.2CD9FC44EB983]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sinh; %! for testcase = [testcases]' %! assert (isequaln (... %! sinh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sinh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sinh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.sinh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sinh (in1), out)); interval-3.2.0/inst/@infsupdec/sinrev.m0000644000000000000000000001000313316017127016202 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} sinrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsupdec} {@var{X} =} sinrev (@var{C}) ## ## Compute the reverse sine function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{sin (x) ∈ @var{C}}. ## ## Accuracy: The result is a valid enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## sinrev (infsupdec (-1), infsupdec (0, 6)) ## @result{} ans ⊂ [4.7123, 4.7124]_trv ## @end group ## @end example ## @seealso{@@infsupdec/sin} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = sinrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsupdec (-inf, inf); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif result = infsupdec (sinrev (c.infsup, x.infsup), "trv"); result.dec(isnai (c) | isnai (x)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (sinrev (infsupdec (-1), infsupdec (0, 6)), infsupdec ("[0x1.2D97C7F3321D2p2, 0x1.2D97C7F3321D3p2]_trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sinRev; %! for testcase = [testcases]' %! assert (isequaln (... %! sinrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sinRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sinrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.sinRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sinrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sinRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! sinrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sinRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (sinrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.sinRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sinrev (in1, in2), out)); interval-3.2.0/inst/@infsupdec/sqrrev.m0000644000000000000000000000767013316017127016236 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} sqrrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsupdec} {@var{X} =} sqrrev (@var{C}) ## ## Compute the reverse square function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{x .^ 2 ∈ @var{C}}. ## ## Accuracy: The result is a tight enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## sqrrev (infsupdec (-2, 1)) ## @result{} ans = [-1, +1]_trv ## @end group ## @end example ## @seealso{@@infsupdec/sqr} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = sqrrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsupdec (-inf, inf); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif result = infsupdec (sqrrev (c.infsup, x.infsup), "trv"); result.dec(isnai (c) | isnai (x)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (sqrrev (infsupdec (-2, 1)), infsupdec (-1, 1, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sqrRev; %! for testcase = [testcases]' %! assert (isequaln (... %! sqrrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sqrRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sqrrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.sqrRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sqrrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sqrRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! sqrrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sqrRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (sqrrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.sqrRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sqrrev (in1, in2), out)); interval-3.2.0/inst/@infsupdec/strictprecedes.m0000644000000000000000000000562313316017127017733 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} strictprecedes (@var{A}, @var{B}) ## ## Evaluate strict precedes comparison on intervals. ## ## True, if @var{A} is strictly left of @var{B}. The intervals may not touch. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsupdec/eq, @@infsupdec/le, @@infsupdec/lt, @@infsupdec/gt, @@infsupdec/precedes, @@infsupdec/subset, @@infsupdec/interior, @@infsupdec/disjoint} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = strictprecedes (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = strictprecedes (a.infsup, b.infsup); result(isnai(a) | isnai (b)) = false; endfunction %!assert (strictprecedes (infsupdec (1, 1.9), infsupdec (2.1, 3))); %!assert (not (strictprecedes (infsupdec (1, 2), infsupdec (2, 3)))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.strictPrecedes; %! for testcase = [testcases]' %! assert (isequaln (... %! strictprecedes (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.strictPrecedes; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (strictprecedes (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.strictPrecedes; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (strictprecedes (in1, in2), out)); interval-3.2.0/inst/@infsupdec/strictsubset.m0000644000000000000000000000444413316017127017446 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} strictsubset (@var{A}, @var{B}) ## ## Evaluate strict subset comparison on intervals. ## ## True, if all numbers from @var{A} are also contained in @var{B} and @var{B} ## contains a number that is not in @var{A}. ## False, if @var{A} contains a number which is not a member in @var{B} or if ## @var{A} and @var{B} are equal. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsupdec/subset, @@infsupdec/eq, @@infsupdec/interior} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-05-16 function result = strictsubset (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = strictsubset (a.infsup, b.infsup); result(isnai (a) | isnai (b)) = false; endfunction %!assert (strictsubset (infsupdec (1, 2), infsupdec (1, 3))); %!assert (strictsubset (infsupdec (2, 3), infsupdec (1, 3))); %!assert (not (strictsubset (infsupdec (1, 2), infsupdec (1, 2)))); %!assert (not (strictsubset (infsupdec (1, 3), infsupdec (1, 2)))); %!assert (strictsubset (infsupdec (), infsupdec (1, 3))); %!assert (not (strictsubset (infsupdec (), infsupdec ()))); %!assert (strictsubset (infsupdec (), infsupdec (-inf, inf))); %!assert (strictsubset (infsupdec (0, inf), infsupdec (-inf, inf))); %!assert (strictsubset (infsupdec (-inf, 0), infsupdec (-inf, inf))); %!assert (not (strictsubset (infsupdec (-inf, inf), infsupdec (-inf, inf)))); interval-3.2.0/inst/@infsupdec/subsasgn.m0000644000000000000000000000414013316017127016526 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} subsasgn (@var{A}, @var{IDX}, @var{RHS}) ## @defopx Operator {@@infsupdec} {@var{A}(@var{SUBS}) = @var{RHS}} ## ## Perform the subscripted assignment operation according to the subscript ## specified by @var{IDX}. ## ## The subscript @var{IDX} is expected to be a structure array with fields ## @code{type} and @code{subs}. Only valid value for @var{type} is ## @code{"()"}. The @code{subs} field may be either @code{":"} or a cell array ## of index values. ## @seealso{@@infsupdec/subsref} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-11-02 function A = subsasgn (A, S, B) if (nargin ~= 3) print_usage (); return endif if (not (isa (A, "infsupdec"))) A = infsupdec (A); endif if (not (isa (B, "infsupdec"))) B = infsupdec (B); endif A.infsup = subsasgn (A.infsup, S, B.infsup); A.dec(A.dec == 0) = uint8 (255); B.dec(B.dec == 0) = uint8 (255); A.dec = subsasgn (A.dec, S, B.dec); A.dec(A.dec == 0) = _com (); # any new elements are [0]_com A.dec(A.dec == uint8 (255)) = uint8 (0); endfunction %!test %! A = infsupdec (magic (3)); %! A(4, 4) = 42; %! assert (inf (A), [magic(3),[0;0;0];0,0,0,42]); %! assert (sup (A), [magic(3),[0;0;0];0,0,0,42]); %! assert (decorationpart (A), {"com", "com", "com", "com"; "com", "com", "com", "com"; "com", "com", "com", "com"; "com", "com", "com", "com"}); interval-3.2.0/inst/@infsupdec/subset.m0000644000000000000000000000532613316017127016215 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} subset (@var{A}, @var{B}) ## ## Evaluate subset comparison on intervals. ## ## True, if all numbers from @var{A} are also contained in @var{B}. ## False, if @var{A} contains a number which is not a member in @var{B}. ## ## Evaluated on interval arrays, this functions is applied element-wise. ## ## @seealso{@@infsupdec/eq, @@infsupdec/interior, @@infsupdec/disjoint} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = subset (a, b) if (nargin ~= 2) print_usage (); return endif if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = subset (a.infsup, b.infsup); result(isnai (a) | isnai (b)) = false; endfunction %!assert (subset (infsupdec (1, 2), infsupdec (1, 3))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.subset; %! for testcase = [testcases]' %! assert (isequaln (... %! subset (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.subset; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (subset (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.subset; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (subset (in1, in2), out)); interval-3.2.0/inst/@infsupdec/subsref.m0000644000000000000000000000620413316017127016355 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} subsref (@var{A}, @var{IDX}) ## @defopx Operator {@@infsupdec} {@var{A}(@var{I})} ## @defopx Operator {@@infsupdec} {@var{A}(@var{I1}, @var{I2})} ## @defopx Operator {@@infsupdec} {@var{A}.@var{P}} ## ## Select property @var{P} or elements @var{I} from interval array @var{A}. ## ## The index @var{I} may be either @code{:} or an index array. ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## The property @var{P} may correspond to any unary method of the interval's ## class, but usually is either @code{inf}, @code{sup} or ## @code{decorationpart}. ## ## @example ## @group ## x = infsupdec (magic (3), magic (3) + 1); ## x (1) ## @result{} ans = [8, 9]_com ## x (:, 2) ## @result{} ans = 3×1 interval vector ## [1, 2]_com ## [5, 6]_com ## [9, 10]_com ## x.inf ## @result{} ans = ## 8 1 6 ## 3 5 7 ## 4 9 2 ## @end group ## @end example ## @seealso{@@infsupdec/subsasgn} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-11-02 function A = subsref (A, S) if (nargin ~= 2) print_usage (); return endif switch (S (1).type) case "()" A.infsup = subsref (A.infsup, S(1)); A.dec = subsref (A.dec, S(1)); case "{}" error ("interval cannot be indexed with {}") case "." if (any (strcmp (S(1).subs, methods ("infsupdec")))) functionname = ["@infsupdec", filesep(), S(1).subs]; elseif (any (strcmp (S(1).subs, methods ("infsup")))) functionname = ["@infsup", filesep(), S(1).subs]; else error (["interval property ‘", S(1).subs, "’ is unknown"]) endif if (nargin (functionname) ~= 1) error (["‘", S(1).subs, "’ is not a valid interval property"]) endif A = feval (S(1).subs, A); otherwise error ("invalid subscript type") endswitch if (numel (S) > 1) A = subsref (A, S(2 : end)); endif endfunction %!assert (isequal (infsupdec (magic (3))([1, 2, 3]), infsupdec (magic (3)([1, 2, 3])))); %!# from the documentation string %!test %! x = infsupdec (magic (3), magic (3) + 1); %! assert (x(1) == infsupdec (8, 9)); %! assert (x(:, 2) == infsupdec ([1; 5; 9], [2; 6; 10])); %! assert (x.inf, magic (3)); %!assert (isequal (reshape (infsupdec (1:16), 2, 2, 2, 2)(2, 7), infsupdec (14))) %!assert (isequal (reshape (infsupdec (1:16), 2, 2, 2, 2)(:, 2, 2, 2), infsupdec ([15; 16]))) interval-3.2.0/inst/@infsupdec/sum.m0000644000000000000000000000364213316017127015513 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} sum (@var{X}) ## @defmethodx {@@infsupdec} sum (@var{X}, @var{DIM}) ## ## Sum of elements along dimension @var{DIM}. If @var{DIM} is omitted, it ## defaults to the first non-singleton dimension. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## sum ([infsupdec(1), pow2(-1074), -1]) ## @result{} ans ⊂ [4.9406e-324, 4.9407e-324]_com ## infsupdec (1) + pow2 (-1074) - 1 ## @result{} ans ⊂ [0, 2.2205e-16]_com ## @end group ## @end example ## @seealso{@@infsupdec/plus} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-01-31 function result = sum (x, dim) if (nargin > 2) print_usage (); return endif if (nargin < 2) ## Try to find non-singleton dimension dim = find (size (x.dec) ~= 1, 1); if (isempty (dim)) dim = 1; endif endif result = newdec (sum (x.infsup, dim)); if (not (isempty (x.dec))) warning ("off", "Octave:broadcast", "local"); result.dec = min (result.dec, min (x.dec, [], dim)); endif endfunction %!# from the documentation string %!assert (isequal (sum ([infsupdec(1), pow2(-1074), -1]), infsupdec (pow2 (-1074)))); interval-3.2.0/inst/@infsupdec/sup.m0000644000000000000000000000507613316017127015521 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} sup (@var{X}) ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## ## Get the (least) upper boundary for all numbers of interval @var{X}. ## ## If @var{X} is empty, @code{sup (@var{X})} is negative infinity. If @var{X} ## is NaI, @code{sup (@var{X})} is NaN. ## ## Accuracy: The result is exact. ## ## @example ## @group ## sup (infsupdec (2.5, 3.5)) ## @result{} ans = 3.5000 ## @end group ## @end example ## @seealso{@@infsupdec/inf, @@infsup/mid} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-09-18 function result = sup (x) if (nargin ~= 1) print_usage (); return endif result = sup (x.infsup); result(isnai (x)) = nan; endfunction %!assert (sup (infsupdec (2.5, 3.5)), 3.5); %!assert (sup (infsupdec ()), -inf); %!assert (sup (infsupdec ("[nai]")), nan); %!warning id=interval:UndefinedOperation %! assert (sup (infsupdec (3, 2)), nan); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.sup; %! for testcase = [testcases]' %! assert (isequaln (... %! sup (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.sup; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (sup (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.sup; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (sup (in1), out)); interval-3.2.0/inst/@infsupdec/tan.m0000644000000000000000000000504113316017127015464 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} tan (@var{X}) ## ## Compute the tangent in radians. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## tan (infsupdec (1)) ## @result{} ans ⊂ [1.5574, 1.5575]_com ## @end group ## @end example ## @seealso{@@infsupdec/atan, @@infsupdec/tanh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = tan (x) if (nargin ~= 1) print_usage (); return endif result = newdec (tan (x.infsup)); ## Because tan (nextdown (pi / 2)) < realmax, we can simple check for ## a singularity by comparing the result with entire. domain = not (isentire (result)); result.dec(not (domain)) = _trv (); result.dec = min (result.dec, x.dec); endfunction %!# from the documentation string %!assert (isequal (tan (infsupdec (1)), infsupdec ("[0x1.8EB245CBEE3A5, 0x1.8EB245CBEE3A6]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.tan; %! for testcase = [testcases]' %! assert (isequaln (... %! tan (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.tan; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (tan (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.tan; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (tan (in1), out)); interval-3.2.0/inst/@infsupdec/tanh.m0000644000000000000000000000470213316017127015637 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} tanh (@var{X}) ## ## Compute the hyperbolic tangent. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## tanh (infsupdec (1)) ## @result{} ans ⊂ [0.76159, 0.7616]_com ## @end group ## @end example ## @seealso{@@infsupdec/atanh, @@infsupdec/coth, @@infsupdec/sinh, @@infsupdec/cosh} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = tanh (x) if (nargin ~= 1) print_usage (); return endif result = newdec (tanh (x.infsup)); ## tanh is defined and continuous everywhere result.dec = min (result.dec, x.dec); endfunction %!test "from the documentation string"; %! assert (isequal (tanh (infsupdec (1)), infsupdec ("[0x1.85EFAB514F394p-1, 0x1.85EFAB514F395p-1]"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.tanh; %! for testcase = [testcases]' %! assert (isequaln (... %! tanh (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.tanh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (tanh (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.tanh; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (tanh (in1), out)); interval-3.2.0/inst/@infsupdec/tanrev.m0000644000000000000000000000773713316017127016217 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypemethod {@@infsupdec} {@var{X} =} tanrev (@var{C}, @var{X}) ## @deftypemethodx {@@infsupdec} {@var{X} =} tanrev (@var{C}) ## ## Compute the reverse tangent function. ## ## That is, an enclosure of all @code{x ∈ @var{X}} where ## @code{tan (x) ∈ @var{C}}. ## ## Accuracy: The result is a valid enclosure. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## No one way of decorating this operations gives useful information in all ## contexts. Therefore, the result will carry a @code{trv} decoration at best. ## ## @example ## @group ## tanrev (infsupdec (0), infsupdec (2, 4)) ## @result{} ans ⊂ [3.1415, 3.1416]_trv ## @end group ## @end example ## @seealso{@@infsupdec/tan} ## @end deftypemethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-19 function result = tanrev (c, x) if (nargin > 2) print_usage (); return endif if (nargin < 2) x = infsupdec (-inf, inf); endif if (not (isa (c, "infsupdec"))) c = infsupdec (c); endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif result = infsupdec (tanrev (c.infsup, x.infsup), "trv"); result.dec(isnai (c) | isnai (x)) = _ill (); endfunction %!# from the documentation string %!assert (isequal (tanrev (infsupdec (0), infsupdec (2, 4)), infsupdec ("pi", "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.tanRev; %! for testcase = [testcases]' %! assert (isequaln (... %! tanrev (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.tanRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (tanrev (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.tanRev; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (tanrev (in1), out)); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.tanRevBin; %! for testcase = [testcases]' %! assert (isequaln (... %! tanrev (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.tanRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (tanrev (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.tanRevBin; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (tanrev (in1, in2), out)); interval-3.2.0/inst/@infsupdec/times.m0000644000000000000000000000546513316017127016035 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} times (@var{X}, @var{Y}) ## @defopx Operator {@@infsupdec} {@var{X} .* @var{Y}} ## ## Multiply all numbers of interval @var{X} by all numbers of @var{Y}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## x = infsupdec (2, 3); ## y = infsupdec (1, 2); ## x .* y ## @result{} ans = [2, 6]_com ## @end group ## @end example ## @seealso{@@infsupdec/mrdivide} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = times (x, y) if (nargin ~= 2) print_usage (); return endif if (not (isa (x, "infsupdec"))) x = infsupdec (x); endif if (not (isa (y, "infsupdec"))) y = infsupdec (y); endif result = newdec (times (x.infsup, y.infsup)); ## times is defined and continuous everywhere result.dec = min (result.dec, min (x.dec, y.dec)); endfunction %!# from the documentation string %!assert (isequal (infsupdec (2, 3) .* infsupdec (1, 2), infsupdec (2, 6))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.mul; %! for testcase = [testcases]' %! assert (isequaln (... %! times (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.mul; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (times (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.mul; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (times (in1, in2), out)); interval-3.2.0/inst/@infsupdec/transpose.m0000644000000000000000000000311213316017127016715 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} transpose (@var{X}) ## @defopx Operator {@@infsupdec} {@var{X}.'} ## ## Return the transpose of interval matrix or vector @var{X}. ## ## @example ## @group ## infsupdec (zeros (1, 3), ones (1, 3)) .' ## @result{} ans = 3×1 interval vector ## [0, 1]_com ## [0, 1]_com ## [0, 1]_com ## @end group ## @end example ## @seealso{@@infsupdec/ctranspose} ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-11-02 function x = transpose (x) if (nargin ~= 1) print_usage (); return endif x.infsup = transpose (x.infsup); x.dec = transpose (x.dec); endfunction %!assert (isequal (transpose (infsupdec (magic (3))), infsupdec (magic (3).'))); %!# from the documentation string %!assert (isequal (transpose (infsupdec (zeros (1, 3), ones (1, 3))), infsupdec (zeros (3, 1), ones (3, 1)))); interval-3.2.0/inst/@infsupdec/tril.m0000644000000000000000000000467013316017127015663 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} tril (@var{A}) ## @defmethodx {@@infsup} tril (@var{A}, @var{k}) ## @defmethodx {@@infsup} tril (@var{A}, @var{k}, "pack") ## Return a new matrix formed by extracting the lower triangular part of the ## matrix @var{A}, and setting all other elements to zero. ## ## The second argument is optional, and specifies how many diagonals above or ## below the main diagonal should also be set to zero. ## ## If the option @option{pack} is given as third argument, the extracted ## elements are not inserted into a matrix, but rather stacked column-wise one ## above other. ## ## @seealso{@@infsupdec/triu, @@infsupdec/diag} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-08-04 function A = tril (A, varargin) if (nargin > 3) print_usage (); return endif if (nargin >= 2 && isa (varargin{1}, 'infsup')) error ('tril: invalid second argument; it must not be an interval'); endif if (nargin >= 3 && isa (varargin{2}, 'infsup')) error ('tril: invalid third argument; it must not be an interval'); endif A.infsup = tril (A.infsup, varargin{:}); A.dec(A.dec == 0) = uint8 (255); A.dec = tril (A.dec, varargin{:}); A.dec(A.dec == 0) = _com (); # any new elements are [0]_com A.dec(A.dec == uint8 (255)) = uint8 (0); endfunction %!assert (tril (infsupdec (magic (10))) == tril (magic (10))); %!assert (tril (infsupdec (magic (10)), 1) == tril (magic (10), 1)); %!assert (tril (infsupdec (magic (10)), -1) == tril (magic (10), -1)); %!assert (tril (infsupdec (magic (10)), 0, "pack") == tril (magic (10), 0, "pack")); %!test %! A = infsupdec (zeros (3), "trv"); %! assert (decorationpart (tril (A)), {"trv", "com", "com"; "trv", "trv", "com"; "trv", "trv", "trv"}); interval-3.2.0/inst/@infsupdec/triu.m0000644000000000000000000000467013316017127015674 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsup} triu (@var{A}) ## @defmethodx {@@infsup} triu (@var{A}, @var{k}) ## @defmethodx {@@infsup} triu (@var{A}, @var{k}, "pack") ## Return a new matrix formed by extracting the upper triangular part of the ## matrix @var{A}, and setting all other elements to zero. ## ## The second argument is optional, and specifies how many diagonals above or ## below the main diagonal should also be set to zero. ## ## If the option @option{pack} is given as third argument, the extracted ## elements are not inserted into a matrix, but rather stacked column-wise one ## above other. ## ## @seealso{@@infsupdec/tril, @@infsupdec/diag} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-08-04 function A = triu (A, varargin) if (nargin > 3) print_usage (); return endif if (nargin >= 2 && isa (varargin{1}, 'infsup')) error ('triu: invalid second argument; it must not be an interval'); endif if (nargin >= 3 && isa (varargin{2}, 'infsup')) error ('triu: invalid third argument; it must not be an interval'); endif A.infsup = triu (A.infsup, varargin{:}); A.dec(A.dec == 0) = uint8 (255); A.dec = triu (A.dec, varargin{:}); A.dec(A.dec == 0) = _com (); # any new elements are [0]_com A.dec(A.dec == uint8 (255)) = uint8 (0); endfunction %!assert (triu (infsupdec (magic (10))) == triu (magic (10))); %!assert (triu (infsupdec (magic (10)), 1) == triu (magic (10), 1)); %!assert (triu (infsupdec (magic (10)), -1) == triu (magic (10), -1)); %!assert (triu (infsupdec (magic (10)), 0, "pack") == triu (magic (10), 0, "pack")); %!test %! A = infsupdec (zeros (3), "trv"); %! assert (decorationpart (triu (A)), {"trv", "trv", "trv"; "com", "trv", "trv"; "com", "com", "trv"}); interval-3.2.0/inst/@infsupdec/uminus.m0000644000000000000000000000452413316017127016227 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defop Method {@@infsupdec} uminus (@var{X}) ## @defopx Operator {@@infsupdec} {-@var{X}} ## ## Negate all numbers in the interval. ## ## Accuracy: The result is exact. ## ## @example ## @group ## x = infsupdec (2, 3); ## -x ## @result{} ans = [-3, -2]_com ## @end group ## @end example ## @end defop ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = uminus (x) if (nargin ~= 1) print_usage (); return endif ## uminus is defined and continuous everywhere result = newdec (uminus (x.infsup)); result.dec = x.dec; endfunction %!# from the documentation string %!assert (isequal (-infsupdec (2, 3), infsupdec (-3, -2))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.neg; %! for testcase = [testcases]' %! assert (isequaln (... %! uminus (testcase.in{1}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.neg; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! assert (isequaln (uminus (in1), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsup.neg; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (uminus (in1), out)); interval-3.2.0/inst/@infsupdec/union.m0000644000000000000000000000725013316017127016036 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defmethod {@@infsupdec} union (@var{A}) ## @defmethodx {@@infsupdec} union (@var{A}, @var{B}) ## @defmethodx {@@infsupdec} union (@var{A}, [], @var{DIM}) ## ## Build the interval hull of the union of intervals. ## ## With two arguments the union is built pair-wise. Otherwise the union is ## computed for all interval members along dimension @var{DIM}, which defaults ## to the first non-singleton dimension. ## ## Accuracy: The result is exact. ## ## @comment DO NOT SYNCHRONIZE DOCUMENTATION STRING ## The function is a set operation and the result carries the @code{trv} ## decoration at best. ## ## @example ## @group ## x = infsupdec (1, 3); ## y = infsupdec (2, 4); ## union (x, y) ## @result{} ans = [1, 4]_trv ## @end group ## @end example ## @seealso{hull, @@infsupdec/intersect, @@infsupdec/setdiff, @@infsupdec/setxor} ## @end defmethod ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-13 function result = union (a, b, dim) if (not (isa (a, "infsupdec"))) a = infsupdec (a); endif switch (nargin) case 1 result = infsupdec (union (a.infsup), "trv"); result.dec = min (result.dec, min (a.dec)); case 2 if (not (isa (b, "infsupdec"))) b = infsupdec (b); endif result = infsupdec (union (a.infsup, b.infsup), "trv"); warning ("off", "Octave:broadcast", "local"); result.dec = min (result.dec, min (a.dec, b.dec)); case 3 if (not (builtin ("isempty", b))) warning ("union: second argument is ignored"); endif result = infsupdec (union (a.infsup, [], dim), "trv"); result.dec = min (result.dec, min (a.dec, [], dim)); otherwise print_usage (); return endswitch endfunction %!# from the documentation string %!assert (isequal (union (infsupdec (1, 3), infsupdec (2, 4)), infsupdec (1, 4, "trv"))); %!shared testdata %! # Load compiled test data (from src/test/*.itl) %! testdata = load (file_in_loadpath ("test/itl.mat")); %!test %! # Scalar evaluation %! testcases = testdata.NoSignal.infsupdec.convexHull; %! for testcase = [testcases]' %! assert (isequaln (... %! union (testcase.in{1}, testcase.in{2}), ... %! testcase.out)); %! endfor %!test %! # Vector evaluation %! testcases = testdata.NoSignal.infsupdec.convexHull; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! assert (isequaln (union (in1, in2), out)); %!test %! # N-dimensional array evaluation %! testcases = testdata.NoSignal.infsupdec.convexHull; %! in1 = vertcat (vertcat (testcases.in){:, 1}); %! in2 = vertcat (vertcat (testcases.in){:, 2}); %! out = vertcat (testcases.out); %! # Reshape data %! i = -1; %! do %! i = i + 1; %! testsize = factor (numel (in1) + i); %! until (numel (testsize) > 2) %! in1 = reshape ([in1; in1(1:i)], testsize); %! in2 = reshape ([in2; in2(1:i)], testsize); %! out = reshape ([out; out(1:i)], testsize); %! assert (isequaln (union (in1, in2), out)); interval-3.2.0/inst/__check_crlibm__.m0000644000000000000000000000346713316017127016035 0ustar 00000000000000## Copyright 2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun __check_crlibm__ () ## Check whether crlibm is available and working. ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2016-12-06 function result = __check_crlibm__ () if (exist ("crlibm_function") != 3) ## oct file not in the path result = false; endif persistent use_crlibm = verify_crlibm (); result = use_crlibm; endfunction function works = verify_crlibm () arithmetic_test_suite = fullfile (... fileparts (file_in_loadpath ("__check_crlibm__.m")), ... "test", ... "crlibm.tst"); if (exist (arithmetic_test_suite) == 0) ## test suite missing: assume that a package maintainer has removed it to ## save some space after having verified that the test suite passes. works = true; return endif works = test (arithmetic_test_suite, "quiet"); if (!works) warning ("interval:crlibm", ... "crlibm is not working properly, using MPFR as a fallback"); endif endfunction %!assert (__check_crlibm__ ()); interval-3.2.0/inst/__split_interval_literals__.m0000644000000000000000000002211213316017127020352 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun __split_interval_literals__ (@var{S}) ## ## Split string @var{S} into a cell array of interval literals. ## ## This is an internal function of the interval package and should not be used ## directly. ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-06-13 function result = __split_interval_literals__ (s) if (isempty (s)) result = { s }; return endif ## Split into rows, ## using newline characters, semicolon and rows in 2D strings as delimiters row = transpose (ostrsplit (s, ";\n")); ## Normalize delimiters between intervals within the same row row = strrep (row, "\t", ' '); row = strrep (row, '[', "\t["); # start of interval literals row = regexprep (row, '(](_\w*)?)\s*', "$1\t"); # end of interval literals ## Bare numbers “1 2, 3 4” shall be split into columns by spaces or commas [bare_numbers.s, bare_numbers.e] = regexp (row, '(^|\t)[^\t\[]+($|\t)'); for i = 1 : numel (row) for j = 1 : numel (bare_numbers.s {i}) select = bare_numbers.s {i} (j) : bare_numbers.e {i} (j); row {i} (select) = strrep (strrep (row {i} (select), ' ', "\t"), ... ',', "\t"); endfor endfor ## Separate columns within each row row = cellfun (@(s) strsplit (strtrim (s), "\t"), row, "UniformOutput", false); ## Fill short rows with empty columns cols = cellfun ('numel', row); max_cols = max (cols); for i = find (cols < max_cols)' row {i} = horzcat (row {i}, {"[Empty]"} (ones (1, max_cols - cols (i)))); endfor ## Build a 2D cell array from a cell array of cell arrays result = vertcat (row {:}); endfunction %!assert (__split_interval_literals__ (""), {""}); %!assert (__split_interval_literals__ (","), {""}); %!assert (__split_interval_literals__ ("1"), {"1"}); %!assert (__split_interval_literals__ ("1?"), {"1?"}); %!assert (__split_interval_literals__ ("1?u"), {"1?u"}); %!assert (__split_interval_literals__ ("1?u3"), {"1?u3"}); %!assert (__split_interval_literals__ ("[Empty]"), {"[Empty]"}); %!assert (__split_interval_literals__ ("[Entire]"), {"[Entire]"}); %!assert (__split_interval_literals__ ("[]"), {"[]"}); %!assert (__split_interval_literals__ ("[,]"), {"[,]"}); %!assert (__split_interval_literals__ ("[1]"), {"[1]"}); %!assert (__split_interval_literals__ ("[1,2]"), {"[1,2]"}); %!assert (__split_interval_literals__ ("1 2"), {"1", "2"}); %!assert (__split_interval_literals__ ("1, , , , , , ,2"), {"1", "2"}); %!assert (__split_interval_literals__ ("1;;2"), {"1"; ""; "2"}); %!assert (__split_interval_literals__ ("1; ;2"), {"1"; ""; "2"}); %!assert (__split_interval_literals__ ("[1,2] [3,4]"), {"[1,2]", "[3,4]"}); %!assert (__split_interval_literals__ ("[1,2],[3,4]"), {"[1,2]", "[3,4]"}); %!assert (__split_interval_literals__ ("[1,2], [3,4]"), {"[1,2]", "[3,4]"}); %!assert (__split_interval_literals__ ("[1,2]\n[3,4]"), {"[1,2]"; "[3,4]"}); %!assert (__split_interval_literals__ ("[1,2];[3,4]"), {"[1,2]"; "[3,4]"}); %!assert (__split_interval_literals__ ("[1,2]; [3,4]"), {"[1,2]"; "[3,4]"}); %!assert (__split_interval_literals__ (["[1,2]"; "[3,4]"]), {"[1,2]"; "[3,4]"}); %!assert (__split_interval_literals__ ("1 [3,4]"), {"1", "[3,4]"}); %!assert (__split_interval_literals__ ("1,[3,4]"), {"1", "[3,4]"}); %!assert (__split_interval_literals__ ("1, [3,4]"), {"1", "[3,4]"}); %!assert (__split_interval_literals__ ("1\n[3,4]"), {"1"; "[3,4]"}); %!assert (__split_interval_literals__ ("1;[3,4]"), {"1"; "[3,4]"}); %!assert (__split_interval_literals__ ("1; [3,4]"), {"1"; "[3,4]"}); %!assert (__split_interval_literals__ (["1"; "[3,4]"]), {"1"; "[3,4]"}); %!assert (__split_interval_literals__ ("[1,2] 3"), {"[1,2]", "3"}); %!assert (__split_interval_literals__ ("[1,2],3"), {"[1,2]", "3"}); %!assert (__split_interval_literals__ ("[1,2], 3"), {"[1,2]", "3"}); %!assert (__split_interval_literals__ ("[1,2]\n3"), {"[1,2]"; "3"}); %!assert (__split_interval_literals__ ("[1,2];3"), {"[1,2]"; "3"}); %!assert (__split_interval_literals__ ("[1,2]; 3"), {"[1,2]"; "3"}); %!assert (__split_interval_literals__ (["[1,2]"; "3"]), {"[1,2]"; "3"}); %!assert (__split_interval_literals__ ("1 3"), {"1", "3"}); %!assert (__split_interval_literals__ ("1,3"), {"1", "3"}); %!assert (__split_interval_literals__ ("1, 3"), {"1", "3"}); %!assert (__split_interval_literals__ ("1\n3"), {"1"; "3"}); %!assert (__split_interval_literals__ ("1;3"), {"1"; "3"}); %!assert (__split_interval_literals__ ("1; 3"), {"1"; "3"}); %!assert (__split_interval_literals__ (["1"; "3"]), {"1"; "3"}); %!assert (__split_interval_literals__ ("[1,2] [3,4] [5,6]"), {"[1,2]", "[3,4]", "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2],[3,4],[5,6]"), {"[1,2]", "[3,4]", "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2], [3,4], [5,6]"), {"[1,2]", "[3,4]", "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2]\n[3,4];[5,6]"), {"[1,2]"; "[3,4]"; "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2];[3,4] [5,6]"), {"[1,2]", "[Empty]"; "[3,4]", "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2] [3,4];[5,6]"), {"[1,2]", "[3,4]"; "[5,6]", "[Empty]"}); %!assert (__split_interval_literals__ ("1 [3,4] [5,6]"), {"1", "[3,4]", "[5,6]"}); %!assert (__split_interval_literals__ ("1,[3,4],[5,6]"), {"1", "[3,4]", "[5,6]"}); %!assert (__split_interval_literals__ ("1, [3,4], [5,6]"), {"1", "[3,4]", "[5,6]"}); %!assert (__split_interval_literals__ ("1\n[3,4];[5,6]"), {"1"; "[3,4]"; "[5,6]"}); %!assert (__split_interval_literals__ ("1;[3,4] [5,6]"), {"1", "[Empty]"; "[3,4]", "[5,6]"}); %!assert (__split_interval_literals__ ("1 [3,4];[5,6]"), {"1", "[3,4]"; "[5,6]", "[Empty]"}); %!assert (__split_interval_literals__ ("[1,2] 3 [5,6]"), {"[1,2]", "3", "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2],3,[5,6]"), {"[1,2]", "3", "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2], 3, [5,6]"), {"[1,2]", "3", "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2]\n3;[5,6]"), {"[1,2]"; "3"; "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2];3 [5,6]"), {"[1,2]", "[Empty]"; "3", "[5,6]"}); %!assert (__split_interval_literals__ ("[1,2] 3;[5,6]"), {"[1,2]", "3"; "[5,6]", "[Empty]"}); %!assert (__split_interval_literals__ ("[1,2] [3,4] 5"), {"[1,2]", "[3,4]", "5"}); %!assert (__split_interval_literals__ ("[1,2],[3,4],5"), {"[1,2]", "[3,4]", "5"}); %!assert (__split_interval_literals__ ("[1,2], [3,4], 5"), {"[1,2]", "[3,4]", "5"}); %!assert (__split_interval_literals__ ("[1,2]\n[3,4];5"), {"[1,2]"; "[3,4]"; "5"}); %!assert (__split_interval_literals__ ("[1,2];[3,4] 5"), {"[1,2]", "[Empty]"; "[3,4]", "5"}); %!assert (__split_interval_literals__ ("[1,2] [3,4];5"), {"[1,2]", "[3,4]"; "5", "[Empty]"}); %!assert (__split_interval_literals__ ("1 [3,4] 5"), {"1", "[3,4]", "5"}); %!assert (__split_interval_literals__ ("1,[3,4],5"), {"1", "[3,4]", "5"}); %!assert (__split_interval_literals__ ("1, [3,4], 5"), {"1", "[3,4]", "5"}); %!assert (__split_interval_literals__ ("1\n[3,4];5"), {"1"; "[3,4]"; "5"}); %!assert (__split_interval_literals__ ("1;[3,4] 5"), {"1", "[Empty]"; "[3,4]", "5"}); %!assert (__split_interval_literals__ ("1 [3,4];5"), {"1", "[3,4]"; "5", "[Empty]"}); %!assert (__split_interval_literals__ ("1 3 [5,6]"), {"1", "3", "[5,6]"}); %!assert (__split_interval_literals__ ("1,3,[5,6]"), {"1", "3", "[5,6]"}); %!assert (__split_interval_literals__ ("1, 3, [5,6]"), {"1", "3", "[5,6]"}); %!assert (__split_interval_literals__ ("1\n3;[5,6]"), {"1"; "3"; "[5,6]"}); %!assert (__split_interval_literals__ ("1;3 [5,6]"), {"1", "[Empty]"; "3", "[5,6]"}); %!assert (__split_interval_literals__ ("1 3;[5,6]"), {"1", "3"; "[5,6]", "[Empty]"}); %!assert (__split_interval_literals__ ("[1,2] 3 5"), {"[1,2]", "3", "5"}); %!assert (__split_interval_literals__ ("[1,2],3,5"), {"[1,2]", "3", "5"}); %!assert (__split_interval_literals__ ("[1,2], 3, 5"), {"[1,2]", "3", "5"}); %!assert (__split_interval_literals__ ("[1,2]\n3;5"), {"[1,2]"; "3"; "5"}); %!assert (__split_interval_literals__ ("[1,2];3 5"), {"[1,2]", "[Empty]"; "3", "5"}); %!assert (__split_interval_literals__ ("[1,2] 3;5"), {"[1,2]", "3"; "5", "[Empty]"}); %!assert (__split_interval_literals__ ("1 3 5"), {"1", "3", "5"}); %!assert (__split_interval_literals__ ("1,3,5"), {"1", "3", "5"}); %!assert (__split_interval_literals__ ("1, 3, 5"), {"1", "3", "5"}); %!assert (__split_interval_literals__ ("1\n3;5"), {"1"; "3"; "5"}); %!assert (__split_interval_literals__ ("1;3 5"), {"1", "[Empty]"; "3", "5"}); %!assert (__split_interval_literals__ ("1 3;5"), {"1", "3"; "5", "[Empty]"}); interval-3.2.0/inst/ctc_intersect.m0000644000000000000000000001151713316017127015460 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun ctc_intersect (@var{C1}, @var{Y1}, @var{C2}, @var{Y2}) ## @defunx ctc_intersect (@var{C1}, @var{C2}) ## ## Return a contractor function for the intersection of two sets. ## ## Functions @var{C1} and @var{C2} define two sets @code{S1 = @{@var{x} | ## @var{C1} (@var{x}) ∈ @var{Y1}@}} and @code{S2 = @{@var{x} | ## @var{C2} (@var{x}) ∈ @var{Y2}@}}. The return value is a contractor function ## for the set @code{S1 ∩ S2 = @{@var{x} | @var{C1} (@var{x}) ∈ @var{Y1} and ## @var{C2} (@var{x}) ∈ @var{Y2}@}}. ## ## Parameters @var{C1} and @var{C2} must be function handles and must accept ## the same number of parameters. See @command{@@infsup/fsolve} for how to ## define contractor functions. The user manual also contains an example on ## how to use this function. ## ## Instead of solving @code{@var{C1} (@var{x}) ∈ @var{Y1}} and ## @code{@var{C2} (@var{x}) ∈ @var{Y2}} separately and then compute an ## intersection of the result, you can solve ## @code{ctc_intersect (@var{C1}, @var{Y1}, @var{C2}, @var{Y2}) = 0}. ## ## @seealso{@@infsup/fsolve, ctc_union} ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-12-20 function c = ctc_intersect (ctc1, y1, ctc2, y2) ## Reorder parameters switch (nargin) case 2 ctc2 = y1; y1 = y2 = 0; case 3 if (is_function_handle (y1)) y2 = ctc2; ctc2 = y1; y1 = 0; else y2 = 0; endif case 4 ... otherwise print_usage (); endswitch ## Check parameters if (not (isa (y1, "infsup"))) y1 = infsup (y1); endif if (not (isa (y2, "infsup"))) y2 = infsup (y2); endif if (not (is_function_handle (ctc1)) && not (ischar (ctc1))) error ("interval:InvalidOperand", ... "ctc_intersect: Parameter C1 is no function handle") endif if (not (is_function_handle (ctc2)) && not (ischar (ctc2))) error ("interval:InvalidOperand", ... "ctc_intersect: Parameter C2 is no function handle") endif c = @(varargin) ctc_intersect_eval (ctc1, y1, ctc2, y2, varargin{:}); endfunction function varargout = ctc_intersect_eval (ctc1, y1, ctc2, y2, varargin) y = varargin{1}; x = varargin(2 : end); ## Always return at least one value if nargout == 0 nargout = 1; endif ## Evaluate each contractor function fval_and_contractions1 = nthargout (1 : nargout, ctc1, y1, x{:}); fval_and_contractions2 = nthargout (1 : nargout, ctc2, y2, x{:}); if nargout == 1 fval_and_contractions1 = {fval_and_contractions1}; fval_and_contractions2 = {fval_and_contractions2}; endif ## Compute fval = y if both function values are inside of their constraints fval1 = fval_and_contractions1{1}; fval2 = fval_and_contractions2{1}; fval1 = y + y_dist (y1, fval1); fval2 = y + y_dist (y2, fval2); varargout{1} = union (fval1, fval2); ## Both contractors must produce a subset of y. varargout{1}(disjoint (fval1, y) | disjoint (fval2, y)) = infsup (); ## Combine the contractions for i = 2 : nargout varargout{i} = intersect (fval_and_contractions1{i}, ... fval_and_contractions2{i}); endfor endfunction function d = y_dist (y, fval) d = infsup (idist (y, fval), hdist (y, fval)); d(subset (fval, y) & not (isempty (fval))) = 0; for i = 1:ndims (y) if (size (y, i) != 1) d = sum (d, i); endif endfor endfunction %!function [fval, x] = ctc_abs (y, x) %! fval = abs (x); %! x = absrev (intersect (fval, y), x); %!endfunction %!shared c %! c = ctc_intersect (@ctc_abs, "[0, 2]", @ctc_abs, "[1, 3]"); %!test %! [fval, x] = c (infsup (0), infsup ("[1, 3]")); %! assert (ismember (0, fval) && 0 != fval); %! assert (x == infsup ("[1, 2]")); %!test %! [fval, x] = c (infsup (0), infsup ("[1, 2]")); %! assert (0 == fval); %! assert (x == infsup ("[1, 2]")); %!test %! [fval, x] = c (infsup (0), infsup ("[entire]")); %! assert (ismember (0, fval) && 0 != fval); %! assert (x == infsup ("[-2, 2]")); %!test %! [fval, x] = c (infsup (0), infsup ("[0, inf]")); %! assert (ismember (0, fval) && 0 != fval); %! assert (x == infsup ("[1, 2]")); interval-3.2.0/inst/ctc_union.m0000644000000000000000000001175313316017127014612 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun ctc_union (@var{C1}, @var{Y1}, @var{C2}, @var{Y2}) ## @defunx ctc_union (@var{C1}, @var{C2}) ## ## Return a contractor function for the union of two sets. ## ## Functions @var{C1} and @var{C2} define two sets @code{S1 = @{@var{x} | ## @var{C1} (@var{x}) ∈ @var{Y1}@}} and @code{S2 = @{@var{x} | ## @var{C2} (@var{x}) ∈ @var{Y2}@}}. The return value is a contractor function ## for the set @code{S1 ∪ S2 = @{@var{x} | @var{C1} (@var{x}) ∈ @var{Y1} or ## @var{C2} (@var{x}) ∈ @var{Y2}@}}. ## ## Parameters @var{C1} and @var{C2} must be function handles and must accept ## the same number of parameters. See @command{@@infsup/fsolve} for how to ## define contractor functions. The user manual also contains an example on ## how to use this function. ## ## Instead of solving @code{@var{C1} (@var{x}) ∈ @var{Y1}} and ## @code{@var{C2} (@var{x}) ∈ @var{Y2}} separately and then compute an union of ## the result, you can solve @code{ctc_union (@var{C1}, @var{Y1}, @var{C2}, ## @var{Y2}) = 0}. ## ## @seealso{@@infsup/fsolve, ctc_intersect} ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-12-20 function c = ctc_union (ctc1, y1, ctc2, y2) ## Reorder parameters switch (nargin) case 2 ctc2 = y1; y1 = y2 = 0; case 3 if (is_function_handle (y1)) y2 = ctc2; ctc2 = y1; y1 = 0; else y2 = 0; endif case 4 ... otherwise print_usage (); endswitch ## Check parameters if (not (isa (y1, "infsup"))) y1 = infsup (y1); endif if (not (isa (y2, "infsup"))) y2 = infsup (y2); endif if (not (is_function_handle (ctc1)) && not (ischar (ctc1))) error ("interval:InvalidOperand", ... "ctc_union: Parameter C1 is no function handle") endif if (not (is_function_handle (ctc2)) && not (ischar (ctc2))) error ("interval:InvalidOperand", ... "ctc_union: Parameter C2 is no function handle") endif c = @(varargin) ctc_union_eval (ctc1, y1, ctc2, y2, varargin{:}); endfunction function varargout = ctc_union_eval (ctc1, y1, ctc2, y2, varargin) y = varargin{1}; x = varargin(2 : end); ## Always return at least one value if nargout == 0 nargout = 1; endif ## Evaluate each contractor function fval_and_contractions1 = nthargout (1 : nargout, ctc1, y1, x{:}); fval_and_contractions2 = nthargout (1 : nargout, ctc2, y2, x{:}); if nargout == 1 fval_and_contractions1 = {fval_and_contractions1}; fval_and_contractions2 = {fval_and_contractions2}; endif ## Compute fval = y if either function value is inside of its constraints fval1 = fval_and_contractions1{1}; fval2 = fval_and_contractions2{1}; fval1 = y + y_dist (y1, fval1); fval2 = y + y_dist (y2, fval2); varargout{1} = union (fval1, fval2); ## It suffices, if one contractor is a subset of y. varargout{1}(fval1 == y | fval2 == y) = y; ## Unite the contractions for i = 2 : nargout varargout{i} = union (fval_and_contractions1{i}, ... fval_and_contractions2{i}); endfor endfunction function d = y_dist (y, fval) d = infsup (idist (y, fval), hdist (y, fval)); d(subset (fval, y) & not (isempty (fval))) = 0; for i = 1:ndims (y) if (size (y, i) != 1) d = sum (d, i); endif endfor endfunction %!function [fval, cx] = ctc_sin (y, x) %! fval = sin (x); %! y = intersect (y, fval); %! cx = sinrev (y, x); %!endfunction %!function [fval, cx] = ctc_cos (y, x) %! fval = cos (x); %! y = intersect (y, fval); %! cx = cosrev (y, x); %!endfunction %!shared c %! c = ctc_union (@ctc_sin, 0, @ctc_cos, 0); %!test %! x = infsup (0); %! y = infsup (0); %! [fval, cx] = c (y, x); %! assert (fval == 0); %! assert (cx == 0) %!test %! x = infsup ("pi") / 2; %! y = infsup (0); %! [fval, cx] = c (y, x); %! assert (fval == "[0, 1]"); %! assert (cx == x); %!test %! x = infsup ("pi") / 4; %! y = infsup (0); %! [fval, cx] = c (y, x); %! assert (fval > 0); %! assert (isempty (cx)); %!test %! x = infsup (0, eps); %! y = infsup (0); %! [fval, cx] = c (y, x); %! assert (fval == "[0, 1]"); %! assert (cx == 0); %!test %! x = infsup ("[0, pi]") / 2; %! y = infsup (0); %! [fval, cx] = c (y, x); %! assert (fval == "[0, 1]"); %! assert (cx == x); interval-3.2.0/inst/empty.m0000644000000000000000000000507613316017127013770 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun empty () ## @defunx empty (@var{N}) ## @defunx empty (@var{N}, @var{M}) ## @defunx empty (@var{N}, @var{M}, @var{K}, ...) ## @defunx empty ([@var{N} @var{M} ...]) ## ## Return the empty interval. ## ## With additional parameters, create an interval vector/matrix/array, which ## comprises empty interval entries. ## ## The empty interval [Empty] contains no real numbers. All interval functions ## return an empty result if the input is either empty or outside of the ## function's domain. ## ## The empty interval carries the trivial @code{trv} decoration, which denotes ## that the empty interval cannot be the result of a function evaluation for ## a nonempty subset of its domain. ## ## Accuracy: The representation of the empty interval is exact. ## ## @example ## @group ## x = empty () ## @result{} x = [Empty]_trv ## inf (x) ## @result{} ans = Inf ## sup (x) ## @result{} ans = -Inf ## @end group ## @end example ## @seealso{@@infsup/isempty, entire} ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-27 function result = empty (varargin) persistent scalar_empty_interval = infsupdec (); result = subsref (scalar_empty_interval, ... substruct ("()", {ones(varargin{:})})); endfunction %!assert (inf (empty ()), inf); %!assert (sup (empty ()), -inf); %!assert (decorationpart (empty ()), {"trv"}); %!assert (inf (empty (5)), inf (5)); %!assert (sup (empty (5)), -inf (5)); %!assert (strcmp (decorationpart (empty (5)), "trv"), true (5)); %!assert (inf (empty (5, 6)), inf (5, 6)); %!assert (sup (empty (5, 6)), -inf (5, 6)); %!assert (strcmp (decorationpart (empty (5, 6)), "trv"), true (5, 6)); %!assert (inf (empty (5, 6, 7)), inf (5, 6, 7)); %!assert (sup (empty (5, 6, 7)), -inf (5, 6, 7)); %!assert (strcmp (decorationpart (empty (5, 6, 7)), "trv"), true (5, 6, 7)); interval-3.2.0/inst/entire.m0000644000000000000000000000543013316017127014112 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun entire () ## @defunx entire (@var{N}) ## @defunx entire (@var{N}, @var{M}) ## ## Return the entire set of real numbers. ## ## With additional parameters, create an interval vector/matrix/array, ## which comprises entire interval entries. ## ## The entire set of real numbers [Entire] is a closed interval. If used as ## an enclosure for a certain value, it represents a state of minimum ## constraints. An interval function which evaluates to [Entire] yields no ## information at all if no interval decoration is present. ## ## The special floating-point values -Inf and Inf represent boundaries of the ## entire set of real numbers. However, they are not members of the interval. ## ## The result of this function carries the defined and continuous @code{dac} ## decoration, which denotes that the interval is not bounded and therefore is ## no common interval. ## ## Accuracy: The representation of the entire set of real numbers is exact. ## ## @example ## @group ## x = entire () ## @result{} x = [Entire]_dac ## inf (x) ## @result{} ans = -Inf ## sup (x) ## @result{} ans = Inf ## @end group ## @end example ## @seealso{@@infsup/isentire, empty} ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-09-27 function result = entire (varargin) persistent scalar_entire_interval = infsupdec (-inf, inf); result = subsref (scalar_entire_interval, ... substruct ("()", {ones(varargin{:})})); endfunction %!assert (inf (entire ()), -inf); %!assert (sup (entire ()), inf); %!assert (decorationpart (entire ()), {"dac"}); %!assert (inf (entire (5)), -inf (5)); %!assert (sup (entire (5)), inf (5)); %!assert (strcmp (decorationpart (entire (5)), "dac"), true (5)); %!assert (inf (entire (5, 6)), -inf (5, 6)); %!assert (sup (entire (5, 6)), inf (5, 6)); %!assert (strcmp (decorationpart (entire (5, 6)), "dac"), true (5, 6)); %!assert (inf (entire (5, 6, 7)), -inf (5, 6, 7)); %!assert (sup (entire (5, 6, 7)), inf (5, 6, 7)); %!assert (strcmp (decorationpart (entire (5, 6, 7)), "dac"), true (5, 6, 7)); interval-3.2.0/inst/exacttointerval.m0000644000000000000000000000616713316017127016050 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun exacttointerval (@var{S}) ## @defunx exacttointerval (@var{L}, @var{U}) ## @defunx exacttointerval (@var{M}) ## ## Create a bare interval. Fail, if the interval cannot exactly represent the ## input. ## ## Typically, this function operates on interval literals @var{S}. It is also ## possible to pass lower and upper boundaries @var{L} and @var{U}, or create a ## point-interval with a midpoint @var{M}. ## ## All valid input formats of the @code{infsup} class constructor are ## allowed. By giving a cell as input it is possible to create ## N-dimensional interval arrays. If this function creates an ## interval array, all interval boundaries must be representable with ## binary64 numbers. ## ## Accuracy: The equation ## @code{@var{X} == exacttointerval (intervaltoexact (@var{X}))} holds for all ## intervals. ## ## @example ## @group ## w = exacttointerval ("[ ]") ## @result{} w = [Empty] ## x = exacttointerval ("[2, 3]") ## @result{} x = [2, 3] ## y = exacttointerval ("[,]") ## @result{} y = [Entire] ## z = exacttointerval ("[21e-1]") ## @print{} ??? exacttointerval: interval wouldn't be exact ## @end group ## @end example ## @seealso{@@infsup/intervaltoexact, @@infsup/infsup} ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-10-01 function result = exacttointerval (varargin) switch (nargin) case 0 [result, exactconversion] = infsup (); case 1 [result, exactconversion] = infsup (varargin {1}); case 2 [result, exactconversion] = infsup (varargin {1}, varargin {2}); otherwise print_usage (); return endswitch if (not (exactconversion)) error ("interval:UndefinedOperation", ... "exacttointerval: interval wouldn't be exact") endif endfunction %!assert (isempty (exacttointerval ("[Empty]"))); %!assert (isentire (exacttointerval ("[Entire]"))); %!test "common interval"; %! y = exacttointerval ("[0, 1]"); %! assert (inf (y), 0); %! assert (sup (y), 1); %!test "point interval"; %! y = exacttointerval ("[42]"); %! assert (inf (y), 42); %! assert (sup (y), 42); %!test "unbound interval"; %! y = exacttointerval ("[-4, Infinity]"); %! assert (inf (y), -4); %! assert (sup (y), inf); %!error exacttointerval ("[0, 0.1]"); %!error exacttointerval ("[1, 0]"); %!test "N-dimensional array"; %! i = infsup (reshape (1:24, 2, 3, 4)); %! assert (exacttointerval (intervaltoexact (i)) == i); interval-3.2.0/inst/hull.m0000644000000000000000000001752213316017127013575 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun hull (@var{X1}, @var{X2}, …) ## ## Create an interval enclosure for a list of parameters. ## ## Parameters can be simple numbers, intervals or interval literals as strings. ## If needed, broadcasting is performed. ## ## NaNs represent missing values and are treated like empty intervals. Inf and ## -Inf can be used to create unbound intervals, but note that these values ## will not be members of the interval. In particular, it is not possible to ## create an interval with @code{hull (inf)}. ## ## The result is equivalent to ## @code{union (infsupdec (@var{X1}), union (infsupdec (@var{X2}), …))}, but ## computed in a more efficient way. In contrast to the union function, this ## function is not considered a set operation and the result carries the best ## possible decoration, which is allowed by the input parameters. ## ## Warning: This function is not defined by IEEE Std 1788-2015 and shall not be ## confused with the standard's convexHull function, which is implemented by ## @code{union}. ## ## Accuracy: The result is a tight enclosure. ## ## @example ## @group ## hull (1, 4, 3, 2) ## @result{} ans = [1, 4]_com ## hull (empty, entire) ## @result{} ans = [Entire]_trv ## hull ("0.1", "pi", "e") ## @result{} ans ⊂ [0.099999, 3.1416]_com ## hull ("[0, 3]", "[4, 7]") ## @result{} ans = [0, 7]_com ## @end group ## @end example ## @seealso{@@infsupdec/union} ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-02 function result = hull (varargin) if (isempty (varargin)) result = infsupdec (); return endif l = u = cell (size (varargin)); ## Floating point numbers can be used without conversion floats = cellfun (@isfloat, varargin); l(floats) = u(floats) = varargin(floats); ## Convert everything else to interval, if necessary decoratedintervals = cellfun ("isclass", varargin, "infsupdec"); to_convert = not (decoratedintervals | floats); ## Use infsupdec constructor for conversion, because it can handle decorated ## interval literals. Also, it will trigger an interval:ImplicitPromote ## warning if necessary. varargin(to_convert) = cellfun (@infsupdec, varargin(to_convert), ... "UniformOutput", false ()); decoratedintervals = not (floats); ## Extract inf and sup arrays for remaining elements of l and u. l(decoratedintervals) = cellfun (@inf, varargin(decoratedintervals), ... "UniformOutput", false ()); u(decoratedintervals) = cellfun (@sup, varargin(decoratedintervals), ... "UniformOutput", false ()); ## Broadcast nonsingleton dimensions (otherwise cat would throw an error below) numberofdimensions = max (cellfun ("ndims", l)); sizes = zeros(numberofdimensions, size (l)(2)); for dim = 1:numberofdimensions sizes(dim, :) = cellfun("size", l, dim); endfor targetsize = max (sizes, [], 2); warning ("off", "Octave:broadcast", "local"); if (!all (or (targetsize == sizes, sizes == 1)(:))) error ("hull: dimensions mismatch") endif for dim = 1:numberofdimensions if (targetsize(dim) ~= 1) to_broadcast = sizes(dim, :) == 1; for i = find (to_broadcast) broadcastvector = ones (numberofdimensions, 1); broadcastvector(dim) = targetsize(dim); l{i} = repmat (l{i}, broadcastvector); u{i} = repmat (u{i}, broadcastvector); endfor endif endfor ## Compute min and max of inf and sup arrays, NaNs would be ignored and must ## be considered nans = false (targetsize); l = cat (numberofdimensions + 1, l{:}); nans(any (isnan (l), numberofdimensions + 1)) = true; l = min (l, [], numberofdimensions + 1); u = cat (numberofdimensions + 1, u{:}); nans(any (isnan (u), numberofdimensions + 1)) = true; u = max (u, [], numberofdimensions + 1); ## Compute best possible decoration dec = cell (targetsize); dec(:) = "com"; dec(not (isfinite (l) & isfinite (u))) = "dac"; dec(nans) = "trv"; ## Consider input decorations if (any (decoratedintervals)) dec = mindec (dec, cellfun (@decorationpart, ... varargin(decoratedintervals), ... "UniformOutput", false ())); endif nairesult = strcmp (dec, "ill"); emptyresult = isnan (l) | isnan (u) | l > u | nairesult; l(emptyresult) = u(emptyresult) = 0; dec(nairesult) = "com"; result = infsupdec (l, u, dec); result(emptyresult) = empty (); result(nairesult) = nai (); endfunction function decoration = mindec (decoration, decorations) ## Determine and apply the minimum decoration for i = 1 : length (decorations) if (iscell (decorations{i}) && not (isempty (decorations{i}))) otherdecoration = decorations{i}{1}; else otherdecoration = decorations{i}; endif ## Only check distinct elements for n = find (not (strcmp (decoration, decorations{i})))(:)' if (iscell (decorations{i}) && not (isscalar (decorations{i}))) otherdecoration = decorations{i}{n}; else ## Scalars broadcast into the whole cell array. The value is set ## once before the inner for loop. endif ## Because of the simple propagation order com > dac > def > trv, we ## can use string comparison order. if (!strcmp (decoration{n}, "ill") && ... (strcmp (otherdecoration, "ill") || ... sign ((decoration{n}) - otherdecoration) * [4; 2; 1] < 0)) decoration{n} = otherdecoration; endif endfor endfor endfunction %!assert (isnai (hull (nai))); %!assert (isempty (hull (nan))); %!assert (isequal (hull (2, nan, 3, 5), infsupdec (2, 5, "trv"))); %!assert (isequal (hull ([1, 2, 3], [5; 0; 2]), infsupdec ([1, 2, 3; 0, 0, 0; 1, 2, 2], [5, 5, 5; 1, 2, 3; 2, 2, 3], "com"))); %!assert (isequal (hull (magic (3), 10), infsupdec (magic (3), 10 (ones (3)), "com"))); %!assert (isequal (hull (2, magic (3), [nan, 2, 3; nan, 1, 1; 99, 100, nan]), infsupdec ([2, 1, 2; 2, 1, 1; 2, 2, 2], [8, 2, 6; 3, 5, 7; 99, 100, 2], {"trv", "com", "com"; "trv", "com", "com"; "com", "com", "trv"}))); %!assert (isnai (hull ([nai, 2])), logical ([1 0])); %!assert (isnai (hull ([nai, 2], [nai, 3])), logical ([1 0])); %!assert (isnai (hull ([nai, 2], nai)), logical ([1 1])); %!assert (isnai (hull ([nai, 2], [2, nai])), logical ([1 1])); %!assert (isequal (hull (zeros (2, 2, 2, 2), ones (2, 2, 2, 2)), infsupdec (zeros (2, 2, 2, 2), ones (2, 2, 2, 2)))) %!assert (isequal (hull (zeros (2, 1, 4, 1), ones (1, 3, 1, 5), -1), infsupdec (-ones (2, 3, 4, 5), ones (2, 3, 4, 5)))) %!assert (isnai (hull (zeros (2, 2, 2, 2), ones (2, 2, 2, 2), nai)), logical (ones (2, 2, 2, 2))) %!error hull (1:2, 1:3); %!error hull ((1:2)', (1:3)'); %!error hull (ones (2, 2, 2), ones (2, 2, 3)); %!test "from the documentation string"; %! assert (isequal (hull (1, 2, 3, 4), infsupdec (1, 4, "com"))); %! assert (isequal (hull (empty, entire), infsupdec (-inf, inf, "trv"))); %! assert (isequal (hull ("0.1", "pi", "e"), infsupdec (0.1 - eps / 16, pi + eps * 2, "com"))); %! assert (isequal (hull ("[0, 3]", "[4, 7]"), infsupdec ("[0, 7]_com"))); interval-3.2.0/inst/interval_bitpack.m0000644000000000000000000000627013316017127016150 0ustar 00000000000000## Copyright 2014-2016 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun interval_bitpack (@var{X}) ## ## Decode an interval from its interchange format. ## ## The input must either be a matrix of n × 128 bits for n bare intervals, or a ## matrix of n × 136 bits for n decorated intervals. Bits are in increasing ## order. Byte order depends on the system's endianness. First 8 bytes are ## used for the lower interval boundary, next 8 bytes are used for the upper ## interval boundary, (optionally) last byte is used for the decoration. ## ## The result is a row vector of intervals. ## ## Accuracy: For all valid interchange encodings the following equation holds: ## @code{@var{X} == bitunpack (interval_bitpack (@var{X}))}. ## ## @seealso{@@infsup/bitunpack, @@infsupdec/bitunpack} ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2014-12-23 function result = interval_bitpack (x) if (nargin ~= 1) print_usage (); return endif if (not (islogical (x))) ## Built-in function bitpack will fail on other data types error ("interval:InvalidOperand", ... ['interval_bitpack: parameter must be a bool matrix, ' ... 'was: ' typeinfo(x)]) endif switch size (x, 2) case 128 # (inf, sup) l = bitpack (x (:, 1 : 64)' (:), 'double'); u = bitpack (x (:, 65 : 128)' (:), 'double'); result = infsup (l, u); case 136 # (inf, sup, dec) l = bitpack (x (:, 1 : 64)' (:), 'double'); u = bitpack (x (:, 65 : 128)' (:), 'double'); d = bitpack (x (:, 129 : 136)' (:), 'uint8'); dec = cell (size (x, 1), 1); dec (d == 4) = 'trv'; dec (d == 8) = 'def'; dec (d == 12) = 'dac'; dec (d == 16) = 'com'; result = infsupdec (l, u, dec); otherwise error ("interval:InvalidOperand", ... ['interval_bitpack: invalid bit-length, ' ... 'expected: 128 or 136, ' ... 'was: ' num2str(size (x, 2))]) endswitch endfunction %!test "bare"; %! littleendian = bitunpack (uint16 (1))(1); %! b = zeros (1, 128); %! if (littleendian) %! b([52, 63, 117, 127]) = 1; %! else %! b([7, 12, 71, 77]) = 1; %! endif %! decoded = interval_bitpack (logical (b)); %! assert (eq (decoded, infsup (3, 4))); %!test "decorated"; %! littleendian = bitunpack (uint16 (1))(1); %! b = zeros (1, 136); %! if (littleendian) %! b([52, 63, 117, 127, 133]) = 1; %! else %! b([7, 12, 71, 77, 133]) = 1; %! endif %! decoded = interval_bitpack (logical (b)); %! assert (eq (decoded, infsupdec (3, 4))); interval-3.2.0/inst/midrad.m0000644000000000000000000001475413316017127014075 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {@var{I} =} midrad (@var{M}, @var{R}) ## @deftypefunx {@var{I} =} midrad (@var{M}) ## @deftypefunx {@var{I} =} midrad () ## @deftypefunx {[@var{M}, @var{R}] =} midrad (@var{I}) ## ## Create an interval enclosure @var{I} for [@var{M}-@var{R}, @var{M}+@var{R}]. ## ## With two output arguments, compute a rigorous midpoint @var{M} and ## radius @var{R} for interval @var{I}. ## ## Without input parameters, return the empty interval. With only one input ## parameter, the radius @var{R} defaults to zero. ## ## Parameters can be simple numbers, intervals or interval literals as strings. ## If needed, broadcasting is performed. ## ## The result is not guaranteed to be tightest if parameters are given as ## strings. This is due to intermediate results. The infsupdec constructor ## with interval literals in uncertain form @code{m?ruE} can instead be used to ## create tight enclosures of decimal numbers with a radius. ## ## Accuracy (with one output argument): The result is an accurate enclosure. ## The result is tightest if @var{M} and @var{R} are floating-point numbers or ## intervals. ## ## Accuracy (with two output arguments): @var{M} is the interval's midpoint ## in binary64 precision, rounded to nearest and ties to even. The returned ## radius @var{R} will make a tight enclosure of the interval together with ## @var{M}. That is, @var{R} is the smallest binary64 number, which will make ## [@var{M}-@var{R}, @var{M}+@var{R}] enclose the interval @var{I}. ## ## @example ## @group ## midrad (42, 3) ## @result{} ans = [39, 45]_com ## midrad (0, inf) ## @result{} ans = [Entire]_dac ## midrad ("1.1", "0.1") ## @result{} ans ⊂ [0.99999, 1.2001]_com ## midrad ("25", "3/7") ## @result{} ans ⊂ [24.571, 25.429]_com ## @end group ## @end example ## @seealso{@@infsupdec/infsupdec, hull, @@infsupdec/mid, @@infsupdec/rad} ## @end deftypefun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-03-06 function [m, r] = midrad (m, r) if (nargout > 1) warning ("off", "id=interval:ImplicitPromote", "local"); endif switch nargin case 0 i = infsupdec (); case 1 if (nargout == 2 && isa (m, "infsup")) i = m; else i = infsupdec (m); endif case 2 if (isfloat (m) && isreal (m) && ... isfloat (r) && isreal (r)) ## Simple case: m and r are binary64 numbers l = mpfr_function_d ('minus', -inf, m, r); u = mpfr_function_d ('plus', +inf, m, r); i = infsupdec (l, u); else ## Complicated case: m and r are strings or other types m = infsupdec (m); if (not (isa (r, "infsup"))) ## [-inf, r] should make a valid interval, unless r == -inf ## Intersection with non-negative numbers ensures that we ## return [Empty] if r < 0. if (isfloat (r)) r(r == -inf) = nan; endif r = intersect (infsupdec (-inf, r), infsupdec (0, inf)); ## Fix decoration, since intersect would return “trv” at best. legal_radius = not (isempty (r)); r(legal_radius) = newdec (intervalpart (r(legal_radius))); endif if (isa (r, "infsupdec")) dec_r = decorationpart (r); else dec_r = {"com"}; endif sup_r = sup (r); sup_r(sup_r < 0) = -inf; r = infsupdec (-sup_r, sup_r, dec_r); i = m + r; endif otherwise print_usage (); endswitch switch nargout case {0, 1} m = i; case 2 m = mid (i); ## The midpoint is rounded to nearest and the radius ## must cover both boundaries r1 = mpfr_function_d ('minus', +inf, m, inf (i)); r2 = mpfr_function_d ('minus', +inf, sup (i), m); r = max (r1, r2); otherwise print_usage (); endswitch endfunction %!assert (isempty (midrad ())); %!warning id=interval:UndefinedOperation %! assert (isnai (midrad (0, -inf))); %!warning id=interval:UndefinedOperation %! assert (isnai (midrad (0, -.1))); %!warning id=interval:UndefinedOperation %! assert (isnai (midrad (0, "-.1"))); %!warning id=interval:UndefinedOperation %! assert (isnai (midrad (0, infsup("-.1")))); %!assert (isequal (midrad ("pi"), infsupdec ("pi"))); %!warning id=interval:ImplicitPromote %! assert (isequal (midrad (infsup (2), 2), infsupdec (0, 4))); %!assert (isequal (midrad (2, infsup (2)), infsupdec (0, 4))); %!warning id=interval:ImplicitPromote %! assert (isequal (midrad (infsup (2), infsup (2)), infsupdec (0, 4))); %!assert (isequal (midrad (2, infsupdec (2)), infsupdec (0, 4))); %!assert (isequal (midrad (infsupdec (2), 2), infsupdec (0, 4))); %!warning id=interval:ImplicitPromote %! assert (isequal (midrad (infsup (2), infsupdec (2)), infsupdec (0, 4))); %!assert (isequal (midrad (infsupdec (2), infsup (2)), infsupdec (0, 4))); %!assert (isequal (midrad (infsupdec (2), infsupdec (2)), infsupdec (0, 4))); %!assert (isequal (midrad (1, magic (3)), infsupdec ([-7, 0, -5; -2, -4, -6; -3, -8, -1], [9, 2, 7; 4, 6, 8; 5, 10, 3]))); %!assert (isequal (midrad (magic (3), 1), infsupdec ([7, 0, 5; 2, 4, 6; 3, 8, 1], [9, 2, 7; 4, 6, 8; 5, 10, 3]))); %!# from the documentation string %!assert (isequal (midrad (42, 3), infsupdec (39, 45))); %!assert (isequal (midrad (0, inf), entire ())); %!assert (isequal (midrad ("1.1", "0.1"), infsupdec (1 - eps, "1.2"))); %!# N-dimensional arrays %!assert (isequal (midrad (zeros (2, 2, 2), ones (2, 2, 2)), infsupdec (-ones (2, 2, 2), ones (2, 2, 2)))); %!assert (isequal (midrad (zeros (2, 2, 2), 1), infsupdec (-ones (2, 2, 2), ones (2, 2, 2)))); %!assert (isequal (midrad (0, ones (2, 2, 2)), infsupdec (-ones (2, 2, 2), ones (2, 2, 2)))); %!test %! [M, R] = midrad (infsupdec (-ones (2, 2, 2), ones (2, 2, 2))); %! assert (M, zeros (2, 2, 2)); %! assert (R, ones (2, 2, 2)); interval-3.2.0/inst/nai.m0000644000000000000000000000427613316017127013402 0ustar 00000000000000## Copyright 2015-2016 Oliver Heimlich ## Copyright 2017 Joel Dahne ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @defun nai () ## @defunx nai (@var{N}) ## @defunx nai (@var{N}, @var{M}) ## @defunx nai (@var{N}, @var{M}, @var{K}, ...) ## @defunx nai ([@var{N}, @var{M}, ...]) ## ## Return the ill-formed decorated interval, called NaI (Not an Interval). ## ## Ill-formed intervals are the result of an illegal interval creation, e.g. ## @code{[3, 2]}. They occur if the @code{infsupdec} constructor is called ## with an invalid input and survive through interval arithmetic computations. ## Boolean comparisons on NaIs return @code{false}, i.e. @code{[NaI] == [NaI]} ## is false. ## ## The interval part of NaI is undefined. The decoration part of NaI is ## @code{ill}. ## ## The infsup constructor will not produce NaIs, but a warning instead. ## ## @example ## @group ## x = nai () ## @result{} x = [NaI] ## x + 42 ## @result{} ans = [NaI] ## @end group ## @end example ## @seealso{@@infsupdec/infsupdec} ## @end defun ## Author: Oliver Heimlich ## Keywords: interval ## Created: 2015-02-22 function result = nai (varargin) persistent scalar_nai_interval = infsupdec ("[nai]"); if (nargin == 0) result = scalar_nai_interval; else result = subsref (scalar_nai_interval, ... substruct ("()", {ones(varargin{:})})); endif endfunction %!assert (isnai (nai ())); %!assert (isnai (nai (2)), true (2)); %!assert (isnai (nai (3, 4)), true (3, 4)); %!assert (decorationpart (nai ()), {"ill"}); %!assert (isnai (nai (2, 2, 2)), true (2, 2, 2)) interval-3.2.0/inst/test/crlibm.mat0000644000000000000000000257112413316017127015412 0ustar 00000000000000y8VmB$%YCkנ!QJBBR2!"2'<@gAܗs^}o۳}ܶNGǡeym}S7R)] h, a&fv[̀Xh!76;h ~DGaeI;:!1:!a9?ܞq)D= zgY=N1z8q-ooAuYK (t33vjz8u'O'Y z7y%~!Oӭ$u7RVvfN'I7u2)g;Qrz??s`~v~+3#,gTZ4v˦nR9UG=KbSl0ihV">.UpS<"ϬN|8Sc!98G灼eSe3!V݋PQ|m'@vR '74Hb&O,N>i6|&5}^R Lּ`Cr/ܗesAJW`l0oԭSXnqG)K^eѸ&lȎg'm밣|j~h6&{`%4CX&vZPSk`9&ex&&14k'{w}&?F&yG͚/{[_=`u}lԶ msf:.hKKDos.uO>ݹgKݷy.u'LGn?I*Fuj{pB$x/I~iL^>Ms ]N~=5>d^$۰۹R"B?ڰa&%6zw1wLv fPb1hLĨ|קtu$`[m,Z`r4_b R2bKjDD0I.K*FoE!)o"_k[@( )'RZyb 0m=p3گ2S2WvOgmC)]g_;ήzbM|}O +q}p8Vnx3և$ pҲ[Nxٯr8?=|N{$sU'88wgD浺N}+yoH5-1jub8O-8EX6 Ub9#LNlc ?װ<@0RK|oCʙeR4`͹Wuzqpcq`:ȹ5z|;Ɓ'wS(k;9߾{Wn ĭs[:RW<ϥnKxw8yN8s.upwuok\x$y;xRIYQwKRɳɈvWŭLQEԩ:zS|B;ßOS#S&l:kiƌtdT?x0t. A8:;}O崨Me9Gܕ ^ qi'u\.ac}W>v'i{?.Ѵ[ {E+AovJ{ÛjyG*5x"\p΅]Βη&bρm-m_xPB]]4=0p?\z_V&G6S#%_ߛSvS-`ptF7mU!4qZ_Y^H0of#㖉X5#Fle:v/[ƵbKRمRD*[!&%Ku4N-R&챪#3luo{ /ˁ&X^7 vpXI`:71 X _` ɩ[=^o @#H/\#/vdui81~lI) Y]8q:$μny9U<$GJȳ[7BplKTCl pr[ xH`ֱvZiL=[ݥ'df:_}7"3v;3+>rXgc9"WŸǀ'2/u|#ʏZ^ыSЮde^{浐x^X͑f@-/ha!޳(:^+I]pק鼡Hp]}_LLNJo }_ ~I˔WEX2D;s*0&ߝfaP)^z =w՟b,fN>6Fz5.^ KpxbD݃{Qe* td;$Y3~a!rb ݈a,Tp24 /00(*7߱ێߓ~"~v7|3?pV>X%/7~Ş%Rl~uX6}U)P %-}F1KYFfw,VYӸ4hklc. ;il"/9߻,%+>Jķf1J ?ڷz7~u3ݰR`3= 1Ǖ5e,mZO0r|3'(VX}TVQl6[r^kW?lÍD=| ׍ͬ=tekKeZ~k#pu虡~' H8]1|K]_ ˎ=& 3<ct8pobyQ<ap_Eg+='lwH yQ,S)ޛ `P1}[䧏W^+ u[^3H=Kp5ׇ^b|?>4.Dס 7&do)O-&z`xzqxi) /~E"Z;C;U)p_c)S$>jvbōϟ`"Oz\\$"Zi B:%{K{8*\M&S!fqDna%v뉶0>yUjw6]emku o{* ౸~JZ~5_\l.9> 7;]m:6'ALKfqj=K,tkpW=6>e[=-9=iV85>p 4a`#~Nc'#* [#62:p`9=gbuO(1j& ͮASW75-7Cp>-֍YŪvWR x.JĤnp!~}5xH.fLŌ2'aqo^n^8varYEK˭ EO}: j`Ww345-a+)..Lb7_v$T't3+ =t$иc(҇eEHVXu@Clpٜu>u'+%hX} \M"A'6Ge<֗=n끛1ttpY6j;DJ؇JO^e^u J3Pâ[5f<(beagZpoͻ r; Y2L[L׍BK9]Rw~]'/3Zl3|A0z`ezp06DncZ O-rH gPoK_/yT29]kJа"T^'X#6M1#>;ѭ (/t Eִb~rkwrB} +5xP}OO:poHm#/.@{KO#*_pHeO})wY_]EIN~(\}rf}~2%H:;}*\9w5/tBP=S֋+6j*p;83[ϝs{l&y U9Tp|Qn%X'/g,>FOv|nz:?x3sdNVetK_߄gu.FүV\œyko2F2~8^?^%FHH1fA:7pXxmFM86S8B ߫7kU FNj1&uSU3;0\DJx<Po^{C<[qm@իx0@oN9s94]6I7&]3mz`2k7J.c  XGQh:(~,rNfh撎hDZo/' "/_s\? > ^\ٲ.(=MS~P!^ Lg;5jzh{j] ?:GyXa-쌙˶@qliYl#hfiD龆KE[ lsNu0x*"$b'<>߀p;/k+~LB+Rg]}z57-v.[í!|XP%|j.`u3&^2X0h \\93%*z8;,ZW#>ZF040K1>m޽YKOLO7˴# ͼ䗃jgzrFp"$>^=BUiW6ߒ)Z'af&x|U,_.|ńJr?j}CpLd|(N%F{lTjǢ*8$S|UKyHeT*U$_e2&|U_ૻ _8H;W񈯤k>|WO̻l| (*|W=kսfW-4Z8s*q_U *WI3 @nWfT=R'P|U8Nix\; g߷iWb rعJs_p[WkWJy W4D|DbL׎_f]6mz_u?l_W% |k|&Cث_UzWvNm+;t;`fʼn[$_]ݷWv:_] zO՛k3<}allWkj)8@Ǿ4ro _p7|%M @^$_ ?#%+ _}>BUs 4Th|u W?_scUF_}p)۪!ck}&b~`r-6WLj$_z|~LW[᫽; &x|?[+|*|O9sk9զl'EU1KtK CWI%Q-UؾQWXI Iy˿ }(b@|VWѺv_S|3=LՉm1~ +W*$_(*`

βu*j\^_br)<ȘΡ _3|XW"+W 4*=M++`aP2W4ԡ񕀰'Wz/h|{N-{HC|+X_"[^غg˄BIjUL|nN%j`WG~=}DWlpXW'|䫈ߙ_5j+BW *Qi GzUl^ h|Ut 'W{/m"j5]N%u-W R|e0YO򕌭WW$h|u$H c)|FaZȳ|Ղ.㈯,yr) (,2Y/0_mF|5B{IrEUIW Xw|%'HUj WA|6_AD|WE*|iHpk/'_ 7&b![ )W>$+c4I\8j$ߩK_) D՚_{AU_wҮ>FUԞf`h%tWEZN_N~3P` WIP0Wg_*ܢPmk_ J F!2R*4s{g1侮MU۔Ϸar>VsF|e5zWsjLx+~$_4̟ ʅbO|uIW_wph9h|Q׺,+~_em}'Z,ޮ& `O0\sA򕭜Wn G 2z9 z^BjHQ]3h|lkOI /th)} u~bΦ+CF_ocvvO4Z⫻Or37P|sh>W߯S|ૐe-+o˾U7`P%h|^IWS)rC|fox|e\+] >h*VTυ+VS|7U_=pJvzi|Wi.'V=vD)lO+FA_eaׅ!Jr;tρZR|%Dp%W&>__'r|U<9I')|&ؓC߿k J$_)ɗS|`C_m*Յ_7{2q*&_2zM,UibWi_q!j\WQ4bz}.+W+WżH*g};h`jɅR|շb5;nK:1+E_p |P$l0g]>",ӝqye.:_=Im_I_Q;Eo~*{Ǎ$_J]P@`9+ _ծP%8mzS ֌6zr.|ZV WP,!07:HB^Knab"I,5xkMp cu>Tvt .ch[L#=xlzG|%'L\!P]M/G^{enW=6 P/.[vU_~<5 _vK_rmİ(<]zui84YD1vjWx݂FU3.`K6`"ӗ [V5urs pWgϭ2(kj =|vgeur O,/?JDlk*灖0CohrcwHl-M^ϋzOWB<ϛ2]Pv"%7v|P9XVp<gW,.WwN–Ҳ3UMPP;zvjp!isk%TQTNWfV,"{'Q(5eͯwX浐tk[{fRµMα=愒wOmm4]֒LJqsA1->OpdQ}PÙNs98lnXs!iX>:)*x&M"׈O. ݽQ& ?v܉ `-^5մK/ j0xwĤ6y(7}/R)ûU,^#KnlFbz<`7vf@zŸ2م E˳V==-Ј[U7ʃswOrW`gu^yBJKcΛ?¼z\Nµ&0KeŌBvnB q#-;7HXXk5"MG2Hr(bovHpxu M9NלGN- 3ƾCKoff`?ƱڛXu:@3>ʈ 0g]0fiGwil7>&Zo6`Ss}3g-oq~mb%% l2' ;k&;.|iUe dm?.".lSW]6FvX~n2,RwyWbբ}oCLc6T-łkKf~OYiIk L̳I7x/Lo)M9 ꤱ=/dW.Iwdȷٯ;CVd0O%rYEu)~e8&{Hj{+ynX)!5)T]v= 4Oxtt9߼[}M{G`- XX5sЍv '.g_&wgoo oq~21W SF^m:Kf#MA+L|4VFK>gFw [Y]lz <:YP'r֩طN_*~R͛[BدC91}/nޙ_*ɸT,}wK e%y 1zzFo4!8;&d$.Nn\ҟ!LJaLkvIpj]?na|w`9~?4q[ᘑ+`8|uRLXZwCJ&m_ uv>B쌯x5^m i׎ #˻Z4GbۂtAUO3! aM[>.ʄxScFWmȹLʛYǭleSF N ۥZ}9hăۗ._Y5la+i Pz(Hdn-H+xy}n{"Zrѡudݡ=}uwɍ>orG$>\KІ YJ\Zha`YoW z/ raP|TP~(d[o!x+/zʆX P5BG1#w+% |/vŠ.(3FEýoɰQb{x9kt6NxKM<tYL >آ#ǜM3@iaŅ_/ ![`VUʼn/znkЇUS'hOpXgFWƐ;}~\eNL##\ |<9 4 IߐI V2`Uej>Ǖ<.-s6-%ީB˖ƋK!{&nǝ`ñG'ؠұaL,!"k6{|;rYձWxC&mW!O$o:VR|)t4Naڞ+|SQk$$ZC41;hIZgV'Ժ \r5a_ڏnfPsB V3yCx7b&vG(O ˮl\12.;j%:-&hqsMQ(Z:9BVW}֧[?:\ ԻLX208Z0`at6ثog, ;sּ߇0X?#뎏?R2w<ᳰC'&^Z}2f{U6<JXNHʤpMَokpTGZl }՝Lnz}%Y'a;XbﷺX|UI\{y{n]' ;0NOUo񁇲"ΐDa5-qwVQ0`,ny]4o=5<7F̔pI}|Cƈ >w'5 8*8kг[ۑRP\ T6|iv~ ~Eoe1׉CA pE+8~yݓO}Eߑ0V]Sӫ&78*d<龾h+𒛁:#=0HHݤgwy XbuEe `†Kq7lb|B>#}돾 @mg\oZ\H-TO>:Ҋ`SdӘCx=(s`Qt_hp UuLOly+A ē i/?D;X4n&=~|{'TCоN%r2>Іn)Z})er1Y9؀V}F ԈN`! ,m{+NinQӥ pff@vL]LyWI_z+]Sa' H?%V_ro] \@0'?)ϩՁtqu%9 $}e@'6rU'~>,hn *$ƻ f+PE>}:yA`2v5==T=D9q@z z=5uA z]yz=?~=`= (Sӹ6/G2fѨD6??O1ë%~߶ wWׁ4g~@c:ΈS{ bx9|`c p@mX/ʝ8p2}E^P2x9 w~ 2y2>X| 6%~R띺TT@0ӡ|m vK֎1Ƒn,p!IVܡq~v[S䠏cԷ^JT6V\tnO᧴סӧ@33ކ`5yG'@4B\LX;B\C ;%.8ٝBom狻Hr1ƅw+QdwLÂ$çR;6]Ⱍ$jY \1v{X:B0#t(`\]7窡1<7bxC4)l`?1U!  J1[ZWtT .R/vB4 Cow` &M/J>nǗܴ(P bx5NÛG? Yjbx4uE~28l:ӻ;8Fcx:3CS.k#wP ѵ o]XhX<ب <]K0MeXq^GߔT!+bR$ÿB2;P k"O2"YLqX谔b2Yh :Mr a w2S by`_?t2|k>jA%1'M 1 bx ?'%'dM"osyxY͕&Ecٯh^K!P`|57Z_}Mcx7ßJ1|C R oqʎdJ wާ+;>%PL߷'x1|$×!G0)Fߥ1!qoX]=`EËt 14}Dcx__ .M2 :,34ZgE2|o1i _ТW`-O):n !]$[ZMR /3+, mxo_rl{^>O2_wIS 1[ٽ{H/ bʪv˲@ a97i Eۓ& @S_wF q /X/-;5)4~(!qF:B(/> %_{h>wZ1kH cnB2*C ϻ"xkxUe-ACbxG9? >~bIo o|9py6dxZ[s#ob b߮4_BcV䁳HHɓ`x9 ?{Ӏk?$kH,*LJiqcaZ/I%5nV؎F+h ;I0YHӕd|a0zc+X𻗙Ǔ 1gwfHK3Y \%?ᓄ(7_N0|ŖP sbƽ\~HdK֘ x(]b]/.|, $$> zM~бPTdd4[CtJ_]/[h ߊiOC*=}nbx3=I^J1|Oec-[mh ^_3 9L=@d1BkKó$p)6T:cYi +bk {Z"OlV4 ?Ųɇ`x=wx0 ;;'!w JOa`xg dH0LC ?i uI돋P\f8t_Lc gkh$Ί}֙F+ˠbxcN?F : x% ߩ_A1^odxn4?SA2bxvBkI1|2'kh ~Y+;|h HEi ?i\`Nj z]5ÿ}@0ч%<WG=aq(I0st{eDH>J1otwɐ A~@$> PPdxΈEv$ÛԥDŽl?ߋr ?oK2#1R;|Ab>!b7锹#ëpߔ;䟠1uLǒ ΅m4_O1 G6/~K(drO? bn  vdV6$ MJ2oixTb64_7*E0n/j Գ4 _[XZz8V>&fn~y=q/ T]{4I1(* RoPN5i 9N2|bxDž˝*o ֻ.')h'~d$F#Ws`?Acxyi&a(=kyh _O$\)g~?5i ;z~ II#CU)/VD1 ,g -:fE2Ic"^.bqd54WHcx;A:(Ɔ|2zbjßs1|0bxa:~?#3I2|Cǟ$3&.&aI9x(&bxW_W?7F ?q-[ ?Av.P^F2>fu}5%2ӋbxJ!j B2ƞ3:N b?% oS2J1ܹp_iD ⦳/+yM1|b2G 1g,&~_WnmM'`rp13 |x.V߷?cG  o>Ӯ2>srμ ; XǚdLEq )Xb7F|^1jK\ Om^4IZ ,;70(ە`݈Z_^=J-F23"{"/E >ʷZVXI`S ?~yhL23K}mk&F/Z5 4JW&%ּ򃳓Eܪvoooooooooooooooooo \nEt):G?6L9ЯzMyЯmT}<ܩ<\8ڜ0z7w*TTc5GUjR%QmUjPjDjp-BHčSj0/jp/BAč1P5XU"nB`T F/P58U!F)T F෨U#n@T @_lkQ5q"@`ST fG'Q5XUc7jp9gjc삸U#Q5xUj1j# U{Q5x҂UWjp5' nDXqcϾDP5<j[jpϾOcP5Ug߷Q5jT 1 7.BT ~m܊]̉Q5UP5UQ5UP58Uj-čjUcP5x-@`kT vD`~T F}|q jp#n,FT VG`čG7G`T C(gP5G܁Y\|<^P58UϢjulUmQ5x5'jT A1čQ58UנjuZ5qT A܋'Q5UQ5UcQ5XUQ58U7^P58Ujp$_@ !n@zF6T ~P5)[j"T A`kč\솪+P5#j.j"nިlQU_jOj5Ǣj/3j F`čU-Q5xBHT nFmը܀1Ujp'jsjC?,"|UGQ5Ujp"nD-P5UףjT ބj+B`'T >Q53|Uj"j1T AT T C菪UQ5xUQ5U1T q jcT n@3,,"|Ug쇪܎1^\ʨ\sQ58UP5X UP50@T .Ahq=jqčèP5<EXT AT ^Ѩ,֨\Q5<T Q58U/"n|&,lUCP5UP58 UP5U7&!n$T a:1UQ5UQ5>'jpjYT CCوWjjp?ẑQ5Xq]T >@`{T > U/!n\C`>T nAM|UcP5x Gj$*T DY'?s'VI2[E2סSTr2SFG+Uw#c`۟+' Yk%v{̩he36IXc˧_'=ŒD?XJ~n,WwOi 5`$ܪKj`kόK K)xm }i;fO؊;\\q $D)^W fq"LӸ!\и/҃iܧ1ng~N6< .Ub?ފ+zB?.tˆpe1}/|b݄m >8ྰoZSU[߸Op Rz0MkL#LmLL h4TG@9#s&k ; Ι<@p0 M.Bws&hshp `ξ_~3LL7Ι ` ` <@)4AoLL 9y& <503g8&_0n&?Ch8o 4<<}&L9hQ}0M]MO37'L3@@y}!s&L͙#;`4Bܧ&Ls .:33g8&Vh&>hM͙Z3@&4܊&!hMsLL@K4gh0?L[e?L ˜ 8gq(0q?L M 9@e}hh~ w `<y&W `!J"4gh5gh(&ka>g5gh5PvP&hxP&Fs&~<h2gxt ޞ3C@ϙڢ ۜ ` A@]4<&!h5g8&Lc.3GLCPMCL?L'M3 C@+434gMcʡ `/@44D'2P?"c3 E֢ Vϙ#{@oNLLcMa48dgl0ߜ 3<5gxp ?L{L0M+nCwhX:gX7g؊&lcMf y&h&?LsUΙv3 ` 4 ` n}h}23G'ha *ϙ6 Ȝ `4.Fy&o@#5b?_,C:-iǠ:gh8:%1qiKBvGQ2$%T*PBJ* B##e{ݯ~}qy>98bsNjG]Ďo;|-mG9ZQ~峭Q˚fGᚚփ Ck59x!?`g W&;7ڤG4+<Ӹ,Ǧut[qI?:),kﺆOR?-hO#+4fS8aN<")⹧Gʹąwh5lZ`VҜ[+ݲT2v?†Oٴ,>4ih?}k8@#Ϝ\4Lx)1.HaP.|"j9U_z]P﹂P}zOHOj翉mWuTs&e<{.f!3n3i7XӑPs8 >~o--G0mk5f-2gw!,m2p Lm=fOɈz*bؽ׃|0>7)ICb‡/M^Ih)kO kYh=.ZN_M[) YUC> vz%~Q*- &/ta>?zQ9'.Sm Y*Jupn,װeeݵ@qSIjd>v*?+b*o]/{ dΎϷq`q FkQ@4y_&ܚL5K{_L 5cZ[v,|eߥ>Иm`~'.鶫w=+wJVޝvw76G55gKK%g:χvɪ2xl&얖OlʎSgjfߺʙˎ,<)ˤr=V1P&fugY݅oMnTERmcZ<仢Am^&(Bşrk=peZE$.;92`$aj]NӔuE  4u߄a70 B~k NC΃wg> ׾~BpN-а_S]!SE:&̈fQ#1t[8fOGOwUf.cD4==[MoRvg+`gKsZ0~bIײ}>+E2&v'?]161U?_%NY@q`V>w"cOd#?;j }N '+|&⍋-AS /_ݾBF"[F~>L|P`(p.)xg #cݚg[nh~ȹtq<|:iϏ~.kׄ\ BWo~$uj}#{G;\0O;fhz.5] qu7.BA+s;1Rc  kYQ=ṬezLý3\FnT(Aye<@@nSC_4v<^-,[ˋDhvwTW8Rɡ=fg1n+MNH=Ur_7ky X|S8,V}~jC2:E?-Ĝy7ގD}&Z0* RhHSDFEYd 􍛘KKSAWS*tςwNW^a Z|<!|qM__a+8~gq4Uɯ t.-r.Z>= :dz $5sNb)k_/3gL4ÒTc1uThq|6E [H*ui@o_J];e .&;"}|!K?Q\ϪOQunz~ Tnf]?'7̅stf{895F%㛜g:۹ϞiiTgSYG5 䊎|CGusv$bVjC'\h/p[ۘ"?|GG??-D~zke՞ʵysν^Eαn5L꾡{V\/b+xzhTO?Lh x\t>bJd*|,cҦe*$=8ZU<;$uVבz>'O߾dx~y맴fr+8 ?T/Fx dQv*r~h>{]nHK3T,7> _#썒'Q8Nh߅NCZ}mq'lWpC/:,dmlܑ% >Xp~NB& ~Hʠuʥ̕ºfrDM3G[S,D(0e<4dnV1DBzfoa?_T⟎'uv${CUY]7j kTR>8u] }bsÌ>~7ax%VKY{_&CSY/%\ʟ:Ye Ͼ/k,8>x0I)HhTkemF6sMo-lRY(k&ς`'ysƝ5*p'&2xFS\{Ec? ]?ѝh4BT/#>U?,U`ܾq{> <TÃ}k$muO$hZl|%LF-a_UbR׭`>UUX/OvWUTz} $-*w?w-9Ap_~vtI%,? ƎO#.kÎ]yPY.?Oz֩?HAs0w?xg]8JoCD9[QS /@;52GEۮY|R"ZA7wl't tKS`!BW@k։ݤ~{G5J{S_JBk|q+8*lAyͤ">(+L…ЎzǼS4-W};>1KB҉A+J>ol!⯭XAWΎU|p8Fk*F7'>Y“$Z(EpO iiJt~ %A/^3a"$}?uUl)erG::+{FΧ߲/Js0yz 4;]C=*޻=it]wgL>ZA.j.zĝN݂*VQH\~(ukl[{_%/Ǯe~:7މqم%#/ckһu\V WkTw>g>]O;PNNBÈwc^?aU_ %N[y'KѢƷD3M})H3̟]5+>py ϲ;>2[l/|WI/מg BЉ[s?*c/kǽNb$b>&Htٿ}ocz$D^l?.<|߿x'K+FEWϽZ?A_M7=?yտwL^AW\Hvտ{qI^h_=Q<s:iz? }%QVɨqO)Y Ô$|~gO tzxבў9yp {vDI7Oyc׉$eO _*a]IPgٱ^q-V6trii \cI6^xP#I vu+Ȱ98_q `:QSٸ}a9!7h6c'l9j372"\/WY!ٌaCsZH"9޸0dHBYQy7F\/^*?=3 2{0V?_'3v:7߹sH{y}~|FlH<𯂗_z3V s4+(&?vč*|_ۮ?&OG$8ufev/tsv-@ח{$[$o^Xetd ٴ K$x@^y< 7;+B$F2FHޛau IV5ձ?Ȱ,zutXcs`%J2){]Lt?3Dw]Wa[{^;ca:O30r(꒼eNgѿ,I&xDCmIvQMm,}"ͅ}^U6_~׿r_[ ؝<\L-1UiSs8pμaemzŒ aK#S ԸQEe9{[""QBu::l ib=[8Ҩ4.s8]ᮿ8^51Fawi9H K}JStEF͖ZF 7j{5Ѝ~i^~ëPW%6_ SBZ㟟"5Wp푼G,oQ{WZ.dִn{cl'uhcm*k]]0hx*۫"sX?wzH,g_J`FA_PaLU_aa*w-i{Vm7{gBph=]؛ԁxv6l)'ކ)Dl;cME'03RS;О[sɸp2yn-;߽_j9fBKu\V.'\+`VkjVL-ΡF1I~ל1p.}%" l\Y4?W.̦~&\smx ]*Zo=La(|Ftkb7ӾkޫBqc4vpOl!qÒBfII+E#ǵI p 9wX<74)OM|i}:K߈=ϸ~ =Q3IRToyn+}~sz-TQG9c쟱|w:Y~+NLn[JFCCW'ya/iӯ]\3T`.W`d۰S봞jG<^L9L^[0 :rd3 ILj0 8{lh: wټߟ_qAc灚SBP_^A_ pj2\xZC# +-c".Q!:\XhnN IyG* 6h:|ZF]ӥ[pI5DX3OwVyU[⤕Dw>]7/:ҕ]T|a&V,y:XYsZ.+5'5e?j:,nY h x O2GiFIυm5qMj w(S\3Ʀ)-.< xB~~MyjtWy} ѷPǴ  r7{NT懮:''?<.,[]5ձMҬ,MܻyV&i΁{4n #~ `;ͩn#_pFyv2lSV2Ix Ʉ7  ]6`^%}B-^EOz_8Mnʬ^{GS]zM&7ڐ}M!E+&\|ǗTC9ZZ﬜+LJMc-kٴN:Cpkh(% J;Jk}pVPa/f63 R.-+YNx59hrq5Cក>6 lTIz>. |ry@<ϩ,@PfsuM75Ĺ)RԺ@#?`YgmDK>Iqa-Mw5pUTc"FZeO9ȶUͅڴ;̌`Bi(go hoW+|rz%lwsV>x 3SJU0reBJٵ4CsZ6EҢxMa$У,naܛ'꽈nw/qܓ9}p-wIM71]j'WM ,.:*`݁|ScZ_.b,7\jナt,4]ԛĽ*d_o=!|L3MVf5_&ϼjN5>Ri9THLohq-hqgH^h]/6q;NxVoWD阹4,l_}q+Tsyv?: Vҭw_:^_C#4ٜHz5_w(VnXEƉ?g.jyqUZ'sZ㯾.~o0|9YʫLyT>&S:SU&2ՙ w7|MGnʱ\-Ok;†ݷsK5[5ϊʽd_܎+u˱닻?k}'_"l<4UC e0*ȜWGRUsA *k9R*s2 ͛SR-߽'})Y'jQu:Skg'D4@a {"enQv+ Aȿ z ( Mmy G~Reۻũ>UvZZ OZ/>\,d08UKM х13WfP$}R|5#EK;i,`dGޛPZt&3Mm /tuhԫ>g ,ͽoQ,!8֠qk֐a72~.=_?k9akh5;kkLLtpY|C-o%=a9 YLiPCg}8X84St.TjrYl?,oR;umȝMN{1_) Guc;\:d GCsHRPm:Ÿ=J A//xt~Et $]'^>/_* D~ԃ̻1pj(z`6 I̡Ýk\H\9kX (fy8 mF[u4ԭȬaߍw)Ҙ.7%%4G$3#`|'Wj;ÆSλ&(brK.]KTwcuc rk s"J|⯵ x͓ N^RldV\lM˃»y=HU~({A`KEߡaA=|aO64 r0U5o$9Z5ZL OwMaZ,6f-kة{9[ͤņ(*I&bunGbo< :<h1s޴V\C+-xnb߸Yb<b^㗍iUWuh1թڛJFf_oZM?YQZ( 0Hh1jZLp͕ulN*z7B;h0#[ 0=+_I)`i0W4%/4<7 = l_`oOloȳˏ`X~5Ȝ=B:tk@?kHhNh֢4{\4 eo ,{8_Ɲ#6͉3!7phKq>I : >\|>Gd׺BM.t[亴&A?&.Z%X^8FYG([er_v:mKrI(9vTTA/96vs?,cb\KpicwK=!r:D:9ftۛH^~%,R(|&L}c"@(zjIMP]G}869%ZhMiEZS&^&o;Cu-8FIlcCQI{J! 9:>"A}"ǒ^V︼;$3|9v"p`;wd49u(m 9[1Gq$Ö48ɰO5dX޷0"sU_fgXDIs8Kݩ3+J%"w$þC<9=+ |26 >{- ݩ09ږֶx+^cq$vX:IQR6j]#X^?r 8TkoJx~3">_o9B _9Ai¦ɰ d0uL 4+H; [п{ +HemTQa n/Oې^kx'fUoj) g'mmqz{$h鶞<݆z_AȊ΍m(9ET62چr;Bmې1mxw:/m+܆i8C(3сD-9SewY[p(-[ t#$0j Ƹo:ݞ礸⥚rU]ނZ;>ęlHI)nAH譳$H{Vvm;--Pu: ?ۄ 6MZw.߄+MsrDlBU׷0I >vhMhr&'F_ڄM} z&H Z(nӏAQMد8,Oۄ#LlPMx}eaxK݀t)z`od*[GjR (Sߛ*{c6 zť ܀ ƓkRq}Kg7oU@fCc ݀߾vbs-we7 ;\^oaϱmbx,USy72&$Óo+10:s=jX1oINTlA6 {T>uh:%0Ug)9X:xo2nY>qQ}[)V׀u5ѿܽckdMRVFLZw!Qk/YUMw5cTKwנr슛~~j"u/`>, l2 /h8/)]Fuy'^^VKӋ/Z"Oڙ޾\ǟ7.k&b"7Y2ߋY4AKeݵE8u'K"wwoB 㼯"~}~#Xݺp=7EPSJ[9_4-BfWp"?ų~;b^i\*E<a0q=̹D`(ڴzU.@0x)e,S.t[Zhvd>-򇘉7 0bʲ< `V.(^w/hcEP~ӺWwI&1\K7[-e7X p Jރ!骭g[ •GMl桏/*ezUsh;D;=1aDG% !ff^e<6-9OzOGσ-20:-.45O98?/pAeaNP l[îg.CS߽f<מ}H0):`W*}OyLFar.wMX+aZyxA<}\ǻsEn9=-v$Te;ҩKzB]׉#}y"ԜSx6IO7 #Ay*DyTny 0T͜M dd"RLG _sȪ#B_2%BK"x(;%ݹVX/i`U{DfRi @ye!6s/QA/DV5وGMHyKkCݲ~bMn<$@s곪;igt㻬ziyAC}[տ ZU=$@yx-PD 'd'\j.cGI ^΂)Òk}o#75?{̂3fa"Y=rjFҎ̂ŋfAMYЧf6⛅B,n }%=ķ{3Pp} i<o|Kg!d2430;> !x}s 65;;_πߪٳ3 d&-3 iFOfBu2 q̏i9'gӠRnt*E[%4pA 6 :kE>LB4l:XJ]];\k9 ??3 VOy`$9o 3 ^-%gNCc㆔4 +N)&+:=7?Miw|\ekM93AOA)l ܂yI!~OY) ?̵%_9si y=2 X*ONSའйg W:aW6Siɖ2 }#S e(i; .ה5LU2%Ꮩr)a>[g:zO , y$ld6mkLI&!gI0T(== Kn VzsQ}>m%+]LBdrA.I_qү=?KOfretL54W0qI &[w H2='LqC}&`&_@mF :dOwr\{S`Zg{#ߣǁeޟ8Dus{<YOs qhJTxk1qԫM"8DKnvܷe3@>LG}vq88RGfd1:M:w{j+A6uM?ƀb?acQNx1Ui{AW&j)1@θ!<1fOyr .snk:/8q0O(.ScpS(np Q`}&.xhL-?G.u5bw(uY㍳L(Qr$,G!;$/(9doGuF0ۈ(̹X^EFaސj(e%k9WhՏZuz639.~JSG f /#'B{!/Ff5H;t#0X(o1oxFq:p֯*>iV'`2zUzVΈ@[FLj5qU{f27 +s0|g_~iGÐzk7> URCt à0 3@MQgfZqn==f ]ٮp@t0-j Sa4H9.= "&N;oFέfȓ_O{"#?0|\Q'I!M:0 ۇ E˱!H߶zud7p ! Om1G o‡pCH}?v߽k'[X>f3rr.AfC|(h$1E&>!մ$EP(/0!p8P`&Yp cC245Dj:ldA5{A<2>w BV AOdeAH 3 |P ث 1v,"Bw0$|!.]ts!_;>*UAXKkXq+ tL2{J B96m|P'v?dAá>TlN^}rƖkd̙!-ָ'rLΕ: O_|j>97>w_즶1 @:9GdI)o34˥is`4Nhp27m%h9[ɠJ21k4N9FnxS5\zkq~{w;]sU]i"s(̒K,ǟ=W *C8m>q곣0w@sUD[a[m?(]5&+辧gyl"3*ybg?5bR~hQ3Q9EuDR|SʖO?|}vųj Zzz/X{ʺlK:^Y2 3`{))0Ӹn_0#X~T4edNIWUH٬!~p2I=I9~hjrRuVl&`)>+ymgřI~-&U}փiE}Py-bOnl]}܏W@p͘>8+Kݷ9/ϴA\>8sW|R=cJʳf4qBш*k} fDBӯ~7} BH؟(wgwS^\JU7I t>xd荝}@;ѲO !m :y(`^ɷ^8>_%5 *-PFs֠+_ §%')^(^t~m/_^tҵc7zၳ'+‚w~a/~~F/\Xxs2sEEF^h{]{ypP5<kW8C;{dQWz hQ?`_y=P*6yy 0 v։rdȸIqyh@~c`v\^ѠE˚=z#p\{Qeݠ& yNމnw'Sy7|E RRԼ?A1зn-:`zm7i7c9Ev2/%JY 膘\Unhk }!ItÌ|dzYynnc oFe.0T]OO6/@]pRD.&/ Bt1ކ]P9;2휛w`U,.xzv7]@{oFDD3]/nIF W.gbuYÝpc&h['|f֯ꄷW%Nޛ 1ta:߼?4xuB;:wBGl6q篊 $+N qo;"TN<7J` |,"e;:}SNW[퀓˜鯦4u81UYآlq%n",jQ`ʭ}!`숀_P }v:wBEvI݃[DY<:[7;@I{o-_`슶`2Is *6wԇ.fpla^ j!PBJSA;Vi a\;UCY!y;8=8C7_)!Q a婾)6wS>YQYU"7+y%2%]qv=_oo0b`en*|<-GnJuӞ6R. ވ 9g , -߳Gk6h}a^̆'ckw h ܳowWv6nfZOkrՀsmU9puz 3pZpީ mB0P8c&ZKV0mMVS3Q ]1@Aql+\uhȗV#y u(hKk0 듵n%@VN}To iGgkC"n C7yi]l:7V{G DZ=d*guӟO}-0˞*ǭ]TZ IH~ N Io`gB6(v.i:L l4nn-7-"]_uTce_h&MZ |%4N~>ƭZZ5+H`ϯ)L)b[ʫgI~(L_aE'pfa: DelۛJaZno.nT)NfxJ2*n$ , _9#iP37lBͰ`` WwyYkk襤`Kӵf(rToh [W6 Lf dZ&N?\lg뇯j;Dq7S,mfWxo6e3,f{t*5bJ#4⼊h\&xxaDSZhD{MgMV' 8\7nIxڷ 85Gi=蟛h$*&p[aqiO 醒e\Nּ~ c M4cM0`ُ|Y^ z$T 4!)Mpy&HP< ,L?5AgۍW}ץF8GEv{.0 5H~Ug#?ihCuǷt >{_Io !?q3kb4ɎR9^FF6 ~TǍ0`Uk#(ly.϶&hOr&^jjflQ#Lw+4BWeZ#0Q9,)l.!"ٝ`!2b>[ m`>I_?v4[ pLjWh'(jj;v УkYOg5_on+ty.yD4drj laƪf,z^xo7 ˒Ȫ&1Fߐ׬2f>0j%^^GH:Ϩ7hL|T~ːjч" /|7U~g 26ssi MJc sRG~`=vYkoma׫Npi?p=5o U<-bE00zxw=(FrûcGn0׃W[̙$zG5Y+ǖꀑYɇ:8;D|>;R?>뭃쩘ͯu> ʺ: ׳*aOUx(KP̬_Ձ u0\[yd,l~S_󹱕uS5ͻTbTu?VD)PjU# -CY:ۧ:zVDW5G "4`5M*]I:>~C]Z[͇w"o\u0~͢Xd۵!b-M3j!^woq-:o=Hԍ=p{هZ0ItW ;МG-{1Mޮ2+˞JT-$n;R {j᭢D-Zڷ2`eY[5p3K/B <@ HIT{xKj@8B UfTy*"2$"j(tYQ ,9Q5餴5yĖXdk@5@ U,]}oKyw Հu]hR>B]{TC7Q .y{1ZvHm5_-tp KJ5EUeYjPsp{گ.5v{TIȝjXoԲfՠXcW_a#,)S l۴9Dj$q-w jxRvZ;vOWA#}U oeoc\*,L!v*#[ctlD5 >񾩂O gSW~[iNiuKUv3Ҥ &HѩEtr*z*tg|9;HyPWm-J%}u?I̗u_nDJ`Rͬ/!w+A^px%ݱԈ*b@[%\yԠz^˨R ]5lNW¦UZJ?\ :\vlJغX F%J@M)ܜ#Q-wԐp è]e*C1!GXߡRgVD.zO+ ~95e_:taC W*@d1 ЭүuШ%} Q^˾U*i,gۿDQy20wld9#[:̯WˡZhY9{攃'WbR9JNGerR\_QΞUrwǶ\f=sfgL[bX9>cNTvleˁ 9A8󕃵IVRUʁ* 2N.kQeU} 8ʀb׀^6ؔ2| <>VvY*xË2P~X#L箶8}VuOq~I3/ZsViRJ{-jsw#`%F扒{K"Cen>´MUĭZsP)^ 7=6jJvHjfB񓟥 Tnu -EKA>_a֓R_vӵh~/:"xz\+6%s`m w<ܣS g R(Ha)aO"0aІkW) ˉV_PBk|O%]WKʻ;Io ח1ђ8$T9>E~%p7s JR ?y[7^K\%`Swyعb.= ɼY(@m b,=j !mB(7퐻Vo;޷؋&0dܧ2xwڠ|<;ҒEoDjAcAI>H=sqi "g> 'Q܊ɇgbEڈu|~e-O>Yȇ:2!|[pG:;p9>ڞ9s&jL?θçT5|^K,i| 4TJŃna-|#|̇ӬpmIBrG> ɜ~>FʭGb1#wO xMK6pu=rKFFLxp8AL"`FzƩ8Ȕkh%pZ̽/8ơ-,v?!Y]=#_\q (ߑtL;7qslȺ*C9L+O ׫t!_wᴸbh:+(06!"R@u8vARޑ]vpoLdptߜ+MfJ+.%S#P :DzJU@*ٻy.JBNOvkK6o>H{nf'J {e~ċH"ZTG@{UOB||@0C %5G=`nUiu1: ߡI+3?;Uȅaua$rH/.gZZbN5d$&?}#9@b/ڞFA6U9EXmWBr@I[/sOW˃tnz' `C9ȷLdբ1ȁ^5r@IQ7xP&n'S2esUV6WIbp6xx{ږ  T+!z5$M{`$W1&r~fwWC΀EW6<5rΆٛ7r %vT8^V9k l(%ܒKIـ$/#+6ũIJL2$Oe8g}YPrƬ) jo˔ei9֜,?fy_@Xup.̂^=jˆ19NYbj#: F,PՅ,x85euf紳c];r4U^8 UOBN fC~')D,px 18MGZ g•1p?:MjdGbpZ&r)J r4s'2T^kL'j ?O6p].N&LDG3? 13l4qo~{L?B }PʄZLW&ΐ foe@΁73qf Ȱ42mʀ{!o3v =Fs?; M&3@fB''*xS{_π͡'dX0x?zʄ3ojڎ Ҵg2_A*!) 2 -J11πC43%GN e25.tat!2!4퓶tp: Bߔ~6?4a k^:i\HN@m/Hȗtpjm:ly$ut0[gmҁu9A%R<Gթt?+X4ҁ|:y'M2>?kH0c_%GsS}6I⻸GFKW~zO'L/Y޹[WinZN(`'-.{nZ\Xʢ&-<h wTNfZ\pK |OIٓ\٤ZݽFK$/.zip p\k̺|~l‹Yh#3}4ҚsXI7 ^vq^d Ne`J7*~4l<54xú giS) 4[r P#6z/T)ϠRip|/N5 nSgIWzoqGVh"s 47Zgi7g:FNYi4v|ˀ9F8]E|s>4'ח憣Uh}!4xŃ__I{=SNHz r훈8Ia BQ!nCʣo&GL|{`/  ԗ;iYy.4iL9S2HA3սݦƹOlP]Oëل%j5OFƋ~G6OS) ԸbQjx*5֒sq榄95LrnX7V%u"-|i֍q,2OSeXץx stq:MjՍc$]ׯQ}*'*RfM;Q>,:yorqt}£}xaf8iKA~DqѨ?.==whƕXӹwRCqఙhA֒)bƿ3S셂_q!Az,Zj<{+y" xM;<{2Txf {*>@gaD;bv/v*\iFJ4^-86;1Az)q 43z/5LM"]^*|Q;Z?S >Pzop=TfV ~m˺ OlWFϏ59\*6\ g :gNH¥ ~QS1 ?pT>dX*Z!* M| 3 (?SaOf>R1PTV]mQ᎑AopeTxSN/n_*3*̝W3E>F-Txkjjw*v~wW*$yu*2o{'*2erVIs疽ϖ 15½\ Ry/SW)$/Rcj/մ (ޜ…zKLpm=&Tx/tȘ $8W`mH]/zTMGIe!e꫶&=@{o.H'8Lo˛F*Rᑏr_#dA*no*J[RM38-'RH]g9]P'%KQ0ihJ|&=HJvax婍O$~ɄZ$~јX%~}] %J*6?J{ /%ro3OV7%. T/hZI+p?-p7doqQoRmQ)Vs)q.9RU{mJ|/G%%|#MJ05%ۙLKJ\*%I*%~+VeJG<6לp't<%^g3ewgYdJZ5IJkL/lR Bsn$>_3u)q'3]:Q}I7?7@o]9}ƣJ3W E+Q=狟+s%YJ|1}.[w,>{9K(tG2Zk'+9QJ2^Rˈ8UK~Jׁ]z{^JѨ#%NysSH7.-s)}UJYv:J|ځ/ {NsJFsVx嵕,u qB TRW>O {tD (pK{{ _~G5qצd?aG(ŞتA ~)ٰόC3 ;|)p1}- N(z \L{@-Ey%7?!_+3]JORYDwPq9;XȖ*RW }NjoG 'J(.)pC{HL._SqHuPGzA3 |G foRDzc <K36x:۝'V8'k<BLR% ÐY9㏲sɄg(pO1gJ4V=I؜WJ3&ٛp_ֈ3zG>iNzR(KFG(p97Y1m ܮxFMj'WG"H} TYbIX$ Ok# ?D]#(pZH(p;_)p=sEE)p^o{)SC8ŲxBSi8#$drE˝fK$oPc<9{]r<ͪ FkU0&84F='MbBϋF}$S.P %O׾'ǭc-qb[ܯWdZQGS/9gOI~ 9>I}i/Hs%89ߑ.9#͑ϓ5q ?{fʞZ-9ط"ϊO,qS?-_!],? LmtH[2=Ol?KhF=F=E*:fBqs89!9~[Q>9^T'|LcswB;69^Q~;#Vh3(Nf{T o)6$Otͼ'K;H V W'qK$'bxf˞KBe;Jt39~4CrJpi8Isηt$Džsv>&'͇ZE_sQA|j!F跨,Xy"~Tcy2<}2@]1Cl7EHڍᓏ?%÷9,xK7+%O4zp6z N2oVב{b!3^˫$ó20r2|[V]oo)ڤTDpƧ O`R.+֩\Rl^Wd vt21SN -|7%yZT, wQq3 :òu¬K{،!spUd-p2|HIg2OdmP2`2tTVVF ~G@O@ a~yj\KUc^4f&[K=&EJA-HXe/#٣SKd8eiI#l2[S-26l}ږ ?^ yigkMھdx[鐉dDZ7OXᏹ&o^"ەN7'?4O#XeMΐKlNhdd=[$=+7!6^tTGO '/|/3hJQLS<&Hq92:jw!\dp dkkp]$p1Abds3}}Tt/.* 6#@ϺM'ؓG堿 iq̍4Nʼse'io8cXI {1{+=>zWZ2nS,wSOFODzm|I@ouh /l#JO_um4I6z}~pi_F'JNXvl)UZјmiz}a|Ƽ߇mٓm_6gىb_; tU?Օ<~l#包m4--3NY .'ƪn#GUAۨgp_x6zaS2ly:x?FIVwMQm价:e6rF67췑ՃR_F#VUۈoI(bEeճ_pnCKٖ6,Zs@w]dPFL{Pla6(PF'S:R3m#E;[ۈw[~Q{kS־3 69xa96*w]fF,0m#%I,Z(BL-45FɖT*q U˟}wz *o!ۄ-o 3=+\][(ްPڶak-dUR}K*^Vn_I,R&[(jb/OR'BTFema=ҶPb-`u3a Tsn!D>XF6}Y&*7<ٳYkD"7\cbi=\VXb&:Yj\X9⼊7| Mdx*w}?7ᨑ <%SI||\6enQM"|& )3D8E7ѾaW6kwL&m%'>"Mt{Mۖq{1zmpDWLeo"Ŝ7n.M+jGflX~4]&e)k&3'юSZFM4]e/en7S7ѩ9@sh&0rHQDuTm"!2$ݯo"JqwjDF Hx|#4 ?xHI5DZJ%'ny1$FRoMt\%)x*k{uo*SȞezZ;l[&7 tO"Sj@6ߥ/unU dm-^ Sn5@˪f6g mrH@ nt(+]@4)(O7=ie_]}.*}NA|禛>\3i.\\ @ U~6г47:Z]6R/6S''cgmsn@\w6ثJ Ѝ | >P\@n]@gG o@k dM>>RrŽq3G9vm?ڿ]^@"F \TH9a~;m ӳA2Hl1mWJl@E:WI37P W T!p1:GsE%ij}b]tX#yS{7J+#dud8#;hum:]$!Cq9eoά*Ci:ewXG{ܲ{Qeh:Zўuٸn׮`ϕqK`xU:z~uspݏ'cs]eWh+./e%\&$-QuifY:?"z+Fo>ݼ?kF |߯컵޾!sϚ._G.{_ҝMQ6`d]$Fz {~|\$UmGҽY:_7\'Ӧ8=ShvVudޡrl-~prE}:nE鯣ӝ̢jH:Z4 (jL5w[m1Nj)T/?_GWW,H}23\G!E蝤[]Bڸ5hua~c: cMyv|:#1uDq)6В,+фDNڿv.i\ *]^C采u'Ўl#k:554aӹPHIF }y6i ax5tӰGwO([CB,tk(q0" sk.殡6zY ^vsאpn!D~[C=4 ~ҽxd2Zϗ[Ꞔ ]Co=ޑ꩷zT__C3}9;UVkmלt__&7 i{f Փ4]Ce1￞XC)i֐_it =>ɨ>xZCtkvU$컪ɭY 2Љ6P -5(a%(ZC^{֐呻Ѓ\ȺmNgZC5@9q5TzWZEwVQ#Q_*be<fWQ<*z66v3 ײ "g6[=B**V_TXE\;ZV ƈUtY/Ȉ]2* ^E7C߮b4IygsV&e ތhD$U*RŞA.UxnX[E |QΫMIE*Ju6S_E6)ϳof U4PUR^F<˫S\vaUt)StId1YEv;UԻﬣ*uh V!ޏ"7c&*3$Ha}v**<>*jcn>*9TGTI.d%w##m1eN%_GfWm$iZE E2$,VlSח+fcuS}_ O$#s}WХ_ME.ȼWЅcQ^+HPƑ+( :E T/㴂unf)Wtc+Hurr$ͫ+G+{<< .18K9z{+, ;z 8c`~;e%W b$'w t3n C1qwtH\A-\+(]/W=IaTskT-tz6ٔ=·(V6J26a} KϾ]YFNq# ˈOiW qL!YFӯ6'ѯӲ)HV29(ҿ(n&wu//C:Qq2J|^,Iߴo+[F =\[e$Xr}d1p%$ed۟/wv?\FSbHY&/#zt)er@wE}A#m2b-̏6Tނh? eC{ete2jX ~=qvSzz-kztrx4 `e 1Ќ[FWnYF͏=ZFnޜeP2T;2L?Z̖@q>YҜ $L \d׍2evrt2ewŹ?}qO`1U2jqڳs=/:E󪄝Էd]F[H}t(2Rt{ԇl{) ^BtEl,{KhyoGxIEH䷄u/ΧK詫Ǥ-{. wKhw %.)'oCh8,!-Kd=9o. frrkR:L_[BzKhlpu% I=O#k_,zݙצ$!/R.:_B?V, Hu02>ql -`GHaԲZKu@+sux %Ҫ,85%t27fZv 5YB묏7K-!dKDGLg' /!ӋvKHB; 1gмEk 4\B.K;.3z#q "6]#VL2Z!=Gb;7o,E]zuZ"\o|/k) ;iҽÉ\ʼnE41s\~t}%ies|vXD5Og/XEtV9[Nhu!bɊo̻Ż^}ZD^/" }uH${Iu:Ҝg-i/ͼ4H8sC[ ֹ{?/93Va|/1][@: bir2X@!K. ok8x-3-c= TAf ۫!Nq;ݲ>]*j\@76"}І ZRYcGR_/^@ 5 Ht&Z@jC_sPTpvOJ_.IY@.J6_ (EZu+n=T}~_6#P9aAG}3\ߍ<>,*Ƭ`Jз- few7 Yߓ2 ȓ}j`}R#%3|PȓDz*rX@_@G. 'K[TN ̧[a{mmOV z?+P7K܉-6 x4,*~W[@ g4,,C h$ք3\-^G(H}-ۣfJmVd=v:>kF1G_1LouGzQwN#]?5 =#BQohD^IW!ؕJvܗG.vͣ!!Yy(5 ƸH#Շ? 8y$pׄa<`u9i|Iyytl}hq- E/C#%~搈9m=a8HCWUL9t"6M N C9is=}9=_:rg+ټ G%3WUMuK͒Gs Fy!Ý*鶸u}7x#9Ρ;_:Α*s豅9D ?sU!JC琤AJk$fsaKzKgEh17# y<ֿQCt7͡hڂ{͡k_I1IS. Eҕ1.9Fn'ͩZb;x^QCw ׫Eey949*L&Uc匤AD5!)mDt:7Dx>VX("J|RVID sʉ:x2"H ( (>-""GE¹DM4%^[wd`xs*}7N& IDs莗?ª<~E/KDm`f?D©D@ue+j |&kW?f"K'#%u42k"p83 #-%[bψ]чvDTX?"cxED|FŃ4'Dԡ~Ε>S#"[aDaHG|n߶'$}:blIƒI *FD<]TQj@i?e"zt@9nV:OD 3Dj$}1g#OQJp` x~&CO.#P7:DOd _S%N?ۧ#ՈٱFN" ;HDϺҤѹsH+%\(}9@DEs+|N JAVk&L܅T^,ۖ&"[[H釗\DԚ]EQ`;qr%8crs&"Nb Q DtEhFMDɖdD2":TlE@| /L*;xpzi H{k`(~q#/w3t T$eDw]'2̣dO2k 䲇l]ۘ3tл]w; HH; B@9ix7qY/ZEk H+}5]^[I@uW+8nG y \,"Ǟ`- >D@_ESd6R! GssGRɵ_$eb"X&Іw]q];9Q0Pk](R;)vs!N #'_t}&չ#ix[4\x{ "  HL&.pu*I@W>?'s&>xo>8nXhl$T;6? E\֕jR*JPzL@=d4 Yۤ9NeO@{+\m ȌIO]"6iTf:q*O,薉ѥ8۟vvtW;Gcb! ع͔*4O^9I@5'-_z }27ZHiH@W2[J(THWB!v`*ۂx=+~0ֳ"mK2D@n I r# Ç4؆QqBVҿG@UwIPLhi苈?-Pro?YGqB+/i "I'qˠ;1&`# ]l 6u(#1,I2!yIܤ"'+(Hԍk0iBhQB>,XN0ZN}EsjhlY]x,?F3&n'Ϣ5YԙԹ\7VUV͢KjjeHSfgO,_{k" S$ޮiY4YDIwr,͡IYlxr;Wxb;{`Bb` +;fzvU oGq3-2 ^6JDjq7lT0XZ歞V'ploOcu7-Ncn5Oc3/7L1VBJSHXuMS,~D)Se`+_I&gU[v@uz=?c^S.Ì?\|?1}=,?%˪͘q\1̓_EcX 1\ތ. "&l tQF{btu31lX̍i XjBQR]BƁ]G1A N#X؉`:+l`|ׄԎ`v;`'L`w/2S|6M_`YN:\uoGyDLm,c6vU}\29$ }P6ka\bb|vg*6J\ S|V=c۠\]K +>i詉+0V3}}hbf*Ԛұ7̺6qw*՗ܿan_Xư,{41sq. Jf Իn!Ӏ3uc@ v䦁T NZR>i,Gc58Zc tLonc[a{ZcӾ/n=Y.889|м{J ;ndƛ/9eP: U3Ө*Fv喻*ֿugUv]ߠUSn*LS\`]T̗5V-}[Y iVPr_Pn*a."%Jg紟͂i%X% Mؘ"W[t>"uC"vCNE̒]n\&2p2AbxM#OLs8[(wconXcy;ؖ㩽és{0o% rӵ;Q6rXZjrRcB_#4\,'۝,Ve\^,nA,ƿ=I+lkxt /tK>}qN+8JIO_7G/==ݡ:؁bE 6;ڑxmSMAerΦ fs2sg5md0#/`f_5Kc:W_Ic7 l:"-Tu4o]w`U+4B`nMu1cRޒQRż8+ROK{m^HOY>ce-ݯwlk:a(N܇eOw3:rȔhDzٻ?c[wF[cd RQKzvt%{)ܦ63dyDžİ iQ6_g(z{3Ql]gTh+g45$`EFLyz'@[ uFuxYF#'g^ΘƦf9 ckGƤ؈wJ^lQ|/6p5_gOf>\ѽɂԫ˂Kv1cݑE1C5حFflFH$G)&GǛ tJj&j}˻o?Έx,F:d jӭ}x"3[ƃYVtuR99&4GM9:S:Tc:<|+lX3:L]tG:v~RU:Lcƒ;Ot5{1w-L"Gm{6ybD5[ghx[R PC8 @G߸0 zz%h+;<A]^={ Nn8L`rjlҐκ s;>D{;7ovy7Q j?K{K#=N|MEQbn:(C,'jRbsܭEX ENV l6ދuvPϓ}sw)A t9öEg47c Wb1o"$ۦr̀x1/_NRhOC{p~fi[=ؗFaOˬKmȰO:ZdXȻ|ɰ_Lmcďm}k3Pz/\6K7mvE,nTTO+OlB/;MU BIo@lӻ p׽^|#fSQuu0VUlLui TG5Wk@Us> 2[Pw:ɲd8_/03pm2xwO,M)K0'ns B//Zf%(OZ43=4pHf'~OLAn F3Awצ>@i^p K;f{&aoUIܝb> G~6]p9K Yb;lvy+>GhqyAQvVĸɌ#QG/-DȪ1y\9?͞c]B#4 6M?>G7'GIY0ܪU0F`C3#Px? MapV3k Q1P+$Z$9k"u0ecvS<v9ZCϵ@~XXN64*}";Uv/u"Ŭ0r2}pJK66$BhS˷{aSF^Zz~w_DaY?Zy=ԨYJ΋tCc τnt42HsNiq?hewbgl'L><+;4R2utH&/K;@HةCt͓c4!Y{vRn-h7<ATMem{w6>~_B:V`h.{ "r0 4O-uA>FXڱ ܂fȝx;]kCPv]6Z"l>7Av6}ʡ27AC{F5ݗ/_=jAL?#oY Zm!+51[۱w{ճ}z wCe['=ϷXE=H³z(PҐW_עD끽:i%pVs|Jiv%>u1qQԁC3W:>{սk/ȣ`1iYFI#)5p܇(rˮЈўjFT*SOVC !jXK.˗TفR{dU~[U½1 J;d^ '.|Y*ayZoI xPNYscuߔ o9l{^}N^íeID2lTw Wg^+C)RWY BV4+JA6Rp rBחK`ڄ{ H5;'4JuI2b_']ݻI'bhjF1(0&e*Geo:@"hQdzv˵\]-»U;`ՍBtqe£Bz^w3A !+Ual!8"O]/k@W# 1›^ Yo˴d-KbfLos>|qzQ> &M|Jf͑^JYf DC  : 7phtCC)]a)_H2EC0MƆ ܬB4~rȃl!sJylv!?VWIB\[J 4un!9%xzRG0ٮ͆e l8vl, XdNi,ܼ2 R)dANrG]ToɄ?L ΁YBhF=~paW RGK%jCim2v,ҭӁut.7P5gT -~ .ZGyH<%Cp>4ZR*xr?L RJ؄}g*Ƚ5Ex7?=MsJƯS`Fƺh hR7ZJc-`ֵt#4^[a 4{Փad<[2 ԛüؗ&|cop9%yB7`eG~C1DZp=ht hTsQ+mU<=;~ߚLxLJAl)Ml~HlNI[QƮ2',!$j?#$/RDp3U، ]~G&?:zR6'KOظ$!M@>2;-D<#z<$N$iѾ8װ858u)Z_a=?@Wx%$H<V%ñ0@26(Mgb!Ω>MP,XII]nr;<ɸ ݯQ),@l:zEc;1r6ɍ!#?h}y&Xn Fãa(P|Y-5οɉWMv5(nD"tݍ_QHTW5=t+c*\t.p(E{W u1 aݍV "aLb}$Ol{6s`p^gfBXC # T|4WpH8[ef6C:j;D3-~UD`i=*Ĝ6|GoY) ;ǻBjC86ݬj0ȕҫ6æY/?Ϳ+}^/xXБpʥ gHY"; 60FCWx]>ʦV'l'~:˼\x^GH.+ܳ07/p4纩N.$-BȺcAF({=%7`8u(<"n= OBi/!X%Pz8ˬnA"pJ`ɬ}B#$ h!Ǔ:$=$]e^~Bɾia+\ ~EG,]\HM&{Nߛk`Tǽ/A Y~Q6[,AV2bOP[~30?y ˽k/5O1oP-C5vePYԼp#@]L/7p~7PALyX tZ| uгPkྑr54Q_9鰖@A˺+1N+$e+PP>Y5~x~3rZ 3v,=s9 ?'- &!,|j[xL+c}_r+ YFhXV\?x X[(鱫oK3z*~݀`3wUe 8yq_|ȣy/hD+}A/"z `$|=_@No0m={T(LÞCCa _]F{g4ۤDiY zﶔoӈ2uoNzSQS.r)xڿ+<؛{;U]P&h` 4ddd:;u&c_qvqk{{{tBK!{@t]hCxeRe~ =׌FH JBұ5tR8 8LO5&r Kr@h"0k(!չg>,s211{b=_8Ҩ4<2pHczrH#'%=/*j)[v| )-ual-Thd;]k㹣cͩ^Y4:c~#lTGA*CPIN]sm-~n+`;ϡp*??9RmJ+{{w'4-|ɕ/66Rg?~MC),ZΚ"9ss`¥RZnUx͠OobBBGgHHN}thSI8>0MŒsחI@^!޸N* dJtHƺt'?x?}tkMuIni :M<^F4_n4e(x2GXTLe Ex8 i{D{˰d߾;Qlo;?<#a?CS?_Tka%FY8:W@9ޑC?|u+dq 7|Z*UNU`B1xB(ON9NB?3bTn2*__8FB1}uHWo l}D x?Ǧ+S**F9oKXB?CC=e$|Q^ʐg>3'RU* qd~O$!] ǔNв=r_>Z?vߚh\E<o068/Za~gӉҘ1?݇ń$F29lQ\pb*" NQno'7"Ž+$#c&$Dskdc!twX,wnO8h=,Kb$ *Ayc.A,_%ўiZg}OҢ6 !_i\$* Ipگ4kM{#+eO#ZHcc(Ew"{l* ܿ P(o]Tڮoz ?@ 0+o=/4c2u{vvj%5)xs=Yyn5--xVѪĻxed>]zcWB:ggݩs"אۿ:VрY^j{1HO=t,}'įh *k4"AWԑs?׾+IwQ|f:[e )\:NKK~b"}GJޟ ~&KUr}. ܳvPN$݋=- G UUɷ KH@yci W_Nhbª s&;v(IhmY lnN\v{F:߼{]t~;*Brv<;Z(nOsqetB",sa{4Tyz+W>յw?<ز~[wzyeUoN}>k$/NL܀[4vOC CTe[8 ?}7&oOUt}ݍB\R˓{-n@p=~fKP翽tjI-A_M*}ٝmKф տ@l:0%A?ud` &~ǷuW3g*,\zxKȈ}RtOܙsQY oLjvNӚOҹ';碓>\32n}A虿6P?tVgr6?ZϟNj\'{?[;_g,S'/? ׭|7$P7eZ?p#HfZBS,2H93$H1ybXut;>6?}$w EۗxW;VS͹ZޯK/k *,LIvM0Qo|?p`tqۜOp3F<' _3o{(|%#W{yk=}iLudO^s{=tH6 7[ejud!z+`{6 *ɿX V:+H:cQzJ⃏r/б0V)c ϝɣҾ;;]]'7s7[>J Y4s*H,LD{ f&?aƟw_XCCo|AO{kyߣ?שּׂ11u[Rqf LHJ`'r.fH׹`)W}K ?*^4ȑ_˼-ȃ?g tۣf- +%P7h]WsK{y'pX})SKcs,]ԿbL+(ˈ"aKyte5r|1޼3Yj,>y|n+&i8z}2N#ޅtDH\ { ~Io1_A8G!'o_ѷjng!4 ^ay'lnniND66xp}dW$6+džM !,e*d1%UM}S٪}J;Bg}~'e)؏Ԓ=܉B}/YmF9(Nף `FcDZ1/{]ѣkdBd]գCqq}C^?t G35@g ȹvǰxgAљ =HꡞЃI 'PG־'ރȡ^t[ι;U0VԈ.GjȚB%װ;u /@a h[$l+S p/0cs2y<a_m:mJLL?aY^g#x4*0,@tHL3h- ^̥Y lp0|FxZnσB<'1bѹy`.4<^ ֶj<7z ajy0,ȚCd]SpnUyt“l|`l\^jYza=6 XZ!yB<|5kP-lfJGU)NYU9g!H<6)o'Eͳ̓Y̳yx/!kk(2Q+liv C/뒯ck<6݉\ݟ[*8@#LąWXgd>ikyb`=wcdO[qsnoHp^9p40_`3U\ɳ03ב9w,0>wXF`XM]D/)޼1k9w9_hԩ0mYs𾇲@0M V3o( 6}l4́Ʈ%u|LG0Yˑ1{G2 G79uLm$)nÀOIs߻V0]Z@Uu1}|m=n_Ӝ5;|UxjF,?^TG?2E}F'}s :KzbTU^cCRsb|gNU~2ʞ&ܴ@slƒ94پ?ӟpߢUÝ Y9h(qkvX&]߆69*:-b5I។knTRIT@#х9<:buzC=5lmN~j} Fs#?0cs0/hК7+0FFspāSiJsp:S=(;zJS2~Hca~I*]ska)9"Y@9)ϴG3$x+sp,% sWXHks 6sF~sP~W1b2LƷm{]]kDy2př"$K*$A͎gz5︦`q8Y,fPw' M7w;`,}WM):L/ 0p~G-B٪N~"N[N ]%DںRH5=|"_e>GԆDm «ԀT"x? M!ʤDRAqx"1uAr:7w.[7nF}Zݐ/V_+H.'CH(#G- 7D0-~q)@?"|փ}OIy~oc!V[܈Ɛ{X3_C}nԺ-";ok:/kt׈`.тD,ۘ/qI<mGYa!kVS"bsń5t+]< DHW9Fӳd8"p DuyE795"e_P&-w罃 DC_2DͻKHEN$THy2Ξ&nC`A|%m^L."Ж {v8IMy/YTX 7Z HƮL:Ҽ淩HgYLjPFn)cB,7>:G)Y Н"@M9q=־cCGiCCA{/D XsuOK;y`>yrE#+:%2 T8A/YB{D2 @FNan۹q4A?)l1K"8x'V2|GrZPh#@g\|~p^F#[Q FS+E:BVg%} @s`4ݵ,(E5z_]XyEǷ_h3 ?`M쒻P9Oҧչ@§{z8+G=<+Kob&@{YK~K }>r ओxit,J]4W[?ACyFwH4۷+u (]gJC9 Xn:T>QU%7pR"qB9F0V?@(wM\'RJq&@ Uax7>e'l~qF $l Y ;DqSYznO&Oܱ5 N,,lrFg㞆Y sYȑ|9{EĤ4%diG,)s;gd4!DyF8q|C {4^,Z? bݫYp ?.lz;{¥FE0),|ma7 %c%\W+fȓʠ}vJ8LffwJ,L Rfҙ?S`2JqF{dfA3{>Y!fow`e,tVS,0,iIuw ‚BˎᘟngvǸ#)x2<^7g̀pC}br΀3WhMǪ\3-ܮ}hhfݎaf+3@4f񛁒<>3 ]9 G,πL;3ϛ3@]r$ sϛπLz< vQ0,c3 M9 8q \/7ovJ̀O)߅,-^3T8yg;+sd|Ta;CI~a1 ䷵n8ۙiN6jԾix]_> q7MA`4lZ> M:hF40^K0ui $%Bh4t-\t4|Y"4 ?}6Ҙ4hNhcH4ʳ4צ -btzN~4<> Rua䚝.6 hLC9N Gig)'B+4F]"= ROfLviFG> {oN݂ssSPtcG˟ۆ`"[nEx>uii)ؽbS||?=YݲŅR&y '+OǓ[>׌2LAo LE|Pٞ|>^}mz4l¹nSǖ4xg꧗vSju|;X>3aW8OL ]*)঳՜ -S[.'7Q5~RSer^t xfe)RN7[㚥Ssn$d򚟄ƏS$aZix )vb:tte4I)s_~MB}'Ypsߐx$$tXoMSQ焙mgRo^Iʓ&axm~Ityk-ٮwwe;'^f=I`,ճY|'AXI=> N#ͯt'7zElx-L›=-Z&iPžI(4 JV'IyI80Дenri& x9Ig2)k"NS Pxt`YV MvC xa:S<w:&#/W(_5~,iv/=]d"& "@ ໏Y'.i TX&-1 e=[&^.`6f'-&#W gn<r0|FK`\;=7c&qo0TIpR{(F:wPMp{Pcϲڤ'=Fw).8t[7~^'=7ǁCtx w<vqHe2cI^U6oϬAǵq:g˒<w?kAe@8pezA"qY?v>፠ qa[guSUwơ5e36L*\#,pP߳t}YXAzWagq}o8|hqHoq@rĶzG]pŽ Y=&~J8:qX*w,Bϖ ?G]wv XЌA%}c@NM&>>rGZ N]9ѠU\8?><U1GRC2cPvɘ$f vؚ Q£!c0hhDz r$K_АVcpZ;JTrdp:J1Xå_]/; J}3$Ns59g :6<fc0pWЎSv ~?[? ſ`}k 2oюS,臔]_ZOMYQTsb~EFM;sm(dXUKٜ%PDDb|4}X[&p|up(Jq~V¬Cŧ$1Q0c"BAUqQQ8@\flߝ9~et2yϏBoC'GFW(4?@g8VW}p*B'~Qv(v\s7BweNQtK{atQ1O3D,3#л(̹UqY mD3:ԏ-T4*6]8]&G.=2W N J ?nČ@g:!#p霁t|X/z1Ζt/w@\q(R~V} /CgF@A'F `Ao׍F`yGj#G/?uƤF`qW(IGo{Huܽgw=6u G饬#З϶> W,o.CAz]Z08_&_{aaBqɡd:S> =ɿEaTcY_S7dF04F{KaB 5>pwx1 G˺Y^<}m ^/1a kJ/?k? rֳVxax'(sve5JaPv;Ȥ= ny)y"? % +:&6 %5`4+; q9;H|xaV )at:IbcTf:dfF,]JF;ޮoC{Hz @k!ȿ~&|"(HinA(Tѳ0)[Ӄ m!"8:3bZ}yAsE  &VQA[;~x)h |sx pl-;lQ`Џx=魠A 7~Z%g@&+AX֮sODA|)j7e qA. 4φfJ BOFTE>8=yLj̉IAH%;m!)3N!6pvwAEJaf? Ϻ<n;3$ ƒV V`3⳹hʽZ79Oq=x({.GMV?5!Z-+ pK|{13[>AOw ?}~Vt"ŗPle?J5Ql]6sf; $.xQ-rPt_ug=عx}蓤|V{p 7JkS!O}jQ-d#e~#n~ؒƚ=̝Ai"~/GiF};/'!S ~PR;TZ‡>+On_|Bi?yތw8N+p>D5!>~`%DfP? K_2pó$~pXt,]?dܽNN6iq} ibpDSaQ̭>h1s6U]}`HUUBjd>X(+G#r@\>Иv Nt>#ΆmΆ&&"a3d}F lMK} P%AG҂AE>rc>6zx=u9os}zwahjyӾTHPcJ| D+U~߳pXNU>VR}ooALEpޫKӽnmaw6,ⶩ{]ۮ^ΐL酶AIpݨ^:\H/Ҽo y%zaFn^` ,T?7+zO^805 7<0 uoE%CZstYiIo>oo4wq6`[l;V;@TU7Xg"@şz`$8c* s?Fڮ={獓})\cݧ{nF0(:q\\~_g%飲~S@ZzJ7rl: Le"?Ϡt^r{nxdi^n7P% 1Vynp&?D^k};GSʟtCǤnP}]7xh&I^*e ѧmʊwCtƢR)庁z*Yn8Cxw [7,s,$C.z5~SIvvik6Dݨ.3HOmWtA鎰.c )|jwjYva 3\$⬺.Pg|k#{ ktꇃ_Jĝs~'M?l-TSv _+D.(%ܩ[X{uB7G͝0ݾBGONft<7Ͼщ@/Fm'7a6Py n;Sk9v‰[֝1UoXtΧnG;%swEZ'Fqswv(:83uB.R=D tIvw]~6ߚcNg u@~ֻ,[/u@qہ2;ݥGgP IV|Z<PMtv rԭ-j_(0; s); n`#@KIJw@E:ܝ$Yi0_猢ꀠ1wC[րrl;̾}3B`r,EV/~+n}|v;(9&öIYL;<6<}9?C|vp#Z:CFvueKRj`SvvP1\[L] (k @IjUWv>#og m0<6WbsR0hk:&6x4r QVvMO+lSy9ijhY[&V|fC[aR${`+d,}2iEծ$1V0@7Z';g[EVseoYyVL1m5;[ɩth* [`tϑzTI 9ە[ SRl wy ". n}W-)zdέ*@sHU8RjR yp [;DrJ ,UH8Wt~ oeګa-Аa}h7WnȺbރtf8{él_55=Af / ݏ:Le4~fxsE6'RY^5} N:q!AͰY7f8Iq3?pm};4\u3s= ҅أprla3h> ;=6Cl֡fڶh>ͰUfmciџQ@WM{HL1țmוFx@~B#Nm˗69-{ݨi|]kYʩpiq{|#xtjEŸA=kF(N u{b=i?E5I-yc#$?dlt6B.XF H|i&zp.eyf#LVnr)AtD#[|8uAFJMxAEF7EǾTo7ސ_ Pɘ:T6t~_Co3IJ\imlt/mz :Na `.k%64o `;s,=M@S|oy@Xn}G{6ϟ_k"o pbк/7@?"=q= 5C=.X6l$dpWjJoiv6T ߟ;Ҕva:$=ꁙ kGSMփ8s`=4S쬇+ᬌ^AU=<UT?&rAUաrj=H\anߌo)qOjrz]`CBRS:{! }=t:LNs\;V I^u060{::Į xww&~Sj%Ok`"CJ@DŽ6"aw<ndy+u`F^|:Au:xEwΧUhu Y}r¡"WUܨ[Zޫ]9D̝.:Pex:ȪxA׉urܡ:`ʶr`_=.)\ͅ[ ~: }0-RD[)4@k*\-ؽ;T "BR-/Pzv-3';%Ԃo2GbX-J}] 4޵pRLK-fakݲjgQ-l QRKl^ek!ɵ,Zp!E_ Q,ۂ5_gj@h_ kr~I D3j`(g\ x^R!5hrI 4JW~65Plؗ 5 |5 Ռ$5kxŲ\ X|}\.V;kG.'S ve>7W ۜAH8/=ypBUɦfbj1j _>[ fVàh혛C5 =Kt4s ͪ髍Yj8 }GH\L$ -/5fjڑP ~&ZmV]b Up#P>bZiLeU༁ȫw%hy僐*x)  =IN٭8VuMGVUBr**؊4gW/iVAÝWumif$ yz*0^x[ZM=$g.)/WBEjD%DUxO驄MoJp N~vpeUJy(e*̛aE% ^b/ީ !+!>عJae>bDݿ^xTi* 9Jլ}u?Q cYRWBFScRjZ=45]td4N.R}V`\9K^,j]U@㇯}E?*>[ۭ'p a]3^;/>]۟Z* @NFx&[+/8/Jw xN)V65t?*JNSiT KA%}re7'CWe9y[ˡ^:%z?U>-AU/@eF{M9,t=+u9ˡq;`|G}z9$j&/[L OAStʡr*.]QMv{[< qΞZ_&/_Ke7YggsdW#]E )5A12hmOV\|ݢAe03WE+r(}aNePZRgSr4`9S$v^MV-R/&*[&28c92q2/i% 2V=OG_,6lړRX>^7] W,K1ER{<TЖW%BkƱ{K)!%X^”YRg)d`wKW CR{E)=:HfV V~Bs|bT*/y J“W{KG R(vzLR b@[Zܧ..̖gp vrt~4=VR/O]Wn ^lIwP Tќ-;:*J2iS2ߎd[E}Z_e"ϖ׷ @dN t{ךj 2ih>TkK`WA=?)GxXC_eJ`FR1 c^SТ E Wu{FCoP5S,] 1.w%}/wiw$`m.|s\V.=-}?qKCY'Na^1ЅʀbAb1Ap=66e!\ۤYx\y9+0B0kp7~})BpI}RB@b,+ VpBhK:}@|w$U ,XD !?қo+29!+(XcfKlD>$?!nco~I|s{ EECMPy$m>+]ˇ_៝/x:Nc; im=tGIip>8S(ɼlH:D\͇M;-`·A]V,$yE4em^z.}rno8CχU}8یp>x$t4Ob88OA(J:tiQ84_ẟI;Tx,q]P[O~O:߾9X뀃RI R5bޫ81`,8ÞN{C6VupxSp3C&Mi<"OA|8龀jvkw2xJ䭭 (*fApٳ]xM߰ x=[-BI[W\"da9AZSg#~{WMzE,sz٣gRteV:* ڰX$7N k. (Y˃Lrٮm): υC kw|ۚ\>, m!mɹpPkIL.< \ /s!۾G.W 4'tL.B-zbkù&,P& Mݛ ^'rxPo=4Nc9puDS[66T!wr`2Pi˄hcG8< y|\>9[Ʌ^.b"mT}$6e9 a!j8B̙ _[hs`"ݷ^c=zd×UljҜ /_)φn9`+@$)$)8$͆|lH!,ufËs  R2`+Su> 3bA:%[r^%X*}3q٥PwܼO1Mf9DZx(3 ]xtx?Na_Ot8lZyf tp|"$ޏLqftJ$tͰ|0q:vPO*H;@?l2t5f~i~66KߴLdZ9th{gЫ5,7!) CZW;Al(k:$8h/ HBѠTBBD"%)%*L"e$J 癔6T"{ކA~guZXg~֥RYY,T?6LaծVZ.soWxۄ)U+3 .lVnaݍ"o6Y-9x0#g84"q!0O= rŌV7x4,8?0Z2'j`"|~.̞kR΅,ΣTp1̱iv|/+cA_S$7oǶ`O21ϖYP)~]ۭ!Y,"6 [ 욚YQ!ӪU2RYSkfWdĹ9EM}]Ăy\wY-{ܶ o5xDs8֯2~ςY)crbX/nL͂~w5;1;gG߲ .H!:ѧ13_yÂ\󻩑,Y|r;yw7 Ί>` L)p \,eM 3 c ~okSBY02rS/Y 쌯[Y 峁fAؗa@PH,Hyqf,8I|N .#_05HaaZr%\fc,>3NCj|{a怆,5XO]dd T!rF"U1iO{c_c3獭Bg\wþ-͕5X.,:)vsgǝs_&a1@# FT=~/T^3;]#(kü=Ԗ"6,X>4G}Q tx3Bxp;1'NY R_=}V,H>1%QHW,0X.q Ʒ10/;Zu}nɂ~ ܯi[1_}| Y u1}o!Lғ7XP_ |1W*=5 ߏk⮱@W|]) 6;>#mp*#@h Ie<ĥ;;.F0/dq^u+=hĂ)Ed؋Fy! K :",]`[UFUE,Dqo=ǂMK")C?Bcβณ3,7\":ӸASS?McS'YU'D p?U 5çVb':<4 9ųG<1X\ǂ߷b]-FcF<؎Z{Yp74]7VV uD,:6%cL~LJ{L D @:C?Xœ԰E"&UY?^dzLE<Xp,F̻^\SbAA߸_" b gq.ܗl kY9i xVUq/ xԼz %mJyt9e1cnw?ڍ w@@yj'΀̰;x_~vY0%JvEBmxs淲ࣈA:&i.sKW.nݠW ,0&wsG7)̲MXeA y¬q^*-ܶ8 jU~s;WX`^ςGb&~}QYM>cA2K);Jg6SmYykUkS=:띬X`w!ȂgWe1?~_{ς{Ǖ9Gp1B~RLyne;&CU,|.p% ~蚿>Nłh5 %$' w3`Av k j-gRp(mXKÄk=o8.2!ɰ&\hZMgB~r /fsL՟eB͈8c3Ӂj,@y~ 1{.O3CWy S<ܘ:&ړLx<}1 7©>1etg} ^Lk +:֭?LcLa*6kĬ8iDaBj L;î/$&hN]tr0 B Lq YL8"q&(([y@y . `}3Apx7:Hcx's y/1AN&$tq`PT`B ؤ6'!_L4l,n+×x/>ވ嵟q(ͷ0+@3꺇U3v771g0x f 7I=@JT\Elj- 2"<Lje5R_x\~ӻJ%*FМbbS8~Ft˿%a=>bNx0a?Ǐ@'&ˌHc?xx#طlu8\?SV-yL7 &p!}τ/e7_or0 M[s^V0!"l&wTc=P; rW9d2C #= CطD0mn&Kf8 پfy)>(mW駓0(W:5&h:tq?B6b.z. q=}(c,E]u#9 W-Ha}?bO^wLh>g-dQoO¥0)OCοa©s#O~|3WLD^sC~";3s\%jAxVե TO`»նC`2v!x_ڍ3|qGpõ8<-J `|Lu{3ANDӏ {nT?eYֽuq>LT2fBK'RQJϙgLx cj>jxʄЙLjɄ%nlYL8% OPu.31/AznWa'iEO]]ƗELxy"ȏ̯5Ą{>x"3xyΎ =\G+lP nnJ(~!Okn}k<Gucº[_̖c.<Vqm7FEo-/\TaӏX0"]<R͙PⰑv#{k0Vݞ8{ϝևxԔ #-a~,Լ+7כ+ ҁzc&lI4d]f3iW^\>} 뽺Aň _u\Wiu׍9ay<\Ռ>ssد6~ch9ŋ:Lv.&m3Ʉiۺd'qqSv#mzlǾN:(ηۘrj~a+9)a7ab lM?*6tcbSśжr72Օ7gHbl{rQIe=gIp?aIG 3f. ڭ%tD06Y?Tǽo&pk1˜G01Əw/|\Ү#hRz9fwۛǀ~3 HO},ְ䒜h-BƄ؏1_~U0`?J$_e^3g+lҼݐ1K$ /G\0,NXǓBdk€97C#gfà xʿ pπɊ ޏ+1 9s~ʇn x{3  7 ^ `߽݃lVa< 6d9ɀNam<'6:tA69Ju@~o&ri: x~3|Nډq*2Lu pޭK+Z`SUcڦ'N~Oi* ~V8ѩ̀ڒJدjW`f$Pe]Pǀٙgp *ͽ سﱎOmy\G^_sG6oK:d@-w],ϸ Ew0;7][C2f1NV{cyR =݄wDIF.J0` Q^sXVq_(G8Ho=&*au"X[2`,2:а5LO' 3`2`.>q M*:\ݳ1Ė:$7KN&d.ꦃ.:oF ;N:7%ww˹v:[k%v6:eҊuq\č _蠣:qg:,$?4jÝGtA˴E&A#:jvéx: x_C]t8仨cK1t <$~Oc_j|[]Ǟ7tJn$.~zMͤLWM[?GAUՁp: |Ioat|A-}xQNL! !Xl`:{M C5xp}?r-AX _:~x=5)W?g⾙{ey<՛ܞAkp3O<{p a"AoND)@ꏘLI|ĺ/ڦ}!g]rtxұW w*ɝՓa.ᇵ $\8ϟLOtns"6VGaWضv^:D^F{P/I,O&WX6rW_M7va_+7IAÇ֖thAVy ~'.Xf"mzz+߂yvq3J悳4#nR]p)ܓtSmdyIM8 g _<;bXĻfIu~4 ZGi `t*Lma/y3.(|)D2pA:L~Ak:TĤ×|ox\BE| ]E!1v%7~4VϋIb8kHYNHr2:R\_o" &|Ҝ{fY0֞*לA/5h0z& s܄޻-5h4(o{,E/λ:i`sTSlVxmBEc-4~t}S 8c%hpKZ"Ӱ\V`OqwAڄ{iXU4P3TD40~mgfq_;ribMsELWXi`ƿa(UiR~$ lui14+4(U/.W|E/4( ڰ7+ 렗kJwٶ1q\e@<̈A!4HϛJ>}Fkϻ=\dA>4Xjt ?;iB4]c'׀-hp I;ү][޺^! z(>s_ )ߥAE4< jAnMiH$]yxb }SWio6AB_qW0f[C4]>,Zy7*=/U/473*H%KWwZ4H]Gx:`IB #S +IՒDqtR#MV@ꎝ~bZ];n)]ugb:4>c,7_AgT栁pD"S&,4Zf0=r˧P.wf1E95x~{1F+)T3HhH2N٣mY~S!7w(a* JRa5T0A)`PA=MoTy򭮃 hT0Z!3< |Xc#>=3RaRh5+TR˨5a{PJP67YLϕjku C"l󨰛2/ KOwϢBOH-=N^qOC8*ru*%TxITXy%I8NWT:Im =>4| 4QLr(e0|MzR!f^W|qeyS!I <¾AqA*jq7? su{~3qʑ 7쩰ҹ#*6 =mm|bŷTh;w>_ PanfK*[ z3_} שP̭_M/)Cdu''//܆iT0Wke@ S!b>3XrB q*QǯxϊU A%>ߘM|Ri_ *(Nc'Tmꋢ Z{t7*S:[ ;h 8ۨZ S[Wel (R:۩v[ۨpә-T̯"MSR9挕T :В,ֳ ux TPU o?sBO3r㣂dm^*$IX "pR!(7f/<+OX¨'o(@DR() ^?M׹U&) =I3 JG8qH=$ b2=*)`,?R9 V*J P3Ƚ?(v#$|o`Z>Ag(_r퍯XE;yg l=t\t4RUuP@ }5P*U/_|-(-uܷ.@ s(~bb ^;d)^DBn| d[%R xIB}6,h3XW76cwa2j"9$x \]a=F{7x>3 [FP`V>b!n㏛C+Vn{"¹ϟanS5Ox`[,)4ڍUXQ~Ñ6HyJm(p,ץ((Q@WͷKVt6~uѭ4nPP:)Tp)3ZׄܲS@4?%=1C n}~o!@Y ,l|[4>gPI xg%I_(iQ&<иsG^MS@wOw(:k;H[|75@{)>I<O@rݝPh6CMk`&4ۧrb6u%)ނ8MqևQz(`[ӌ0ϙ5pIyP@9X>Wu!2 ԝ`?vɭ~0E9N  8U N yd== ;\"3R\-}hid?BL&dm]"nUF'_{2O^y1PꝪ W~"2߯ɠ]2 {G|^'dX^l.D(d*0K1(bo2fz ubE}@ރZVO ފ-> Z_Ee C2c1^o_7xłۑGW߳$}[ eD贡32p%%Cl̇}Bdp[ A>LE=r$z"J5& ?ڔc ƒ-hhXa Nސfs+|:7k.> #Л JBIoK.;n3߽@ syN`d3^$h͞$9Nqv nJQns!郵Hk` 7#wC<'w>^ &W7Hq^PHX7'97Hpl$ϡhPÄ aW.|9ňE$*o{'~u?KB)\e'p=gCyɁ#$Wt|ȭC7=hAJIp.NYUu*ޘn,K)*uIp>$ |$CCxu9܇]H'~k+ X?l&Wm"Oْط,{Ip\[1Hp[ T7DSAީBkIpod 6?e {3> 1*ߐ?y8w$lN ?XāUZ *a5D5lsD0!B~enI#BV9β֡YDX3a~=W ҈%kJcY ^>jK휍'6 q[$!BٻgsJb /R۳_U{HRʻμl|A* J0.P;Ol&{Bno"h97{aϠ7OѬzc"L={Ƴ|3Sw"pc0tgޖC27=$U"pw{ֳd;DH=iIƽnp%}zD hF]'BփD "61&B[ݗ*KAqΐfOom@6sD6iqoەO/$8;t:+DmtYc܋t>ZDx~v@\FuQ%Aasia2~?B~"\S*R B|⧃ uJ+`S91JQۜPTlI xP\ `tF]rKR Noo#4 :ϴU@+qrH^r@:jV;2;+;wouWn -&,@TbKJt^}S@k–yRC?,^ⶶtd]jN%@CU2B7&5;bq^ۖG`R̃h|uP myiSp5,&@5Q(K\; ևSW@bƀ<͇2}uc]47z&?ZO|/ lr:Lf~uq!@jcNގupKk66n^(>xҚ7Xm(]՜/ Y]Os{vENN'\zYFl,BV>.X02$@ؗ y?Ve |`DR N Wܖvy֕䜃a&Ci | "@\k!xaMNg[$@cHI * zjgCs^('ٶnơ];1}asd6do BBy\) ;8j^vj@XUq-46\k- L E!ؗ*z熾'@/[᪯sq O~rtM^sY'C#|lɓf٨$uua NCl@!p NZF'݊FsOs`' `FC?鱻f l4"oYk͌~َᦁ[/=Fʮnzl> Ԉ]oڅNܔ ,I7hYjkp ސ0Xu\c ܘƖ鼻j2_'kIןj6zfxǯKcFrS]lT"H*g#{z-r f⩵6Q}g]%l>8ύ:_>w 9RF7?xk`=sqQ<6Rsg2r5] z,~'+^F~#a8O/Z e]w.m f$ 6~%&p^v/E~lR^z$w= kVЋ 2ldnEt`=X.1PYW6}&guF_ !/f=+^cF-'U=czua}MIfѣoبꯧ;,y2jc){ g]7h_c36М=t 3:S6rs 5m+5uE2~vMc~bm/x=gq^п4?/V9FdO~q wla=rHȗlĵ=IkvQ ;<,,NIFlc{[o;hH3l4DݷATσUESUs2l1ď{La# W zYi0Ѷ. . 3۫=u3 ޙdoslr94x0fԆy$1QOA?>-_NAM=C7 )ΠhS=~f`AT?)62] xgU_gP>GF 0hlA/'EfU3(C:YpK ZFG :1ײ'xyIWQ)AvFν3hQ ߛz;}/~<w͛)>A.Ϡ-1.3mee\։pvm*gPʻ3`pG g3(%DB z*hi< /Π2+6.??  ^R;>n7͠]!54]<4EFTfP[3qdyRsb Xٖ%3rof $gKg;[Πޤ_ 3%:d /}9Ok/M#3!iV:05%O#[!NYmկjqQy܏iTti4_r7mTVmFf-5u UiS~48Uf}4b$n3>{M >ei[3v㮘idL4:sV4*M pEtT[yO~(vƖC.8ڮfA;/^e=6lF_Cli44FUOL#uCwAis]4jLVF2#'QJCOiٻM+UfTs4j$Oe6Fy+[h ioGr)&V79w OaM~O!ӕSjFSHAR)D u I4L!f` U)B=s)ˁ)F5x5;3{^OAe!SFD`yHl۱0rO!8erFW\oiqj m4Ӛ|x <ף6Է7$88wNrHM!W1)xS tύs -h-=?B'3&ѡި3ώ5?'*m]H`fm$㔗Y56\Y<,^ΚD;~%Ld̯o&I!h:h|} ^:<d?D-&2vNK2sYҟD5PwRDr$RuDS $sʊffw}),fNhj>f!mIf:>sw'»+,4V)6JpB7=z ^qJŎL, iDoc0s&x};kAl8zl*3'bEfR%ؗ5@|+(P5r@c5# el@Ǟ3Ph{8#ka@L/2Kپ =4@+N` }3JJAxfNX8m/MH_5W}(d:ʯ-FБ%t%wrӑrc:*=@xyM^lM:h>^ZZQu!;0pF9h(URLC֛%9#h{Z4D}, !Qc9Y&CC"ZwbeTT$•6"a딨(xͧBTfm.2<('4vV rpm:Q209𻑌$I&_\2rOve"G߷[1t|$ o}3/o ! JCo&:+K0N#זM;{z)7NBS[s"6l]v{)D-Su/1Y:vz2'J W{V E;#ǎE?{ި Ve؏5;F -i? +c*?9z O:xRپQ܇̵(F}kitz}B/$vf{Qٶ}nN[Bh/z̛1?A֟LAW" YA?zƔMwx1]wDr~jIN"X#z7^V7эոtg+FԣQm^nb*ϳ}FigZg- rDM6*E8߂O<~#҂ ;2݌kyӌ8?mڌl*nF~757!{4!Ma\P|#Z{e[u#RjkDO+QĹFmDзq{9ҀD7Mf4u!' Wm{j@U-ڼ ( ]H VzdaWyuEZhk˻M͇{ֺ]кN&PKY:$Cv"ZZd>lV>my=tQ䷩kKz4,lyٲI}qD Hx[1\N~Fgğk衳MIjsꄇ4_5bv~g0\BsW p*AYբ |iѨB=[U?(J,3V_fUV"'z 3J^i˅JԖn&_\7uM]Y75+ 9]}g*PYp/y\qƸmߢIi>K9z?Ʒ#S.a Gl/+C^O:(C'SO M{ KN"8bR d p@6 ]'v,A)҇RbUK۞,|BEO瑧#^9չ>!^/P@ϲΏV o>"Yߛ>"CK\ -jYO*jcݺkeͭиHtjGpHx>6ӝ EsE(/౦fj_R "COv̤J.hc{/' Q5Bt"5rSssyjSߛR?Q" /V*@;v9$e,@%{~\nr@h |Tl]-R>3]N>e_NGg e[SU܏׏zґ7=M:j=:&q%=:^11c=5sd$f[זi(찐\ZFf"iqRі=fnB.p*"_ězT_HAZR)s7RPչ˻RdT,92VM .OFy5~&W6'} )IhDV$ ͮtO@۽A::wXcKZwW&"DdzRZ"zppzDdaxXuY"ښkО~ ']%GNSğ Ȍ%Ҝ 먌G{QcGģ܂&4e{9xԗ#KC{Ô8/lDxmo/|/r8 ]uT<}_{4=;Xpg{tfB]yz=گjbt =yN|iEٰX'D+B1џcPRׂ{~r Z3um mhDXw4ZuWcZ+u3ZxM^wTڽCn/)E>Ay~o|7oѧڗ"\.J=dWjٗ=Bq͋E!W9' N׋ ai>7HjBa[J5E"?ڙ !HfH.uDw F_|+3^6^#eߩ׵ܯ^~ފWHo_ħ;xdWF{Jk,F_'̙MO"}y4K~\L\no]535zń#jb`F8tpԒ<29J}>}BodD#RgwDWokח0wUkQ\[CG?>\8ro`TR;}prRŹP:luDL9@gμ@EcN_ SBÏeݡۼO١(a"KPSt= >7V E:"{P^7bFy,φ'U]w#U"Q{'8#"o2% " B "&&1Bħ4[  xeT@4_#=$V8}W-CEUFpE*?jwxᏈtxf?jkCg-^ȳ~q>?RyQ/2X;ݲ3ԼD/-EMfU%VK}=\Aχ=.Q+Am8Jgymj۝ά7:r7^cs6?rQgf!:?~ZֲN7qzDNyδݠQtj?y[ӌoO|9HWhJP/\0ZET}M_TJ WܞtʪޫB’t9~>M}=i̱*yVmҽњMZmhϠBÉvS_YSORU'Er\&z?䟥Mt'pSӝmճ52Oz1|ZXB/O ~mzȔdթ51kR0 M<_Vh[*?Q(DxKZ/36xHd U M_V/ȟ_WzHĵT2W^ UG OVjzqШ__VRig3\}qɽA{|/r_ڒЫBҞ-U_3Qz辰WJU^1͗fVJtSmCsi4ʘ>gӵ7cw}*h&z}3w9MW{0k}=^?f^'JzRX~}8^Mya&x%oQ)qRa̲:\^P?:V嬓QH|PGluAό*_~e{:h|#X6s&eT;[zճ"‡NWHȷX]meꜾsGU󧶘|2Z\7yJ ҟU5jqr c7e@N1dzA_8ou># WCRk #77)X[Mmi"$8vy`e}M'n峖:54I$TT޾X/W'W|,KiL;0`eNoܲ~l إlZ_hت-ƍfSUbn~o\J|co(6\p+ZGWE^|dfmSj;wki4wL=X/{zΉIO+UFm'13' Wڮ 90rz<.u|ܯ_߾ $9;hh:G w㪢umnRg}5^y6c+c"ZBQ.߬|.>6<,;'dr8_xli{iD=6 **MUĭW8j١,te^;t&.53#U <1/}1GNGд;ePTB-*~%v[]Us^Q}d۩fy[|>^ak[/Y+^tCJߓsZN{?jT* @U?b-J~^ՠ7WKk-QI~:u*Wyq ިmx+fnNֆ)JO]U'_*AW?Rbܼ]BiTS'&&V|$fD ~`oYof?yTiqY1nU1!s׿[D5G0γp܋ lLgQjy>{R4ojX9A9fWB} JeQ6r/x{s)y;_qᨄܧL&ΐ1%TRaj.; N0#οw[1'1dѿmx0GE L &ߓo RNM"#TŹߕO10~3v`Fϣ:7Fne:X@O^Vh/?@LTnV~^/5x/?bVl.68 H}5~18h׏5PDz!C!v6kf!v?ĭiI%˫Nih?&zUoQq-+%kw~5޳$CP; O)sK LsT=>1j=7w6" p~jY ~+~??O͠*߸S/3΢D˷Fs5 .3m5zܢo,e9m~_$z68Ј¿q_ߛEAaRY\$n+vZnGy/y~zLsZ0? `ӑ{vgLPE^ȟ g'Kl #Zd=9z.w zkXMe:Sye]<qa.9-đ75@sҳ y)KTÑ"1 zLJ^e}x81E z? zb 0.c^B~!؏L6VF1>m<ߜ[m昸 B5_m}6>>8&O]Y/l{d 7elG>/EW:b:*6(.9ul__\Uv; 7zedXOzraDh1>޳KP_q|$~ ݻSBu1 !~ &U͝8v<^/_?:{WOR0oXz>@j?Ge5Z~BFˋ碦o,#ɼ䘌/WVaҳ^I ɪY-N~{ͬl;,|a>$_%. 6d.￧ D˰x_W]ֿ]6-Yg"gkؿsq9r7^wT,;70y~]lx<'nʎ=i~oNsѕFM7>\t<]5n'nۨw:;zN:Z\Jh,zC﹟8r&7J5ߩS៏9|it= fO3'7CbteuFcM0^͚2uy8Ӛcږ=hvWD*/h-!N(oUl4RW'/c70>svĹ\9h^bAբi w 6-nWB.jmy5e;Csk][D|3~=Op+H"B^D/(f ̘"JNED""z/3J^\7sֹֺkϞ)}G̞S׎- 鬀\bs%X_Qo}Um5X@=!xԿ[{$:zD}zCus9JߩO!<'+4Anj>U =/F{_#|X?KO]bM 35c0p[*g<`/1w@d'`3XjB؞J~Tx.PLaPq@g@wGqSNjIvE -@S˨>=@a>zT楁+;QHU9gDj5eҧ"hPD9* P5*4tvG1szwr}F]W5@%RʃT{3%y|.U).ן҂iHFi[3-]nM==A|@vL6ztAhʢqo3KJ1eYn=^"x֘H@Y,h1r _*ZOA:Y)^Ƅ◂ADã\{ryiъ%^sf{_傪i.-lSY*AS 5NkL{|܃ݮBX#yƩ@|Q5F [͝x5p͖,җkjDv&$p>] ԅ$p!|^K3. 8DG S۪F׀? #XG[u[]V!Lqbt7BPFI#XHGN@[Kȑ3Ќ;D:/W݅͋Cs@hCkZ?hX Le BF @w̤kKk,.p0Һ5?8z򯱼0_c9!_cyI̯2-?XMXIcc?gCVEsZigeUr;˓N g,BMg,;oX>w,/;wܶ^d~aKHNc^ V$>_ѓ>/h`Cz1qRg&.-ZtG-mWhU@ʗ-@^FW.m]V[0_QCtWe4^{h,iv?mtWdG)-ojW%,Sg[0k?arʃtO&L;/tH*Vj<ʠ Fj_3Wڑì _}#ߕ~*ɳ.rhvƽ7TF0>IZMO7u*w)OT?Zj&DBm@|ěC@̧^O( ?K}#bCT_m߆mnCҞCE7h^J<[ 2wd?h{#kH#ԟ%ƿWz_R?/KA#I/AIԹ:."$鿤/O%..z_RG%uz_RR{rLAI=CsA>}f/:/RK>Ͽ:_R__Hz:_RRoRߐzǿ?HϿCI_R?7_KI/_{[_RRnCoz_R'%u޿%uz_RK/_R/ߐ:_RW/kCR_H/Sx_H?Hԇ %uBAaA>Iz!u_RK#I=C u_R/Nn_H/S%EICy uCR/&RKSAURRRoKAzKA5 ?$u-_RKԅ77Wiz_R/ԥz_R5?w&:?u_EHE n24|bLI\?b,(.3Mٕ?+{^A;]bԶvC{kă~PBwj/z9` ?LxS)7?x-,Ni\ZP2cypfH8{QTk<0~ F8d˨l1ƮuPSJTbK5}f91e-]$B>bvwW!iR_ez5CGθ{\ȏ? S^=)`F]Ŗ22Ӡ LbrcIČz&ߩ|hr ´ :]["Y̭ }A3ybzKݱ˳3qln~Cl}_Bq7z-{ɸo?ڍ`J'4KXזHу#rk w{?{?XB2u.T%t'CQvvlX$sJjj}㡊Qn\d?Ӏ<*]'$^pjBӃp\kje=bkA] ~c uel򔫈Cv_j 'Fg]C( KSjp?[W)Yoތ=S2B#kvW+Fơ'OmpvixEoמNj<'uBS ifE_d h?ev˪ׄ w$׆3w>OguݹUDZ;f 56Q~6qP G|&][W7WMIS,Ts/ԣ?K$ؙ;*egza%{N3cQ:m =ת\Q_h|YqڻCu36zS⮓#8ܳ2ob& 3sf.|xclTPZѦ"'i-OٗaC(K+lfJ WuC]O}ve;F]w5s3Q>C{e[( 9N:&D;&)cLc{gHyūzL;LsO}Vc QqĻ-×TՂn-n$5ݯu\rt-w!5Ĭ:Hnò`6E2ǹӼ\z}gi#'*p@g6*zw '% t ոNnqФO'3͔OF]3P, G܆_zB-pXrv[<ٲIn`h*RtkUGJպ3[-{5j{ͳhhYp®ImK3L#qOxLazn~ئtۊl/T5,,ιav.D%s}ws5h֤Ky'pn[4𯌪 vz]+ W'؞-z(k=Cߪ81YDdИVPrHqMY{06\E򽹊}b~41GY ҳ;ĘŶ<}aw\xlR(=OK'O |Sb 6%ȧOE]_or~V`99Yx| ەZ.,¿K"Q۲sx_ټ _wϭ̽@mc:`i=t~ w`nb\N>E~6Uv|Ѱ2ylIz|C'zypm=/{Ƴz, k(& %@?k&r!UW?lX|ܘZ... f,,|9hX>S#h8&w= W~ b!_O/ٛ~ڊ559cW/\'O+Xt^~ Z29{ѫ FlARKXE-q*{lQ5M&B^Dtn͑<>S@0qG+y6Nń 9[sa tZAD<s6E;Rr nAV]|zg@+όe-NwJ+vŸ!ƛ0w]߄o_Ŵ Dt긌?@ژژ0%rbkoq705vDqol/qu}i5'?]P^}Ah:#@iEZ>拀ꐶ Bz@_<~?4Ox42<x 5L4UWuؼP ܴR7m>Y"֭b3dT'~=nNfVϝ!w .s:]7ė,>껤m3OE~szVP4E#S9n˖_3RoRrI Y`PQL\G{4"U6w& s)?'zz>LtunlbNf_?kMnz O< htoZEl*67h@>ֱAkG90WWwo&kstMȍ|CjӀUz;>6zc[MU@ل^p 2ˌmGU;v`u묒q[}Gɥ^auu(8ˎD4ǧѵ5Y ~4zq<4 h\y0CeIzALcmx1veI\oľ6eC9-P!Yh\5@2v`5!\#w6"Kv_J/|,;~`deprЭc77!V7*}KJ,v9@fHPFo9sP4>Eeuplr.O 2 xxp0Mxe"R0p$+eϠTwW ĥlݒ@5(yZ'hpXD^Z' jR(eUϋJb"pߞbp+' r[3 |cse^ -`1hԵ'osX^[\'J  Px/e3\N>=]H[-ZEڶ(lԥ /#}<scPq7uijoL'soS'/T-OӪ@Iә{s^cZ=P= z;) k#Y2ϒjTE{ oɀ6_Mֵ ij!2a9miC~DHE-% J@s}y;A\"_4'^ށ31Iݽ @շq䀆ws]2ks䗩֛˚ J 2V WY NE7|@RwV* FZRY}t f6ȩIWȞ%O Lu:eUgE銴+Oz8rn-ܟMaˆgR`@an>4#a {߃]:)9N6`)=L{۝aG 'CUzС=ZvٮqETYv3gdHUJ%귪ekj#`\*1fh꩓ Х0N!]~9D*&wmgGU |[8R5o?UA|*{yF srr0Gt'&>kìSMc ` y@&k1gj%wQ (ޮ3K&zo3?zɺ$*Ԓ Y?Ͽ8fʨBor j V(*SJL1SŽK]Cff\Ґ?u8Wjo$y?;}$HWguݎi5u8?W\Wo4xna|DC$Nx^v4dz@7N: ["%Ӈez#@eU+ xpչ?StJ삮^7yp+5\Ө5[}ٺRC-zW1t W'Lwԃ>+:sNd| Kn46{$X.7z rf~f9r Pں1SC^3!w-T 0 7q'ͧCi"$r=LU=絛wp׺3b3nAv{ǭHkҪN)/p]g²w0ny*X29\rm&(ר_;72rc&؏,lPۙnxy钫Z_[{' |̹74u@7?o|%K?ܻ?!{jcˊzTaBecDmtN`lpr"Gݧdg[+zgY=xeG#ɃOkɺܜ^DRRƴ涀M ]>̽ fq%%}B| kЮM\SE ^/F2:kG*۲i-rI[vf%FV?: ajV+~v~Je0f bjݣ H_ Yw5CݹF 3 TgT/lW'so-u;M ?8bl[ K#avMt^RےC! Tc(M;|mJ*jUc:h^:׏M^-뻆6bݷ^Sݞvk#M|qh7LQ;ƒu4B7kNs%T=4G/7gG68[+W&D Il}C*EͳxDK.x5vc˗5U&4_l,yNH^9T!`Z֖aIXUFU7gHA ZfyzD'|ݪS[<Ί5*?~>nA:usjQlv+_eYr~rDN?3²w۝ԖLCm}` =͕z7FjR㞰i'n 4+2-OzfMOמx~=Y5!Z JY[Gjƒ Thk.R~M\_8$gj;a^>BXҝZn*f(.ß OI]g_MS13v"x!_W7>y`k%=%u\ZAK2ބfn 6:*ş=Y1k+cfgO#Xv\I|.{EHd$_}r5 S1⺱~ǂdv/aZ|uĹԣ#'b`Y|tz򇌱O {h v:}Ê $5gXo< ~9Q&m}/yA}Cx1y l9/Es0RpDcwFOSȡkX)@)HX\s]]:^[.~ o,@v_YV0X['Sc+ sUTi4b^[VSKS@{^F!(nc PzqX`.޻wz{)6a"Ol(  /fibTs"u;S%=0CW\NOz~M0>d7c m `xԆ zy.dJCnrWC~Wc//ʢabCΫN~ x}j $w?|_z D El2T]" :\( 0%^T? ~XGDG$F z.}[Ks(9lygRg |اN Zݙ_ӺS?8 @W?MN%tKπU@F@ %:b|{v-)19 !ܯSYDNT۬J<>O&32bE 8wm!#ŵ0Q,mG[Px,@S}~aW}cqǡ(MrT" n ݼx8ru25 q}Kכx2&Fe:vybx_4Uȭ5J~Qu` v`@Ƈf+^C'lSVYin]K#.1j.[+FV1T `k``W]/*ukA/WrxI0M] uB PK(0ų8:}X^pѴYՑR'!97ֆyT,1_([ >TNV(alh~3exעdK:|WQ A`0;GmLz(KZ~ZHX D.h?Z ~6駧F@ DkHKϣG? b](#i o TyDkmV(O3j"P  ęt% ]t xxO Wz%)p8Ẋ p^hBcIIn :T&v@wa6d0#̋(_r90Pq%C98;;`%ߖ< -{xj֗]x,5[3ф0|ZmO_5Q&}S4 -_س/`mpQ{n-:/ia(~ehJ殯95AEs. + M@&ra7plcEO`֧E[+UgH`1NK3ε`q01`%o/a KKe*,5bw> F 2umY`kG20!.+E` (>jZ"/ Z W>^Q5v Tp4+@u⧛4J&us`6C oSZo):AO+=q ҂}5hLm z  ])K-(i_h {P@FlπAϼBos|7AG .8J ^Pn(WiM[>6ЈdHk@S3U7A]r  u(:~%iMйro_*I٥_|mF~,/ Х5z:y eJL:(:QfIVcլ?~dd֒TkAɓOo8 @q#ɠUxUMD!hzC9ԩ$"IQ;(G =J-P 4g6ht."q *ݕiq7n;==P۱mM_rq^S-ℽ3/Ql1Ty@N٢K2i1~m( =%]\<$p ΈVeW%Z m;XZJJ*Mi:3P)T5u%S ߒ>1ܮ)2,زI9x9GoTZ`Ͳ`ƳΌ]໦{>|s NvrkW&Š zjXH36F+x.&mlt3~/pǸ~9۝/#C&Y==`Q5^cDokYb*LkE[H#7Ӄq%0sil ;jL[IMX1}.mr6__#f\u9L`γq;`Hj0d);a)1hq~` 1ؾhya,̗<HVuXP{li:`cXNcA`XKU5z\%j5 /o:5<)|V!4S}F/Z`N5K IwՐn!7yG4ro߻vS-|jwhf摗yôZ`=?5QM7+pV/բ~.Uy U8[;WWrR*礬|$W^|Q>F,r|R J^Ϳ"_ìL;~f4c>4ZS͐$5gx[꟝1%ݰU-LU-l!UO=.SRBwr\Z qt([?m&iM[;Ԗ /=Ej w&R]Zvw*~yo֪Ոy Szjn?j4<@}W}9zTxS͉A[৚;޷E>=o(>hIv8^OI'vnyמl{ՌBj E;NՒ;{,,tu3 gU vd:ӣilGmݧx[ޯKQkX^}N֋Yf՞\Yf*LV5n jnef%Gj7ԋj6=j]g4%JŎ[!zc5"A{~XOIF}qj 86BQ]-`Y_u*T Jo {/+UiNl #)}Q;9lY4f:݁9V0V!-:۴:yY`]F6|@e#N][TLer횦e; R1tY[ʾr?:\oY2wc-I}bTan+z޻#FRGNqc: (Su6l~: '3k^āz7g>_4,G|JͻK|xΒ~5YΟxiaGuge>VguHGu:cO)%;uc=ʊzѫo՟xP Vn3UygR!c9[\/0㣟4A?y?cXh"Գ mLO>ZO)R 0 J2#o5j}8hC.U|8W^t.]ڮKn̝W^jDE%OIn}a۠@tb; `'jW$H#Rgld\`p[n#ڧfrtaqYO8"I$3FGbWUH\քIG@kFI5Ζ?R84*OJ-O"s5ےُU4N 40tL #ͯn{fCQ_N435VR 40W 4 :_gitA?!kGOD vi~hSK_eK߿QV)5URZq!G?Ued.foԸfVoަj!>ECEe2~nVKY. ?5JG˞b]L]@m7xQL! q #b+#+ =LP?~!~4z54os&Ƚφ)~]yⳬ!:vCdV;AiVwCc,4Q:9 7mGk>Wf5oLYE? h-+6>^ځFhX讆nԽmd.Xϖ֘rKC(ϰ14:WόڅԤSjNƔZ3iV}xz{EÁTxHAyh|jC굳ntUS3o@53Xє X/~˭yu=^ȬĩY~ySNJfcm,p!f2cR"+Jz!\K喒'dAͥ_5E533p`!p|{LO5?T|}'Q[#qP iN׾/=Sf᫤uLF߰q[NTFoSCQ9hpq &jҫϤ4]'RbyYxx`_yq'+/4}!G<50'h͆iT-VK&"ö=LsdOaIl/B4]bj|K&JXS2fUEofpP:э )4s?Oc5qV4'sњjUG=O4b4ռ #5kodZFi 8.a5oh{XGi4Jdh:? d'KoL0[)ܧ yEI)xu%SXbGf<)N,[|,T̮Tf7""͑#Z"wb95 ՚xUO]!ݚ ؇n((nM*sÇ$}f~k?S{5s?4Qͷ:4[|uԆ4,o4iN9=0鞟|ըbIf}ܣ#U.h^7w4 h>W}:cRqgC3cpT_/g4Ge5̋AVӚwF74ɲh15{ @dE&(,m*S}OR nJйRzO Pg+gu=b{E}-~sVacAֻћk`Yz)mTs>eHkl|{kMN v{cekfkd- mZ4$@G4յĞ8@Z\E/vϓ6wE懸_jeU%_%BP]A-|LFNtۏw"ZkϽ4͵>ӺV;`"Q'V˟w)VJw=ZRk>LSVk;/ra(-KuMRVZ}&yNZ77;~a^VO7O׺θUPYթ:Wm1^+pȎAKpy(U;V&}2W |.""K v1.Gˏ%T%Sk>3Hu4/Zl-o)YZR]T-B*edmL)7ϯZjkb˴~1:ʵY=䈪ԪQb&5Tq)~rּhb޼XVx)278[J:s~4k]׏hbuQn injSKNQѨ5Fo׺oepިExm"ԪF8ȥW.]lbوǽZ9*A>+Z/BGiѺ/@o2吁duwXx9YgN2(-jAfQYGYhG終$)짵*d1MnZlUPeO4fcJjVht跍S-;Z5 csHVؙV腊VUrԉVV̗K/G^r7X\ZK CCԐ$iSjVݥ:}oW ,:+Otڟ>TTu$u-d}}$xIRBW}HfHPCT9oݠ d/^߀D<637%Gy^?g (/D=ÕA%\I!KMVAH=VT$ּMN%_E6B#1 i?Y)!| e y ö@Rsz #? 3 .%V)Y!׻tnO@Kj@oY{|,<J![Uz!]LӮ@޻W|0?t:$պ)B<~uKNAϕq+sG!wEt g!/m7 XPgUHw4q*dctUpl!d8Y]Z>gt"*~%a#s7 c]ƘOd>DWA Dq`J̕h N.ks?9)9lz[ O/i';,)S}w)z YRiv[=hLmskzcnioQskkd~/'tpio+ƢfT1z¢]KyȡM3>zK;vE6bg}w6e`]` ?Tg|/w-hǿӾI}Rm=F$0MD[XٜcZX^e.@^x=\ "M'{Vզ]=iNeVQSNVzaUnu0RJ՝jOUq W@*i!N uݿ+e%h ЈNڪkiհkJ+jߓ~/u5gnDPk6KզܫXhkPfppwc픑uQ,#QCS%{E Lh$vK;`S܆˯Hڸ_jm!&+촿 _ԏ.]c  .jvo\ǿ6.rna.luT;{=KU&QMGm.ܵu[󘟖ڙ><sYQqאA.9Iک^a^jMGTlk, l*Җ< vqm#>K-/DW;Ev0r'b$mKv߅ 8eC`v#Fr~#ڡDml$mZ67ikKr|XIaS؞g[+e@m6>f8EOr.U{\+{kvB|.+څS޿z6vt{YpoYâcGvʵz9F?iQ%n6# @J;UpjLv!u+f4. 4?Nݺ9G^ܸkԦ10I]qU k].oԾ.{}^mP% /ml(bDCĵX>{Q- jCVGF"6ݴi&jknrQ#ͫaO6&T_hYz5mxIW܆v^#Ӓ􋺱4 m-ZǢuLPggM{oCY|@;K*MmyvW _8aǡgT/zsGLmU_Rg/Cyjj_'\>G(w_<\M sI qG^T>cVE} B+(SnCw9 ?ZvXqZ+XSBBeC1C%kj2Y!nfp?2 "KXAN\v {Y55XM-Tt/Yt~ӭ( ɸts7Oh@9h1St(TTGrB'eFj<?L }YvS!k) +Z%B4[[ӁVY*kAU~Y]Al5 퓆GMhI6T&aAڟD@TML22xl {|_t Ը6 m2Kqs CG],8%}| *Z~n)9Xx4X0jwLv)4P\1/QϠﺚ.X hbgdk$lcT"I{Js+FZYx{jI椭oG1uh%'ϡV|3)u/fW#œzIIX`#3-,Z0TcdD{f{w0-T1u\*׽:::),œ7?^YP¤`1ytvV ڪQ_iF8ՌJ1QJQzI ?$(w^mvR30"j.[& :ɝOZxhmB=M|]K^L*MChڏ21myϯb2bܓΔs4YA"$24ԖU[{-f3 婙u*[2I{֠ib6AՓCih9/΃]L]x6t!^*Um(]{^ΡS/iN-?^ށf sݛR݃dI>ك6G0pP\at7}tIjF L).:W5/ǧCK2V!ؖ6׉x+:Y7eu -:\T:XhVO:ïvosX\A!uBwOt^֩V`fјR}(@yܣo{C\;#VTHGL-wɯ?>w%p_({/z_QIG<֞0@,Q]@ZFpΣK,e:+wg+Tt3 \n;N1|6x J/Y?O`g5:t4ϩ.D)Rt??cOuĕR5;y%x괝Ǩy֯EV.ҥ uMu$=.9nթKj.cbICgxTfeP9E.ө&4.aaC< c[)" apc:*)_j80G!: +6?Furi]uVO,O%Fm܊@^.wq~pUݚNjm-5<6MU|\S:yijm3J;:+u^9fN:@&3[:-7.m.nJ=;3Fm||.fҡv0Н=afDB~p.|~%WaVO\g 4?fIzP=m>V}(|~ V]C!%<坜;L>72m} /,cx4T,'LGV\ d7j`ɼ[ܙU¬b>&F <ˬ0I,Z7 q`9+|OTo`~Uq؛xoZGyz3"ʟ04xq lҝg~%nKf8FKZ)ˆ5~`q20.)EgԬ&so0 kIQ%j?fxXa!dv uIlwN|{kTf;.~eT7<@= ,qqL֙VD ay9J|h#>ekOe)}O7$87FSnZFyZ,am:Yse+BR\SN<޲ֈPMXVR׭#aG}Wz}4s[0Fpv ̠9]Oص:N<-rRn{Xjڌ?L5Y {@˘S^e 6x cJ e./ԇv^~< Yu`PP(\Dὄa)ϰDCYO0gQ ly ,|",r @% U9(t'j$3a} L90hڨPdw*Ќo7:Α=S[#`1jlAa*e%yY쭒e2X>.1mE U> FdDu9a@: WLImmN-Y]96j}ۍ #" [Q0qJN9EK&*qJ3s ׺=^s|+Q ?jy|}o{'lKأ/sQ. َ_oz^+۱Yo=\6xn b,a֧[bDwfNf(RHe;ĭ P2LE鮭uX#SպeO qojf# eyءsG"iX|1lc͜?[0?Dm`ԓg0OQ⻰X]ys ,[4g6L? 9}9^*8)=.=2k4[y˺Sk^~ԺyChu֦MxwNh(.l#OAxnʛ)[]*TmW`-IvKmw0놮MAd_B8}]]ѦѢ_/򅂧Du= LŪIX;.nџ>׽$RndC3x.aPLWX%),;%抺K ј[r? jy]'7*E݀VXɐ.P3}RIw?O#%]|#uµ85s0Aj5j,l]ݧeP]baTaXM\2 .up-nĸ LWXmzgϹz/(jn+{~Jk I(7fifxK? +Qvw 0`-.K]U!+V5[ݾ]_XlU.з]ܳQ#9]E)o%yuc^ԝ&\2ta[w貸eTce,L ѭ99cvVK#&T몜k`U *tyQ-OJ+LRS߹4Sw35׳Nw)Hw~CiZQ7V`0AWEש=CnK/t^RrM~`U >fӯQ>cu.}úUQ#%`ݚ~gҋ]#E[޸.ޅLf bOmpUNvy!-szq6tMWL%qBWh/TW~r2e۳7#1e܅4KZ<9}dlbY~u!|+\7Y*uG7EQ /{Kq{ޮ?KxL^ ҖnqVkY j1zm_;{֎+⒞A|CZql==Ý.zF2&1(J ː|έu58۟9m=Hd&/m83zc R2Ilu ƮH6=6Դn{^E,ּzi z_;?׻䕑BݟYgqJ^\ysOg]=EoX$(.M/0!g|TP{>j#={y=9ϭ?(]fM؆7fd.Ь)գ5 Tq$䥈hMK4W${pB^f*DZCoG_QfA#Pod+Ie;Z*ى3֓^/J"UѣihQWz˻c5-5-9s܏O,,>SwTO:yW쎽^NIT~Szdvz éF%BYlVi=l"PRO5}yIJeBU^ۚ^5P/HMb(sX9 鵻~h[S_ug/ľ}a cP/1ͷ^?g[^.zdȆzֆR;hMI.KZ2SpXUHϵ!z5>z|KzF!  kn:7Nފ[`AQc=)!)&zl^+z3o _>z]!Ӽc9E=xƹ/w"ag(f3D%iG>]yWmD P<h,rռ}} ``nUL*u^|'-O%&a =#""yUpUu&8)'vK4 j#v^Vwy6%{߃pUl;m͛u|1nx!~QQ|"j8'yY(/, IEJUZ澾#gNjt* XYN8O JIK:ha&n\E 0IU8$CQ4+Vm\=tniq4~˪" T-@xO ̭`MwCs27.pv-%mf!DNko4^&˶{ mgǞ[hw'Pp HsU4.[t gx.l0ofOq17kX4.L9 pVͧpz5s8<+kW@)ŋTcy@-ߠ .rn3}/FA>pJ0 ։ ߨ)_!%6ooTx]+ ?甼 sy NKܧs n'ڻZ4~!T5|QWe<ŮKW1oɿw# 0Y,;{ }1G|E}w^9~yo>^p$Co2@FS)uB}Y{-$_&:XYO.) o~c 2ʀ}W~YXtX0t^YU/KSjK]-k,×&q8Vy;IKp;gK6k mIgT%xTc#8fv_JX=lu9SW8gmD\5;KN"XzSxAD|~l=C^"d ʮ %_Q"E=GX_zZ=DXN,CXEl;q#BKe^Fi}k Ek82$q"]x!"$Kr +qEg쇐9@I'"H:+Gq= 6/~+K%(µh+('x#tW_8ZU_@:#!⟏F! ٥+ju*ҤI!w?ɩ"GA *@Tt$ o#hEzc%}]wጂ>XCG>4d#f$Be\Qf*_nQ/D,jğ"`JM0sD*f8i$xæz (LF0?䁸;FF;bTph\ ,|КtCן"uV{"|Hۘx#vP󆶂{ad l!蚌P1[X("\=g5B_W &rDH!S;{dPNxb-Cؓ6zfI!n-F0qiFnE"*d?,!b) Eɣ;PZ`y.~VP>b>EЕu jv #U얹bDv۟D9P}?Rx-֦!;$៯ut#~ko z?&#.-cҒx3N5QwR/`ڍP8 BܿJ\oxJx30Xܷ7"4DHZ%D[# (bvļkA|^D)e”I[/( t!gUzƈ{omBJ]+lj|)^T_IĭZ;mDs̛]u\BQڻw !-9? C|Vr8Fƅ)j8!ץ6$6iV껈mb5}-4@f8B3ڒ7\KWz^ӏ񟢙D5kSVI9OQAE_5gRzy2jzCq&v}8߂\wr՗)70G>V Շ=+MRz!4m?;bO-B5]bvxl u=k6^襇/I黬܋7\ _M Yn6h+!-n[9QNyUDV跙~B\kx S+,n+};+_s=Sl2wf*-|6>IO߼TFzcd?}Q9F`6?#KK01u!eֱ1O'y)>ޒl_~+>ԫ(m0mFQIi1c{Wa+*}GU"hb}l REK Hi5;geaA9ATr\sԇo s 0kRl][)߶ϭ?<~ɯ^Y6ѿ{TO9ϺX阶EԷR`2Qj=;SQ*gQ?Jqص+?],j!˳#uQpǷy|ڬ^2uL&Xݣez~'pj:x)a芸^1vn f~olm3%Ć |}"FtSMj"FNfS?En[>ӏ"co3J}2}mUfD_6+D+9۷}۷:~6S?F"v:5O7+Vm7vsHf'}F6{}6D^47]y {)w"~iG^a@sk_DA_IHrn +-rw ݆SR*3I,6r}&2 ܺȅewq; yē{)R>Z_Y8R4 eBR"gIJAw@9VԎ%ȇ835$2_k`0lSs020QI9ި'D~㈎z$-g8~Giu\iFmBiNYѯj$NI#%9'PdӒJ+$ P--s阶 0B J "r^"RVT!co\֘$~{ЧWȶ7H=12H2>%srIa -hۅR, yjv" 8Zd*tZIDq4E(ґkT=Nz/r2z]>yqSX&GIwLnّ/NCyȾIhQ^i&F*}98=o~+Ic#&b?Z #O^?GY!!l&k.Cdo[ ȷø@ ʳ?˝|-H(H\/Օ7)H'Z_N,;z8g;rF=I?o\g׏3-pDS˯!I$ədG^{qd򟖖Ab y4 9,iGً3I F,!pAf׼&S3I$rF2o&:R8[ %WV+Hc\9dS$c2h!~Cݜ Q(v/!Nq|$}R0D*'`Y_XyzR7![KĮ|:EmZ|CУf-)LP8X;x\C}rtaSGe_O;;EŸcDT\u >e} Tv(Mk3eB:m-T*!̨4ٺ먳 mś(z(zh-'F ]x,*YxtĶ@zڵAT,Ϧ$j~teӞ~*H@>7d=8bT%-0$:bnˡ&*vWDO1~VE/6$P.cPH[[P "iaiM0jW-ng=[[:J BYIfu"I?Qv#6ڨ˲Z{VmT㑊4u:'m{0B:/P)&"D@Mz7(}B2926[h ţh{1(vc *L_T۰Ga&ֱ?m#a(3(,ƗuQ"G`?% *'!?e+ ն.MDHqi^Pe@("|'(C/юTGT`*$2< 9 ^@Q^ Z 9(@o*xK> LgFS^ `Fw)Pwn+Q]8P!,"\o(.jH=~_ xmfi'*g[ 5ݣmFۍ D\o[@b {QUgrVS=je*=Lz8ԇcPaWXP^vG2oJA55>36ކҰe#.8g:AL/>L# ƓJP ˨C/{U"gQvrIey޻n_$k6B RFL7P9kceP&P Vݧ7Q:oMQ3_MB)0c;BM:B~DP@9`( jY熃B1h`$[qsp[ z~yUctĵ*1ctTݻ<mo:լ.ݓ[ޞGݺ a4^D[z|&݂2l{NhoKFmEBSUVĮ#'hN G42g;[P\ަ`f (,.RA8P{8%zww.W)]a/^4,t -PZe$-1C;tܐXҷ f4lچ-Ūa; ]5 + GWqL5+&ӗkJ.E?Ujơw I 1Wrn@ޣpVwF3Qkm!.?營ѳX@ڙ6rb9 LtZg(!0M(Rȡ3БYi E,+_ _#f磳Z:0_NҶHيUw-HfW>.E9V@ ۿ|Є37v e_ h'ܰfqf 'hC<L {iL}GS ]FoVbGWR}G30gvlFQ5MGFG_B7~%;ҋnNAz3~_k]fMvMA봂T~߃G?@[BOE`fJiu*):2jI XI4jrhs 9hsgaq]UC_LvۈZ?B>, _t+ۮ{qe3lhNnp/Oe >P4?`0pijQP3H~3:,`0Hz|dcfdd@1+$cH?Ocd kv~SmS 2m6J<"oxQ,I*l.?Y 4XuUM6xv{*lAH74 z vw93(= d& S3=gH_$)b ݼQØh0Iz8dFk ,ȀW>ek)Vy U Y%n)HT]jq.@/ bК$A <15oQπmFMm MsV u #`)A^9A@:0 apghqeo}Π/YVm`)A0854hl8Gxițp 85Tk@Ps#gA;a>bO ^1M[\{l06@d~f0*po䭝AJZS߸g-[f!{Jc BN4p̩$6Xr7p0a :4na@Qs/8g;:o`fp@hܙV6z~oҠ&}c \¹v >HÇ1hC͏sՌ]k~Hk{gaEih~eO+a9G݅ǬR7 KƘ - R oœт>휆Nѡw} o{B9~3T7 ɓ7xfݻRpB2ahP<ݜ!W D9G.OCL5&=L:팳ab_L CKV;k;׆U^Eg' QۃcO2DШpɚBx_ Le.O>'1\-1mO2 i%pQyH/ͽHßC1BQ6I[sGφjjUk Fsô'%BҢM$j['&S Yd#qIR,_ /WM²r%/W ÄR R?z6U:|.{^bs0)6t2 *7. Ԯ]a8R2Ppk^'WL3L⛡lfWb w!"S!mחk! "%PdexWoFQ/}u1xBa&6L_݆΅6 L /5=!tolU:!ñ  2h8G 5ZwnŽbÆz bԮ)L`yÅ͹kW e/_[7 NJ_2s[+O.dU$uy0`cςȍK_ϼ6 zH]+ m2bX_Y>r}f4c7{ppHAxߐ$Yn }d uLbwaxctL މ+F[FL ԌF$jk bwz$*ěqzK'Ը.}j>5J-:5a1&Q:{?mA$Ck}z5.4~ї`;k:[j 4v/4r@reحz⍘FD1 0s5 syU6]3 7T cO]Fw?Fw>QWE7?5zSUŖFL9rYFj~fF蜐47s?2Q FCi{#;GF_rA^FyF'NW#8Mуolҩnx>t6rMݡ\r6-Oh$Th$P#QPҷF:_~J.7qLo4ygփHe!F L`}yHScEI]tqt#x pK5hSf$hDM-RQ}豜ٻgѰF)[^WR YJ3JyQ?H:dS4Hy!վgDĽ N7rSV㙺U`5u,h)Mjn"kIb0Kܴ+72lbYl$9 *73Pe<22 xm͈0HuC!PҨ*_a$[J])1ꐜ7Rxtm .iԈ6o0zhyMAÉ<#]wܴh7ۍeȶv珗)hFӗi>=HBƍa[4Fj7䜇$"5e^dF1B#ƌ-@F3FЀַJSFFc9֍w6 ݾ1_Y,w*jS+W/W f^Z<0 MT6S^4JMm=dU;1ٖ5k|15retyEX( Iqn:4o=4K^[vA0=0kδh jgGu#/x#cdF?LՀ{&L0z̏f&?%nLUf ''a"p+(y,[&΁Dl9_j>B]XMt$v50GBm-rQL%1 C[j1 sׯ{WE0#n)`qL[X"2F=;V baC%PßpX7@*QqV@SR FzpE^%_Am˵R6 ޾+v-3&!>A:Bn>]4&2T5[w*FvN( v(,pbegofa `>U`62>4:y3q>)y=e;eYT9XaVoN/Ua{(aSw2j0Fce/k1q|;s &3E.L -t%1+#P1"1w5We¹5m¼80s̘'3l f9@pzI8ǻ5alY @*:<3 cufkƯccSn802d6x'?+F♌_ e0'Jj B >nZ›sf-}V !,G|W9OKx~r?{k|q+:cv8S߸d "vPT"i;gsrx)ǯqso]#Ӻ"!ƿ}*ތZ[8^bZXdwt$''{q qU&i)cM7}LW6:r0 xh*b㷯_0}'0ci&8.E[(ŎٷwP8hq݂,QO%XjwP4Bx&KG1}F8cQ/k.\w i H~_o=@?^F/}fxjlqt%i|}|gi#ۿjeQ43cOy ochx+cu [LKf0Kc=b&He3㘝O\mg8=5$݌Ƕ-s(7=Bxg5f08w&@g(8H#V+ɒqIic?5awKگ_ M2^Z~)-ɸy<&јu0"5ʸiDtۼhM5Ә$F`6ek5fQ͸IgxCYB 4˘{+$am t}/ǾR%>0~k;lx/c{݇d^:#Mfƍw)KMvy1>i,rxnp͍`l%4!gkd|־hx(Aul{שN̋eJB:770ntb|SΌ?aNƠ6Sun^+=5eWZov9V82VSz@ ۾(M]}ap  mW6~[dH?Kȋ}=aϟ[rS2[㚭ʃeevU^zrËgh 5b?U,5HB; WH0IJU `qo /k:hb$ paK6`v!o%Jn}lšl ،L7/U jTP ήߐ[(b q؁JRE$*6h_#lP6JSV& m2p-f\/#'s4{5t.#ft+7;/z- P|o66}~$G݁{(B\X2«2K4Ɔ*Y6`wkOthzHl\!J3bHVps,ml?k?dL ;]fM 1eM}| *wݢyu8+zj e:&r'ڮmA2K]jOT.;(1/+ MƽώjΙ*[\)XJ7b?fwcu( Rp^_ߩkuS0A ,ҨC.HKGD7X=6' 835.Z IJ bND1L$0`SEsa~4}%8aD9}mqfu9xUe}fP[E<ݨŲ\=1ˮæ~ mjjʱGKJ Xa$ucFO: a̕",`U^&Ys'ݰu'vFz{dw,hV>K0„N7\['M [=V0'i܎}k@Qzҁsc†5aKDBDXGdr#;´rX @og^lOvt6r@tw ;rZok$t}k^zkP(> YZ uJ;&3XP؊8+rggqXÏ(sley3>P@ ˌLb_CCN{Xk$^]| m<ƞ`c x \GGue^t%#܎Wpn~?bPQxkS-p9#TU{82{Ïpc_$gJLυLNddɱ29)}O mt΍GU<:N5B=ΝWQ?, ';gcEppWj1._r7܈"OG. \/C0 vWwp(Rp.7>pzM?Tqþ˓Yʸz9.qޥ?vIsU# PVIs%JE٬©6e_?u\(yᆣ:Ό2WkŜ[W µ7pv.SN0Chg#4ժx*峓]иõ>qf7P8c9,nK#C6upQ:3#7V)oN( L%г?pvbW-pGv[ݱ࢐ʁOpKZlq H+8DǸǪ36|p:(g7¹#C`GY=UN`>8-EL_'Sr5 仭wX\ U-7]A=LsW0+\GC#w׸ #'lnZXtqz gL,ВѺC[U1{;<=Lt)me{4OC]+{$.Ǥ<ɸx,4ͅlb,"H!Ô)µ{Tඅ4 ޼ʾ\y'7QVm6wzX;T?*=}RsCRjAS'8nA3.W7/wlkgˉJ_;d}61f ORUQ00?H71;V q8ze9aWʜk09[p0 |/N&KFEFq)uw8p0kFF=LD #/ b8O! 븃^vJS" osa^p><ۗnͻ; jk͓ϔP|`ߚ"+x[.{4ZF ,#@ Ќ6JƯr32d貯_jx5'ѵV~|%| ޗcOnP^kq3,>YQ{9Bsmes3 $;`Wl6g1;6?~xw b>\ዒ:$]-My~tS39hE#/3o6/}FS_NϘPĬB^luIx$xXb\IN947Ǡ/I+xJ8to^}d=t|1,*ʨT1B\&<.Żw6W]_iƇݽ.N]?M%QTQ/.n*WZO_Wk:>j[?}5cbX,2K Ra%µ]xc}..|MnM=t;>&?WdfOG:~[HYq aRy8u+}p76}Z4' N3x) |khm:>C粂!Z>Xx(}김r@k=/zt},}z:ˉ>NjVE9ew^qYlm?Wy6<_ 6tvj*3@5ݱ33eLS6wIǪ~EAӮI:뱍I,cFDhI8`|GI*&œY:&S WɃe-gRNP{j&t{. >  \jr-~bB=}Ggx,B|7фs+^zT2wog%02@>N26~|a2+:'5E?󵫲3{ݴ5QӓckD.2 ezeokorȜ${W{ wS4ŁNM…!ogM"WށjMx_^q5ym,ɡl1X瑹nr~ 378o&&{4~nhΪO13`\_}xcB3#6 o.aT&cKA&>'-4y$ބe|R GIvZyKMM'>\M~C IucgRm~gq&rcLv%(,^U6jbp o&A ]de/NTdpTSjnj]&K&Oh.(Lz>=F6}lɕXu5&l؉ZLT[LkL5fҞUn0ԙXpoj«LXٴ_fjmasˮI\Y'l&CHnLY;?Mquŷ< #:LrDN4!,P68d2l SDԓNa&;v[A Q ٘ eL$s&W/`LWTWLs.?1AT`hneQY19l(N7iV;vkDǵ_bL}L&5M"ܭ0iL=][g&&YǏu74+ Ue35 lnAd$e 5SnZ ޤ wۇt&ŤޢL nQnXW`. c3L 'dcJ'z>i7!D4~@ >W)3O+!}i0AE+)~M̤V&ls׹!YS@g#/u^E=M{,>xe}X8ػ͕>a2}Qk{5e* _δ-&(^B>Ґ#8U$2M<$(b!r2"TxE0}CI }D EX c9ԆðsIB%MBjO=BYg@yp5cZ v B <H;3g%xjb'5lw! |U36(p}&,!:[>ѐdoH,č@ orO07&=2Zq=03 cBd5!v`E&YP;bE.o."8܌dձ"#\1{+< ,>WŠHǐ焺lb/!^= .2_Ss h%Pȇdv]luk/^^Qvo /xeqB5+{>X7#>P@EK $^.a #sҮ`X8Bojg.Qۻa6G5p%TPܢKhlg&e CI{>ؠP.pIR2g,nA0UJH? "ܱ",?)o8B`vܕK`R#,Y6ۇ ~w|=Bj \~J ٯh:KdxHY$8%7 R]/*%> S'>T/Vy$; nBDˣiѫOM ~zB–xF@_͚i!MY)#,P 󳞅ߧ#aԣQB˪,P~tKxP\V8Evq!+ ƕj$Ԍ] E Aկ@m5Tfo n %Eg;mȸcžI }T.S>AfD1vg߿^13ѽ^O F[0HA~Cl#| xHMl$\HH{$1e8Y,~&Nu6C}NjY|yu7LgMdxu>g\;[+~Ğx= @y}"kVh{Db*{D׭}"#+›њEĴs/rmڂ1r,C,ե?I#Fs}I@:;R _CoS!ΙFE="V> ƈn>$>r6z*Ck_ ~#>6B JfD&jD!H3X'qcETB;mR#NmV[`6~,'B?nuчE1!Db_ 2eB'^o){dq~d(!,QToHf C6!-I.r;b%*6DTch-9>S[yψIͱDǽO^%@Glɉe%NU)g"͏HTbrx"qDї(bxcm Rs_wE;1Z6l CzzG9[%TRCqU#vp^[!*Md&"v+`۔sCħ)[ b7M:Ѐ0EtAevZ%:ݎ':ntMOyy&b&6O6Dј ܺ)Qi~Y_OG./X}3weIޛ]bS b̀18:`x#tD4XR"ˉ W Q$}no~QR:x8'WĜ]>"]ȈȒHM?ȓJI2-I,HoZːg UHg4DYRRcCB&|A$pR9&&I k'zzUIFl9%$ה3ES|RU·R t8MCNőwٯ$|'}0"=TǑ"*EFI5`e2RG˒qcҼ'zV;Rrѧ/ f/<&{AdN2Jv3#~c~IcEzVPWkEcxvܞLI-#7Õ`{s7NŕdB菼tӃQ^ʼnT?%Ѕ_Ju0] y;1GV HܟNMìB[lZ_ $ ` -hBHޒ& -H}j؄QAjIF_?{K76x[T>{lѤ0H΃Qu6I\4ɪpk,H-1[&XeCRG;3 HwQɤ[^_g Hѡ{_I%4?Be%YJH${s3RkS Iv}$1L-zPIjPF6.~f\L˥N -#7 oUn* $, AzK(ד^ l7"EQ/I 3I]qM$Dw ᦴ}6I~_}$Lhݟ$ W{H0 qbe~żvS]5҈/%jXSi&} zI5MO&2IoZK͒ ,(IgR sniu"$ހ﯐UdX>2*KhAW n>|;&Uo~%qph%8omoD T%+Hm4avRIHvB!2l E{72l)CB IQve+ك;o8nq{WF*s|4S9b,dS׬lAq} A@& pO<4(@=m SpEpyM7H[|ЕycTb+igu̞, G,l h59,8{ÓC[{CRc RGpd~ 7< hK'PճҍsNkL:QG:Od~1x)FqxISKǘZ|@3nnHh†m^JZ s]U1-./嚶*TQ-@|^+fP_8A|u Tҏu&uGX~Fd"mOiyN%o]|7Rnd ^yZlf; m /9:PXowF/lɬçAϴa2 @gU10W0=e(n0gknsv?Ȁs-r%cOS$7pY|Txl&>j5lբ8 #dиظte/ &(nE tԶβc\m@ܻNpSJvl{lg 4> |``407#@_, S#l!#f 4LNkA@Ue<`\x[\}Y ߱)W8Pex6f>EHoir~X1,OU[xgyE1y0DPx/́]{R@ToU @]KgËۿ}ޞ@=@n00,,YV %C R3,p/lF8G xHd'E#~^ݗx}ip4خM2 1Pݟ,vDWԎDm8f]80 H3FG+T՘~& G#.:oD_%ݾԹuôw 8gep h왷:T\x#0N~pǠPV\JO{ӁOs_RI@·<yLA@N@ˁO7?N&w>gҭMX|UI,}AOz:ޚar~)0<@"l zФ:i/em R-W.|R?,̈w85 d*ǴEszC$.x 6 U f' \SJ @n[Pu6)0wO\3W翢: hyэGRd`zi1Z=@W ]K??_ l"wIb;ScV 6]*Sv%gJ/v3LaSO" [*~< PQ^J A' T07Xj@VJ }ϋ:[g:vۧ~n ?_cl[,.^~lS^ Wa~p9! g( J>tQww[# QΑ!ul݆0qY?0Ța%қ(Ts^u$-~G tQ*)gA_P cI[K=E_T- 3NL4(e52Ӵ2gŢũ PB~EЂKY $b3U@ MZ 4=Ps|zi]Pjaی(~_ֳK:ۖ s!ck)@vqT5{ TxnaXu[toum^-G&ܞtZ4|@B*؂ &K\}0UP֍n ɛ~7@IUniٛ:@=@٘i*](_Zfz#_6% Ef#/fMx C\E?R*# ,]qJ V `AK1@P:%u4~P1 }X *jsUA@*HJ&'0@}QvIz Me ϑxT+hGI O`׷XpC\DUMAuya 1ʲ]3jv9͠{InmHV%>R6f@5XO(頨ڃo$\'>wڥ5\8*) t2H*'%gd/@_|OL䁌C iy SLa쵃wsA׾uu| hR5jTh)CA5/3}f?XQhW$ Qj r}]) .NAar[@UZv2ArY+H!T\;_IVPoKAc~86t=.s{xQ !rǓn eƓگm) QW"Ff_?|yq}#t}w0;+qtM#oɀe(uuEP]1ŎIPσY'AϢAݩ̓@KjY(LevIvm28wzl5vn35 ߈Xq;PB:GNq|Jnڰ *;yf:M1/Ը5 aB:1 ! FWF"eY %|D%|,MQ0Z4oȜ; .*. ZY씗~ĀC?'s/QЦ?<. 0{LW~Z9>4x*yRW}xZ|(~I3Cw L B;U)`+2^@nÁ~ Pa`W'# +N 쀬<oY0 Lj]9c>ɩ< >V@a5c T0Ő%"u=dG\ WC/ ~Uw6/<(#.~|o\_$^%|i):iĵMоM36d@Da> "&؍$m˽ I\:7{9XPS9 r&C&rN\Kδ]O:ժRy3v5 "X+`&BU3Os}d~|rE:_*PJH }v%FuJwz(ܢRy_.@`9DB6d#Ē /$5$?гi<; cCB|~,kx9n_]sm~EE}RIȔTmy }f<[C ŶG!"yn~9b+}\N$\ Z!uOHL_Wɱ' ?>NBB +O/Bwׁ!"Brf #P,*EڷܲRߏ?'ygm܅_ /N^+XYX[С* u#2@6$|gq} YkMš4?BP5-!IEp7[>q?y4t\~y Jy %QQ6rPnЙ=.&324#" _^v JI|H^-X N:Ap]M\]&Zd:Tu:aU.]<⿼XKhw*%tfʿYA|wl#f._Lm=VtW{oT tw2g8# z 5Zسެi=ozЩn>І%wdPMZ-'ژBYe@gџ ".$BPǛ݂Fӹy@d&!LDr`(0 ppe; vְn5>?E(z܏܅,tqS V J۲PJY67ݝ MUNrBklBA,uCD"47Դ0J*7ɀ:D4 :a?`>p >6!c$$a@ݒR/ L; x2t 0-6x 7K>&ICC܎x7-ABE~:*ONnJV RVWBwr/:`5B1(侏]4s߽b-吶怪LoˉD4@thE$=e"]):i:\ Ƀ[8/1a6&yM=, :5ߞS(Z}p+(5o[?BOb Pj(کms_C4tο*66u6Ae#jm穔f ]жs}=ڡ>9+3)ݩKͭPqm3Ճ[Wn/IB=к9Ҧ~(cuݩ'w^( 3PYV~@Z޾-h]*c;N@y}*W~C/ZZ7o]\W6n miZ+&744#P9{=~*e" =[&!` }եhh e@]ߒ2ӎwjl:Q\ug 䞏^t{FVZ̘⃽̺vE$F:A6׏?f(̻zl~(vill;珕 pb= |ڡW%J~$ɯJ!Oo='p{{LWT[yVPi#=qre4k-4,q-ϓq`eu0 *,霆@ʫr?_ O6 $k 5B[ah,?t u9/]yU5Wm9S 3x}{k=CY '83Cـ>E0\yaڍL <5把a8CT$s7O{K6_ +­ pXIˆme~V:IxhƳpwU2xbh:|PE]Ks𺸅 U OsV s>ޞ|q d? T owj]N)3|CL]T+qY2T?V𡓃GI7j5mGlGw&hK! ko~me #8I <Do-nsp41#37)8 *2"xI\-RKv.%j݁fEpI$y\BSB]8<(["PB)}2hi^8\ 1Kt9܇TF3zwsSk|&]n|Q`b"<̖/jD= &=x =n,S#&)A. J7Q=L]es k_ޅh˅n-ssGG֯_̃?3( N7]eR=NolJïI3b7ߢ_'%klwl&K }Yܦj8ڧWb=n׍jЪi,_.w6JfUJr; !Nm}0U킫UKo|1> ~>ynn~y@" >YC: ='yNHhMSqW?$M냿o3=+t0|FOp}Gg{4wO ܤ(-}2 oI7^α$z~-aOqϢI⢖Kp`ޗ]|o7~x:$c+ wr(B,Iv_ l_5y8>]_(b[ K -aAR:̬0wC4Ê!tK_) 6pF+[G~jT@|EK|@|s\MUDH 7"ʔN^?pL;FY|q0s-1Z3TpQ9o=4 q;(gz<0{'ԣkGcsRS[4@ ~^ɈNc/7eܿ ~2[!8綦:x!.cVB>TjݒT> >WpH)3Eיa/ةDȳ%BuR&-C".}4h_}kS$1)_i$6 Md]%U#|Q5g y D_<,o$Ya~ 4~x3x |Foɶ|FFzNFH t_m^ "ҲwF NՑkӏ دPKhw?X4/?܁nԑFnu^(|]},wi!?^(tMUC^X|WCBӆ1_!u6BL9Y$9չz9 *yδ@-W={$sdNz: 7)r͎ Rt +d#<\KdHrul Ҹ7邜f8!YY#6HK_c[\+X cfSUSZH-Pu#}="ȰjvFv?8od wDLyKzp8<,Igode4 9d^!<1AH-]Y rtbiր9.ʘZ? $g]#3M%!k}yoCG"d(HϮTG> ߱}tX4Z{PGG,j;$C^.t$yr$DxpWO3vH?JZU]p%^r5u=j堵*yO`w2;Hu |h>+ i׶7%%1yu+y RSn@? 9v)eȠ # PPjAjx`T!i d孆\Ld//)1'P^ Y|eíJƩ7HټŊ1k$?89>Ӕ|,Գ}A =v-ҽT+F@Ysqh9y7Aqɩq8 .vه7? WQg?e KW\>#׻% hG?KW/rAsN7rKN\rFiiggs+srrթ;;C$'˿!eTV%CHکsZ)P`pp=,##53a¦ɌՔSnH+Ǒos?OnN"t-td7 rS:ˋH#c"Ϟxp,zY!{x>;G nCF߽1Y u|hDW@DtUW*/4(mBAuL=:$wn@eslkGmqRB534* ½~RDM<"? _iPIƏ%Qgk*YrڕQνzjkgT=W5M6D}}iW5X4qg6&3EX4 a3IԧEm)OArtPJE(-/=i 91e Ju4hrVS9lkˏna|> hQ6Y#?;'\TQ[=[2 6(WTF~e J>{̯+j!{5}ΨE#U؂,أ P%A(+dȥTTon *1p;prQ7`(ԝ9։CdOk% }jz53R RxrMEue騟U0ʷ#i(gąտ'^m4b|Jn r-B鴨e,f\ P1؇yZ>(BT`H3TچR[e+T}lT0_A̤ (:Ur{ivJEy/ǼAux !WɽAUΞgWOu\Wߔ6#@#&Th.@*L; v5 u_c 1? oB 2iMQkk/_i2K %{_QҖ֮=(ۇ鉅_Q|7zQd%DTxJeHXkAT~r0c]ȟ(O'!S;GugQ𜀺q8JdWi 72_mekj=e?)zq5ac=x4 ٭pe?+ۨϗwQքwQnq (>ZQԮ-\O%D-jN(w v14V+gG >>=f/~K18V nn<7/*EC~m@QJ>tQw7 h&R?yzOJ |.~:s[}1Ut,Nˢ5oR4]N#Mщ|>Ah'UC7ѯesfh^h Lg?tT3H5EU <@ }u\ F_-QA#^y>z {;m)y} K_COs&>- .=s=u[r)y>Dx?#Ashs#Tk"]D4l'E@{,+cЅjSE'rXtK_!hpHs$t0$HE oĢw |d6Czui_=Ag C^OeY_VZ7y ZÑtwl< pB@ ۮg1ޠAߠ&ECwPoj{G/@A>'-shD}WEK.twb͟y=rF^ PM x&rhAXS8јp֗c_QtᡡChеAqXhԨ'Ѓ} I37ZБYtĭAI4b!06Vy#865T$jaR׻4^+јx`+`~@ )6`]\dO,c۴Y'aD_[`HD?$aXCt|T3-:Dd0X1GB1_`d+oc$yb07\w0\޲ML=.['wW0;51z;̛b :*30h3i) IlG, ~'7&+&_2[ɵ<&5(1ƴ}b31!7 saU閅 w*v}^x1F,`9uGN-gs̒0z4r1*ļ楘E1Q de^):/S\ F'J=2b=&=՘^&z5Ndٿ[u XgʗטMWQ0?3BS>a ~TCOfM0C11g0GS~u`f?cN?C_hW9S{1jF0nqL ݵ{ØWzB_1WQ,,rFdbj-@(Ȍ[w:cJ a'h-`D^r&1#GLbڴ0E1s;Y1}sBR60"> 0r ˇc0pi`z&N XYb6p}h gfTӃ,q,o!,Qא}?{Hـu,m+^%Uvc!,yWa_`K,PO.!ȪETrRX㯗&e9w"do9؉xX p,"o.\)q]Y}1l.V(A@M 8NVmN!^jaMt}9lEǀح_͛#ûTN0g5=_9sl-s믯%V~ˢv*[Zt6`Cʷ$ܵ&az [e籍V~Y`Ḭ$ic- f,8bmb>4!`o ;b+9 {l#Qq-G5]aA]ؙF>cUx'b kXs{X.skKVlBID#6Vm3lX~m Q,oX }EU1ؿ&s?-ё@,{~F^Y7Vnʊ~39wl@\p[P6si,6 Ux%濰xc:ͅfr}vQӽxb澀 ^WAX.6|_ E ]X ^jmo`8[u/ۄ`y~c%X[ŮL(82(Pa\c3q_/xŝW~+*Ӫ9V,j從y'2Mv!b"\v?%;VS>k* JH[N(?y9ܓvgp;Sݾ& ᦍG2jXM@S5pGOUq O>;3󎛺a N%_q.4)ǥ\3ñ}ChNje<{p^Lꏾ:.Ar챺K SksPz WmXs=Tjvs7ƅyhⶅHO|qʥ/\%y do+^Z %EsٜPI ww]ԝ#\mƅ5fw pW6p1tE(`@y\BS m@\3c'm# L;pja(]U yL^փvCt9Cemµpbb' 4(;YIl~DBFCqcja1ه7qwpt.hbp[>S [<4)?![#sDܓ#= 4p}}ؚOq͊#5p!Gk~(Sr2՘O%lUpu 8$Em onqS7 ]n9.C7pnNVrqw/UgNXfFvqDλWڱ#B;G5_{K)Tam7^wP3iu+5K[ HKۻ_e7G߀H%>sX e@K~Facxc|Ld yIUFі& ;Yus|IOm݇g˅O5:XmT%u'*/ngj$LN.@cb]Z.=hyg3,Yw] 5k+w5ċ3i⍪cL?^ŋE~u͜~W{8>ѮIl]iR'šZ[J'_s_KŷX 'QϲȾ%|WtN I;։<ȇ|}[H?"O2H(߰Gpx*_4/)K xZ 2FOSP4Ћ2 u/|\ /Ayi/$u:#SL'hu*ʎc3W}BO`^c#Lw M`p|GͦwXi OL1e *qE<;BkC7ަOBvg&$}fB,?s؏'㗭!;9c!:kvJpN g͟i?{7]} (w{1]ۡ wŮkKׯkM7r󝹁x3oO1׎hU> ƿ|O;bNOiw} Tq'[kVrI㻕^xuxUٔN HGbW3~8ҁ?Xƃ6g[aR3~c%|VN#>tWů~xOtA|$+ >5iߋ:Ԫ w_379#8_o]}n_U_nF쥟 KxM71S#o /m? b<86x/jPY|MΥ5yUS?@F?v).O?L<(*GZt(Fp{?:,J8!VL09nxsmHwIqI,]PJ Qų*,mii!9{xSg 9~A(;uPpPǛ,e.xNĝ)z,Je#M Rgr_XtRNgCG.<Б//)9k"'sC#sò-=`@t9i& 'X}4> %BZ.7WY"_nxB5hB8뱜B"noζ?{HV}\cLx0w$P̤ 0<8od7?uTZ(wшטgk,<' Cr#b© -iD3g7vVYSBLn+Ҩr7w{aFKP)ჽ}J\9FG|`-a'9hqT5r2_+OSt aEUP7-o"Fv ژPzDpoR3iWlR ^ Bk!~M1Sru`X1V-âqH_%@R`G]Oll܂61!b16[zX!b@ф(3╏GfjNzL:q_(ۘ(q~4ݜ4J9`AN 'A<_ *I6#-5'b+xǨsv1/^'iQJVvbV.{ТHp:~U?q@?%tם#߉QNJ4cza_Y;Yy} ęhčwIaq͡%0xSd qMihQRc/+M1REUg$/q$2T2)MݏkYXcR$m/PM1vMNJc͋D_Gq/IW(v.%uiX$wkO"^繤ڗ޳$# s2)Dٳr4y>8,i9Ru{'l<1oDM*͐! -PHn*$bg-݇K2H{HZFTSIzht#It )$;f묀'_?Hoo m_,bKAs$KG mh{F1H-^+R܉g H XɅ &m^QE*8|=YOBS(#=K9IχZԓ"ʓ֑vwH犫 嵤ҿsYJoIO~j$ނ,$ͫ?U|GMIjx2VJ:hPtEqS3A'FB1tt<|:-7'I- >9]JzwIIZ?$jXv|4$,]u1Rlaҷ1^1͌ '4u>a~ ZRG-p$-7Ej  LƵ4)Ήc2w@Q/R91yutWOSɢ"qk~4,u۔$x0\#>߹N28\W&>c>~-5O&/QcaDnW yE9HV~&)='Os:8~ʼ䴇p阱dce #N:!rWɳ'ɇ3O$D #Brn7j8Fnt+jU˓,(u[>}34ɩj+JՓAI^䞄 fo?,' a:Z~QKQg=p' 40]O19\挊%yKU Wr.gRe '"چɖ}/g.o~7$K?# ]LdK5ypQA#9vоG'b<]grIaI׵l؎1q\#yQ5\=I*֚ ܵN;aEm$ߔvU!wxuТ7}H{7ȹʋox$iU}kbI*wr?d@ٓ2sMv9p F/"mRg~&i򝔰sT5l=uŔ Os'c=KxI1>U:YF J&Y\B}Bv޽$K"vot) y'N9]XP+ӿG"ɉo{NbF-]Dm.="F?&M < ظ|B7I}D6#rDB*!мHz9Qќ~x97#zQq:-\E9WPd69:Ѐ'q䘧a].rLŢv\\(ee0+eȨ+ɹɊ5IU-4{߅$9ɨ+Jb;1s2_+k\vd1dcXu5g,8 & êgNEO'2//v"Ik۷~5.B_Nn.kmoF'7XC.ȹ:Fr3w"#>DžwO X%cb˺V)#0[Q9J"JCQg DPDߌp/RBNfɂ6(/.P2ǝ>NQC,G1<Q2·@(@ҡXiU!'(_M8Hr.E}b,Hyzr^ƖXH hRbE n)q/uʱ!NSgeC"pmSR+V?GQ@O>Os3đD)vԬ1,)d5@DXg) o#9Eq} WUw]ӔBD9ĹɚԼU b3vb^Yۡ)_/OQdBtZZAS,˔OA+<(%*[;3oQi|(턍CSʽ(E)1//)P*,̜SV &xRw<7)#0ħNf h,u"=N1B0Qp hf!Vi`JϘ\JR^ CY~yFi.^ R*$K^U"d?MQ:͡OF^S._hƠU_)1ayJ4mE~ir80|y(K~/B~g4иM$n另(tAPb.RQn]it??sr7*>o`5qu("ez~%ruS lBcJ\ܯ'9_q(64-q휃C 7W-J=2KUsJVa'$6ߏb K#,Ɔμ|۞?I {vۖC76NK(o5(JEU/)*)C*(؆JЩ{o)GŌ%!VϖR^#R[k{CQ.T-hW+(%g~|C)t!L]=2#(h#ǫK+F(')B@6 6E<шlAlHj(SCK:(sA@SidߎAJꜨ^/E*jIB/%?*hyG)!"BS? QNP7]Qn|EQ?(Hu]0~mҖqho?Xy x%Dԩ{s^GW27٠76K#e(C/pùaz# AOL i8|*e[%QYY_awLZzkեTпӗs#4ɠʌz,|TpTG*'%*Rq~RFBzat{FdNlӠOH{zT*VWE?,TSMuuT9}v#z_ ˼eT+k&Xj)LF#t UY K}G]X6q6]Rv,r&DvXH,-#_KD4P_l1d$g,v.*sf58rVEMڳ\Gݹ A:OrEeioWhGhP] j<[GO{;K[Ht5|^nAi[҆?jҖ~ɠLiU·J.Ш%Li!ksf4+44{D-N7fiM\is)h2eĿ P#ͣx3xvytmUD>foO|͉\1J{xG7yr (F/du0cрedo'ƃ-Zb󟍑S7h]U4gi-ӂ~,_H I$,vAh,6iremTt0-嵳^7(5mjKg4*fF2S?t{ ĝg2J+ECɬizۯvh0Ns;??VL#B۽:(ۚ|n$iC:-yq1-ƍGm˄ QiOA4!W{wBhApډ )v%x 1D<96@s;L%ܿpM*:;FB<FEZ@&4/"̛8ȧ6\C Ҷ^nDr6^-d+4e,\SHd~dgѸpR} griKLk:Zu>tMgԫ”*ZY闣iiEAw/Thmh+54F˥4%94&em;H+PDF6~6>_=ohC=W3ӛi{ೝ̭I=pwQ޵Dw~w)K {w{hVγ=ш^ƴ,6DV9Z^e~Ŵ` ho_ѬjL"ߙ1(V0MGIP-M;_..9*b;Hs,~ pi?iw0o6hge/l A{li=lB[sY_ڤr;|ӧ:*?fC鏲cS}̈́C)~A:_Ny1amaa<= +}[w<ݻH%Jzl_!ȅ%*&iON{cC@Aęnl {q$Glz{z9jURownqǽ҆oo 'z[dxmE%?Ԃ7(WNY^.{)mحғ]*.󢛩qkPzKstC0u͜4=~@kz*sMϿ9{&ƔG,ȧR.|dz5=$bNs me :D>#qFg}EI6ܦ?i;^1?}@EQt$ޡ[䝋c{+E="_]w=2Az*ߥoLڧ XM,Dy[js$^2?~71=RMDOEҞ]OgO2}Bw۳L$k.GJ}xFzv3ʧ"G_B?R*9t;Y37U'Ջ3靟CjHJck2tolnA2WߥZfM)t=ة+&xŏeI^h:Uл<@9'oMҁ2zgM⮂&D;=ZiDg:PU~ĝtv.h֣S_鶯O C-27NeMƱ?*B7O̻G' M76/ _BN7E=,~t?Fot8m0A^:dg o~`] o.0 x,RrnD-wr o3 cg[c֋J1UUR7)[2UkߛUzJ-\yz>Ta.>ƌT#`8Z|YA#zyrN˺vQ3fF X>n`d8Ȉ@zw٨#0.L f舎T`I-Qf*9c%UԘ1Bž?M>BCqP4S cŊu|Žqs/ӯf}2 wk0L,~bDmFpƜf٣z/gj%֧c|O-+%&{jWη37aUVtm.2:N}}^ s!є=!>؂q{V`hs$7ghs]B,>1\\:G-_f$f;0uo:I83XzN hYOk zCCc[PF?aI8ɠ+vS Q=XXs%΃gb|@7J5f3rQ7 {*G nPF 5$:+}=bxW0w35-hƾ]@FA$a.8`L}d tR6=0v̕#JƈI%#twv,aB`sm(tϵ7k&##X "0o_ g|˓c8}[)2඿[w)SI W$o31 n͹BǽEBm2;3?ٗ3ZWH`_ˊcZ U?fP¸VN<Ϙj0[zhxZ!45sΛ{hք2`.=ch4&0&2=gܿ8Vc-jRU[yW\k=m`@Tj-^fc,]Y+Qwރ2yJk1e "jM ˰6FBٵ|((8\_ hb@{0Y!E"mgFqMvFX+C"\;cFl:clLQedޟ bhnMdx(d+ýE{(a^:0njZ?F|o75CL2,ʞ^͈xg!wq~cCt,% 1 uN-ǘyewEowr]Cpq\E}d0JnTo2"_5l3Z 3lZ_@oNJ&8ڭ0;z?ץ=ym-Ttd:0Qu9dܝ/r' 5^ha-t+~&5~(qva揲k'ogď~*?+xI1[,gݰc;)C3eQaWS1?C¤_|;T)I {9ZWikw*SLMe f/pla}9bI)h194Pm ~Cy;կj̶k?T[ wsÇ^dFa$̘gj؏L $qsVLdg |9)ފi3ALu}X]ui籫nwef(80gbl;Y3o(%,^ad=ӭu KشWfpݛGMz03}2;SuÌ:4޵yomawm[bz[`|){S fw1~-f(t,{e!I=ݎb&Lf_3\cyqC9WK׿1eћ`)}A$:faD%Lm滺xv-x] smh7}{=>b|WO8Yjt#"s/JNTa4~a렾'Pdw=׽Mafy&~i3=cJ*iE#}eʹ8MWcL6E 4'^Ŭ{q&Vk41?g.Xf"ٻ|QʝM!}9!iԴ}{$nq`'z~饳  } ;4uXbr-J窨יF3_U|0n2Y"MDYjYxMPjwAVР>}4e*X`V'X5C|rM,wȰDhOv$XHYG>ɂUO^Ȇ`G\3maIψI|r~1Nh FXIl)tfǒiBXjgYW/a hNϲB5YOΰV +Z,tPk1aȲ(yU}Dsphp)KX듑,}֍CY}ZXv C^H6lZS3`ݓZn6>+ mHBaӊ._X]eCYvܷe}]`R_~sbMkX5uf6gςݷqd zqڸV?_ w=O?:W5g}w-فpeAcn>xw7+ne D&bw?xחd=t5";yXncE ]z kfU8 ڞ 0&XBKq%`ԿȬW^c xYj2E XJT5V dc'()޹m1 uդ5[z r,!VWvﲾ mr5pM=Fdsޠ? ϱGGكj̤T}k晰n7!7٣mv!Q-/s_ t(_$]oџ'W%]=,f0/uat.z.,q ݆c*pe3&ӗm؇ 5mn]vlQvDWGC;UI K.lA֞dVn}>sc;ZHEu6a>ŃsuvՠlV[O6o loUa0ےO5d"ȖZkb6%A$lie ;Ѣe|'W) d#Ԣ^, ϮBO־1اuƳع$t|q*MR &cc"/)r?|xG 6'Bbٹx#^۪#aɶA[+"F S@/KhF۷ mLF\.a|KvMTʾ*+UVNvz5L9{7Go٣z~Coi~g;ސ(y}qh[+{zkFd+3;J1q!˟J-&mlK};.-VzqV!KN=^}D^vjk4c{y& /aώ[8?,d}yrOOy:OJّ"lGJz4c/v<ߢ9vsт7쥳_*ѫb/'@1vb[SonG42mNKE^6lI?&$s ys Ho/t!NlzQ!͔ G9ֺ8j΋p_qew??4_08U!QhiV r~NyN.)rF<~Д9"mr/]e 9|"EЩ7R{cvSw6yAe9TّyYΨK}q@%=MOor2J3 MR dYΩA9q#qUΠ{ʫY.d/9T",8#Sf 7& pO{S޳GwL9RzN3 9!V"n߱ȹY,*G^99MLS*ِ=[xzWGNEݹwDkkkp=GN:vSq8 inl6Ɨnq+@z>-Sޜ?\2kˈdY^u1v_A81kW"9qɼl.$)S@GoU 971%ׂ!PaO{ o&jM08Wl 8[~?㤝T,ՙ{VszgJ.fqJ85Ō9ߖNBF 'ܓU󫶓SQekW# `źkfe~9gGDrf{D }qM\u\Z?*p>AI6\ ~Ԟӎ$tmՕjhWn5m=W\P+J[\DQYM+ CUunP%|mqƛ ཙ7u*-jݹsS5$[ܗ%5܈37^e#R wslդO1W"[|HgyJ: ȍZr'^7}5C#pn֡Xyg9+t@'Mzȅ:4]#qG^#rgnש6uwRG\?w>l >½ yM8ܤwt ׆oC6[kNB ݣ/pE|?}/}=\c)ܠ;Q'\GTҙ/.{9n#.~YϿn*wo*]v@w oTէ/! vϼz5?Q_Ýu_Fx]}xb=/=7죞%*{drvu gv+s^[n ljuִkYu\Wsu%o#ձlnssQ-l K'jwCJ3K;<[Ui\ 6Qb&]WӾ\#7Yx$mt}K w[|wnOW.v[I:kM;m F6}wK\^ß6 ~Ru -{rK[}#7۶;=Rc>]:_[[ϬpKlj+ܖh]WqށWxJQ <*217/COY޸Wn6/>jk9^&yNqaOz^Sgty#%(Um̄kw>.yp!-J ˗xmO|'/w}`Ax{c=qƼ,x)Gy:a}] k<唌0ޏOEfݭya+gx5As$G^@U /_XGOy?F;y%;ՏMnxRSwD ^JH܌M^@S'|ߥ޼]Th/c^Dl໎hnŠA<1`WvD"Wuʂ~쭗Ag$w0>p^Yv;{I]wp3&\u"x^Q͸(=܏y[,޽90p|[N Ñy~j-zYK%v+y6_ x.Pu<["Pa egU[j)d?('z`hFOuޠќFv6>J\Uh~z$\϶X+{Ļ׆&^j_|tgPؒy#D=jxaLryO25K|5>Ϣx>o1]N*E@S۪~άCy(ȱEӭ|IIcUqF/3m$!63hɉLlN <>>>gO} ->>vc|rfp~:a wơMrn4mkO{@`?x_{Fd歯3W>z;yp<|?76jKV1ϝ3]zёcldnnJy{Į\x{c r7xeJHџ%+ڧQ^F{KV"˕3̦{b,6KܹQK>u;G4,g%t|Rw-Խ2sEQTn|POPZu}s{L"-K$x$ZU]yeoPR`տ}Ij@+/hmRaPUD%灕]3ѻ?{DXV XVibGqFSEq*DTT!&D%EB*JBр 2Da2<׽|#o}ku]rC"$<`yZ_eF :{ <&ϋ,%&R KBW='57ϷRpkB)rBuuc/)bM!>0I0AͿNz䫚AOg(ޥc܇6}M쀉pMI] t| '˱3oh zUIU`lRP37bl*/c9xOL4uuu-; ~5j vcm _ۙ[QXGRG`ݞ9B2?p"GHz tȹL;=}݃Y?ˮ>:MO[iha0R3=38g͇YȘ(40~W*INe>P';*-f[}=vIW]Ԛa)?7|y uxZ%iL+ T .]sAcХ.>0X<`x߃qz]=wWW"hPU"5L(̼'w3Vl W4e|sj\d؈SA#1 n{feX C> td2_LdžtPP4FXw!ќ^\q=לHpiO'To\P&B3$"rƞ&}jG}|/r߹(Ӫq_{r"j 5:qPhu3v}hz%{_$`|D689.'3 @INKA%k{ fF8oV'%3 /A`?$tmHw0/kbkoC ݟ0 1F32e BLyxֽZ t:,H}QK=ŜӐ?* RẂW!v|h^Yk>Qt `~k:{6t% ɕv3vwiI}/Ŀ74aoϵ+amZZg<;]ՋM6omMc96ls4Āe+9;(8Tt=&u" [F{q֓w([zLp>*5ZVwϖk9G)̀Dwy w&rU_AmDY6ޗEKZL&a+ X ߀8 YCs|#v ph1?N.ZcEC\yBӄӇNNbhF4)cQ!*m{%KN'[myCwMu15!.8nHڵZPP沽|>vg xUzwұ}އ'jq-j@S^m0mHq+}&`}A^748o@Ǔ?a&ŗZ=@pֳC[d`I3l h 5~鸔9&_!n!^U9PΥֹ14J|8=o .,0"+>,:7c5=j?z@#/t<=G͟q{Z|A{j>ƽiuȻ-o+-$tw ά rmx$,^+lZ~͟+yAvxw^aa;-%! 蟫HP֕]H_ ,ǰ;1O;U`ق[ sa\8h5g_iYY>4}z*柏j.$8Ȇs~!>,+nmc~]׃mzhoqCWD{?;ć6C5Rﶽf)KtFFtd.5kV'ICv[\wglPe`򲩠&>Ƿ8"۹:,.zYބ6gGU1a+6[="x%==~\x\ ϙWQS%ncv~Һl _s"jP&W~eb g~H#nr8[Yƀ0EL{gicDnu@ytdFCBqm܏,X3si5'#oJrewQxs^~i0ApO9//A'ȗ^r6{}pR!hڞ/l4S|itK֣[xY8BQ h;1v9B$d(M!n2(Jˁ/wTӐU7gb]1%EmD> V@+6p/M488~կ%bn&t9^g}87i0'(`p,gۅk(pыt>OlNY2ph~"REr {϶lðw:|!.siB3hJ!ilcVi OE\Z韬BS*ܸ-7Qo5a']Z~Mu1 1.eh굦e;WѿkcUKk}]_UϿHWC пgƈ?i Ƨ~U]9mV+ik{Ŧ.k [Zm?W[js3V]"96+_Qq_eTii 6 wk_k^]9{9 mh'꾿j5_, *:hE$HsῪ߼q2弄v̮Q>=hJkmbӟΕjۗ&P=A~epMWr|ۧ>_4v^znoʆzgJq|do֏;l%43M_G-Iɬ=.+ oSiڡe еܳ(Em`]a^No уu67<1Xx^}+Xua<V[OˬE@n5 /7D5 /_9@2hax|tKqXM`U)ep8BCi3xh-1$/Sv%w+4n䢭]k=(:зoK8J>G)9),{ti )]|,qn"hWi@}<4=(FI9߇XziVDs#2U׆UWCo(pU>Y d;=um7q6Y!Ļ;|yq=]/~|]6oSQh1džpZ#r;SDsPqH.Z*dW1j7]F>` ę=f5Se ]]5rCP҄v@ c[ 8?aSfG-S)z r|;Q凔P0t/2q HLerots:`ele>3d­dVҭ ޞGuo~^ƾwo:XkU\ O6iexGu!&|zW"V0gVg}Zʯh9r.?eE`vPpG5b&>Nu5=B)gN׊1(tYʆ{|l~K?CΩ`Chu2w:2{C 33N|8_e^5#Mõ:3{p^T5ԗ;] hg  ~F}ARF'xxke2 HiZҊ:X2y:2G:ݘ{ s},hv;_8{ro5np!(CHP^[n| 3>KkƂ]kG.G|z,hRVLS_ :͛9AuOŒ:0JU1F`mظF+ ƭY0@Ft;o^K\Wa+r/v:活.H>Wtv-]w? aª3{1äK!.1s_ jtElB(&&4}lОLbϣO([P[ׂz6'-fӒOXlQp`Jt{ICjj~58Nhl^/BZ\p Ӥ@?s <Py/b,a.Yf F=?(ssk`&LU\Z~ » TJ +ƈVDQ. E5OtZ#ku,_U7kG^}/\n7yklɽ9 A'Qgȵ{NES_1w5QޗR6qM;*j4>``SM+].<_;%\tZwmv6N:>G+u'yEaTHi'-{ jАba47|GVɸ @yGHxTdOtVYOoZЕtWO%N;k}oOlN81vT"XtyA1][Gl}H {L*.{ORisE`#4>Z|MwXur)rQsTV%Ȃu;ZJ)X x(%G&Tӗ[?@ұsrNC<㯳f 2=FQ>BԼ1}(wwJv_J+ +h6\(VYvd?_4{/ ڛ25MI"Eun4PMSƛR'!PhfyZ>b Kv+]Z4۝V˹lju!6aƙ90jdo'S(.O#& (W(LZX [L*偐Յ7 \m?Tlfw21dYܦLi :]¨٬a9>2%oJs7IOl&򎽞[>.l,OD.^Qڝu6ÁXJq}uF(=jP-XT1F2a>iāSnq|8>8K$K#+psr,|+i«@g)\=U)ϊRJ\ɵ 7dٍ0^QmGbS~%|gվ3)($}ي2CE O&b,7z(c1O X؛+Vgs~|9gv>g* n[\:SMwEo)t'{SlX^AV}OF&pkM$32;L[痛 1nEW9^\<[أ/ cn21Ln-bcd WFt`}LrULwMwKJkUbGp~@H'jd^ʄ{ZrMg_fdqϛX]@X>, N>]Žfp+}+@bk` > 9| a 9)Ɇmy*Z[MxǛ_8}<^xq[pV.y1!ecAI 4p{8 Ekl<Qϔ? @2ٖg~੷/qx0 ȩy~M"X_~ ΡzCbǝU-WZIkk8-7't©JFvW`a˨h&./mS18c˅_Ω*GKqyoy{H]}׈Ifq)&L?mxLo]b6_bO(\_7ݹ^?Zr6  TTޅ 3n,}gLB[BZvU*˥\ ?+ocIu< 4k} .k^d9!l>_:H*o+0>0_u& k-6TdhvH.)kê?K9?/;@d8f|{*mVcmW c><%qiX5<d?vk|][߼+zAmAs ۖ9 ,ly<<4PJuN>YEL| Ƣzq}x׻SϖHDQj˝Yw`ڎTJ/舵zr xe1݇fWխdg>݀;ŗqֽ$H{,_>JPPUiݟ5HWrOsG:@USb3dCuv[ǁ[ :gP|S }k?#pe6E{U~@ƈξU1ȥwuԝrW)j{^'j꿩4T8%z8,kAZ|ຠY@gϢz|5u^:,BM'6+)*p?#%ވճbJG1DEO3 ΔE~ݵ( ?إЊ0­l#F|42d#r[kЊ`N.`+ұ<]>j ]H@ni.GY4g%꼡 &*tꡀsW7}pqO>qOI:XsBr`_0,<|̓7`o#IM4m=}osV0r: eNߚS.m"0-gEQ6Kd ۙ1Ll1{}!`VwC?dUW de0wr5 tݣi;L@J={r={OPI3׌$"sfFm.m1>5`ݙ+ `A}1_-\Kޮ5|zW_ V4LWκ Ѥb;l4^tMwX8 4>Kx%{^ 0V4<^*?nCAw5Y& F)HWs?sXzHucA&{l2s;Ѭ=LR}"&m} :3 ͌>bGXąV4}: 缚acB=DDP;zP!MԒrx7~h=UR+Kw*`r7&th}O^.kA!tߝx.79Z1Rx?u+!P3!qSŚsLx\.jzCR4cʾ?eg)[)r}do\D ʊْs'8PtIo=]=N~w=B+3߼KOm.Ů&i/~Ң_|ЍH|.TyҾg &Bѻ{~q۾r2jwG|i\SI=fA)" V?iqjզX7ce[ig %EOI&|EQeE9w? F8@~yC5e`]pOw:ru-ja~M^8t=ur6R:ym`]U3,ZxL.)8l~_zXhֵAFlx t>o3@4<JKou9vy}pzߩ5BhT] VC?J\~ҼMcͿj8jM}%?Ye8b}g `tACLtMo`@[ܨ0cf+OLH2[$ '=J 26\/e8w^V]P?A÷3~0wYe_~/PrBtd$AYWӚJ 0(p[2ދMоqOf_B ~9Cu#DfYG_1Bj|zxkJfc2O؉ФWkloͬoWx6k0ϟA'CEm K ȡPRS48w1s6ur'Mvu ju+ H,թ!EP|VND/L{~h"^=n}Zp a}ceWc\TN2/K -w6^Soe g3l{ (ӰsmDGoZ0v^i% \А8yS`, z0y ^|2x ^]Bou@i!yS.V=9W/.{pulXxPdٻϙ?m" \Ηl5)v,tQ82էZ я?vש`}3mOk˨* xl:Y͉Î 9dυErfeƝW6-6JQ=*WD1WCyWLnvQvGhG t/"bΰI Z{Zeз>!wJ5J-t6p~QQ~Պ.\?d֌FDzνiLW-`wcilt/I.Zةyü|J=K k#hj I-e`gU/W _XȆM̟(P*UI <X2D{r ъՁEp^/UΡBF/PvrZX} %UauaadjG~6q>}AgDwǼ cԁ{KI}Ol4+h9uW+5b '}\deIQ X8wg6 =/>.BѢœe%{ZJ-|Vtrmf+. 8~d1rvCv` wba> ,tW~E:FEK Mcmp^Ll<6?9<//}N%ݟ^r Lgto# lBǘQ}J2BIԟp-ӳK%E2x4sV;GqL;̋O Y' |h{T0B6ᠶdj>?H j2-ݻ- w%d[wxz;̧`r4\,%bµ_*mﴳ~/AK5xHRCBz9ga% 8mC5 ΰK<,d.WJ2Uځꃕ`њW]U^PFZf14~*XN2AiȌc[_f`!WhrbbkZˡx3:еCy-p=hs. ,I2E`5|ec=|~ tBts@]> hKSصv3`8kMWI1 0۹C; Ysw8Fa.-X4I> l)neZ|m>㘊>*A50=mp=pגwz@9Q3\qY'8:`TZݎ!Aa^)8.]ҘQS3/W@vL' \$ [ )}GM-t` Σ^n*0G+za$# efwipHn05;jqcm!jԉg~򽶟9xF.n=5G0M}7E܁C.JA]=<޺!{S;Ae>׿թ5A[}yM6nxϫqpݻAGeK<[fč;u~"pCbvxc=ؙ%L.Aބ:h;rٟjyK:軸mg=i7ٸTHacVܼ(ÙG ܝjuoa#ʫg,P/9y`ۗ3nj wS˅m=ѪcW7cl}s+~E;v"5Wkf:a#{Wn6fo|C:Y( nƕTuhүDb/6 x6 tt< vuwnM5t@U(`= 2fO[5ehnwB#>gxg^51akWԼ'(&-N@VI]uBpGof9#|[#OpW%'Mw3fL:\\'ˉKMxk ߚ?[uVu 8 QUAdy\ sʍt3)^9xmRDc7\Ln[_²8KG03Sblq [T;wM*5#J\XHj9 h6āqM#Lϔ3!xvA5XLSr1ЁynZz]1M܎<$OFs͗ Lsѳ~V OM;$Kġ8xP  qHq-# Ӽ[h52c+G#R unΝ}Mp癍 [zB4>,Sfs0kp̾1j3amɉ.wkĤ;pmE8HRf?S˞;iXĦ~Ozκ^E;{1vR;T3ae{b&?֐מAe;7/bL4 # N^t@yWr:SE Fm64x*Cʅˢ[Q)]DkHV;|֥n0l;E@wA G& Ȱ6>z{Fg04&1[c3ϋj'[]V {vJW<⠭-ӹvX/U=myo5R07S #deج)$W/x"- r!Hۺg/>)O#k4u~!R$ |8䠺极Y ;\MP, UZ3J6sXڂ֯Zso~MA LVǣ4נYQnsT46y_<Ӈ.RC=KJ G2NZhbl6nݧF\}Ь,G? H< ,8+/ 68v*dwVnz>16GdP4hʹ#ܹ$ߘՔ#R|]_Txڿd[jS* R+p7ctnU;{p EaQڟ iJ&X泾96-ߐ2f?Tx84y]L2~,G34x[9*fD{nSRr Vk faڌ)- Q(aު@iRM]kk_2 i0q|KLWR /9h}ٔ+'`M|) ZYCkBNK]Kdwa=Jy{Q9ߵ uOa$[\VA:/+P̅gmՕ^?iA*%Z&vE;VIrBE 5ʝr}@^4\bsRy*t eHOv2oT@lmT=me 6M=WK5p̻BNl{gWH'x<NeKPs킸lbiB;@UJV \g#v. 8- bޣ_ sGξ SvyQ 7Q= W+J~1.>Fc$Iӯ>[%i:gr;G񃋒OdZ L^a`$(!=pxn}:ބ3kmYu1EaV4C}u>QOM Yr} ,+޽il2hcVztަH8gtKIĥ |X*2Y=*i6 PDmcrmXXMZӄd-'z !ûKw$sqvOZy4 }7;,LeP׋u؜Ν٠E[k-i+Qp/%wRqv^Ohu3;FLKp޶%RFm?<3u W,ގW IIl/B މs=Yz$T29]cيNusѮ/0C}jG [fa:0a&;-J.m]-]scۖU]4زgw/{ qpп{@.t~xl. սh`3Ke_cP|w@v97o5Sc|toXuH`gRm&V8' _[&B)UҒngl2~69|+gUG?;5w=Y0k]xh4Z_T'"OS%ȟj2Ɇ۩#m{y:^.n9L룉L?΢ě%ǁ9!ac;ɫP]<,Ny!GWg8pRc⿚VRf"utI;ܻv.:,Zp^ NMl/Kӑ@)[>DJ 8dWT=ʝLgDl-)_z]uS0KpǯoUf0`~Vم.G&]+C=O"_}X_Qw;ۏd"ͺj9arz~l?["5"Y袗)Jܭ7 QYr7FY<,#J nItY>Z zy}ezP] ;7a;7XbipS'L託yr.\|\ś"S2 yۜ-x,ldfRLP5]mzA[&)x:}~>tv=(dU "/3&ZK.(:V6) IUZPxʚ-?GeXMAk𧾛>Úōky=s`0!`5Q Sb[М_I(fIeF?MִNUP TKnf0Ѱ)N!^SB-9x.'iuj`n/A_}ͻ,}zM1^ׇ(^Wmu kL˅'eР`pWUs:$~ik&}Ӯ6Ys¬cwmF'8ӑlPvBR,6M; Zt^~^\ۃOGc! Ii(A* J * 2"I($I!d TA?Me%ΉF~>x.Ó? */2j-{Tjʅ{[l ,T[wI ݝ+<މ&Ǽ|ؘ* l9כr>?Z?mڪR :]׾mV cH%r2خs9{buF(zq'{QAS |#X :0|d=U>4ΝZ!_C6V@1\JXo|(kYdE֋fPsb!v "8Q 2B+W7R%~r|hF@H}v )9F.CkGY^Mkkf,i3#7Й?:yڊS( >vk*YPܹaYzXGO1x$Tk4ȃb_fxFKxg]yt,vctW{DУo)n_s17S0‹f9HIb`Cgb2g6)}/q60/m}Z=Ok3>7^m*Z\zRg†{T^W_U& ڭ'pO fs<5`n{SeC Pz|Z/>S@dۿ$th|zٞ_)Cl=tb@YX6/&FETfa`y7d8bS *H(?/7V [meٵrgx2e_XiI tԍ )4X7tf61JflxǼF6e75C:O=3 [X.[{vMm #@c߇/ɠEoCt~~bՍl|: -V>{?rH>c&`i`@a&<59πVa5ytfLmgh%7J`CMA:p읫>E :L-ӫT|zXzчs:oΒtyJq5|/EB-[7-wtL(^>l ~WPc{+O=#1Djśg9Pypǯ՛PtIjs0%o4& @N@8OC%kP#'fD 6Euz:2VY"` U>J3ig \p}ol5.uLS^ F W&4,{byuoP&^XRمkQH.ŗn|@Gj:oo5Mݏ/L?zog~Ig@b6y9 8:EG=}_\~ kBo/Nl:/vcy<&lѹ'{~:r>TzϚ=Y~*qqs&:˰Űp!nx/z*l=LPQtiV&gT*|U6b:?u ]^o\`7[1]r8:\}^[|;x v!Fp?s1qjjs&rֿW;y,d´Fv`B ;~ܴ첃!L%2GF3`U\rG}6hYdT?kQ:-6$vQPƥ*~j/X>eP)UJ ¯lK~WݞS^'M9.ݱ ʪ5J7,O~q֜_%ګA!lIɎP&`Ϭ;WI=p^Ao4}L{.ܢm Y/Xژ[)+aM E~*=dg +=}֕'IC#m8H΁rdEѮdX|I@X@U&c{?i_FMKq`\E4z(Âueru;MPp7,7W~{6vHźi[l99 YHMՒl$?RS,1nڧ :HOċQ4,<ȄS:藕07n|ع(axpg~\}[hy+O!S ߾ }@v5oNίauqox?n u~(JspG̫#`q flwl0f[@}6X3 0^ˁ, ˃pU[Kċncust\פlОl _j"Cl{SQ7 Tjc5Ϋ2aZpc.8΀D:,q\Sץ᮹C ֐!pS tl"]!lǿ !M8 tpA|98@5j3N@վmIXl}Ac}7ceOY1Ѳ몇 _`;p_;G, ?%ԅRQ,}(oE(Ű}]Ǘc̡QyߞZؿ77zPe_u[,% (VZ=T|um[~lo(-i!эn6Rd@tn#[/, :M0GJ_*al8|g(>K|#@0* B,ث!|Aǫ8!b}> Ob Ri; w#¹/xm ]fPvG]jG+ѧtTߤtA^1%'r$5&iPSbx|6yrJa{ +)0#FP 8\Cgeb77Auי8smt¤e4<:#.ZHϢd}]y~Ss&rNWY |5]_ 5 Ƚ9^ 'M/ @is ̐7Ӈ_Դ$CP|x?iH]Ǐ%'[6`ϛC_)v9xDiXgg:unֱtިl%pT`l88؉Vk*ҧk|T0 ,)n8T 漹@6)ާ=;ɜec푻c̢a,~^-E{TP \-6[JoqG{șaAR0 [6+J in.4:$kG+]tj-{ ěۆE#Sx3$h Jk+$^ gRCp6;/Ȱu1ICɷ)h:z SGnr9Ψ/ݘ€Jؿva9#3tc42h@-A%8l齚HՉLb}^M_?H!^ez/JZ^m&ŬJd(h&GJkH+GV]-6 ] m!S8ܩe3jJ\8pX|Duh>RU7QTMD;{C3pD`풰 SH=P%iฤ33z|93֙WDRz#P厥=m'UC`@e6^S”A!:?6]zt;Xw׶! 0ĩl3&\?BfPwy*-4:raThy~sg dʎ&DdTt'`N޻"](cƯ*?0];vl8"Zp$VAE 3G~%/_R#bYVqu =ק qyo-U{E隚d(+vŋglx,.꯴jގɔlX {BJdٸ׽1n~sA+.0 ^@%?0qwV% YW:(nccF0l;rv`W/}n^_@#d0i?#yMDS G9&xi3Th(=m {̡П,S דsW`&7ڵ.+/\x0.~? L~Xŝ+ J!!d{] ND-+&kaD8B2Ֆ=#u0qN7mBFoaN@ ~8J]ȯ<rO?ܸ lQ Я8Y+AigKqFɪc}%~ ɲAD7慪ϴ)00}k;uʳ( ΏCy3G(z"&|'iԐ$dș?w2Q 7oAHj`.:UvGtBpڽĆ=^: Hx2>[=K=9:H֠n,'k.yU-$™zRG2l 4JI9j./_dKYShΝpL ygr%=p0Ɇ!Ŏn_<a= ^^ "A]>E lgH1-m[1<5Z:܍&ê7M);*Mbf[YdqrR]{'ov`cDž9nC-:NCY1'N)Z"7Ǜ. TTX10B"M;N4T~xo_aPK+G<+4ꡚ}qj7j`5%c缮3aY"qj|l cЎ|y˻'_p*A&q&> ɣF4n{)OS vLعmh?ƼhźTJdA[ AQƐd7wh4gjFVOj%2>{pH3v& |Z(|fL g/Q8Iu;(XJA#o 侼D # t{i6Rmp/oG Yůoe+Ɣ[ vi`*z#&!ضY7>t`-P vɒkz{ΛZ>rj`p] 2mfT%&cۛ<\nѼk%5VRy•GF9ۙ kMXi ".gS}lFC%ƲC{j78y`V7p<|y y7֊kBj*w֦asZ0oq7a ݵثTaC~Ya$&,e͒g=\=@?IPܼo嬭WU\ _H otz%ڑ#C0?pqnmCݨSS0N+NW(KO@0ż^ t /⪃VM؀D1K~yzndBܨ /uӍAHY]"F֗8b qUQ`R{Uz9A%,{{5} { `"EK? ֒Q?a1&n^{_'f־QYH!}#}:z@D) 768~hʍ37*ˮkVW??TFCޜНe.벡 E|_ ]ixQL"cɷ־'0M`oז\[*չs>K'Va8B?}lLK&eUM 4bA.% s~ FS8c ҥ< *62n0Ӆ@|V{ÁpƜULs#X1(j>\1ٝGps6{umCzR1ɁY-$r[$ uSK1~ZPiAQ4 _NA͢Jp=gjl7\+]^xmF,j[s`B:\1rku$'ѧa|73ebub#뉲b$T]w1xBƍO87s2 __S F xrz9@ wsl$Nu7wM3{GwF_%;i<S=gA/g~`2Gm^۝;q}l% 6ѹWhTa@ǶpsPX~&W~Nd-cR7[0ЂR?~]$вCuZuwbgI 0匦 v=](~'Aq.}u@6Na)y4BrM2C*2Λwc$7}Z)pxlny7 -%c Y?6U_AtŻrq^.vd}ƻ7Ae g礃{@U K;DvW3t si=<].h#[Fا^l ֝բhs:%Drsq_={Q,1Jޥ^ s 3Ű&֭mZhOTۭ7sr6p6>s'H+?(X6,A=k!aUbL씺K4{`εʀ^0 r~ri[ Ju/ѽ>yÏ0`I2 ݩWix6-Y:jz'+4 rWSzqNͤ\io7}I`YqsNlN¢C;t!Q }Q:!fuC 8tϚ߶H7\ݙ+?5crƃG(s ٽ0E/mv %ŧQj94_Y{FkZ&p2Ք-E_>5y[P5_~*A,ȟ+ B标WY69˖#apԭj|Ac$6JěCg"=Dl5mIՄlPkLQ?OD8ڌ`y߳拦 ASI;`DlŇϴ3w̛k~%?v3Fs>N4AșF#*7^7Wr|հ~re¨/gD-SO㽆@e0'CO`^۟̈́Ό,l{yN%3XR \6Ll~G/-b#ܸP1BGKc [wlb<$?$0ul|gEeNLQY޷ګe׀QSmH7ֲҫ{sd\<6%»6/|>M:77Aw;^dB냃}U kHp̹. 堬u][,֯q$pGkl +h(^ь &4ʛ\u3'C nā ݍSrb\=؁LX/ }"dxzDV9rEVdp7Ά"7TO`Rw )*l-H7D,ey#nы|a>@~+'_(:Á?:`X|o*^ Y勻Nj5wO#YpG4Y7h-xTve_ &bY8#ߛ9g \\M5*mHϺ'dWh]b 8Pu(YwCrrkS5+9@:.}[;[ hO^ZZ"z q8~fo`⩎V8w}Y~+hM]1353l^f_{uI,9@CV̤ju[RHi|_PяupjŌX$u_$ew~3 v@_w*66?=2TE=p1yɫe[RKGq]hXy5G ,8T6gǯ VU#ŒBSbw_t/6@X{M!,ݲ ^ڽMA*y"}ÄcG$o CI6s`[})aK7 w¾M)no6LHOBczOMV/>+0MƱS;nzأAPeG@cs\#qpϏ}s[~ńz=)1"iq I9H\xwo}l&^yMq"]h}WxS{ie~au6ɜTXvÍ2݁\sXo.<6o/u GWؑQuz b5=`Gƃf:j> \ܸAjZ{U2,)|h=G@sHarD24I2lpKIL`X{gno\O.4#Վ;閻 YUH,H.JH`왌mHX8;/2,ӟCr^Fe+rrt,ݸ3u/mB VymOB3APq(:||sFTGl4nEomrԧ!)e~56q?824[A~a~Pi@kXs{~]P{Mvg6`Cgk b:j8Qpp "=6K`mc^6E4O|;!طڝ*Ԇ< 84R"8!V~ @_zCc2hZL@|˪iB[PDz>>qkƍ'do!YlDp~wVvA]M׿PVje`TJ>>9Bp<"+x24>!%涒F9R V{~}6}>J@Iwxb{Zg+G,J8*?̱ sAXgּ0/Pj dvnEh'w;v71M9M3/"OMc͈8ybIXJtgZ.W HMŘ~Ya=(ׁ ?F` ߣe+ (/2nmA=C-:ܼT5 ŋHE>'@?R6|ǃ:jiKU{GϣJv iٻfghOV8a>^!gk=we%J][zҵ:9rȐb9yV& qS4**/@SEuMR!&=-9$-:7P{ ;o(=f9| ' ,zern Ҍ̡A$VaX_sKn8WHnD&r՟y}xJ]xn͇},j A@\(*9o@~&c"%D1u'2sNH45ɛ dzpZWg~='Pbemk/Ӎ/y{qcorܯ5} yW7@z-N}Cހea 48M MT5g^8e/1A7u2|kq5, ~5Y0V)=^4e,s+^Aeć=f-sߩx€rݻPr`5Gj)* pXA`k[h-OA2ɕrd( &͵!xL!#P"Y]eK!VO\gxqœ#C(KmG6b[9# c/p=do\(F+c;D0(ڒ.lՓ*mv㶇שr|b|Wm2 5w_L$Pnob\ Kl@@g@|,V3}~A=mWb9qېM`Tf3;r3Q^q@=o/\ s.\l*sդ pDsizk:/as] aZ}7]ۄVopO3͸ pE2xtcCz%P&*ی㟈c=>RV|li~hcO&q{:~1Dlj[Umߚ2 .=[ B L#i6Hp7]~ڍ;+ŗ"ipby hs0kp#Mؾ.AHf ~pkp3'f)oOR_QīySu T̍8$+ >#_ f T~7r 5z`> x?.;F+)TLv,`r7'k \L@+cMbsYxFGo~snN&O2P"rf)p(kۀ{xyfh5pKƴS0 QX2ėנ]ĥ U=w+1>n&MwAk.lw;p[ ]0(c68_$ׅ m H)Y ߟ#xB1+W~ҋ6ҡWA+?ȁBl* ~fAh=~n1n4$7M VoPjK: (r,ˮ&gU5C7Wzu4.پ,WF)c*4t@uo 76Xp퓅X~܇Q{#Q2 {Ͷ7 -xϧ/ȁ"Cv ~K,~u>{|sX63lhV c F&j}}_X0v$օfu$Ic3/[A}ȥsKPJD m8;3Ra6e!wVkM(|߫Dը6=,v7m׾?~f~U?5 *7N$s]_[)El6w>a}Rp!Ӊ+9{) o }G,U¿سEk+]; kX%@`WmkGh%{nȳ`=vgsf0d.φ;:oV$V1$0ƭ1^F @u4or>9 0y  'd"@e!$<['˘J\6ZuPȯfv5讐J W >:׌`c<RW- ]mW&qC fz^hPKk˷sL|e*c:ۗNg`O._CV|\+__+]LhmH8~| 3Omg꜐Aē]KlsXB5}GM>TvNF T\"JTÊU͆p߽z>⫞?WHZы[:{rɧxT3{i(Tc"Uvp;Xi [r`pݥ]+x~ʻ[Bj M`|&)\Dōk|7Ä,|$4ܤ q~a}3o0[.=|sqR-4S=@@֛bT0.\ig×fK#&js2{j}z$'e^*i` ކ,ܡCC85k\%Nv8=Xt>JU{cXic;zA`Qd^~Eo.#tpZ):D'&4M=zuܨX |jSMgG Uou_Ah; ˓/rܾ7v2>KJ8Pw8Gg޽À f;ȸL{J61fߍ#'.¦nC~& 96yQav=z;m6\} elҞ~/ cf{ Ğ3ppOFm &.R>:yEz- 1 ؓZy%X j\r ?&ׇyo9唑}9ϸyjtpw^a0NygMrZiird(J>ϐlطm!LvA] ٣ W8tBpD!BR :)ۋ)piFpw"cx„Ou R7($HWVЇ3s0o^3:?U`oM5Ts.=<@za}p+Q֋LT;֣48}#]ȁvyX+5>Tg #|A%1_:a[9*dJ=`A CgƏPQe0бxe~€vw#=4vY!]„O6s`Atxv\BR·g׹x}"3EnwmH.$QJˢI1fvbŏ+~W3aQv+bՕ!R'OxT#y`ĉ02?BeBܳ>mT7,>vmtجB6HJ']_iX4}6 ~}>G1ūR]3J;#Уqޟn~+ :lвʎǑX0o@ʓSðFVˆ[Rf 7Z߇nL/o[rfHjX?[%Xk{_R"T@ [c`|dh!lg¶_~0@~#~<N]~sWg4$jLTODIXO~ ;әdTos|9 'ϵ>Kq;Q&efmWF;%x8rK>nd8l?NTkI8f=:5N_lhpwj ݀׌ރ׎VMip&0l>JGӡ*nt9ۂ!565#7.dž'_G0#t8śۊo-ӎ;#@Ka9p_Ls7G@ :xV/Ň\"0,|6(uݕ${iϾ5.ιa|O4,ڙ&wic>z6+wP`|r. [ׇATTTr&0|:N?_rkyIL;،WV{z/829o06 dn:|6ZnL8(\altHG͖ *mG e؞S,(Ͻr4f2o-Wtgb V yH&@FVz^1$!-]0ʁ#p2@W5_r~'M1v?әv6w+ Q:LGx~ "BB{^®!hܺ74</$@unҸߵ>J03`2'y\#B-\;}f rKa> ".]E-pYҸg'8iF|v)A=RF+3Px]M0)%oo{Z͇]P] uи{{~6r)ٰuvhA G&:5tqlzMK?XMG璪ShI]rԤ5߸!p_cKYN3Ĝ./p @kpV'6~[MjGSJ=[&}]{`wXQH`-(hDǝn(QC@?#yd=7H@}; Otᐋ'Pv٭B ܺK .e錺 fU+Jl侻[m}3|*=A'kNlaB;Ew_Uu3ÁgC;RR[`=#N^4s&'=:GЀz<‡,>9PNjW.@\iř`\knIF4X |ndC:iKrXõuJOmUZB~< {]sC(֮^K Zp*K}M蘩vtG }ZCe2Emo%Is8cۛKM/w$y/v [ ,+·ܡ߫ H׆Q }NǭnLx+e@y$S$BũMIlpGEW2ҚAXc cjVSkKf',8y:eNkJb㻛{r4徾af,t mՃOWhp(:̼2vBC45ƒفo2#xȺn\R#:bEw-yHC o@6|=XH|̀{}1 u_y (jw)츴\<D[ a($6WO3KCj^q:?fáj-!ՋֽkbAM6-VnTv\f=>x EQM$"J@Rx-N/wwT\ OTaO*Sm]mLxp2ܽݚUUVX1Rt4՘Tގ6S*|!0'޻XcP5Z1=-JV|$ߣ*Xwz\ 9R+v@pJ'F2TfدB|~guB! (R ?tDau>h-2e ,qڪ5D9p.B] |ȰB0]cW8;GDCݳLPm=9Q#$ܔ`B OВ'$9Kre?Lukn&뭭Yv|6zy' z*57qV*(u3ֺ^M+TɥGtx}QO xaPu~J^j8{WNS:\MK~#G PrP@E?fa8>RBw~†gmKc;#j~y<W_"BlqߘPGb-ߊ,cRIUx=| >_ۻ _Vxߏ.KZ8\6j#IBz?+] i>Ħ v =a:ɪP1pd }qۤ |Eh<ł &E!hMu>*$$ j|sdX-U:t$nm̕N45/(vk| W=Vgِxx?2H:"r.V["n? E[.z Z2Wt R#gCy6K"Y Ε/HĨOFEjn\~BG |;=qDɳmˎ9&Ӂ hYz&7V(gÄ?s>4뿒yX,pKTxF}pw䖺z7phwJFX?I`_ukO׵-C ly57U+αQg[(ZA/+N'Gʒ^wm* ~_e_ O!94ܕ & l8I"3B:H~kiFu=48a[FֲLf3pϷ>s?ȅr.=l9nYN=3I?'.EKJ_bNWz wgrrөRt'|{vۣNw"E1C1L|ͻ)@cnvy0NC圗?0g xnxv@W: v\t\3:r>MOo1[K4Iwyzvsk=^wJˁB 8КaQ"ōA5aI4(;;S6A3sjRijռv4d|{<Du[]^2QQ&2{8U> ySt +o<=F@iR)brk``zv[KK_{V!q޳nvUn5Oip~')rʛbYsS~tIYS6&yh?.*"~&[t_f z0CX|1?-Emz9N $ -k: Qg_(c2Ev3nۻy`ØYv*n_oŽ)Ғ_a\{Ň0Q`D 8A‰ e4 ӲJ`B>K(DQA[| ƖxS=-gL] mmYdž/"C|/YnnBc )g{A˽mÞ\Tr߃ex) rIO᤟"S X6%Cзih XVs̸_3Ȇ^u bl0ӹ75#'4X~޹mv5&??;37Pn20>OFhA,9-$頜 Á)|(|WoTUa[<'^pV>ڭ yccX-(KݖEyx};vMUXh?fې'Pل ~4bTx=ccos :cτa~[v!$Y?ӻ7!++z<ٯcdؠ'7:cDĎ%ƼA?YpFÉӿGnQ~7K}#gL C8h _i0?背ؽ&UdO- ɽ)q#@IB=\jV P+섨bsx<7{U*Lhe33 |,OX }/2Flu |XOs@ZE_b7,35bu]<8A7#gzp.]-]w<ϧsLx{ Jt?6,@a+i(2 5w*MK;7beݼCJ\'Z!pqPv}.yLXߥ-Y%| <| m KT5u~5, c{: o[!׀2$R҈*\31E"/ F@!b+4X) ]rw]lS J[lEv: zv~:I䱙8OURz;50z'r@۹J~QxW)M m<!YNU ,!;%Ğuq ;o_6 C^T̈캜D5#O 칛7A@{_ݣX&曨GÔ,ծXӈ[JXto5+ zu =E5Kh0%9&ۆ7CĭOqِӯ⡎(J}wLfT7zjWS8OO"`%բI$KEoj )𤧬}Vp<([ME.G]鱫20| ]YC@t)[>zRFGٛ#kIV6xjbw^51AX~}tj۱>{ً51:bܛ8Ɇ/)"ѡTMܖSx;lRw>e`>i\f8Ǻə2w߁@{/fTIS _?~vr*|;)Dh)׿$tI^p_O}s9^`R#V,T5g`+'M4ٞH`W6_& ČN k7P:Z!yW7hu ӱs[A ̟w.(EKoP UumP.8s }Fxepnx݇T݆hC.Ng"=Â'_ֶNplAWO h#\A- 9M=(ʄ5g0 wbA e`æ5 Mi {WsJ,pQ v/>`T*xJ)'=f"_ow`CxL6Tj&Lׄ/ "@ z4llG=sNGchuﲈ7xC#&z w\B6P*"qfɳNsbOXp ;t'hpYB2y+|>ЏRۣ M39ҌWPMu˪DYY]x*hys|F # ^zkG.cýSB;яչG5H7WAޏ}tͥ@lW=LWVoA&|l>F}uL amx(m LO)8iw]/vѾA i4g5\G\vz3H1_pqUa6 ⾼a 1B}40h:$EQ5 =Gi:V HL(x\y`=Dԭl A9r:\\L84`-/u)yWގ_aۍ.]ogFG5 Tt(3mȶ^a3is}05Nnv}YZܲDɑ  M^u =0xɁ>$\#xW'',K9~<Mrn yh7^ y8_%j5lpy}.e(KIolK/l7-6nߋo^׀Pp@d}?9|F+ R<,z4vg/&6)^T_ ㉪!Mly=@~-^*addXT: gys'J˅MW^”ɘt9C)d&n&P3`1|}z}X-Nب%*ʍD]L~s~[lgƍn Tרa/)9[t*性T#6>9YwV@ٯ-2k#MOR(~ =zW[uۑ @*+S'|Z4}5w/ |h ]fy{`$L_u tALlB/G7d+ߍ?mr 6~>?(t^b2}{aȅvN}Ym6j'K (~q(1P.tc\;XD)烨hknr\|U֢-&afm^]qkUo)S6xN59Gs=iΎF=.ܖ@ۋQ(b2Ӊm'\yn+]OȫH`A뇯lћn=_^.<G`5ϞVE49W{XۼΡk°=^Sω>DQ7٧ܻG8 .Qͷܻh]Qى~-FBp^ g -mPX8G^ LQȕu+\ܶ@_0G鮚:m gFB!hϥLoȾāNk9ӂ<ڥ1kc`tVbkw^9a`lo uMUZ$+7|:u7^q6tZu-ƕR!o,}{z3{#qaR|ApQ3vaU_T'0v;י$Щ {RL)9M`OQ. pơ"N4@kw.oF[!?Kq},w/w pׯaXv.ܝEߍw|h >9 .zOZՙ9u<|R?&ٔfs-Ə.߾Ria-'c'y?q]'q%^DiN2p՜$<$>1g ]uaCqCꏏ3S_4zziA:f7;Jf^ā Ca3THH?;_kF[5kqK? hmo abW22]Wp^;:*y}9̆|akZp9$ gXQM1c<ȭl:}M 0޽jfƠ l\FU;|2n*Phg&`?eù 7ս*?rK (*pbu~AIHT=?x]BiO }Sh3QaP_#j7<6_P 6!'yAA^tKɟ*{zn&R9J:U;Ǝg Wt3Z z~>/;A0w sulTo' a&\OTe>Փ3,B))HۨaiqjIX]o5C`F&S`adl x?Ϸdށ,+f|sxӂ7Fν~g2k#@C&iޟ l-a=\5z2+?[†WhOw4p?]PCn/eO˲ixoN_hW IBר%2Uo|7" ;~ar`fɾnF&7"_Uqϴ4 ϻg̑`=GAGmPvvX 4PSz };򸘉m62 .ظivڗJBÆ%Wp`SR /|iQuBz0VbYoޓmcPYRF{T%k'ذ3n.T^k=7YVkixߵue7vDl=1{&Ͽ#V]b$L&T <WˏtaӾ!$x6n,YY'U?[ ŵH^ ֶ\;.~m5ڌ69LP@s3^W4gP,i tqb?9L σ [&<^τC"  Qkg+1\5u!&xcb&-H7Cp˨ W~qw[ˀ7^&tmԾ o3hxT}hF4CZ^Y~VS]"\֕l<uR~W<,Ə4j({yQIX޾Z|>nlL;^'o4t/毟Zw\ |~; ~ Cw3 O[+qL%> 89&I(5_ V:BAti0Xw<#@Q^$t.(+I=j1lz\=Qۦ}FpP+!JjhkmTB6@q-\"tt{u%c>nF3Oa_;nDcR'M_GAcA8E:ٚu +pw+-]TXgB壢cO0pQ,FBSè4i+'6g(`YYdix'ql>JX?Ȫo}O6;4V?H&g`¢n{A=ڽ!ҹ 4|u#;'^P*_d^^KޙK]O/쟐+ɆbVSet3lAisi~]5բH7ldIqqɕxܛe_z4&HQL*:%zq(2|,5C&`2a \;rJ+L [^ y65M`,}r/kAW4KVuR,!%0̿i/.%9\1 +_+Bq3-_reG60)8U`O7Fօ\%hUx~0lLv|Ƃ0DS; b=~Q.Sqd"p~NxH@ !p;,7^ SY=|6 %\'9L6Nn7wppdyr,yhX#|_;x+Pv G["&7AcΓT q/&㾊2>mߣOC1 jK!I*[SGS | .~מ\% iHniaa 1}D4ub '> -6w( ߏ/ /Y'B(zKfL׬AOoda͸-2C/!@O|fmL @};S`;ָ[Vf섥>+h,ϗ+ JѠ荐i6<ȍ+H.L|))@ϰ_jxA!Z&7so?UcrqLY> 7^ M!`..~Vo> ,~ɀdf7NhҞ+#@DY8ľqZwgs@{S4"/[t~7cs^::qǭ$:ʎbA U 踂 t=#D0N;G``=wا4QӌvTPC^ 0{T4N71 (ACNd P:S>)Y)݊ x@-A@MD}F?c?`ײNgv{F` 9N09TpߓQV'SA=Ͱ%]hN8ژRn dn񡅑wWVnHWHwC^(ގ1y죡}$ ?xt*w4DCFYo֋uEњ+E۵!7/ٰ(5nC83!WHicGx^M>ous֜amEhU6#x#΂Sߒo-uԣ7D@|_u/5Y]·/`q+ĸ8cϡax/:w/Į_e#-G#yv֖|+)X17 -٨}{=wK v5sﳝ*0Ѹ @wn-{׹<4m &e(hrƲs68难D Z?^v,?T&q[W̡ ,Qi  :T|<*8[;jitֈ~H"T3’!ͯ%~j&˓y1Nh0 йQTD /r,ʃih?~@yxw^M玸0 cҗ.{8UpZ#!m"M,X?0!M. VjJk& COn8D*a"COkgv* ,ѐ/Exoze ޴mwa]\VR\ښF;gN > _v$_z5&eҊJ=riFA) .8џ/XdLW\+ߚ UKzwj.H=kOTա]#Z:Tv.O@u3oq (uh{ o'w؉5մ)8'):pFN Å eb?p\` zQXk~0\tacYg2#gZICw/BzouNsFl+H_&h"0Ўc pнS -Lŷ (|UN"![h] #%!˿n:/nξ}R9G|Dh2|kFpUۡ:ICF=ضu\]ӎ(UC !ܴoLtN~6N`ey:^|(PI!s#GG—Y6װ!Q<&Yn~w 4:u {s>$OqXྶՅcп|'ȼ^*< 4l)a2IݛAՏm< [C{ 8x xvqlǁ4τ]xq U+NFoH"kVcSE:xh=vxzroR[Z 4n?|M˪bo guPfN:S7~dcî% G8׺QL-tb펢$d|s2cOע㞟۷Skw,&f$H6gw \;p!sߺ5 s!l1`8bf"ck5.W"Y7Jƿ_oo/S\:|l/5#p$]%z6/7Oʿ>vZHK2YkH hMPҗM 7 ;`tN6̰ y!2xãAĤϦ^m[>{'5GlA$!A!:Zx6ŭm1?#S<긌~Q+_.gSJ*0֐y(;sTDW'BzV5uD&0W%F jo>}b.̸~κ/bl_t`Sfc?:ڀ16fL:;~crZM:6u6j ~c,HAaқd.:^D'6( $e4?M{ԛhwo"[Xn{vVyOu`[8W "ee6uО7b辧LL=h (} hh=@c.\kGuDY%= uYCl@וZ`|yL"F(#^4`Z[ ƑZᤛzwǗ38oo5hw_ YLe{8xy & e[5|K U ԾVۓ/ Dc#h-!ZMTfPo[lPu" ۖN]% j̕}9! :]MYF3ǒ) <rׇ7OC 2t*^6Fqs7G#+^*.ꋩgNrt?6F .3@R`N矓s[gmIP5xYVEWƹ@d{k>-\B5͏7PXmZDm2-~Kp&sn HK{ՍfDN;$خmA@MSӫws']$y]]\4ݖ4<6q/}b"+`]訆ll=ffUG TѰ'IGMq sFl_^9Aq\,m ŋ7K\~I~ 9œݢvRמb:OӶG_;KZ6MXtWvٓ pDkCxÁ7L+ɜk1}kAGl^,Y /4&p!Oc{l++Yd7TAub 4n~܎бg/Eٟ:Cv-u+v 731k_>bfTn(P1>Up[9-AxNknM3ˆ:\HXIgBeɿqM ҃a2SN/zRMQ~~z"WmFfqړUYiGu30KQfPL(m34NDT_#Fw  _Irғ o{DG+lߦXUa/M+]hPs^tadÕѳXiّ*\/Z[p} :_,*JvnϘdp|"7\e՝_xj0:]TVÍ ]LHsd<5e- d7@w [VzۇlgzT^{lw6[6}fU~XLEE1:CTVyEZt`y )2ϊf=͑*L}zX%^UhGs8i=CTlULJF܃O m90#h`0TOe)#}-}(R:Y~7ýf2wV|J64Xm7+A{J,/D'- K9ӍGiYuÃ+`* =PWȟa v4X6bGG~âi$W]tuP0%#k#p%c%L4aFKWjnm{^o% lF`8};bUTCM1r.́Ut07Sv)4_V;y`DrefxT(nh._wiVK5 gʭ:jaCƊ߮lh]r:Ʈc׶jWYӓЈ6%]#Wiv?^]UpBu+x=wncX!s>}4%.s)IFibE1ƯH2NX<:٥rЍ&hQ5ڊpOqdɏV~`AgQDzKxYն%5"r~B»Uk†!:p;=zYC>l@3p\"$<+]؃v6suQD>;:2*KnỏՎsZ\<0:3|$S \X{.6WzSg!Λ/:7J`ԷsE::UPt?(kl .͇W@~\YpJV߿t$Urzsz~X7ܮ ɵoӬE@eLabv1S/Yw |D!O(9_C֌^7{=]0v [eWdH)bQ"tY=?(Gb{9pЪTp;ʁz$ʰpy=wK$}f5iTyf؛30_m2|t^qeX„@ЎK~>!2)K'lmBm/H?൴MM^Ph|ACpQ~뻤8{LOZMnv%_(\g R/lN;ʄ?? ª'tdػ'+rz'1` _x45%.+?`}bshaq#Qioe\G^(Npҋ*E& p@ew憎ML` ~v VogleGl9Fѕ &S2\.l"L[L7[X}l.0 )+ʞ+:aCOj &/{??($jFC {= V_q3od+w0O//&0WD$ Oa@cK<ạwd|uW[ iscE7DuB+:^n0c5lގ.k9&ׄF@+ZvJq7@ 6@OˆoJdi@eE6.kl*Mvzw~eJsps&ޘ:*}<7gTXPH9'e,]pH1ްGL#.oBѱgՑ, . "Dx3x]\-M3ìZ˹3^=L @l5[neệ*Fd"jһ,qQӜ_ w8x_kbϞ.Ao{Xe4V9`'tVdNWڃXJȲ\ߍoHH2-cs[6]lxw 4?^%=ϗL^@†,?:HN/S'w>%&Rv$q#mWܡ`VɴߑCv+N.m0+Ovв^XށL`x9uR^: nv sNdxT! >4WsplP5tgQA츞+_\Ԧ*?ރWOQ6DCuoqK[XPtԗw*~D0`(eBG0x!]?"0N,_nBG||w_NJ@2gko00bK!x^'^>:g3صwJS~L/Qzkގc;qjKXF> efk\k>`yHǥulf1 W+Oh`pBa, c\g:ɨ&͹'˟5RSl_ ZNbJOI(v3k˫T=0 hF⩯O rКf%ɬWrj;۹S5'-h>-¶U?|?pKN7[^,} }RiԻrOU \r*ǟ(y7Jڽi1nwOGJm~c_[Kd!}d6*u#x}Z sw|=NQ(=Ĵ ÅJ&BL/)6X+ZCF{H 9yu'XnqԀ$2ΞnlՎ{],&}j`Dq@[kƨ c0:J <kVz+́~}B'T7oC;'&I؊t2>uDIfI&=  tMou|xzهllgat>~i!ßc|{- %G O'%ȸ` {u,n.-8r᩷xzn}Hw1|;l;*5R1E×6Ae~r,n^z=1ej!.pPߦ3Wq[:۠ V>]f5Z_yΎ[c36z}YϊtJž ay-9TۉU 4rG\xF9Gŏ7ªk*'l-~ #"; I_lP?v-{$$!qǵQv]N g_љmPM[ΡBpW(2;M5џkCڶF\zO^?|)vݬ2P©{ k(k/JA^TV^9 ^)Ld6l£]*m`[ne/.l㞭o낲Q&^߽2΂J^?:Mncz~~[ZFt=ޫoKTA6o82w9'*]h$0㥔ZpUuL\lx?@l-B5Ik$[%dÖx #[Hh^j6w,d^NJLvP%~ ō <腐.1=ѹL'x[k( zǁcMr z{l1+<tOO>=Hw|.h2 [ub˳.ܖ.[iqk ghvc5,rb"Wd0]titf\M2DILt]YhpXQ= -6%`/Hx2^N#_D3plNfSKx\)q.6V3nn,) ƊV| &zOܾ;Ǿ)`]ky}tSD46;N~KPam^&6~Vs`Qq~LX5g=FEGkGEy \t٧ 3լmCbփ,0dI 8Z}mk-^\KS 6wQ4nވj./1O+`zGp̖9xv`giя]px!.U#~#ՒI%-My|*xVK_ ŸySʦhʙE].ؾ7W6!|,LV!nNlB& Y@0+?%+s֛(T|XQO<݄)W*u̹6X{¼|Ge4GK#2](yB=g0ngb:# ƘR'CgrAq7; y7$[S0t'Ă\~Y] ߍ[0F{kV` )dIjjF 3ðx7-鈶@ʌ xX9 g~^Jŋ\cȦP*816n(O SٻL<CHiUwîחay*+İ$u+ Fp+YL(ωtXE o+6Hk'Pf/=zU͋kzvrF@X\1Kߩl #6cHw_?m0!򀃵k1ԛ-9A&' rUZN0!*dyy @kɡa8ӖbX/k_(:H@@- ?{&0dt~{Duȧx˹R+^OQU W nǬ!LJ~ Ȼ:ʌa.=k?{&K11F/}3(ܙ&/JAտbTQX{3n"'2 GӈZw-,8vfnInFFn@I˽*Y_(A^H}rY&u$~'!P"S_K|o4't!SYT0zYpj؊un`S_Hi;HL /'E`¯թk\-JÛbY1)749(e/SIn64-+5W_A+b:8(^VI?C0 gg_  )Rz,~d|=}qI"4_2f5Ā+ rםO>)DW&|xܧ>l>y+fw"A TYswOZm;=бY+W$ta>ʂlKbAKK]pu5{^>ٗ賝vD;V @ۻ7O=CƟ?w@_2 8WKEB9ޗ Y`[i~kSqLC/|Q,"8v" / ":*; 0' YFåbLZÕ+BwI$%kK*q:JyAkhZWl<o\o08%w夣aDw E'Y*3W> 3f"<`1&N.yaX#8@ʁ-+Vw5. # O.vŏ"f (?w|}0fSy«One37sdlxo|d]qx~OX)98s'p,w>\I=4=w x\SK8xpEBnjҎC#8k~(^Qn,2G2PxuJu˲do %:ep#8U' k΍=Yx6Mbk2֌W6mZ'Y=œ+p/4L.FSPśp#SpFsSZ6o0?GICYSw!|-؅fuuQHf6<|) bjz#<I:CWje @_(Z ~N݋:' ] Fk=St*nJ /Įvak&:l|urc'9zUڣoW1qAi?=)̄F;q^sK;<) H)OZj_BgiY'i/7%5гs}`^l`"3lЖbƖW91t3Y X\\1ht0fo6}B_%MƇ 0Reufޮ]@tWZb'ܙv~k' emI!lصd|K,]\j9cLc,2THD8(&p Bׄ 4nwoB' S <%uyrkld+{7S kr)o_K/:KZ,2i:~( ʱ`ё- }t6a ?+qXNG& VQ{5$j"RwdV_R?KcZ;:|)"BÉ_6ک@^qڙHVbeP i_@z| H4hLHuo r^d٨cI:čFFQx {T%i2U 14 :1ig(G:ʱ;0#|}jN8Nk PyCp4Hn; G&z[cB3{@C]W;A)_Dm_ònl;I>Ď6}vDT#([N`] 'vUL'b_'3MV~?}@wHLx߯_YᅶWO'#tŒ Ӵ Fp<ԭw9[qԋ|Xg+I@Ǔ`g޺b#Fj+ơJ)*=&?>PqgĤ|ws|) IylD<_O)PX{x9g 0 7Pta7* mACQhӗ{dzÓv&MVWhڮYI{sZ-țJ5 2#UdЌ=*ev"=e?,{R.^W? {E?*$/.sƣ[H>aa5ؘxq IO>Jcwk^a^*H. iw~q;'* &0>o?[Sˀթd_vMG?Qpgb 9sD]x>Z58 M,}ĂS˹y&n֑#t ]C >5M V>W{m7˯z+{ JS?8,ǁ\$leQ7L/{ C2xu#rY-jbs- (i~ZWP )W;7Fߦޫv^Fe-"l-?mWZByA20c=NGS4 >ײ| *6WN0&9_n)$iC-ԧ~0x=MwXt,ui)+i5RDo^_ND{[*Vlbd!] To^WY;>Ԑ3~ UFӍp}+KK_Vr`v/;ja|8orױ 5f0 J#b7q0^:qD5/X1DI°U{kG!7vmɢtI3o7j-jk1Sqúَ˝A%kf.Xp3N]`o=/^|꒾@wx /D4ny 38-x_n#oTIe4(y7a y !PCԭ!Aq>B4zdwЛ.9c5gx?hdmSܬ!)p~I,Z#$anx ^aSEKQ-z{1yyrm$D{hcwS0d^ L*8l42+`usdp{wZҿ,n tt7NLeiTFڤ,yfNyqwJXK'%x}HƖ5\Y"*6WYslxpX@+J<rx \RU(Bkŝ#ixp˯tfZp+13A8k 070pL/lj?P]j-4`J6-]$Eg)5+"e6K93La0yIb"LJa >@ʓهE ǖ+(UqVpDUZ߃hxMD["pA1z{uq7YH4i=LIj W+͟HT[ОGEQ~CǮ }hQe~ߢ2޿Hf-١g8X"o7n=ܲdA=K vR! ߿2I|;:39zSJ0+r~<3C Pu75nU!PI Pkoִr7Qֽ9ѿАKdNSV#v[wPhq{=U P"a!P?*\+mHla8/F)EvҤ|X m&}%!UL^A>G5]V`7hpeoQ#xYE'%[71M"gHY;=H{hʔdbYy)?g_ZqA#3 D,GiלUh+ܡ5F`^EF^:Eϋ(Qܾi{Fz[Pgo*wZ*cUKWC@7Y&c3 z?w|',P.ҷ$tr_p@W!K4?]X"P8ƞ;is ;:6l>EEn:3>x,C ,v{̊wf@YB:[5@4NN6媒 N3 pvg5Y 0|~vleW$u? Flta{NW}\g cGM' vv?7>燡S|fh)4+zƷHaC$\q5* "6~rべTuTSU ۋX,cCCp0>blё%5MiM(Kb?gb#TL),c GB- [)ld%^ƽmlDf=!TĂg.׮S1z: -eˎu0|@_cbptVl&ЁOxg%&_vKpqzA \Zl?F5Yot= /G?A@t&J֐ |?d>p|-o^(SK}'Zw S:+u)/dJdjbof[= R d ,>ŵVzili nlH& 5Ak.3p&{ sC XH[f6n}٠yެ6=>|;UED*8L@45Pw `8+[[d|SCPs(Wĸ^6vqrU88_tݷזV/7.qT(}&ƫQq;d4kcAd`o20 ʞ'Jx5:Kd9plj64 k}0Sd]7ѭ[Id|u5hs2\S;61etGi7gtį,JٸO_nfa1vm\SuK3!(W ++^w{S:^Tq}½9'" 0䗮 2sd8P`TW7֐nEErV'˕M%0`_H_7&߱ΣrUg*hW*)=12C*А6.bޙ jWUjD~ۖ^QZ8OU!j @Q?\ [iHaTJdG٨)k5Zf;Ck7l!0x l*ۿ}+ahv};RӚyćuځkC^4 '(L {<3C@ϟ)D9}S=3UA5 ?k=ktqMn?& |ʁ& nϋ+CBMm+(;E'wmśß*"-]e$PۼKap|B\MlL6Zvd+ l-[j cbYT(žV0o@ okwJ\h <01K~==IEJFGV7葀O#LL%n<:aKG'/v(9p1-՞d He5m(hr@Xݩn<e~=-JԕhN3 GP t߲__RDf_{3ԀTxfq0ӡ,^19 [lE_D( Nm>ZԎ`r7 p{pg3Zѭe=(hOJ^x2zm]>c\ajT0GhA(!"(,ę~l8I"p[fT(_~=l L]>,ny'rNDFCVZGO%~DگMC5$6`J$ϬY:$jMߵ2p 5cʓ\6zL/|nv\"P>J}^pJq fecAEv)(_yz_oCTiH{j`<7J=fP ca:ג*x<a.^SHZ?Wl]vY5ђ~HX+.]f4gRL2vC +\abbi'UսJcsগqCEӅau& ~3GG9V&e,-mʂGwX'p^dQc;=}/UsĒg1[<_ۉ2OiW @5/igcr*@Xэɿp*2]}?T `ft '#pýTt<)kQEõ?'Apy x߽LdfՍ/*D0:\!{9`cTH1 hu"?fCK|伧 uJ`c 09>Y&ईش}!+Uֈ576a/!\I >'mq*ŝe';q6=nOf Be!^F'M <6jST/2pX_W<)A#׭chE&V?`3=Â@4dT}KE 'iXPB= Kգ:*MAV,6Zv7}+rQHY9:/x@`ѕ97@T \"'% Gq*:$8 rә@ٽ^qvxƗы2$8F\RGÿqw:~Zz0KWt66/firnsgzCut7S;RJS4z* K mY5|˛PH>E #"mkl/DCs~j&ooKO$A4r6eS{fU 7bӪpw&J.朙]`Y`5vNV p. n֐>5 J7Ttu0i XbUw^:U)l6>y( 62|R0O=C'"\ylmFY⤳ vtcO}Ffo\XFGR/ e6q׫;+P"vld,09d!7gK3B@Zt(> ?bxyg i/_^ ukȄx;. 7{᪂{??8o`P:N6}@>O? ԼeƎ[<-ȰpD~-5Yʸ![kS{Ƶ%yZŏ`gyFY9h߇s"ifƏ N_ā=uɹ=o5^,yJ{"0`!>?/ j]y{1ίA'cו-_lCjiyJ]'W cOIwI1dP_~%AkXfQ:e" ;tv0ܢ,Fk*D1Gs¯w!b^{ޚ`C3EdeW=i3e"%]}pÏwۅ,IoTDsğ7 *e PqR[3ΏFm|k:/qp2F?om. jr($CY9Ի{6]K.? #"AK<}_:ӛtAِ22ѹgןwKQ00ֳ/+v$>aE[s;&7.\_i4Q6ߣElݞh 8Fz0 Deu1ӡųsz8MWPvfY!G֦gb|?Y$pGN]V I(yQQݶ m=F:=RFP_TNw4ccq9_,Ъo37ѰdT u|2M[Vm 4w*6~+ [3>~m'=G( o֨s2)uLP_HƇ: Ym* y Ӈ`S*pb޽,NRЇ8mtE=%A-cM(o2SfzS!@bFHtˍ껏|J q xsܡQC6eGk0VTg;m8xO` \~OA-(st86 O@Z(p~%|md/cCp8 3F: yӟܝWݜ5o7A˙AeVC0O! jр^.:e<s_ 8v=#b hɭGN_6$3A(>dIFV?ʀPK t rcH qžmG޴ <noL&AsA nJɖtp 6 mcVx4tSwl)}5V/x? guUE.6j'ˮ-pbvQLm?S&` {f¿8=k \h#$[?ӠKG]-KPTfp&henO=9d45w;US\ΔLS2J{xȺ,h+oOONnG],z._u#ԡtXJi/[`қtc3 v[cLW{琫!lBzyrtm׋JK:ux+hi[ RoyAAdH&D8oAß.ힱn(^X&@Y9 P{_8/"V&[o `AU,\09? tKTSy7vg piTjʦA*FOJ\X WMG@O kBٍ{M!|`! ^%f>{l2׬ aʂXx"[}Hf}cfc> i̅[kG鸙!LV[KWg0qBj04谻WWaLk}j[㍰ۉj)*{gd(3w{ ̲=X=${|gOn(:\]s+6JA"7 'Y?.x*Սp&*f,i_x~ˆdW&%[)B}n$27!ݎ<:=xzU-X' (M ܒŭE~B٭9,=ʲ0&d uF>*)Jԯ"6L4:[.v!C Wi{_d2퇥u[ݺ8Nv'AUhu{Ɇ?e>O- 01icD?H60ѱTloF\ Qy r&)ˏw8[v.)̅ALj&/\Ta/{;a'a۷uS FfA`.iQJ$##4W-{/oQ+ƚgZ˷3ȸAd w _ nU)m|<oX")p2+,Oß깃-KYy<D+=#F-?pN9kش۞lԁO\sXbsabdE GK yy&vn?yaJKnF@Fxvv#/qmA7Y 8!;{>/ .,0Ha͌귑iYF^BJ.㳷˛̙S,LwzSLIěƽp%Ź |#yWg'/&+ʼn9m2aͮlmIި Z R@UV/ަ`toT %୰]E0);U8N&蹭WӺ >"qDhIͥ,^oԄ+V USYhguc+5(L^I:nTZ|Œ-&ч^џN6^;cߩ(S'kCy1lTtXq,& 7 #F4?üĮrlB!0Y."jaډdSj3vkvN_"]♃_'48J7|W][ aa#Ϥ11?ŅhvO~sٛ+6?CzH׫x3bgZ17enG_u`-2kJ^4ebM?pYͥ^~3+*߮DLL :Z(a5Gg@?:XP8Dih6#dl)0f2 NKF䶓X!vSНcUF@q 9r60qg|tGVUl (~":W^b H0Кx:W zar$6v cAa&pBױb6J!no_fl9W{Ir0J:~ YьݝwNIam=Me6dj4 jQY o$4g@WNP!IeF)oU1GlUhD^[/s&zngvu<8]x;xhhu-L<7 Cӥ&U0RmgA~C+pS*cxRfdS9&d)oRgE@ ⵽`; Z+61YE4|(|7ɩ?x>aogi|Srk vRhs3X4Mp *F}>L{瓖s>yGv?.Ĩ2NOnšg/FY+yx 6Ys%ћ٤[*oĈOL @x:g82۟Uj*Ý-Rs\+~P'žRH jK$(R ٘uR*I|v"=*|eN+KH ߯i -;41^S>H+qNmYѲg&ż= M'_x7s1͞ZX^=8c M_6phV>9t%eOW_)x=\A\z4~1G&K=b(my}ŗ@h^3GKm^aH33?aOE6; ̑ecњC}Q^5ZlRT|ՊE(W92v[@c-fHlst C2ě56/2cBkہE*SbB/RP.(]."?7 vF cj56W~˔/w 5N4Ż)N}޴-{?C/D<[a/޵ F7Sa}\.ɧWgG^p9}QIymEx *ѫRʞkj@4-1wz Vc3u}q<=?p|]||QB?~dUv zo V^-l. _. ,oJ: {g[+]J4\{7 3CXV[ɝzуۺ ¶:.=IK9kcS,J]W ]k{emu.ˍ)'k`4UsK6KiQ֩ةDϺGvʿɓ%uJʒkE]ˌku$Gk=3[ǫ㪗|'o7hi;:"j'n, aĺYwu$~r;Tr߿J|7.lLՎ6a]]WelB{.{hŶ/}5WxFt, .T_yFCB=beziηV]MބPL955V&uoդޮ*yݲӃ?_ѿ=&TAe on zQknZX\[o$/&z͂vĶMoH֮ȞvJT{m$qŜψ}+ͼĬptBt!<|G ֐``-۩:.vΪQ6p.bt{/gכZc04*gaI/KU@~_n~Z~QV*!뗆yTH1O_v|(5qyK+yv/Q];groxgr?yv,afe;jE4k6W ^/Nأ^SNi_s+ˇ'jG٭s1v7rs1o2(4xܯaC [F⚆!=ca Tsg*(q|KUP[Vu%n'Z%5>tΌٯX}v :9CGUۦ]붺jdȣ!tm04Zr ,]~n\"|l`GplзkhEٓ#9f o?=뷟єցAo]|/neyN^r\V,?j-f2s^UU ==|~`׈KG#7q\OCyHE"ǴVϟ.gYK'EnSq#3(CYlo)!W maZhrW#~P0_zOvջPlki@)v_AUц:'|-G:Qm*'/s_ϔ7FA%'.mU1 X7НG5!>?k[n- Wu? 3$]?l"2չ ?`@{LLsI$d'Y/*ZCu)hƒ i7]+fN֤M͇ LIqWd~a07nO;ZOE0v5"p*uH Y<(Ra>MJf)@>[׆cG}M1}=?D2֫Däwu p `ݘ aT-((µyYV:x;,&vpi0rRy^=i4<}]\?{˗|j3g!`C̫L&+uӯ((r׽I2=6=eIA}dfp)´_! xjgR/ATCPx3ژ] vy8c,?q|4Pz*Gw!\U+ ظaP4%17NwkE׻JLxB@ JI[/ClZ CKyxŵfq7Q!@skV7EQa\pD5(iN%eci7X8bZ-IU`m^~ Et>tMjŒ1S$Uw1Y"pދ?yh>`S&hD]j;1kjKPGҨs7|#YӤpD :sKh7 {*qgqѺUL2d \+ܦ©*ƺ^|ݜPjI6TxrᲊvlV{Z@U.]SecmьB ;sv9uU8ֵ61p+^&sT酁/ Bj }˅Q9R[:rYl~pΆԭmh ၗ;Drza*9h4v0H$Ƙ29NqҹLX/G^s'p\O-~x}"kr4߾g{`ռc!k?ip`x._-M'j& ɋp\*έXU+ě^3Y1=l)2YtJjch1\4 vtwS6]~۱{#ܯ#Cx{D(!aԌomWS:J{pr7.HMl%{!L̫x;4BJ,\ s~1Q-\~z"Ju ƭH׏a J%=u~8|vd]X~jE7 =_|4>)U ,财5 $̌JK)x&(Yy‡Ј0៯(Ji,߇ZK\8}6/āv",#i=╣;{OLiyvp-?C3&|/oRTR׸;?䛿ECJxQ ytUⱸfo7zXM^|L`~R&L+qv^QNف~-r l;"8s4 8Es܀fy{MsI"D ugBfQHB2TTH$2(CI@H%Jc&9Z{~>Ͻߵo\9s8cSO: !TجO*s[+$4dqC$s |I rK7nw#nNġũ0g%Ĝ1^bGInyH 'ڍf">ދkx`ј׏CFmMu!nL?KYfɦ{za&W 6 +#1bXJB&iV5̍RUt E/&fubd,=NZF3@v^|u;{w ,fԿq4rRfoY۬mV6+ffſjVv~XfE>n9wwP<MK] 13rH_^.mDPbzIl^1e,7Y1;;g$'Z'?.Ώ}K3N/ɯ9[SHdw l~$gl|럌['RtGy'L@R~69 biQ=mLqxyV܋&lO=#CC@HP5{ABΖ@ȣ ? yFH2m} h\$d~e}|k+Q|$ {(:'Mhn*ڼc{2iOVE@8@&?fOESo"٭Jczq-z/(NnжGK FGʷf@a2h>+ 閲uo"Pr$`~R=0/l(s (Uϯㇾҽ,,}:79|Cr2>A, WG!a[]aW%+ Aa"H\N+55.囏aQpuOrgn|$ 2ޟ2މ]R-;̄)5l$KѕZ}/)< g.$w!V{HeΡ6nr_!M+': pfmw cZY'UnF:qrvm3OvA>3ܩ zrhF->>~rh7-mX]*H9-͵*JG~F-d:l2x|q 9p/IIjG7O.ٖ=hVy?AEp沉 =C'6M!J a' dQHƣZH1*@Bo=]Fe(8G+Î?a#!hCo )}3]! )Gh]ׯA˃[k?}TL6pSUPz0OZn zZb~L󜝸7@ ;J|Zs#xIa 2r\gUlK<' 15l(c饙Zş1 R\$"86ZLAdZ(x:oT,sc`O9Pל8v ]o5"}#])˨FSH8W8eI%4͘BoY*TkRu)Wx2zw*!W9{y!C ]䶒4+4CĿUrzdQ} ,5|4GuzŎQmҽ&+ЕGրwtd"UPD?Q:J]|(X'lBaDEyRb`? 7Rfe!NX<%\ajV R5Ȏh;Z 9.&zoω67M6,X zVݭ%":'^. uV?<9KNFewtGG )ߣW(|,&.4F%ͫm?-)џt)I7>TT"n$liEA-j9 {Cw-5G.Ьݟ^!ݕa aSU@0 R@lye>N?@NM;}[='3@s|ႎd75O$lu9df@L&Ť:-7t;'mٳ*1C9g5~ׄN0GKUu A^e(ƛp6:w.~Q61J7gqv0TM ?8&ڟUIZ+r)[,OvӃ9!sU 5Zq},9CMkQOmtW`f&+:y;8jYcZLM"_!_.<%n@9j;@'H^y#*zo>A φw{ #I>Pyk*+ST9.#{JlKt |V{eȈenn9Bk-M} ; \Dz}Tf*@ʞ͇!}yA o.xbA=%}e-lUDbdDv4R9ZdwXTqƆ ~l6,{Čdvv."Fy0ę^pQz`xT#D#>Iƫ]pȮNPKW&%j2ԁg-en%n0Hٳ.l\(rF ޒٴ5*pz{袏"(K/b:0r1)3Rh |Va|샄]BqQR(YYXc}#rF5 Ri2m'EF=?MoZ 7|>Ue ES-jNH5qR.N#AIӚa('c|3`$ z+Ht©[o8Q5xJ;lB},MBe uwfꡧ7G]B܏/SNh˷{%C9[jqys5^8|$(:e`4%^lFݻ,:DSK+AP'BzhCWJIgƺ;BՍ2Pyoڐ~ƵAPdFUe0t%;gO$9v-Pm$mA]m;t8~~ b^ᣌzK,! N3_G3]r%ٶ3Vp/CS \@UܟU5IIv7Tߏcd׾I U)'{7Ls7թɇ5 'x6BGuCAMl9 BX' ʿ!faE8Yay4ڭ= 5z&c\Tך%<vGeAťːϩzp;Duj<4}}DU$-fw}#{ͬP뗃xeQ1k 84ȀZR4(u5&9ڎY%l,gX&dzNJ2X>qA73Z`ݍyFN/F!I{VɊy >QHx~l21R(D4| 4I\ry5o&sS>j2,m";dX>>L_^@4;47+égQ7ҪVpj;o սQfE.[MWl;Wă*JE/A|yeМ-eQoZ^9!%ܖeiC(w<0lYAq}u*}y@3ȫZ xB⌊@Z7To.R{/V6W:.屾.~fSM<_H2)1>j?Cx<]{52h4$in<(H-?\+5z\l f5~صEvڞq%ˎއ$d>CPz ?bl\dv$~8}%aI&ǃۍaBI`ԏOr%95DgG{X<`C =Ay Hf/łM\\1ysQgh kn:xQNR1&c'`o5=iEV _JhC*|\z(oH4R/DD<%9Z ୃxp2y]^\l SNЄB?(?׵^G aŃ'ηh`Qo mV_A~ϗY$/gx䦧RI),U×̐6: ;h C$ԅjQe T;IM]Fz꫙ cg~ƒ]sk`d~z{-᢭Vsߢ?{`t0q} U&pZm:zbS|挳#GN+3m1VטW)m$&dMBN*!3}LׁmSTcf7~Yp; Oԓ"<!Ƨ?}+ S5 ݦMNҿ.Ń}m@Iq{6`x"~N7pJ!n-FWGk4{2?VƤkR|z}#_bQ-ZxKL<$r!]]._ uWGUGf@.Hx,X&ƒJ2BրO3gZIk u/~!;瞳)M[Cg %(P֠9gcg\;]jk*@kkݹB1S䄱)ӻ_\ JaIZbnXJ?~.V/9c 'jl!\dE Va6Ʊ]Cb06W9#f -ewAwZ889BT07QZ95l1F~LeϏ41kjLJ,Gh{5LpOw$vy!JF"5w,s3WhScj6Tq$y֜uV˭b'R=^+N_M3,W!ϰ{bjNcdk$|VtWA=}gXvA-myy@oa.n3.PHcJry;RzA ?8cdy$zlIƐϹNi]OŃO|=۴1d! W5 GMATY cBYII -RW: 3Bv}x1j{hÙ.u]=0_ǐ z{_"܌ d.F|4-ʆ5*4H͏. `8O9}C*I(u񮞟\L'Y96T5gOG}^\`K<\$p̬4p$e=Nz'UܚVvɟ]#"8wm)QL%K[% !<'9qQ`}5=5ɄD;Y¸ԿvMgyӅ{᥾;ΰTR`]9"Q#,Aq~1^)-Kkuڱ ۾;?Ҧ7Y5^cO)2hf 'lOSʫl*~zVO_Əv,:ohʤ4ϙ8~n m#%dwI"6xK#-!{4YNoy5YgaS)'kF_I!pmo7MpfÔؗ#Fۜ0 AhXp?n/ Q<ND(̈;bthlFWvA!M7s%r#ZTp⛻kyo/5q6эfE֡b?mF|k>cK6:&STaƵ )5}{Ms7xŻ=`%l%U߭'ܿ^jw4#+?ǥ۟ӏKϨ\k?}X&ZVEl;nBppTsd88YU`> ].H 2de@'y2n+W"j6>yHK eЅh rFIlgҐn Ľg :_PTx|n~m&`~}0͙6Fu,<@Z~~0q[=8F7?| .O^C_|O =9BME}XRMRϪ@7~$aAvd@60t7毓n~ 9jh.U_Qހ |zIJ r}34~E>{Alگ4GducEƟ!.,cȊ;j LU홟ΐ;WjI -}5bZf> 67msds7W >Vge2}. wWHq~|d-ʦ4?J>"o](>7}ݡ'c7#Fac;Lq -xt+}Hc|͵zoЈ;DV X|tIγG?5 0ԑa r*_AF05kד7TMJ8jG 5a7;W{wt셹 9Nzax UD%\MH\zR<8~%a{q6G IFH/\G$9!/PR>CjBN5إ;oU}P^(k(}x;TwH˓LdgAKZ Z(̃.2<{2{NF">ϣ8(A(//]>i$?RĥeעGjH3V_3N )XɎ:*6Y=r*rC/:~M+Αjg|)}v{y:bnA Ya|̃}>:/TҌ%AVD/x.[zGOe~B::+"HJHfQ_c+ 8wD[~04V7WcDxqs}ߝoBjMavyj74{2Vg gz?cvE+dÅz( mM};q\eȰƳl@dnDRIKZ5O}Nq._VV ,͡`ă̒vy,F;#[Mwfێc1 Gp鴽rK-qwgZ Sx-$= 5vrH5GRfEݽbky'{1ĭ-;hH^!V7&uI^GMqqqGd_I Y9|Ǻ/6d@m{U|i2"Ã7/]my@C#F~[rxJl^ @R%<0]88P kj8Ky+/ 9\u֚X8+ߨ=Ę%PAЧ6' -"jF,ϝ@e(cafB7G}ަfz|%8E5{ϣ1M<^1'\/D-  R0!ַFsraz48lH-E\ZRd߲ XVכ=ҥb5j y;-G?MÃ3lU~r!.W=ڙPeaV@avҗy!Gݘ igb> R + BUI~;MvjV ƝottξyvDT=/K|]gg>+=u:\Rݼ%S?j:Zv ˛0~JAHq B~.n&Gڄov/ysQE3qX>yE BuvvJ <[ {;;,wnǛj?o#g4_ZCUPw))av,WvOޭKć描t174:}vēɏAy)eO_.?O#0V;j*{N}1IAz.ڥqB4Rm0:qxx~7"A*5A}ӫ_hC^,Nf¦*3Wŭ:*::UHˋ*xWdo {rlx]ww flFqC ;HLWpK<0߮'4,ܭ{eLN([UlMO{-WZ/q}w[-P ˜U+iG ҃Y2x-F~`Yi ^/Gb+lMS򉟗NwAG~](%*1_lxJz* m 9p\{`n-!;.њZB)${yXsRJoij''L<;%\~TG#]TO*5J!1_#gIx7pSxCӏ m:B.~J_%WDU"*J_%WDU"*)xI˘ц)Q)y))rq S"cJDbJ4D\ǔ&LÔSL^LHŔ~L”'т)})1%D`JqLŔFLǔLOLÔuL)?1%S"0%bS"0%DĔMLǔULZLx)YqS"1%S"0%bS"p)qS"bJD,DTcJ4DaJyLx)0%bS"aJDaJ.Lx)S"bJ!L0 S"0%S"B0%B S"0%b S"1%BS"J0%DDbJ$DƔ2L؏)Q)AQ)!))SS"$0%S"1%S"0%"S"1%S"0%S"V0%"S"1%)D<ǔ^L0”&LH”LÔLÔ`L)S"X1%bS"pa)O1%6DbJDDhaJ$DbJ(Dd`JDDaJDD`JDDbJɩL)NS"bJ;DCLhS.GRcq~iP)8 ngxbnl?T|C M*4}`m aТoSt7RQ,}BԥT;coAOفd9}i9%e-pnX^ՙi1 [ƍ?zha6"Gp3N q$n8Xj;Clj7;]G99KC!=tgP3i_ .R:\KOSkoS:.Qy8G[+.*HZԤ\=||Nv{["n܋۝Ǚ (ZyܞipLDLƷ|&|0֦S -&co %?phe w{ /|/4pYu͙>G:r\YI MEOSAd88q\DG7y' Ċ##~pE ,{gBf·iM#UyT#2-oŋf]wiߥf]wiߥf]wiߥf]wiƟ_Z~V.܏c*Y9\,!&*wĬRFFL.BOṈGԔtHFFJL)oLg#bSG ΝKN$?c+ܡq,%Ken3m a;揅4vyчLƮXX’Mc0>Y.9d /`QƀXQO{twQA⼚YMObUEBG(BF6~LW ~Xρv kS5+OKC"5#^? #{t4\J+5fm+c1qX%"ِʇS~65IA%WGNMzxlHhŮxNJ]?B_______C7~fwtOW0W)V X:(|}X8K웨}s7Q? TǙI·c&?sXϠ{f8?gE)|oK76:Aog@Ixy_ dX/nx[F~<.w?<,u0RyGa9C [3nK/>E t\~;7^ӑ~廊4CS/Ml2fW"f9G2148w]@n'&>{SFT}' )?o[R" WNLBeJI#1XU:rü**O'e*WET~`b&Sb~^B%TN3ؑ+wA}k|~׽R dte@~PMז}4V^ȯG2VD"cWh2v#"wNs U3-w2B,E"NDfV$ lGQU]aк#R鞋ދDxWBNޟidrSB4O˨:˂TdOnCڈS]$d 9yӷqf+ ܻf+\)_pN\~ICYWAe+{.䚜uDoM:-; p|Z(LO@Zޮszf7i@tU ގ+ȖWA)B5x|9f 7` ʂT(bohRVGԊONhY4sv gPw_R ibR}ŕf?]WM[zHJ/vY o"6[EZ,ӣq Piʹ铷h!z^ L;t~q48Q yXQA]a*{A5SqF&PJQ#Z0(STV|rG?q&iPsA~qÅBr﹀(rnT '7Q4p3#і.؍.{/d/Qt,SMoAX<6G!C{#$ÀE9sJAkрs /ۯx 4{_Sw?nDF㾹x*J}&oy=oT"S^h)h +T.@d҃Ӟ!y;eOG,rѰT!g E!K)Ȅ\=%\p!{\Ԋ>1IMX:Ƶ݆0z< bl=tRrO, T2^'[^Eu|jXe#dW/N>"؊)xQK&g94@?3Zgb3Bl;XO 믉\ϷLQ<zhSU-=CZeuxMheu4#9O-=|wC+~ͯN7]{!].$$٭? É $-o?̏t+~Yt9k =kk(: JPҁX|jAtܺA#Nv'%5c#Qflt7v* R||ʊHG4gOs `Haȁk-C"ȦG +ydtU#cE A)^8$Q~Tiq PdyԐaKAQ o-VmF_gGlv15's%h~*{ys[gwMfFq_KTă?P *p^(zks)Sf}ɰN=,ֺ |aәгPb~(ZE=H6H>zt,f&25CTÏwKIhLPee3Kv4=BŮ }GՂJrHїZu DFR~-݋k`-xC|ՕvICQ*֖eith sk'͟`vKKoq)SQ|Qk rBM9M]2ʍJrxt_|3FWj p@:SI:>ho𣏿V}ٜrp@R+/M~AW`DjtJn5b~aEں~d r3UY 3PCMV}zd0+Ze"RXɡwOBޠDN1t@^e}J]AjIFaRD>/BaN-m _a0(U«dykގk&"|ӄX&(1Iw!>lO4"81q '@{jl!5l)Mfr5+`yU f^;{t MwSkA̍Ǥ mIxzuP<9b)Y{ͻ PxB=Z5,'GXv+70ڱ1E{o:ə[+0D?on ,^Fվ*(CgOG9 [rpi(2"%t#jMHu5J[ fկvT峿XqںԀ<;<{4JdcN}U|NH ~2dr=Ё(li$ 8v$a\6)+j/xA'}S7dc˂ ϕLս`~vPQzYy伂sǽ Y8؀@j .ʀڎ3B¤^WE^E"w|ή>k AE G[wCtjnzk6qT*>E̹ g#^Κ> m}\$R+ƌB䂫+~&o7O 嶴z4׋ |vպ%@~fN=)Ls| L;HGnm)y (;!o6#4ԢF?V{dIi-_!sZ2\!:FB Dؔe %$e "yuUQ W衹yWt Bϋ=h=)/?dqU4|@O)IgCmvKg/̘*;%(ճ2q"uQ (Z *vXh)wҹh>!M>J0]e#]Ow<ӝQQQn_e ?Xڠ*&̊xJ/Yq nRo`;DK]Ax9OeٱJ^m|Np)csfclvbF㺿"pJ6!Jy,OIEz|\ihq%*o7xO*8*GrNbpł=fPy$7vX"@gw*@,H:}S|EX曲6o௠sIl>kb9Z3-83X{3rxڍ7#zȩŚHz/A?7d$J z= :?Ox1$钅1edhg<&Jf6HYf Dzji񨴕 T/zBRrx)M}\+}{ӦH8xw^}~TXbQ@'6\\F^Ԭ>||oD]bYӬG`ˈ,ExzCOUl `ZˁM/M~@[ ?C^YM8ٯ<4itzfz;Xbc7T9Դ528w t_!gң s3}lB̝%lS ~w\9T)ay.]uGHؖ?80Ӛ% j.#".yTxMPH:v*ImsG/En>)cTZ|"Ah&D10%z 9EH )"+HsU%6@ G#O+;dN21-:} %\|ո!hU>_ 2٘D 0tG4#o:OߡbB>_sqoB-XZm)'}b"*^"zW3{љ.' 5 (+AL"TgJrز`xAt~IrL]f | 1dMeZ^.  1kÑI:(58x+oٶm8ڵmdFٶm5uu<7ߙjz{]%rLY#sA7,)s]t}˥'KN/{XTSzlX~ЀuAG*Jl-Wk;F+u1Zmo!ϴnzyXs+9SuA-uz 5m=]dǧ$w7!TM]Z>OXO@ꐭG޲fu!e%SmHRERCh|Z͑_=lT,s6:O17_?^kF:ʛ^&ʴ{2{zs{zm/;o$۱5˷gD룷OE]z(Y~p<=|oڟwxd [̿hSN:yȚd]6`˒uo-i&-_}iɚn Ztʄ>WXҤdoGL#$tr3Ozo[T~V"$YYt;edUaƿuo&*$韍-OF^{H_xAdȜZ u0?IgB 璴[9Iڪ t@1~~A;4n7%5ڕXc~5[X_/95*?c9?>$,6I;qe% x$:~ݓ[$vx~?ypfk/obIڄm.hA7Lҩ= IՕ%c~UH{NyMcAORNFs%iÖ$iw^%#?N58/o:i!?"?׉z?WMFq+Q3w%Q{.QMdvv8QKPhg͉,/[S w^2s5m}6#Q<)Qk?2&Q;2yy%jDӅA'"~YD=S>3;'jA;/Qk4e=yDjv6Q[$HF:nn#yD}lv^&QK|[ HԪr'gMAfo&O9ft=iv,A?Hf4w~`Wv~>A[LfG|&LYf[t=fv"A/N/da tFo `r6cvnf kv΃tٹ_6;H[fN 6An`C(^/ s:M( :q2;k$uJ Lf/x &hm (wv3;ϖf4oN4;?>7zy6;u/Oūx 1;xgv+^ofx}av$^`kd~3kqjcv$}B6;ׅf!/^ϙ{SsxcvnnZ}/g1;~f5e3;o[ir4;/yk2Z%(@lmv1^f?ti9NOf8oNV?p-N[_~fhƛәft8=j^8lv$N_a:v>+Nǩ81;Oyt1;Cfqz+N?8R]N `X6i^qdv5N#dVqiy8fv^3NߚWӌ \ D֯ pv5;f4kbt.Ϭ?]/2-Fs^mv110ng%?яvO'FtҤc5~0yd]Po@ 1z׋hc rhQ+tL*ZMxh}&Zs鋾' ֐6KX<]L{Nm}b*{69Zm.f9{WO_toPڶgR^m/M?_FM_ϫX:ZumhrbYu`dխDiR˳~MG'ht+Js_~\uH(XsQ:shJkh UbE} Wm31Wf?-kR\=7^=="JZ_6wNQ{T둔nꖗ[+F[ËEie]Oj6}E=RWH`Nޥ"5fi{\:|2RG|?g]|-f+"y^΍B^k19R8%R*V ngG94$RעFHEm#5Q#uKjDm*y7 ,Y<[zy{;v=^#c3wߎ ӝG:^оӇe?q?nִ4l}qc%-oD3#ɡ•PG2.Ѓf6BKb#{v%B#[F zzrf΋Gh=Ov'BJ:G1;/kZvOkPWv~ \o fpO סGpivٹK·;>ypcv4\O fµnv^(\{`v&\7ӻf/4G#v~7L=gm6;?a a|iqdôgAv>>LtyX^7; Lwٹ}6C[v5L'}f y0- {y0 1;KE&?ZMPyτh󃡺|{>5;_6֙O U|T3; f灡5Tg6:p2;IfBuyPov^;Ts cCENv^$T=:!Z;wѮ 3;%D/7 ty3 ykv%Dwfuv4Xۏf75;? Y|mV|z -fq<(Xıs`mUVo6;[W:Za-;}my`3;moA ;MnA2_ ҩf' }ov9HK `+{fv>7H#' jvγs ΝԮ;{AqΫiLٳA6;*@gz<>Pj#P's@M0;;]󖁚;J궑fyy@hv#@Dڳ;Qftnv ; U0 ЉfSt}mvʱs|h]bv+@/ 4syՋ Pl6;/;γSZ$;m tӰ-v˾{u{g= vӱMׯoKӮp.p~r\q7}̆ n:̈́o\u>jo{8z UsJW=KtS\BW}\5n\쪷_Z6xT&:ukۤNj~v+d:=9EVwݓbY.Z$(_&hy\|Qmhc\tw}^.*gCsm~&g̈́mκ֩ΚbG9[[?bB7s2(YSY<6(a`:1tf痜s7vIg˜4Mv>Imy@vINz:+;/U|yf'M;FrԙGlv>Q{g;ws,yGuΛ;a>vQʱoz9w: ۋovm_';(v렿;켍nYΫ;h\케z?z*;j7"{m<^ߛyg{]׵ #y1{;3Jίi;vvz;_i5vv:;qN ;isv켬γFUߝՂ9o'roC8koqUV=#SFG%?#tmNqPdsrcuop ckKpX~NAWЏ68vǜ舵 <,naôyΙ ;39/1L'sSg\a#Wݜ6IE=8@1T

Y!|2`agm9+p.5rkΗb87Hot4mtlnY9/ pu.u \sw5/}8:Pr:P+ @@V9Wyh-uӜs yeoM4玽qs~[_6瀽us[ۯ3%J/]%y.L/ q\㑞zd6%>Ñ=uEa [{h6 AͺF&7O5~pIwu]77~j7 6톋몭x:.9!jW6hɽ}gI6-vٽF묋 DZfչ,g3u˽wI=sl os;ji5FbcvMvni^uіkFWuʵ==NMw;Sc|4lon˖lV^5~wmt6uoiF_K#=fS^:5ZsmVڨyKlB0m+w}6׈;fʹ[{쭩(ovTt0iN1fny7Һ뻡l^ R^蒦uY_m믞v5zZxy=릎|f^u@AsYK 5592`sTMTGmo*mɕ4bжo*GSʪ9.3R*SDm_H75<:!ˡy L:Ziu~}ȇVqmW֝Z?EGxd{"gF$.i{jߗEڛ_lw$ ;LYi^xWNf]ɌE|$3CU$Z|.*a59S|N!frMbkKϥt,kSW^ϫ,ՓK;̯n\_?bۜ 4 5͟{#ٗ͜47~h,%s&m4XsTVژ_3Ԝ+6̅ϡ4s|,?2u9wn)Ƙ+f[KXu- 6sincIkڅd]aDv#-ɵO̮ڙd`Nv(Y%JkQcYfZ\{ev.:X-.o/IKco}DBxzջPz{3% dOI`}K>zcǤS_}M>'=)8z9EiOʣ>}S[R*Zm+OYo/ˈ6v[V;jPorɽ3^֛zR&[ 8tz>Rc\cWv#G}Z_5څ?mKW:yfX_izKʃҎo/ZV,陦Dt]~rʹ6}G)gVO֟~;.M}߷/> /G~0ԹAޣ%`Od/ |s8lriSo{^ ݔ~̜S(O_1Pe?ti@m2CtH`ǩOJuS?$.OOo3H6ȝ} IfsI1e$:w y~FK{N3X:N3X?weRo \c'C[s;{Ӝɢsc';y֜ .}^=1Hr5Μ/KD sd/v({9ϜSً;s~e/Ƙs-{YWxe/}s0{:ܜ9/uVyn2by&龙Dnly~&]kJnM&;P(y>.7Vf5xJ>-,H|d>o|4zdvGbʲ_>Rn/;+G񙝷\f}eSuv+D_gʼ|ΏӆοwNOZz*On?ɻr-b~+*'@?r@zКeɟH>s'' Q5O'6;'Ӛ'ɋZ'`{Ǭ~bۤInʆ/I|޺'WOϝ~i[9eC<_-߷|iU5Җiybj6/Ykt_m __s /_8^y/7n|;+K9r/fzjx>צKF|Y׌ ^HY 2;Sj|YɎR\sȳsu M-@yzI` ݘmʮI>ir7CҮ&٬ Йxty:mSC|?NgM@=+@|Td@ɜ8Pn_L@Y([NJU%=JV\c(nw`u@l>!>ևJ%OIp`Ͳ )cs#MUa~L^$ڪ X{[ԟAa%Nɵ7A2:Ñ $˕goGQ3HJV:#c|2.+X[Η`imv;X G`Z T2ST7;,y9 iy 4;"Hav!1;"w;ٹ_5; f!r%;"!nv2Do f"&S!r;"S!lv&DfB;*k7bkv^)T f-B3v9T5dBeV";*f<8TrDžʃ]|llgJPdv.T _P93P7;*?JA?,;&;y0fäy0Ikv&L.=a=di}v>8LBäٹo7;7<9L`dR&v>'LΗICa|_hO1JD^f¤0t[p9 #ypq7;.kKNro;.>hv><\KepQdž)7v>:\nc|a1;_.w˓7Ploφ(2I4;.p,RZFJ^HytGGB|TO!f#HӃos3hv~=R:?f"Ev3RvQ2n;%f%y(Iov^?J|b筢dys%fٹ]4;wa<4Je Q2;%f糢(jv!Jnuc绣d,v~4Jb/FI;QRy|9?GɱR'Jfyliv^(ZZf5bv$Z6`%g 2;-UΝWv-gByT?S|r3;-WF˳_\)Zvva-cfS2Z6;-iD˥G,-3Hybv^;o+f=bXov+OsX^(Xfv>)VjωXoX 6;?+ίJQ;+{X n}?\m/.5*Y=@l}s9|n}]嶾.cYWex}v~Ծh}].iX߇%ogyY>h}^BZ߷: R/~_j}__2/o>Z痫E~/+\ˤ}j}޺? Y Wm/a}y?Ϻ 7Xk~oWͬ mog޺ MZ>d`ݏO]rߺ?!GfZ)d~~xjݷ qo`ǐì|j{%ruC6zZAdd~$} l'V%RyuDDYO"><cݯ퇬6uFFH@~ H\kB=uGȅ} kӭB2vuH[dDv~tg7:CGR4κ$[뾒\l_ŭLuI&[$luI[]~hݗ5SuJކ[뾕(;|kǒYº%N-1ں%6Zu뾗da`ru?LZdlL;`'2qm7ލgtuM%Y$j뾚|`_;߭lruM֛'Loě%yJ{hݗYsRuNr ɷh뾝_bݿxu?O+jד$uOI}?rۺ'y[gU~'J}E)޺(Xo~+ow]ߺ)gZ#%pu_RlZ'CN>j`ݯì&)/VX19~jה%%2uSBluTDZIe"~,?a7^غ*ٺ* 9W$;>diowiruUʪ`~LcݗCYq~iݧyҸuVZo%kuW>ʭK}]9Ӻ+kZyezg~Z}\^>4{l٭’uX X~[f7 2uY[ųu_Y[D>Tnow=uYTCɾhnݗ9 ӒιO->o2uZuZ:Z%h~`ז׬r/;,*Ze~w뾷 l> =`vϭR#u\ 6_~\9E Vɝ!m4plחItQ+# O\ip`E*):"3b:n ǓU&iihX~tuՙ<̰6M긾Rt=Pz{ Gas-=ѷkx َfhtiOB¡3x[=B}u-:?Nc[D-> ]78{,.Y;M]ۿ9^})|ޢMGotwӍǷ_Np*4)͵'.wT:ɶH36m[|"~ :4訊x)Ew\slB-vx4h}^ugߎ紎;SxNǟs7뺼wxNNs銟xNsɖ7~0/wCxN9=X`xNˌsګwxN.sz?6ۉϻI<9شb<9MtSWُ@v\A?fxNsZk>}M+ӗxNs4<9χ4<;9utj<:x>944kK9=vCs:0Ӕ<[48ixN;s"xNӝsZ7ϩ]m<;Os%9 i ӕ^W<@<*9ut(<9=}fsn;nxNss/?#鬺xN?smJxNsS s[}3cf籴{94>uOޙ4GW<T_t~;R(U|syӇT9t^9 s::ӽw𜾞x[s9mϩ?ӹ񜞾W*fxNs:r>MVusӻ| s"SσxNg9=Q x9i;<[9}iLxNmt~ 9 xN^߃Ӽe%ixNݿ9 1?<69 ps cxN9UxNNs-ӗv_ ixNc.C<51En? jxN sq6xN|ixNfsj<D2nFs?<{9͜&m ϩө:cӲ5s; vxN|scCzq?<9tT΍sz>_OVo+ӑn_ӂ??颪xN/sf<ڂtG<{U ϩGs<ϑ9=>7vB+es:`$7<9-WU<1Svkx4l>4WJնs`9- ixNc9]ϛe6=xNso=O2 &'< 9s[$SxNszz_Vt </4 T<9Mc.Xt\:<߂ bEv94,xN>6?ixN9 W92xNs&ϩ_%<;59~xNwfAia<K9 >tILQQl%s@r9#9瀂(" 4 "(9瀨(;ֽ};nxc}FUWC̪BDDp_GPã2FCmixw$vL dQɇPh?@’ɣ |㝉T2!XC)5!mty6h Z炇*.\:bh~;$QZ,HT_/sNZ,|3jLp5&=>:^8Y`i> 2sޙU""v A|x.7%:8"?IDD*X=/cG}E%AD#DKpTċw+_"6!! CT^8ta`-}lTaUΜ?/ <&|p%sX =4҄ߺ-{#6|R ||ZUS10@XO5W;7ƹRAxۛx0[MWa>i%-I#Aߛ_Ok Pehl4sH)<,Iq][K[Ym'f- +l[- a3&@{>}pҽc l-ӱYxMTxt/^}ȯQ4] lf%]Vlџ3lrϪcSemyjp6\e ё+<X$ b`"SkxAd H}oI`bzWμ >$ծǃ* @>.h5{S˕0KqUXm޷:,-8Ov;y3IdP*Ŗ*`UTḯꔅ8VIspk `guYwǹB? P <1G"u;H(g;|,-R-WO27B8bUd/lUؖ kxݖ$o窨m{k_y $ }oI^VP{l΅28|u^)Nb&R( q?}ԱBm}e!|^%&%V.b}(gPǭ 8J>0 , !ʚO Rǵ yq oyƱU*ahA8tB&;O]>.a?@U hwX,HU# ۷cEB Y-D-PG|xh ,ssHl% {[{.Ô η?7mD_d mbq uazm9{gW"6f+|0S +jFcFlg}gWg+<b-3Rv'G2&YV4^>,Uf ԎcJX.GUϢ&,@&|S\μ:h(nrӁ+͓Aqf>#j-W/[ׅ?0yy_j{ꄈ)/ݝpVD pn6jk|['.0'k@P# yV\} SXXw;J!).@BlHץ7k?llN&ȷ |> UAfNVM 䦆݇ϳon [@ByC=| 2l2#g`m?>q``~N[WC+*z$ |tU]̲,բok﬜{K@kA(-'.p)8t/MM-.gYu4UnU~֣"#0BU@P(Ս%\2\hskZ<~,g2XEfϳLOA7G2ja)z5={aKF`K|j\a& J[ZOTs͕;Qw:$Xڧf1Cdv;A`k|,d AKxOthH;;7w5)ϛj^iD~<;uCJ?`ES߀'7&|'/]ʆTJ?a ,kSOLnv>Cvp]c&*.^ w? -`]Px>6@)+i<:v(i "6]F]-[@5i0@4dʽ._\Q J9ML@GШ^6sm`ft2PnĦ~* Zx h5]_||w}V 㹹{@ܑY7덄Ϩ#5Np̟2{?ͽ|\ 7$VQB;v$h4Ngj^)"=Z1[ڠ!CC 7"@LϹ.Y`?_} 0Y 5z6cw:wNerh;ӾN*Ҳ3 v A 0F_>9s6/7[A*9z~(Va+c*JG " f8;z~ [ 5-<^NCɣU8j!/KJV^D<=! Jbd"սZ8 .mL+m 'Sȯ|_5t2!a NL"}#<^?ΰwY BkOV[ݏtp=;y[A-`6Uå&av}=2MSƯ;,[{o[# `& @͖qu`3SU,h=u%ׁ\Uk; q]@,IGw ཅyP.<8iޱZ> %s/}09_@?bUio=Vy\8w ?EoZW7e7>NG&`Nj9`/6`)2ǝ'xW!g~ RuVgB.bSxt%,oVkxO-x޲j 3lZbϡ9ÑfK&<%B|,ϋtA,[kbmi'qTʻ!5G s?ֶR{8{ Mu߾S. k@U@- _d#%,#v~.EBeĜDk@,?<^Ò }F;OjF6*zvVl.|D7Py =2D+9vj_T(լbgpuJ&PN twS|zJUΈ픸;%8sԚy\@֤ےe;N_q{-n,a:UY?nzz䪶|>h%VxM7xo&!K@W\>F n&сGcQ18NU>/.;TmïoH /PZ$ϓPk$)/7 2s-3~Sxڝ1n %|C yTllrnhN-DCmV݀a XҴ,1k^?p8ѝm oe*SDpwziO`R/ ̳3r=_l 2eQ`[ @{txyU`n#ی.{5 ,SzNZ p]>xsJX pZ:;@16 |ܧQo|:/ǚ^;,+ +pu@oQg {z4op^646rnS{ɒu4;,{ʙO=R})CWmGw[J+lќCe/8rtJݟRH5](C2lKru_(j9tyBԴ3.P: xjNt{9}UhC wίB"LY-b e([.NI\ԵK d0C |`?ڕg$.oH 6[UV~$MBj6F1uf`NU27 BP}v¿>iLh5u&lX)u'T2ۃﴕlYB- ]E\I 0J݄HL䦻@ɛ9#Ba%2qy&KրJ уd#ZD k,,v5-2.8fJ"I8`qkЕ76%91 IS(J']xB%uB$DgeHsSMrrr",1M$ŊHzɪ^"\vEyWIի~G޼:rD%ߵH_k=Ѱ"U}q1髜ÓHGz Oitxʙ<_)#5(D[Gj#]JAX*P7Hm|Uk HdHNѱ68 UDqP"M)3 ?W;ݞ,Δ?sރxKu\rvEI_P"{xB&LG8̟Ce[ocd;c4mYdu{~ɞa>S "~o3-AιmMHxsܗ\?ӗgmI#/sr|%k'8k}j;<ƒ%^{i6rug;lt4PlE)$c0rqW) GQUɛg{S FQ۳̦EӸk\)>)y).ACS(ֈQϻ( /PnIYz)幅A! VU՗rw)# WZ)#h'] )c8:.s}+HiIwoJWW?(ə?B8(G\Z4M$<\4] Iߍ>I7H}7XTS%M*L_9 BѢ;#ypO'eҩTm.)z a QHn-Ui6wTvS}T7شrPdP=IUe% ͹{H}Ԅ[Q@my;7WtMm nP3Բ)ˤR*9o߫_t)͑7|Em7Nxā0느"uϛYe!>5ܮFNa\&[)GJچ}jD#ɉ&k3Mj{DQ_sh C;4cnjh^=ʨjU iF1^ngeڠ">HIEGۨRv&B> m]*}6V9tyi1'.Z'yrzZW}mwO{Eݜ9 hɼ Ir)= ~ZسkqڂPwZ%i"GP'o[ Љפ+7=R3sKG0@DhaKwF/JQQ ]wgfIߠ; rdxMW6XKmBr LGgNoNAﵱ:Z1E}^`~5_M4Q7o]w6Uw]g3&ӹK/Z7^u\'pm6/IzX1߬M#6YQ #P :Ubpc CrwuA-H[%C oWYG0f29wTo )X2 Ķ0[7; 0X53Y XWwMČs~_.Rd^ggl+~5Ҏœzu}8rz1Mt1dD.-V0^id䢌4g`l4ʸ/.6xFd@ ɔ:8ӭϯj0="i`ʤ`4K$l{'I<^v|"{L`׾E5stPh/⳥SL*vo1 椵 }Gڮ1YgF*9 6*OHİ8Z)넠:V 0It։=_zəKce'ȋ?K֝{![nΟQ,٦ fGYZ!BW^,)1oxG0)VJ !aZ%6$kw X.:K/dR''8u_ül`TNþ©5}Ձ )v㰅]6tTwӜI>#wN >-Hg_,`?۞f./peg(4/sDFAzŘ ΆWF>znB?ܫLj#9TO?~QW7Znm6L:sl)}8NӰp}Lac:GR65Vrwnޯ8kz8v(qpJ\hzejxe9)}6N_/߈D9MoKrR-oYs=0gAXUkI#53/pznDyFTSWG8nwq=8Y6Rk#`8sOZ!7\KsNpm,zy\ &e\c΋\~aߧKDpƺR;Cg"#R܃IK\J\7s(s1-r%r1PIΥ,F{Q֥w'No1E dɔ!z' 6~E؞|dGwaؓׯ$ܓϞt̶sr${5n'N:)x2펖[h7K'ulp>9>J,ũS{M>9 ZU4!vjl9S<[8y}7cȩ_܏rO I~f4+iΟR1^:U*_Ȼ_ݧ> .hM~{ebTljt ӋHzG5pwۻΞvZ>hdz3n:nݞܫ:K$ztG&w_ gW4rKp0yFX)v._['q 1cx5OToiE\5}+ōpP0١sU>s5oI"XL] "Í]6ʣ\MTC“оjf,%˻Cv:KNJ.8/]t9 ^=gLy{8\y_/~2>E{٩9Kvź$eTPiI`yuaB˵{ygfL*5oR]"!+b@1~6/3?ٌ,jOÊ6e-+>_w^|埙DX>R}'9H(?*+V~2>kuN.u|Il%|. m<nT?%MDSn?jqkw*e~,O W+q9-|#z1x%3Mȝ\:R H$ `S_T>'%Ưp۰U_ُU-`|(#>.)`P'-p&vWL`{E]&PV%&@10M$[@oɦD@icM͹ˢ 4/ϕS#g+V^я 4:Ӣmz#_<;QL>]X}扶j9A'ja,\ >ya$l/EV[ٕ51*ibFw~\ &3vi~H v{X!F^Bcw+5džUѮ-x}[c5>kⴢ +yYgnH&Lҟ}9~AJ{mV9 !)᜹ۿ܉=$(K?߉M )>HLM@--]Dz$S5']GjF_,&B&aGKBVBs'?b%5}?eH?hdY#Xy$Qm/$ΣG$T3y_<\%v4Tg+lR)&?C~HM3wUTΙ&)')TrV ]c$)rŘ R1??7Gjf3)k ;n>rt꒲"~=.RX*!%!\HJq:sa u;!.,2ыhqPwy i_#}0eHKLj G^~ ] 鼐^yNytCE~Yׁ1ߥͶ蛟x@4/ L筂ݬ/rz2Q/\ledt.`|e@rge[2P]7d֔_=%kdQ?)/2|j&iϗd c~P$R~ךah7Wyՠ&e_lrkꚳlXql~չqɲke7>Eyݕ?gJfل2{ݲd5fB 7emcOB:s&bgUU-#wk0_YYKiM߲K9($U惧PiHojMrf[KZIBmEzEi"gp܎ۀ\rqYĜ\RY]x~byQaf>ɚ-ÊhZ/KPv~ Cn3YCKd'ﻡ)[vN"|q*s/+}j߿rOCэQS:VGV;tpdNI߄/ -4TZ4U—U.QBk 7~LmUhvSAuc5[E %b ϟ}Q8_U[Vuόզ}JJųٳc8TĵbE E_e\u(vdJd(&][pI=EW6z䜩 cm(^Ox18u?)41e'^WE5ҏQm3+Y%m4[ZJc[7-?1R\jq)+6SC~JSk¹'/L`l()yӘ*}:qNiqC]%Z+~#eBfAU{%(^\RR֔>W^5_Fi~|!ME{2I;Ɲ/*ʔĠkvcR;!6j"_kԮ(k":[,uJ6 NCq- OOB[5T20jUʖHRԺToٛQIa%<_r[*eOWײX~4 V|*>Vl: {[y9;_ՀkT%Q}퀷FSN5dU{A!+Uݫ,|ު}.VQw~CY_Sncmx=TeNw*'7T J!U+y՗~~ p/TMG5Yj=b֖_d՚z Ԩ>L[ ZzIr#Վ%߷ex.pU͔P{:{j/H\Ajb$'ղ &P;MT~OpW$T8;E_SRי2POb \|s^>Ćz6=x}꿟YıR!+N{n=5Z6t U]Cv"XlUi}?GRRkpiIpi0H+nKh8?ǰ5󊽦NkXbo9iPh>qFj!.O2tYYFIx(WTSdX .V^ jϼJy35l nIIiFX'9I:N@hqHsS]-t9KZwmr!a%J:k3]z=&ZHT6imD'hGw;OʡGd57b7F[9Rj*$>д+׼`s慺fՆ~SM o._҅>> , -3EsY%bi~\3*Hɵ=jSꟄ.%oi.>bZ ^ئw'rש> b߀B)I{@3o $'Pl3u5O^g9\oHC@_:MSZy3]1;)00 tжMגM40+?Wboi:?}ԈT old2.?~^ :ٻCUVwאYKOO}A-2oolXk)Wiv2AZ=kY?}+𿠵Ur䎖"i3k=1MZIf!r]ZR|7x:U0YgVju5!E9*v'YR7ZmTbj PJF mUta%VQ?~x~K=WQܢYײ@ _-^h*6IQOc#pVFÁj!YZ[gtFnI| Y3b,dЙψrЩnTSJc3#gtڎPGo5:y 7jjuآSwz ~0ס|GriF'~)җ=!"cͤKyc_;n{e?]ELoltINNꖚ+њ^l=͟|-\Wy2dd|uSMا΍~ûD(shO&saI#^UxQ=BR^oZccJ}_9)U X˶V_IZN$qUcl gzmhћ7,T4*c7tbQFu;~&BIf_κ ʮT'UNxtO@_f|>hy7?So*qZnӟ:QwS2°S F?8;x\?m%i[493\<:&ٿ9ݬM_6Ɩ:D:r]H4?`Dpq&ae¦&/XMxh/=Y7yd00wh'vִ].=T'M:lрO[+ta:Z\d849g雺 EB˹lL-Ym՚S}o*;'o>Ps1 +t;N0txgkoNZR TpwBUt!k5yIlO淏;e] VTgO.nӥ8-ң0ܖ쩆Ӧ|J'P硌WˠSc -ei^*@&izim9Ǵ8L>*q+֊4Jο0@H"bn`=}\!BYsOM h*hb oOX;%h>+&h1iEI,Qsӯ=>s7TtoC7mͶ͒lló nf\I$lCLl#JCݖkGVY~]ލm+.zYĔf{erk.FJڎIvȠ7`eR[6d[+5%۟ׯ%[ZV;zwA!vAݹꟕg:Iu:$8ؑK[إm9'e ϳBTTEkM՛ORg -dFvYβf4С͚]n3l_g=(Ml䷳wYɉ/xIUO졡4$پ+b9> lϮR}m]MUW)ÔI^tspH!=i"՛>^l(U2_V9 0-7bpEڅN zY:u 88[P+u⣓K*զ^C9PxM uhs!vqu #c 4ofrKw; seȞs|ֲ&-hg|xcэ,n:{RIU8>"sz11.K-Mfʨcى+O2'"8R 3tbݝ t֓yS܉!'yW$S'z/{5P!R)N]n3Ss L>ǪzVS? {czrKzˉ|.OUgӡ-4^.G!e)kf赝 ɿtrΔz5uLf%9 \u󳺷篏9_rH"U什Vg7fC/w6Oh9nĥ;>Lޞ%!OBJ.ߓ(%ۻp*THt ƻ9,mӕ!wš['.s7 ߸h)|rcObc2 bW]$TwA?|0ka)D~Ѭ^?oYkN^9 KtsE{ur:C޳1&e̥k;boYZY7ﱮũX>T_N(I3ZeTVۉ(3|nVȹam.<&qsؔdcn{:m#z{MߙznVs2ŠUUk*K 4ʎ4o}p-+r[b_MEeJݽNeѓV=V_@OŝuKea:},UjJyLλQ>ϻw+~}r{WƯ% |ߺ;;ӝ`0~@%v͝mSJ́鼗4]=<-Ky^93xe1YcY/f{ =J* [x}Gȣ#vw}?ÃWUf<}sؗ>C71o2A:,,bJYby-jOX)ϹOBN9 OlΧ]e:?zÇUEcᜇ7]n݉#8y=Oe,CӒo հD\ _^" -v߶*|Zi5nț y(96+9Xs.w?@p`cW]ߕfʽ*M֠; ݾBijbAMǷ(*4~y7a[e_ƯԔ3}Oݞ~ʍ{X#^9Tp'w`6w*K?<-~nC DX9jp4r c ,IT#t^BՌ?ċ{\ ;7Ӆ=Ss[EW"yv}Q<>_Fźģ;ۿS6>4/dG?pMY6ΆeeٷV+=5ߋL2v(L}lk}(}54x49:5YWsfd4 OeUH2b.V|(O `#=;ӥnV~M#Z@na$-}7 *_\ ,\(,,G" K sA/l%{oII7A26O#V o7$Z AAtc @\mgВ)ݞ֡kKI>.{,q8pXXFyZpG_`ͿlK]r7  N~|;؄x)A{c~.BrZ_HvrZ<͈\cѷS:!~g>VGZHμ{'=E~';hHĶZȳ?=YiYk]Ҷ}l!w%ݽ42k>9|(gZ!Yh09Z> j>g*; ah ϓ-tj7 bC5f&BwHȵ χ:Rxy;M`숧2XoCYX_>?5Jdxq-TbA(Q 0?ѫqBfgتo{-v٫gb o^Gq o-O93h3ŷ|f]LQ#ҙ5?>Wcw0jL=?3ɐw"Q˞3IjKMy֙keQa9?Iw *aW4I Mf:F+ա12,3Naf\+aCeazY/ik 4J1]K < O/J~z-"9sӿ#8Ǯ*䷐\St^ ?^x(.LPIn8G݀p7V\+=~otQuin;E_&[G'{qE*{J [!c $"B{FD {#*B0I9 aЈ XԈG|Vnȏ0Qܲ[񸭁WhLWVN ҄ .b*+o! re͡ڑoy^[ED4xG>k)xkfiV$/ȐpLk52!7"K>=^m5yn\Nh>*3{G5WcҨI'Gl#1<̄QQy^wCQ=yKoFv>5 ΋jNqreuiq37Q2 K?>E|a39%`1v=M_SG?H 3+-c"Z֌>3-|,Ҷrĉ=:aJ>k}ӣM S( 0%DZ #jL:OGpyc;ڙ$yY0g]WX&c|inwcn'8clgqZSselU-%pLORdB YU_1\DbovQ~e}r} XQE*Ŋ/AI[[#ꉱC4" Hk~g72v>o'X[CcCŘP_bՒXNgx[CN6N,E,T܉n=uGVdo˘iSqU+q1o]W㌧M^( m n޺_Mml^-Nnq~*7gBFz;qm;M2DΥ"yS< x{7<`cB|SwrH3>3G6swu+12E)"hω.o-AXry<)/{2&?{<6?ac1>O񧏡^<Ϗ_ߐ'\/ aO(Z <+[l^zﴣqRn'hӯ>HJtfsb/KL~%TQ $X/w%>x=J5TQ^Yϓ D_dxT`"eeH_L^,-Httܝ`Kr%qC`գ4q~QًDTĽrB_׮&nOd P"N-a;tq$V79$K=;ByzIz:|Bj#.W m+1VͯfTny^[:5XgH!5ގεԝTj{T'=aTiTSi4۳VVit4Ң﫟Nk~58ę4i3/V5)QLQߜnSQX6nRj  w")PgxsQΗڬ$Gi*BuwH9JEfGe(9jrǜ@U*DG,<;do"jP~9ΤHopu"CtI)^.NM2~F3lڿ=c"EщUΞ'E:l2A(ˎu Ƥ(8)*wYe~8ʼnu$R[ޗHPb$soykU$(g’$(qL$Y+GqQrlߦQ o4v^^yAZy{mbualbC}(uC=14;OK%A$1yں5x!2u[D™iq"mA*Vd^(Ae!wN"% q40"ɳᆳnD(/oU3"Ԍc E$ʊ%)"G%[m!*{L}c gQQnߟ;HŘʻ[M(%h QFe2^3b Qp5!j)CՐ%^j[唻~J|:0!ʅ|׋~=;!F!{x;Jl *!Qiُa#5Qn!ge*z& tuvb+ PЫ:2FǏwP D._@r`Y"@P8y$Dޡ^2&'C P+ߋP5c%S>UfGT`+TIg9 z(o #\RUЍsTr(3@$J0J-LbѾ ?/'=5$3Ln6QFJ wPY Pjc/zI%BuḤPkk:uS(TSz = %f\^9Bս[An[vPδ'>POr[QqՐCׄBa.kDCfKV(Z39 T}~01 %2! q(wA{(hn;(A< 7uumqY^A^F9/?7< Ws(TB_lGh& Hy>0NA>ԞG&P\3}Q^XJՙOQ(\I*K 5kM)ߧ&(:!W$Eh{P&\ž(gW~}wnw+ xt3 ã87OyP({!v(lgw65 X)$+2G?fjkBY\P6BgUe'5+ٓ(7=꒬7]aA_ 6ŠPf֔(T} *g: U2G=B^RǏΜ *\F~?0 ׸{B>NB9НG%EPıl( B=\SFS̤Py(T}µL1b(T{G X2dEqlW:rO{ֺ|Bqo\uD4>@vxmXM6~'tyQ(^aS*nP9yQ(bN})*S0,`Ǖ(#/+G\(ԖLp؞Dz?f9l;X? uD4MW&va?mbH][H~ /e.3²o+I>b]q5X9b(Te P5mP) TQ IJd+v~GKցa*J>pd⅝!1dВ0,//ƿUl,޼(ڪp>?[N>V6GN vzV? e&Mݐ:Q;5<;`ZzL`>YL B@)"XOa,x fUknQ }7 r9F 1I<`]68( [؁a'cڜaoeJްGR 8@VX) 1` {YcE XXnd(T>sK_/1θ[Yhp %g&OFa5M?7ΐ߸ȁ8OR",l?9#$󒾸`} Š?!:} KEojR 9:lšh9 1 nb?lJɛ7gm`. 2Y:8;0} "nu؍!*X;/oSiew/lR%5W3l`rڝJؽSA`_yW}8|O9Z"/,émK@y1XrFyXŏ^'`4H`+$mԴCLx:a,1EBmհeN'ÞͅUx* 97l_iS#z-Xޠ5E؅#1HX[ae'~Pk:dGq BRsTX=͍O`oǔW" v)4jcF÷aP(`ϞnJ1ˇ ? ϊ:zz$3v " v+ e}|,)Z?: *¶QH:]u=͕y88 k7 L lyb vt.9QX쭍C|+ly [cvpj]XdvE v҇8vF~mY[{d\iY pW68^>U >pr6څ#XRNa#_ɂŰ,-nj7`,ܯԿ;[ƨt =,!sTTg~Pw9vڶ< VO^'Vaj,,{h) HX뿢˥G 2/&a| EA0/6}%W {$;lMN.7؁1cT3`DžZ`a¦$7XqrX.f[K4vV m{%ȗV䄆>,dgF|X(Pv+p}u}wIք}ZkjgӀ-jTY P\\ eػ+`ђB^_C`o> -L % Ԕ*[1u/ F=S&;u# {~Z,K8_8x_JR^HZ#kߧ( OȇB %. Y1[0KƏ(7iVSLg?Wa-&~AiIX^EeC.ئsެ8='.r6"ƉY{>;uN}W6Q r*qҲ)d]:'Joj8CYa/[x1,2s11yPgn9#Lv1N:-X7qx v_e?&/p#~\qں9y=-,Rr8ޠh`H>I7N^NQZIi-s_y ҒsmףqU0,{%췰" |.ssՅTb>N8Ӥ4qy4O^%ku"u[^8uUq%J9p 6};"wps%p'2QpdSVM872p<|iEQ_Dyub.$;pźUpt!vcpt8d`}$SQ{'İ=1p*Xi96;]s}RT68 YtyܡstX'Q N #"ϣޫ8g# &sZξ%B%qJ Jƹ3< 烷F8E?WŹ#\*7)q}O~N[8U:tžù"gFm24np:P`q^y5gJ _Tp^GvP gIyDwqi$&~vyKo[8ނ8pڴę7Ԃjq&:D>E?p=+)5S=f-ЍD`hN`9|p^Mctfg8_(K]i%t 8Xg~,N qg^ UD*}93mj:a8Ip~cP8LLaP9"~~Pxg s;̤43uA?̨QxGںq=цgmm·8yivp6ᜟ]< }8RlWy"g]~vqX;y1&BKëF~ ]s .=<T-^C"XHx;$D2&mx1 87❑Z[bzZ}r {ޙgx5?U5ƛ!5wqyx<;|/9>7OTݖǫT0^/>g搱eȀ™c 2wY < Qk 'W5+;7Dnxu{^wĴ3xϗaʯ6{ס)xU╡eûyoXdO{Lekwޥl!x˖O+Ea<XhxL豖xC@'~S덷oD;WwR9=owo6x-FrX7By%oYF>1<ޯmwwZob.g:x^)x4ҡ׾T oB*^i(]VGDIaybr%df[H-«!WDqƫbxOKa wޯ/'uW ^Fᱯ-]ɋXǧ|ƄUFQǾ;€7'#cndk%scuuM׺7~rjcYE[C׺XecO3[8Jc|XccE!ǛҌck/uɱdx-<=X6cO;tDW}Xӷǒ>+XcTUD; 4yc{w3bU}!x野 =:CcM0=VEXOci]MWs_aͩ:αyǒ;w,ݱzz+{V=cH}9}럏=v?66XcOv֏ظ=7?cql XFd:e,c.qcq,Oб|{]c >vM~cG=VYثd?.ӱƴ2RKt!c~ul3O؅c[m:ǒ?ְ;oPlsٱzO|.=c{ֱnǒkx؛uP.&pXܱމ<'X3DzKtcw}},ױ"Ǟv;6Nn;fyc笏ճ:ű>cm38[X2c_ :v8cU4U?vU*ǾT>D+)#9c/[$slMRI]j{U6c #t+Aqc;Ç<"ﱋ<">>1Ա_NXuc/qK~,%ec+rcC8V0D:Zcm0qD3Cc=?">F D@ܤ:1 Qq{AJĈǖ"F" 2#.A,DGD#2#ۆx1QqvrD_D=D!Drck!& ! "#">v 9Mt DDQ qدK SC]M@BGlE|2b&b,b >: "'"=")_cw'["D|Xx y,$hPD?DwDDKDD]DMDD9D D!D^DNDDzD*DRDĿǠ~! n .#!N!!  v"~DlA"6!6"#">G|!{w#^Ax<9lL4DxX(0P`@DD_DoDODwDWDgD'DD;DDkDKD D3ӈ&ƈ:ڈ "FTGTCTETATFTBTDT@GCEAFBDb"PQ #C^DO!\rCY!"?< i i'/_RM7%?$aoC$1 _R|#cGgg$OTtdw4!RτD{Ngtd`Q*YDS,4ģc6UjKb-e$a^]lgPWj"ByT@{sa.h4TXJR'WqC7>fPsC!Zu&_*-%)QIeG }" }ILՀ">Uv{ro(AOI{@G~; ČTU^w!w)./`UܻH@tNKj 0qZ%w/GLB{M C'iM f`fp33 l. Ȯ,ꢫZz7>>^~ Y&nL>˃Mد.)ހ Co1AoeWEQ3t;d~{`ӧDc8׮2c;ofFBݷ"|(8$/qJhM8Ц,MTWQ,$EiɃ.3WQQ5Vׁv.V [̰>u=~>h=ahwFUP 3đ2N==p}(r]!+/1 |e8yS4Чt$ؓ%"eCOR^{_"D$xwqV2j9)#lB_zFC @;OOp4TgF81?k B,s\Z@ 0 ^==;:x'x0} Ds?F@{: ]F< :gk9u ?AT=疗oN%aSOboU&t pD=?jKzїi"^%Xf(u]YSH遺FL?<@K?wᦧ@as.ͼDnzJzz.ڙCx ]mVXm m|djQ$y@Er.˗']FI#Y+@0+#(V91'NHG b/Q=qS 5:P}P>Now{x|-@ogKh2wJѫG̨-+ʁ֡#=2B<%Р ߮xj=C4 n u+dWgl[jaO?Ս*.(DR˯n.!M~)}K/L676 ^;Y YlB~Ϩ=;KNryz[}L">5evne+>U/w5L)jk`Kw@q1( ijP683d:'l;8]$@v< IkH^!_j!B DBe[!?w J:FHd\MͦPdhw!ؙ?Wb m*@r_f@oTVSr@{T\-zGGf3}G Ģ$ %z@I'n$6ԳRdѾK뢍T2ĂXH%N*;YD`¢y8 bΛ>J 5~(|S((_y9~&,nHv8fos S l}{[[X[@}2 67{o,*zh AUV S' W_>@F@эg3dG5~d04/ m9 QV\, ϸH.uwEӳ!ykO'f,ËmURߘMG&_8zbg)rئ]pw ==;xR<N()+ԐO')] nO1U^?b'oЩ)J @vB C.u߸5]͑_@ޑZb0uKZ +8UՀcw_m 9GvdBR4wb9װ纓x髊rɆ;c`lL-Nt\Dr[i q]r(thYwwu, _@"Pd |)eP8m,Hha: >]Q*Ҽ*kdc˪RJS!ϲ4Z #Kκœi} 4_y\]" mf'.I@}q,pbe%N艋 ;vno>?Q̷N-L̇EQ8T\q>A #$ǞͬJ [}Xʅ/IMgbIY q[@([<'z@nPMrRXGv= lDN_z!::6 <ݩ!elV9zЮ }yyǵ p=,d_`hg5Xxw>gl}D& X*Y6[ |<[=J@}^Z >=J^vA*#axmhabA)!~'Z?s .*hy/ P[_WZHvz%):'}!C "t,@Fp0ȰiA/dzyHB_vL!{ o1@pKgQiG 夯Ѝ(k{J yGPy@;ͭv y>KȽxqOp#pmx Yux(|7=0mxgx9*+pY=Qc>z2yZd;(J{9ޅf^7O= }`EQc@'Fd] ::r5z'}Ny 6OPE+5f*zMհ3/{]B)g~nH7i"#(3z'(Ԯ*W B:: {s59?;SmClWK߹L;XaI,FjV,Bb? .Z Q*.?[uZ!q 8/GDe/5zX>jZ X.kB9t2#|F;w0,&c1 Ͽďp_ix2^zT!n?ݿNs ׯxoONWykA˒~%: o-: jwn M@eel}].&`J:&+;vT1$7j?iDX&g}|&@9Kb hj< e~y *URCŶb;qZMX&pH}b(w ๥ک+lReᡏ'ts=[)ӇkquVu@!0i`;P&Ϭ]yl{q!{xVȽYv0̼(#b1nN^q&DO*x}" +i6~!_Sow7`-aPx<-39xl$~B]~_n:O3HgXzZK7j$,̲/ f]GU5ihWOfHFt8{+uemvZ'S5RIڣ+Fx˵s4b=]2NiBٷU{jiՐ>8J&HUX&դ-EX; ږvRӎP+Jk-b"6ܟCN^6%e+cI%b,xy2ql]Q#U9d,D3;جcx-^ǛvܩnA??Sƈv]Ƭnn='ւ [ۼjJב6oo =wkߙO]0a=ݶǹ)9,-l;cx!qY-b㟛NWt "k~{tv´8-@4k8tn8z#>>DMql*B[kMeٮl9tնm|(Yo&9- `>:a*<Ё@D yPƳnUD ҡ: VHTO*즊7FgIwJ8D\q=CS-$1܁[[/XP̅_/o:qAu JPV8Y0wAAxe-p873`fǂ-C^Ƿ\WzM G`_Z ZQ7)D_'mIL]io`:94\Z|7t~4mYb/q^ʉڞMZVԈAmp#k>҉ꍿwz*9 WC]?T}_/5>Y+ͮ1 )2ם|~EVƋе\x1mJF&HFnsߊ6+"x\&8Qi-`&ǭM৺&P,Fݱ 'lϝEd[V -6?Qfu崁/?Moz[@ם*ګ'I6>:ՁM`h#TfYOXpMP)oRqX- ߖ&#Ma˱ XزneU~ uݮ @pI?( ^5W*m@4W6Fb6R8d =DϱX,i 5lGK@K+p^<ѐYUa ۻk0)8/pZ%}HTLǜ1]T C{m ϪQ`Ma5XeA3M{jnuWϋOA'="-?\ s&mTp.XKC5z`gH ע(54mZ']ao|`:f. njcT>tJfݺzH<ڕk걎m(KUfHh &L6d>l \T 1Ä8Zh|ܳ9?6) rݠ~'ܩ|l? u)m8̖roHa ~|¥@{ -RS-@1k3DybǴulm2&**zSw"ӳ{;WHfy;nU&DX.XY"|;x|20S&2pT,4~u$~J2/O.LdtԶ}p*!YQɗ 7\"i4 foP:DiX $")Zk?Hs$Z" N5tyJ,שO嚦ELjۛ棟 \rMxj;B|vY[ Ip8I5E#mfw-;u<|EǗ,y d /W?8:6iAAw2x6YϷfXo+ⷛuԩ?[ iųx|bX{(h\o 8R9|z&մZ[hsӞ^ؙj6ArK'k}"cIv7ge~x?57TO*p?@g4MK=pyDWVgQC +ɇ݇'ӁXVc - ^|%)AwAtjM'Ckef-÷Tkqq,\X驿1(X|Á>_ɵowi/,+m0 {:'zHiokiK9]܂򊝏,vJ$=͉9B{sa}lVOrI >^& OhM^ޖøKpNj'@9 o?;$x{TLyxwԇ-ۡ3mG5_?|Ÿ{~$z fhn/a*<^_e# _8?=>Z?XO.lmv5ׇa;@%WRwx>s:4g >7Ogcl;Bs6 `8ɦx=GSs~/ɐe`D xAb!o tpםYड़@^II Kݯ 2F1&9 zl#t#^@ H( üHnjo~]ojx2:ŧD@7wL@n (ɹ9@r!pN55zȔ-@9utlmoityQ&w4 2OcQH(FhAPW&OVԫX Ni_eHnhL&*xKu(pQ:zFt i4j6כ}1^M>ej5tٛ< o53Y,qKlK^h<^m|_}*e`ʃ*;݁?/w|1]Pƀ+gǦ1B :)8LsS6O6|oGU_jϊq$9M?q/5+tg*epq:|^ qSAg;J >}&^ޔ ~e)+ mWGh- Ep>xIl,I.z-ǩk@+,#p6{j@pȳĴ elͤ;=!Yt勣m1x^e8rEc ԍ~N? tmd~^0\F4\{tv:A H?{ptNaAzg{?"~žrM%z-?łWEg7H|bjG fh]Wo-!yb {\Zto|o)!W4ATWo6 pL¿Ӊ–PsVğK?#}Oo^Ȑ?р$L2L`ePWS |"@ ˹Hf>_v.С.3G4^r1`V۽u;d0 P;wW+ AYMܔ6 %w I %Rhn4Qi{D#,!'HoSadq1r8@jҕo/$%I -6>n}cP-U4JƶX4]s Sz/]ٶ"0nQz1f[Ba>g_MˠsHCsD Gkfjϓ2YS痁NU7 !"b  /!F"#!":": #JRB@HITS $QM$O HZIT"3HZITk#$Q-$D EHIT!j$Q=$7D'DՆHF!j{$Q$}D.DմH: IT; j$Q̈́$_"D$Q$Du3D~$D0DզHITBH ITs j*$Q$D5 IT#j-$Q$;D~$7Dm$Q ITcDu;FպHITg I$Q$D5!6AՉH:ITCgD"BHITEHZIT HZIT+#oH IT ju$Q͋$D?>$ $Q-$ÑDk$Q$EDe$QIT+#R$Q$A$Q$Du"EյH CbHZITCאDuFאDuAՑH IT v$Q]$7DufCH9CHITw#jw$QIT"jE$Q-$3Du=^EDu*~$!$Q͇$D @qHIT_AH$UDuV@ AՏDu-fG՟D26@ղHzIT #HZITFgD~$D$DC"H IT j"$Qm$DuCHzIT"jG$Qݏ$ّD5$Q$9D5=CH4BլHIT!jIT"jz$Q$##D5 &@MHZIT!`$Q$ݑDu^BՕH:IT; q$Q}IT#F$Qͅ$D%$Q]$D5 $Du Du6AHITF&HZIT#Z$Q$#j$Q]$ېDuEH:IT!j?$Q$?"HZIT@4H#nFչH&.FչHIT/ l$Q=$Du$O 9$Q=$wDvEH$DuD>nDH: IT kH:IT_FבD56EKHD՝H$@9H-6AWDS$Q}IT?DDHIT P$Q} IT!j5$QIT"j-$Q-$ÐD5@_D5DYH IT3!-$Qm$D>$wD$Q-$#jr$Q$ǐD4CլHIT"OH#BvHADBSHzITS#e$Q$"jV$Q$Du+fF4HIT C$Q IT!v$Qݎ$yD+>$SDu6G{H:$MD(AH IT[ jvDH:ITs"j5$Q݀$)D5.FլHIT{!j*$Q$D$Q-$!$Q̈́$yD.@ղHBHITK j7$Qݎ$CDu5V@HITDu?f@zH5nA~HZIT#j$Qm$אDg$QM$!!$QM$wD$o!>$Q-$DuVBHzIT#Y$Q]$DA/D5ED!N@HITo#$QIT ji$Q$wD@խHIT;!j$Q-$YD~$D57fAՉHzITDVH IT[#kH6GdHzITcD(vFHIT -$Qm$+DAHIT+! $Q}IT_BODj3SdFd4A=^uA;A;8YGȲ,qMGqMiT9`,xn `NogKlW ={/~o PScY7]vwߜ0~ؓk;i`1wwm5k}RcgǜP!t9i(RvOJWrz[W+:d ֒:pAl0>@*l@;ؾo-/\۶RJ"vY47eBr~hrwsдHyQ4"s)*4 th}*x]yuS o4w꺹?ՔX{qUSR M&:jMjLM󚛢jFh5Kf i˟|IYL@aḉ&crIaU=l Nt/b5IБk^^s&K)50~>K >xyh=V~KI1siB@~Rz}7fJ\zT0&7+շNъU%O7ݮ}:|.;ԧ@SN7at/ʺLNQ)BOϦAg4raKyЃX]=-!hIUW&hjW shDGh=AFnW-م i>j+v| tޫShTڎ)_x(?Gc⠱ўART\F:[  kj ?o)&;zD{+'\e?@ץOt޾u8[멄:e~!Tu`i}I﹒ H5 Puڵ:{Dx. *b^+av=1A UCJP(F7m 3%HtbZ=ҷ okɋw]M2mAN3͞R,3͟n<{мfyFG?vg^76WU]kڜUm5v0|N>Y}Kʼn`w/i t|f{u ;/%0WƝ~{ŤYFCf #74$'9V6 io& /n9|:xĞJj/l[=ܢ~dL#AL Yw7. 43}Tslpw_ ݬ*9o!{XJ@ޮ?a<):c%bRlZ1qu߰=ZIO`grW=Ĕ&7FRSyYy.1y9ne-(hK "hr@|WMd^/&êDcPnv1GO#"bY sNĖ/F"eRv|>`MO`(]}JLYu S-ͩ!&p.NUID~QKhTTqQ!$ ކ]#AJf\CRB.v{츫 4®uzjaHja%N«{l,j|~ vOl nA rmQ/׿ bGAa* mbZ!q Ex${tDXv.ºW/;O15vY Y݆iS|۷6=Z[5&b4YqVJ8#Zrg?=q6 !s`su~[%F+NYeaې1pRs: ۆu.UOIjt|3>.ϴޚuG#.ϱ޿ w1Y\QP.\kNE9E)\_1幁!\_噡@H.z'\4.bpyεǕgLo3\yNK80õ, +ϪqZWYm6bqlN箠,7v8h?.ϢtgRsqyL=.3qy&9.1Hyx|/ӌ}9 _eND˳qyy\˳<q—ro3@,ƈ:|\, D}u{o?82O>"BMo?B * }?8I~ސ =}<^?[`heK8p>ȆqN@] E9y U`v8P'OW$زyw,v5Ɉq~לz_[뚿ފ=1_xa\sNAg9մN v/6>knِġz49V*5vվ$)/>} b_j*NiD5k~gY,- Rc}yˍʳJpx杺B4ٽ{dO%oi*U8~ My%K& gf.+K&Ua6Omh5K5|SmkI24I#WQnN]3f΁T$guM2@@Ch)@Hɷe'z朦:M%-bl9wѷ'sK-#{ ml 6/9V=7LF,`ׂ`æ)6ht_q3KB#3A^txIϣ̣,ahYtt3lzP nm˽a9t/>}]G k>~oC[lN΢%ϡaϣia`,4 vtb\A_#_+pp݋mkދ^AKTa> =f?:V6 A9=]oOQ";D `F_+`"sM){_ϓ^ z-R;93.񇅾aE'm ]G7Æq7ex| T>N,@zS$IASF}=E5LDB?Yo%Wa^"` ,7[,A\]7 Ga-`З /x=1:ֽ} xV(:xY_~fn =EVLVs|4{!U{TV'O6"[w풎ѭCѷN\nKanmQsW-(dc~F؄.5O[*Y-v3Mg:`(u($ 'Inp&YAhXz}u޲5:GWtEǗj Zʐ0(q~GÚKŞ_]K'ӄ_]2aW܆=y'@YZҙLysRP4aĿThl-T   G 1GإjΦ!9\0.hiL\{1B52ة &nZҏNydaκ3 HoZx(-dt Ə>b S1_r`y&1.(b1knSXLK l;Eؒwo121l*lz Flx+ƴVMop6Â0m5fw|'f6lGm:X#n<K #N ?os 3F>[0/bBay:0ﰨNP[, v #1mS`_b`Qo1?L5a\qכ:)ǰ9 @Xט>Lt:St5cjX`K0x`p/H1"P+թSj7| 4/ۯ[kpu9g'n _qy% UTփ/Zj+ߺnLIۯŜ 7~L6~QhKۯK"St?X)})`D=oŒV/Ѽ92VkN/I\ݭ2_#pfIIǵ_Vp'KY|gkj0_qPzO\WMW+Zy& ~ /گq~#KO\Y\yk.*گ9\EQoH|d>/>*|؀ ~mS/z\لۯ*X)lZoh }]ʝFۓOaQ31i4=4z>~>?em5f"<p}Ӆ.S h5Yt }͚;??NvgY@9{6| ,>? ;csG3Ei6v#o?h}~ьۯj'\EwzZųaEX->Տz +ӏE+3`Ջi qQ5GW#Xȋ7A<'MTsZ{_Wwa p~Aw֌_0jw _ҵ%_GjCCѰ8:8 6|-{߾;%q(t7 @CZz dmI7ÕQ0,2 f%? GS-i@wxFKĽ_6,=?y-E lzebOCIa=*#S6r_VOSp>C7j8aKâo_stӿ?@q~<8n: 4$~4 =~:>bmC_iK6?q~%ѕ$8ѫd8t$fquDvgۯzgt9nǎۯ#]M _~U!/~e!)_=RKZ~%- ͦ~A񿣯=wGwȿJxqfUQP|bwј@VW M]U9 _{T헝X҃/ǻkp|~53 nvۯ6]ۯ?M ԸƫW5_;T#/`8pnyԉpW+!+}kNYZ 6õ_=D^M7:/Ʊk4#O/#l\Uq^~:2õ_lگ-^ wQSHH;H K]~+mSF: t;62|~~-)ŷ_PS$z~6߾ߖXۯQC]pwC:B-e=݆\o_Qݶ0'\`þb ~`cw㤏Y,FDvIyYc{=zI'Mk_vjInǤ?Mk|* )Q>a`1"3F w|':X6LMX# n#K NgX.L,gmLV3,7~q}$V.J&~{wnLtŀi/1(أ7+hMwW?۽k 4`Irۯ4ϟSҏ~%GK1oa嘠'4XnJ`c>_oBq SV)' oKb~CگlA/w  (ĂQT_H_07{'T݂@YK"P ǖMG hnG}GTb Nz?" u-DxQQQ kBi|Ef'x>_4SԄh (SC2]Χ֠Y1tOnv? %U$ػǚ}wMm J $47L,R}vHta#p:td.n'D+~NAѩS2Ӫ٨Hy"6 |P?~ݴ|ė*8x<Q5/ݰ-W,cTnE#N{ bb"֌ǟy؄bae9`WV9ؑY _|);93DQ9`Ƶbu]?ʂB0Q .ORF"xEpiJ3- $aj}&ۣAd7FCBW=O5 te$${ɂsf / AE a<,b&6 y{NL4rmA%[Q۸ aѪ[˔y)lf2n}mn}\J0 _~V4ODgtfWVj1aT|u_˚] sKƧLDKo>έ5CVdK-ڈQx~^qAmaoWd;ez/Aн6b%SnZhAՀ{6v.Z'ҘO:W߶qAW{?{.aϸ ~Q7v h*QT oK7U{l&7QP N?u?~fdMl "bZ]V궫耶ڒ )GɹaLV5R>VbB_[qDZ_|roH@ y\u/pQsŠdx.U<ߥElQDrs|M 39Rϙ)~<'6e#`_B`+EŴu(}HGL zGxf]W].~nƲui`<#!`TVN~e~!hf9]Yw(G,~VDWm3  $TG7&pȘ&=ĘRZ"pS{_莉ߓGR_ɍTʇ,P\_] UMPbޑ)rT?er ǽ])RJ+R'8~ rmͲ?1E>WdMdtan&gj]M-H~)tG{dхο˳_%euzJzmʹkiI#awE?Z$MX.-&*J >F}Mx]Nn /"|Z)d("tsL?KLLm#3~tj5T0>ɷ49/yA%HƜd7-e= X3QwN}{{BWeCܸԑϿ/n'/]/TyOŞ_ l}{wb֗㾄Ŧ)J'+pN]:q[zGg&@˘7W3cس~JZ͏Q&ʎ![c#'#'K!zTdL4(9{ϩ@ h?4dx4^DC=\$:MyRa"*kmԯ67Dvd[JpzknTm޸x M# #oD^|q!2Z+%Rdi ɘE7#?1!$I,`ie:jVXy/rპGS&H?BiaNԳfBV+Sk\]I+ Jo;N0[3zg U]>_!B8r&)3 3&3W?|p4lTS[hv~shvl( R1psXsSPC] lH/֡W!:.WZѽR"\BF"d<.g$U4TcOZ+f+', N|c^T0@ݠsW.ki4ο *%d$mQ Iк;fAq߮ SzȺb=MD)*0cGSBqt{_%7ZJɒ X~\o PU[xcsz#]Ͻ]<={c;N{W|g}<[/rtS}|7͋X܌pnYq=zn)/^rPz dՊgbU!e,n ޲ecTlrɧ$mh7REi(5JGہ0"F %%9W>Wm5v',}ÍiҬ[Emnoy#Tȓݦ([ٟv}qJ֭uu*7fu=Ӗܻ+c9 jF+<-jyx@صlV.4C.+=7^R\p}6e3h9sN{J?y/9﷬ E874*YwH0+u]zp7IF7|1[ĆsqߐEJ#[lj|^$vCX}vx1%?␽eЪρBֆ9ȿY thD2]ǐ$)K_zUv^QgSN#]Jo׾@v_>T3 ,sQlbN1{+m L Ѡm tt9wc)N A?9m͠KT|VwY /$o^ MtTHs جtp'}Q^|Ntƺ-Ĥ*EH&%_xKu1hf/ ]ˬ T2NZexZ|h~᛽G&a=+em"V &d+m˫-O~<ҌZe F5m9RX_Kpv)T=g?F^.7m+Z0l1?**Eˢ*I>(WyK6̯8Yok->WIUŖE+f*\zv;ffunǢ>/>$~c?/ ?ְ{.xFPPr΋oz1AZIP35pQ$”@Bk?L1XQ6agFMӼ٪YN &ҲbM c8M\]%4/`|1`|dW" s[w}2yf{FXRQgDyK獈cqFo]Zd ~1~]0kRh2ln6[Q/L M7i ^~;_'ioN|U`xx;Q+ CyWWO/>_9eFZym5K#[^S-/tDf.Yh]袺]1 ݞsm77uSZn((nV3YKKY/6]M̖(P;:4+ 5tj.xzhx1A'h;[-^v QhԖ5,FM$<SkFi\ۧhsJAt+ h}NdhQ,xm /]Dfc-4G <\6b៳d˵@좟gx6Zz<>YX_n~+ߴ| $4yмhl-k<j8pֽD>P'뀓;: w@V9:;:&+qMZMA\ `g@ۉ5OX ^np+5E@Wkp6enJ2AMtry=}}n,.UWcT{o+ϗ#Ǖ+[JE>X^e*Z]]Vyu'sU2f B@rtԩeeҽˀ7ڍYe`|C_OHm,oNrM.o̾,.ƝKCnӨ`X5|<1%KYg;A@IDzs2y$Y ZT;y˗<k%gЯv_ xZO pE{b s> g @Cr+DH{>\晱Q7 t*"^ߜVlo'0 f'mIWfO=U gˋj%if^(ܺI>a>fv f=a]@ߓ?Yi@ 40l,;wchZY|0 G៟KN?2 gL[M G{=zQ4pEm*uW_4_N}O9NRe3QC?nӀ|Zib4t4u40zԟu$s eM ӧ5gS?x}^f^ if4PQXk7 7W>~)woePƻŧ]MUaׂv6{i Zysl}B Q)ށBon Prsf prz fkY#"OBNU^O7d rz) s{; ʢ&o 9"y xFx<6=g6?3 γN+kM_N! D2ܰ1 SL(ǿQO _\ZHoZ6&sQ (DE0\x.LPEkNeay|a-pǣ; }&_))NIݙK!FU?sC< 9OZbo"!hxi+̟`urŃ2l N c1>}rUbd qPJnƟ$pN.^uNe:}6ggUc!6 NlZ~x7cT.pƪE ̀y4J(s.S'Kn\.Yf0c&$^Qjwz9ʄ/S'ׯr9~I>bښ2ax-N"VcHipuϯj٪, ou3Y1 Xfm w mA /H:4$*74V jj1 _oM_{(tPՙ"ZSMZ7ϐt @b[iK3Mǿ.j*$kdT~a!FsPFRݭVQVK wBU+VjTnlj}tXӖWaȦt=E1;*Z(frV8b+W䮼S"Os.1 '>UgZduy=##n}6b@UbK Y$qq<_ɲ:=kiH%eV $BϘW-[LT]0;SxxF5КR"W*j4iE4i ć>|pykBJMπQgL &by]l5Oq_c,ÇnM;4_;AR"e:E*e]8<3M%U;GwN{5wO޹vʷ}qq)w+"# /ЉqnޠB){{N:$l2OSHoͲ&Xna2@f}s ˾jW@z\s?cҥx1yrGy7R+TIHiB:2M3˾fӻ%x)3j25g)Fw z%'Ӷ.ROFҩ̑Sd|A;9v4ށO&Jڱuj/ n9Pۯ ;}0 }Q  nRGfE/%\?`}R@ꊣtpO]p|$LlۊHSU.zB+_ʖ )JH XvQ! 3SqY8vAr$x, *$\3+!@?uE61TYb%|.`e<` ЉZW< H/Hq+cZǿQEe=RYP싣 D/1]X ;n)>Kq`[Poԋ5קd`[f9Eb+KW/;F"w,HZ,AL ߡ&@k7}"Xpnp0 RO1,|,D_|U,P"'52!lsB@4I @1sBdc4dY5eфc:O}zXzK6 Hx铕t@\}H6(($W[ԦL/}]Vx Bפ4<~z0* ,-6M֖u}H=rsuYn1Z!#W. k5}joã_RdGps1ix竩;mKoKK,{`eZC6'-.T}q6+a6Xk{-Ыj * f$db2V٠@ixK6yE6K.}C6|8!JvvdM> fM>e&MdN3w^f NUY[ng %Ya&y`qp5 );t$ CLh]ȡa\6Ũd#s 3;+{ P2W 0͟! +`ք9,d'-Xdw/7O?<~\^(N]_M+Ξ~p1$uhLH頍cY:5 ٘WSU,>iwOi;ںR`@2ɯmiWl4Nk4p`W! {~}n(}4Ќ7exq.QP_y >>QͨHRRAU7O0:;B> zZʧG" w+u*mKFjt* #&骏'H2";9_#@4qwdX< q%:S?Ԙg\"0~hbgxYդOg?L۹-^ . Gλpyg:pЋpA7G6 6Lu\ CΟ0Pބ5$χ3߯.P|0[F@J(b {(M GGjP3CL`jE0 kt{Q罊y}) F F X`0HyJ Zr~9'A=S3ZW_ ;xSF'lǏPzt?@W˹wBЃy}?0Tx`5Bޫ:}ac-Jg잓/h> 5~43q;C0Əoeo0?n<7mA ,x;voOpO]-{NR]y);sn9n7N7B+umPimz@22#-\RD/k˗vl5fV?5ћ0 (^©|EP u ..>W[ށx {-j/>p* +OryAU>(GJb>#Ep8uRe[+m}z*g0d:Ʒt5#BTI^ŔBSCY g,BbRB>,.&<0w.>T]ϸQ57n)8CV@/z=LU(m"x{'ˬ?T8V[\|8C>]Ր~IXȫ7gP]5zc)T =:>ڰ} q&{ -g]y ')]ޜJMr9PңQep4@+n 5@s8r I[;IFH^ak(WRk聂W7оsobڤo!_rcoI—o!Kz"0߼<`j2U&ٗ 7YYMЋKs<6 xTXh=I@Q}( 0{Mor $J& ` N3k^2!Bt]NX(|'B -a1)5,TpO0,V2 xs]~LF_徃He"f ׻c}%Lz_=v>/q{(ؖs߹=K{EP 1M+IǴ@dPU-L(Ug/خR ]3*nBJT]I}VT tͪ z Xrr׉Z{Ӽ7i)Kj6LQkn?yp"ɿ8:*n5C?|#;^Pb9{&ג5/zL8Xys'ML'q'dX+ y}O너h~vBvJsu*UcgPz!^3ķ3Ysjn~ΝFtAŶy]aPXnbp@}|Ds DR_s*zG텞Ͽ~]svSkU聈.-z !^M/twfRӽj29 >ٝ yxJ~34^ȍ^VjdB޸a4jzA׺v֮A[QA߫> }wk oOʼP# ~:~a?TșlK7y8ɝ4$T'Q)K E@,GiQBZuyQ+_LЈ嵚1Q B-:Ѕ ˬoPWlY dB;zAХטAmF8ߠcJ%fB7'dOA"bNCPQI$Ʒ)6IеmARc/-D! !.0$W4, e" xIpm 1}z8 MS= =&v%> x7 %S@o<;1y޿@/α_~$_oΕ@KM=jKFy](-p#Mݕ ͭE e:~>7_]P,lB_[ӏ^|\4@%G FπG NT!; p:Q&BWP΍B/;+FUW_Ï'B\\oPe=P'fƫb*2PeHWhճ#P̯OvK"_xԝ.[_;7۾B[{_!afqzï~:73o7(B74@)`D%hZ{m|E +7y W yBc_e cU6+1Fa<%~U4z G?0c` ʜq>u;Mr.})10 ̍AD^p٭Am^w_ơJK T n7q(zN،C"$5P8e<i84ijhaZxwOMM8վ?YqL@]ЇnFc\ 4y{I.$~ʨTҍ ֣S'!l}jGP[Ire [6%F)(Z ^0|7bGڲjOAW\SKQ)d]=82l L4صڟ3ߡ 0e]|0-(p :&يn Ss‰ܱ)Hɩ׋S.W)HDO 4$4{47 5l LCY=6h;Ӑsߑ4:5 ֤m* |A&x4 i+^)Ș>8\y?L r*_)/_NCAs,D `33 e ||Dg /cJ@_[o\S=g1+ ן=f\LpZ7~wzgB,Y@)D2gq{*f)35">3vGfT %z:O84zZ4߄a++Y d2 F<81uݜ|kߙ5 f@Y%Y^B3AYhlg ,%qBPoB Ϫtff Y'+hbbN[m3 3fhOisPʷr.}> RtzH6B}zf!Dz Sێx >ESnڋPktsPZoRsЖk 9"Io1w9tDA ӯ_Uܙ^AEN9*~$qd_7ͥޟ8)B:\PZc 3\ܲ;w%2YazU-P^֗r?\*E< {WNe>bS2AωG1X>0AՌ8'TW-*x~]$#A ɓQswg/1t rg><6ڝ6br+iyb Z︓.Yxn*[ ߯`Rs &A4[%O=O实ضiӉR4z}{E"mʊ̒r"`FLwYKb?ztKrF ),{{+W ]V]ɷGg 'y(Oc[Q3ػ9O;ͱ}oMD倽gRdᄝ9CjKVw1vz Lƈ47'<@O,æo/lPȡI,ϒ?m[Ăe<ł@YC@zXrd (~ %Vs`hXL`d+r`01-a[sƅc)/c9~ͽwp̀{w/g") QX^i5QX?)7GCOLO`uUec=bC7`k|j.=똋fum"ׯ}y;{= ~fW9,D-dXd N^1]{CҘ>A&C̡Cɡgq#9|Co|(C-g%"9|0Cg!9|u3!9č|0CgQ3qQ?5b%L&)nz{%b~/.i?QcocՁbC"hy) V2ZC:N ͋7o~0S//&Z/ɡS^;NP8{.`+N:x2?总٣d@@wN]ໍKO|S#ҴR%e3wh#@6u3 ,*d'cEJi\Ja\2AWE^}@կdHۚ,s%}C%x'<f .3GKLD;ӅSd`虊x4tׯP} 8n1{gz)s`I|F?~jq'g??5a03XV'm : ^>6ؠ=RZ8{fՅǽPv)Pg5PXpXTk0Џ`jTrBKB?] ]10^?Yͬk93VE 4,>r g^Mr7y 䠔7Z*DLkcB>;_ՂvYj.pk߸5gbMJDe-!rzT`4ɛ=SFH\nQf5t=n:|4rZ\qޚ˾!##{!V﮷ ʌW1 cǏr$B-j|_DJKLWSIGTeWm>hY-LF{O; Ӏ/w$? Zw[ta!d[Q:d%n֗@'-AûuQZ` a֥Nԧ2-YKCġ@={Et/͇Iq}1O1^_ƌT 5Hv}#N8xok4j̓7 w2R;i>KԟL1ay%A=iu844=&EeqWɋ.Rڕ% hb.VHp__gy;vFt!T/Gh E֠ >>`"3;|N7zZD!kmwofOȂ;5"@avzzx 9dz!P $D39cڄ p~Ơ {c*$Ƞ1Sc]X@ mOi.Nh5\a٥\]5$Z4uM&j>׊1+ ɍT uCXXӓHt喦D[}M2_[j~,.IrT&QsG m fg,:βlx+.H@G3(3M}I5͹i$ac@}z͍Y)v1.W+~}wev2~ZE3eGHوl7ЕvU ԇ^ME;NjDm@G2OMf#U"h)"lt l(:>bJ _?oaUw+Ml aCdr7IU u vߝjF e]N.F o}sv. >,x)+Іq@Pb}j&h۳i{thJ{|5F湪 o 矻?le$Fg9pێϚP(ZN"-']+2m$딄k2'bぇ$}gÖ_1lp{-8ȨڠiOmzagD2I/}Hrt<Nfb_mY={>bs /t]ⵃ ܎6#NP`Z9]-/s!ahӤ2s)JPׁÀ<$rGuI " nn|P\n`{eM兲fv:f!jy4^?v~Rs@< 4zY@'Ԍ%eUL哜yYkVxvwr7F59>I9|׻s"LKl&s3 =|^6E< ZTʭ\"3aE3|VkvڡOČ T3{$ ;>WJHmɜz/oo 58rPEAȍ_݂*yAkώ1&4'iL9wvfmȨ]L Tϸ^-@ڃ"1aDOX(# `)S{5D\ q:$lg,ic@P(䍬ahj51)z41ü00;=]qKE'1wnn<8߹QJa<}]KXȧMb1ΖTʇ;33 .iŀ Dm`A(\>ĚFI]O9kp$ .pީӑ StNnJL|~ OgnS\|s1CW>/ӸimĕMqSee?|J/ߗ%(|j?ŕOw%XW>=wqc?Ƌ/egGݙ/)Ɇ+=nٰӆ/dg_'|JmOm'Eb}h*W/z`6 a? p~4X/FT't7pظ/jKXQGCh8q4:^oO;x$x:FǗ%|s_>y _>˧q{R?{.axmU|8.S\|iq\>q>Ny\>ێh)*s|&! R>9rCˬy 賍gc|.#S)HD[-iB.pβpN p}w7̘2p&74ïo-$agIPPP (0ç'pk@CT%z !x sMck ֊ 3XYOY]j~l^f!% -MS{ZPS%.\?=m C .ހVAH`{@.5pMOi"f7WU`0\>_sg9E)!i OSptn(Ooʧz/|rM'MOh|qg,p.|^ŕ݆93+|'ʧ/ |w˧n =aǕ%<|d—O |J=×B|ӦMk{b"`=aan`N–ƈYg_>s$1ĸ29,=.K׎m|\˧q?9{\>|n"8#|JO}| )HAg;R> s)n«!E|#R>eiO|!u\] NrNxqʖud^Bc=IPW+A K=Q}(dGQ;7c^ *9 ,;d!}d[e@~kW7/q>p߭M 2Hiƅ-\߿{[WcN-ӳ1鸹 S5&L  }dk0jjRZ|}KeUw4Zx.&5 qjN2]-=@b~x ][3^'il4z,,%b?C'4i , HoۛEq C~Ϣh~y-J, &E\ CnZ ez/֧Bc`A47x~--p] ;565CP6 b3lWx8ZDZ:d.@\-;Fc]~='wztx4{y؂tE Z_0,؊ފ^0hC;򴡋d`=>oxD;4NuIʴ<@߸Վ>>`pv'a{?[a?=p va:g-`{5_a>_-FAt=ba= KtݫJxB CD== M, Y@F KXr ,.=YXvYP![Cx^^@տ  85S.T. -PXfZXVPa%y[7pxȶRT<zhνq =FeǠ MDUDdX0vѢwf`l hNxnAhsW I-_ayftʃb}jhUHWPh/xэ_8M~ANH+sBplnZM .T}|@ȯ bݕςoiBяC7*W3_pV؉Ny`ҧhd 1~\b~ׂc\Г3<QP_TgL"Bʕħdž6jT޼0XededyUYxqa}x!xAKf_JĀWl›1B"SN<?UuWSy:껝!n o/a`1% ~L vǤ"s؛ "؏ M7MbaǂZv{̛A mxЂY6v_ .-ۅx oskZT:X lϧjVj}8kl@,`j a/kӃ`zp-WNƛ:ܓ1Xxi% C.`jxW"Q.X4coG0a"LtA+Qw]:JrՖ|广Z:D`S\`wp&kiD~v'ż]{bF2 + zSLK::6]ئ[ӓ[X5ȌIᔎm(->&b> BxDv3:љ]MN*Kd:E/εWd5B/WUGnXϟm>ȆqN@@2`~j8-k* |ܮ~,N ɀ|cz~s8_4<Ӡ8eOoMik.m֤*>=2|aOo3D魭 <$Iy1@ ZBzVqJ?㦷Now['m}Ghyxz{}M"nzk}c(nzա:ষ, -Gvhnz4]ަCܸmEramnz@p7POoD[7q'oO/['"lR44$,,wB~\@_S]f)&3hmk}b6 ޒ.?hPѽ`]Y#hL_zǗ>eb}|YG_ֆǗAe2>|}A_FǗ1j}|>2f}|F_n&ђebC?Gi-Zu[UY5V"hE!6MkކtnC]oK=;ف>ЀnG݄݁ G4'+=L'tG>zhvBWVFr7t-n:.h6}|}>^>^g=> ^[,ABujOoSqUOъOЊ#h-:;Vfn~>^m[ ;Y>^}i C+ 㧷Ϗ=F,mTv}xzx6~z䈁˯d[Ui宼/}ωFGjOoOo^_2zxz;txz+[Ä*w8 %2/-؀*8ѣ }dz\5˿Y)bݧ7/dH@ z0~b9?x%#^|ocyYT^PF_E_IOU`lt- Yh慱YTzE2>@C )M;C\6lcgYeS7jYhVBb %lAلY IvWU ކ*띓R['/[W_m魊$S>AԓVJHy7u#NLMo]Ҿ㦷}p[J XbV 7] *MozkᦷɂnmC55V# =nz;^7:u7MoýxYA݌NHj~g6}M׃nB+~z&?= µS4=xzkK> ƷӘ7n*S\XiIl | ,,Fl4&m# 0f03mXYc2qi̪>K2q 07a-0Gp2{7,0 Ks jm'<1KL(~zkW 6qF}ž\N^*`0(\h=#F|vS= ~Pzc{`1^?ae:1pma܆-9`Q+C0MO]J2X+Fؚ l Ƹ#*{S b:/b(mn2lA7HՍa{0VS=E&~z;2֥x৷Gwo᧷z n^b;#,:&[Qp::-OoK}}rգkC@q;FF}c1Hq&`}*}

OoshVldz^Cf<yyQ5M iߛrDiAb@m4k!j{WM2 9iɾhj+e,t{Q`R񕡯dxq`2Z3* LeX>=#G1 p"7%SPzNJSVӰ,"붼'e1jrtm}&? }C>|@q[vmWIB`D ^R &NyU/Z`Պtk-tԋ$#3"B5.'1œۆgNG 3vӾf$ombie~.5`VϬ71);o>35>6k% l^%Va}NS떔i2bd%-֭/{*I l(LUT%{?g6Z|ΰM:(?➱ZG"Ucc]6{\cuvy҉Ts&S/=eY. CoߕW\L<? u^[&2LxTlW}<MCi'oG4(IXrjEI3C5z3JOn |JUBʹt &qɑj1Hz>ĆA2eXJ1Qijnfܳ,MXH+&ԼôKw]&O#}V [R0my6}->s fDCVR)D٪y+Vfwk,HZJxݱ;#Ҷxz?Kcy8}h<ɪmfc`ԔRr;8[13>#ҚwkLiA/c5 E)|a(vX?5!$k75G;:&1`ƺr5\O= v0OUr'3^oa\N|MVd箜'rkÞּH|lg`nBfL:VH*{.wj)O9[-C̫AH}MJwy$KRl֫; 8}ҥw[cAՏuD2O8(ݑ'5z)x,+?xT{ 2dc9Bs ʫ19`)uOЬX&Y>D.!< }$= zq?XƒIw \O&qO=hܩӐQJ®9> sP%ڞ)V0,OX WՇ*vJ]l'F!XaX3TdPuaHrzލ1zƾGaW_؇:Y wA90G6'؅z*iMb+5a)b|O.Z|l{[W&h*8G :f}ǭ7WBhTJVܜWJȮ(\y/Mh0Ͽ&1~R bJn&wRNu2gȈޔV&Ff9围|][6GgNR ƷXS.ߢɤod>FMmqG;gu%)5 ~!5AGS>R͜M=[K;Pe^R*?=#nO%èٌׅu^k`xղMs7JZsS?b9>Fv5+_:y!q o4!-YWNe8l,/3I}}KJJ |C7P2!iX8$0"b2 FZ+eq\gzjMg79Z"&^ ڏ5j`Y,w{ Y2oD>?\2S3Z΄}HȻRcl,$S_cJwkF:z@NgE '}ӯ qт2E _쾟}goxI̛/%TnwHH]ܼ6OqDL6NVV y ^o`6«k6g&?!J<~$݃]:UW>IjS㔤|~;-nϙZ}ig{ԑMtߊ*=YJAY8 ! s/S k:WrbzW~5%Tʉc4+:T+ TM_o`깇 &H)N3ک% ֋쪸V6M_ kjsu@8(vM\F &7aC$ut.`Ro2`CLnt s'a'σ(n`Gx(pLB?G)Kv/}떝y,4+%^^ Iʹw}>g\? Obh0@89YBp1-$.,rc;yYdg!hA?ho4*c" dxe ?_׵RP OwoxM"jAzS_.,eT`Ƀcf^_~dsєֈ.AW°_? O%V}sVXKpp7dWx:ŝ\lIov/RB$, ]Y+}<]>sqg̊pR OY9F-Rj+o0ޜ~i@oK%>,i]ihc+ou:o^9l;;?rԑL}z a{5gu'|rw:kfTX|y{ac`GAT.T|WCIס^k,;i]hYywRptψz^Kc{+|_Ju:5G)l,&6.nBX#IΑ7붉cV]+bP3ʷ5פt*v_T|㮛YUgŭO8 gQIӼj&}z'fD8̔WC|FpZ BO&>{6%GE:McJJ:eGHH c~Z~wc,*/%=T.D/0Xb|y:_S2KЏOٝp#+DAӵzJK%YO؜Kt/-#6BFq]駔6ԩ,7xXu0l`)fm^{ao)c>ړl\7܏ mk8UDe1\Pe4^njRb&2{ʱڹNˀHɅAsVvG'k2_~s8ls*X \M@m{?}6!׃]vn淝a@giOX}o>,BA]!X[[yG/|ў\e}ԦK+wc)7Z7ʺya@|w*$pR@NS /VˏhM#$ھxJ26jmuҘ _y^݄ >?N^qO[\4} k6 '|?6|=ŊMxz6 DQ4LZ6z&; n⸸ }< n_ ԢJmBMTQO(Yzx E F!eBft.(ߜѕյ+gwjO8@[E ɷb_& dNj{lqMv@ !K?Q}AN삫NzCX|#|Z\fOxf_.3k6\]f#'xq ^Ud=?Ltľ3ͅ#Hnkjtϸ(/,|L-R3u*4ө ]uLǵ\s.~пofGdn;^7K 6 6J'$T  K+F]L~s"4b_)<4v0D$d*;ŝ| Qzzw VO@L W٥' l^q$=,3y" 9YN6ʡ)}_X߶t>]oJZ{<=ކ?c ;6Is$BC@iX[Ե.$ cb0O{'쎾ㄫƵ^ )ޏ#>[26Lcn,BI}kWuc/M-[AXZ_ ܆eG^yU7WDص~9ߓrkV8JC"1}Ea"KP0fP6S[C΅GaM%C2|{B2"CH%$ɐdR }]s繎B/=X@nwcR|mQ7vyx>fMbDjsոmK,gA'!L7)?E ߞTXnY,xY.TL9n2CY&e6fb׹ irjJr"YO~77 eTړ2`mCH _!9ik[Dg >dP+[bw^ͻ|lmcw:Zق>~9 1OeVDb3ۊ9M_s[^ڶS vzT'e[{S zQ.¶@ò.m?hr`;%̶L 7A*am o<ŵq9QbV_Fml1mbl b 4iU FV+iwmcc?l{mlO\mY>~;m?=}[y?7=D]lote$ڻ6tYݾb;|a46q=Ga .7lkO gRIg&m=/ uv hmCqZ+m:|$ƶ4dPrvZ=Y=[yfP[NSAm!;PPF-){]U$x}O*- n'V}[6)~.pʗMWZmi۶]_>n5VzlkDY zl;C=H y.g(l,2a5m9ٙSn t۴\RlO~ݵ%G38ܕ1xCUO݈8l* tON^R~ݤ_d~pf1uqV]oXp.4`n3sҌԼOrc NaӀǍ{$T2 W} ,S}AMh]oQ?Pi8shEooҺ ܋`5c=aG+XW޳d|< ҙapT֙ʦU_ #c@J0:7YIg3\4K$`?y.`-?1L(`v4oDu N)u"{WQgF; (a 1v׍g gjH j~_H?N;GWrl&P\ pgjk(>xD6rN$>[6- c^=!WSG@F2a y7@1`M5.q p;l4 h`]ny.@wР~?Yt_ * ?/RofoD􊏻~iml)tbO/]~_` by'>;I 웚Y$\ȎLϼ+ "Se̒jƱOՄxE/4"Qw%ZmJpOԐ'3/ vyj&xI `j9|ņRzQ*5`叅oMgJMS h9)sf+@AW[93/{ t.+ڿ~B8{A cW-6^Gb'@g=K??N 6T?^\p"U-6sY:nupR?d6˵e͉dw<:|21sg\U~Xpo^/+$~HYnqDa'˅Oq[ʿ&䩿s^54tKCZs0l(d?@!C35XfEJXS$9og{U)>-B"Z<% yxyTh IU-%,Qmw8'{i?)Pk x?EQgʌ$E`.||ʾi 0ܨpuM k=7vQ(B,+^&s?5`a֝ /<+gom,US௩;SvK`aأ|k b'JY@ AG (O5XHheDjt/:`rt7bN&}u Ջ魹U.C` ?흒fp͑p t3X$XQB-h .?{Pym6(F>#h߉-^wf\z+=Wou7O8_߽ q#E^R Z_*0uk,',|>z+}cO`Y `d=Դro?aK2Xf'J YO`01#m̙c!27 baEџ?")#D//(;LE´n@K n񓦷J8_^49:)^;QIT/@ӫK[%4m{$f j]^xxʟ?_<hZ*R20_ 9-yxUMԎ=U*Zݰ|5n_#|9'p*o[СuP+˛n)^\gwT.tnrΙ-5-l6(ՍU^~ {4&:<SS2|w(< U ϡJئWhYCZ聢5TuAB)V nvъ#!cBo[k_W9ꘒ^" ?,AgAs ?9$5{`P_HPz՗xꀬe q#'5ϚdfˢA[%mѠQ{?]`8xЇQ/$HPA.; 1A{yh[őt. CEK$Ф~I /9( #}P*s\U(z,9e"&Bqu}`/Nv\=uu軂:T:@e@ TjOZfr&3AF7oobmKs{T]Z"fp1>8= " %{hh&1Pl1,=J?{/d(y.T u`*Hש{ :W{?{7bCR@)3AN~OEXAG2APe^o rAAŠDw@?-2AEK)M^m> 1Vb:zEnܒII)jUՂ}ojRH;V fn(re>2 $oB '$H{}X ?Qml=G;ӻAsV_uz@ui'\Aa4h^+y MR=F8uh\Q~T{ֳXcgt# ZP7PkGjO( i+$ʋyYE4ZQ>?ęU|hۍ@D(%26VA]Fo@5N ͓̉ii+X ?ZՕ5 U@Jc =yPN]PCKk~O uPںj;j?q=: l}pj!/dNLQ%~I`* ?хVCYKI|,l?grHV8 ڸ ][96RTz8#nd۝STK҃4j`a*"V~> |cU wWCpP]|+٧`ƍ-o}p2el*_{ ٍp,hxR%8kU*kf>t>Mx'n.>[ݬa\r55O ,KOCA-_u'ފPU X6݄Dxkb`UY :hPIнVs6;rH),x/?J5Ğ-E%fMgz&^\ .z'X S:*O73<'F78)Ԟ'00菇 n1WI !|ՒʿJ Nw+`p7FHx b}( }lwcXe K? V8 ܼ-5 O%6D:eRǷ %]+娿o(QWpvɥ|U˄Oc*[t#tڽrTrȧARl,"RaN"#v3b]kچ<կ - ɪ$}WH߯Ґ s-w_@v*CfJ< B>*`9U~]Soʐ?6* o_{u>h ?:QNXCƢɥf;=&2ߍV7[!YݴyAr[.X@B_yۍDoAB8]DYiB n2@ jf Xwjp'v4)q0*$Iw3Q6/jd:5N#< *dB'U[(g k 'DD@R+{ɡOi J Y&@L8@gW`iR_ ?Bv6o~؈Ro@ ^ =)~U{3T~vQڗ@*J}C^)~ I_? Zqq2k잲yjpfB]Ϟq UD 1jhפ zـ,]x@n^KR I}߳2)D2hހ$ϸ݇X-ɻHAC&p㫐W LmCwH=HԭUHcц-fwKq?4|{,94V0cbJVh!);qhWbGQm (Hu&R^ jvtH*+$=D tQ( }s<􄷜=1V L!h* =,Qc#s↹aAG2絡s*jPeՅo~P[%-(QbCMMkMNMӀ^-hw( ctPOo 5; ^Nӏ\DoJ"mk*̡R!s'-0<4$/YnJ-4Ճr+*tZ]>)@C >?CKU H>uh@_wKPGrOo4 _i)B] -l)ЪIÌv WP{J}o .=9[@}՜(nנ5g6{r\sih& B+//Cʔ  ̿ZB/M={ K,ǗT=f[PC_8'Ŭ`⭖Tx;E(UG:ޝЎC?l8Cs֠%VFw{AHbB7Px{Ђm[Є 3סZ)%`Oq`ǵ&`u6Juf+n?|su/XNF}vS4x WKvöfue(QE\K_), K~VE[όm^I{XI< ~鹱"l(gKvisuojҾWFFi#%L aIz0?kSZ^_*,1NQob肃ɼ9o"3]a<˸^^4&LB 4~8LJ$޼t _oE:2"0a_, Ur\=o̅Yr`gv[`Q7aY0˚؃_ʊ00lWQ0ZW\a^Wa7j:Z ?wum/p ޻bx}Vo/vc7NLwxk;o">ZUWMQ~t4=ߐ?&wOo~F| wH_nQx*4|w}OiL& 盚ݿ ~3\G>n䤐B6<ȃFk) gyU oaYu'O} uZxWnYO: $͆VВ.[6IS)]knzpA(޳.P\\˒x)}_qU -QUwV xFo[Ue:|/f:f f#.p+gymbmsRSS%]ȧC{S^ëKB %'Kŧ 5?.JMMed麦|AZM1p^晖q|2L70x Od6ۺ›뇧6+O[?}`n #nڙyx*)VU#aYKr'A1 ck8kT&n|xr~X6|{ ) &sb (1ڕWZ? Ϗ{8^Q*8\!'!s?rHD6GE8RwDutDN?.J")8R%8eR DpRCDcM b*v^ܽ(.QFxZZ'D w:wQ\EM TaneAv]0ú"~27*ngkEN km'W= @x~=⩍ DB4Cނ0WE?!FJV#\O6!bDL5##U9BLq7Zn'B~DoPnvsߋ҇RC.1$9L~Clv x݋(Q87G(hg"Zw_t`5!ȿ. S^^"bJ\~kg%@X[ j \+I`ĊKfISPx$*?p1*KeBq:s08e,G9@;,~4D)C[$ !_>l;|3v(2/,:[bx zśoē 2XB3.3Lws9U@Enf:# TNH"tՑʱ9D Đ!2!i>):{=w|Cz2x쟆UAn<]=-̳ȕUGzfS*F{y*ا[ڮ수D <*sdKT+佉 ik<#䓪;fH&ן+ ȭ73AxAQҮDV_~";|o: Cj= :x Ĉv#R5ђȞgZ5)ȲUOtxq'RïNj j7Xr<>ZL+qu1VdLǷ7HP?\mw\.R(z%.9Z&xVle i Ua_"tW7ꚓH OP7Wi3D֦.,U'#i%V1e =(A =2ѧzFg_6#;>l^ljC>?"7K>"|1cHORYV$p.Z$nXh "և<| x)զfGV^;6Ε i,5|ɦ#3rfSyp!_H}\'kYW>"fY8Vz!c/Oh#߉I2s~E=*wFA1c"~ChAjzfYXG3ixM+N~a`.Myz!TD*_Փ̏J &*o4;{"`1C1( Iu)vGI!DGiꙙ%>@"7qY yqT"13(OW 5v G(iA5iBGFxǎ割n<Z; EMPAɩߏjr=_xI$Jغ*%5IY 3v-e8o(ub)U{B+:VŢJ/uUccT$>cuП(1[:OQÁROP^ÃRP~ u{q()P|DqbJ6j$uP7#?蚋 =3T 8uF\T/D$D?zluY]Ra*r`ϥGw%\{( pDCLEEЬ{T5ge?wߣyQdxCQݒ'Q%'_q|Z˓:NK&;Q>!Qa4z;sl$ Y:BWbB *oJnISTY9?P(ղ1⏇kG%|EtnmAel ).;hC(稻~G~|rAuxlӶ.h IF'\}%,;'\AE]|q%?b=28:~7 2P6o<8;걗}hT.SF1tŸh :~ u/ke]&D~ouN3Cٮ9J7Gg 2K>V޵a'emc0=|[S3&ЉEbhi`5?!Cr'>Qz,WN tɖ|&ΟI|\+̝RBB~J9-Gx}M;"~ ")_9 `W=3)&Lꣷ.'C_:t=Q ౦'4_QѤ"\ ک9鵚 ]c8|a&y#i%h[gui&hk4!:c.H-1B}*BxZL|2FЭk-Q04x7bx>vI,hpp{kaazVGD-ѾCGZտhɧ2%7uhwg[Y;FƿJ ²ATSM$Fxx_gI7ߚ<,4;xCF90ߢ/7o:㈖:nx+f -E:0 *NgK5iđ2Tkv \`l zKhA*є `4I?g"<}Jz<20 {g':>ڃoͿXX6|[8:H|F:q3qV>zzqz`4-Y~ȱ(NVI(:aNr:!Z'hP4t!f#v)G9t*Zl 5{EvCR`ک} 3yz( lIj*:4k+t&Ur138/FS%7E7'kg_.WbʇoVn(D? B˙$%߬«߼CGV?C_ Mߢ<^n A(@V'B]NeJrye%:o-E|0m(hE5\|Њ.y,ڍ>'ͺ4݅NUV7iH[Gt?)g݉ZiFgWEs6봔[τ%_D'(( 7/|CkwYg=C*hh#?ⱁME9#_n46ڤmfsR5 QGb\3BJC +:_1, Ft#1/noj>1:~X:{ѧ/[ SDk8kǫ'#e0JrnKajT'DKa_*w1?sJy+?9rx< Ͷ$Fm} Pݦiatۂ1NkaZ*T 19UZOOYṃbzu1M̨Gfm0?b>0D?acna@Œ0w^ #&Z`:Cq0ԭ0{ǦoBpfYwRt\ZY Szt5tqR\1>Fa1>(NStd.#S56Fa_91N?X9 l͖cPNXo}bJ?%aa>ϿМa A7W)j :j+FTQc -@ P3Ώ31Cz| m7c=u5Hc(!QRw$P`ro,bLto8xfW1P{Z8OXv9ݯ[?}= cZ^㐒I0Qo1ט> 7}NEc=}a0{k[5Y*LxN՘/V"Ja". 1~ X)PV:{LdAfC00;SkUNǔy}D4> s؍Pfwv`T8?D^#ĚaL@zпv(&0U0\b~äY̌a~0{1-#k`lb=jK&b"G1:y9}')Lͧ/ #gCitj1hkf0bb(e`p{w0m^+l`۠ja]Zh蚋Ưcr^r}AlT=T+Q+BJ`aȜ7MX2%𽸧DC{_c›ıgX CUN`-$pxd_+|l\!mS$9yp]ˀ.~oc|IVqg3C5EQ̘ e2e}F!3!&x>E{e2}zl0zY+|u."=yl='+V8ͿϴXyN9CŌFk< 3lؿ5lO5cd_C'Fcg֜;ʕw0؅wWecHsrSxqq[t,_c~ѱZz1X(͔ 0΍; v#Gk_yF;q FŮnM=O@?˅Z XΑw2gl.oUvNϿ ANcS0mC;kW韐l {{X+sRalG08*+zڤ} pyfu!lX<kD~XBj _޹@'S'vZ@,±#\'(+F?FDb': 5EiSw^ Z|Cb*bsQؘ}*$ E6HbWB[RoDN?.o\O[C'`KNxN<ԭDұᅡy]{^ooK^ۜZw\v+z;/GD  CbQEؾe?NEb;{qI{걪.F}CzjlO@ lO|{jlK؅ouUorƫ޽glU5,ӟjAZj|sBXJ񱧋+ZƮt` _Ud|ƚT&Z͖ޱO6"kwnם f) S(zgxHp>=J?XG cN2><7}5zgW{2)0;,h Vb|d˱OxTGMoN?VU|Ɗ6lbÒ2`农lq??6vU*Z@b51ܺJ- \]O tJGxp!֐sr^F_​dJ7y;c8dړ-JDK?T])l9as8T[Kp7/QYwA^NH<;=\F.M<6![܈+->A7*?$/to?yҁc鯽Yy| 7,wϡߧoPM҆QSWpk[FqoX3o*7z6K=]~}GNf~șY`5Ӹk#?q'=KWvAv'Xc]B μ\4n?e܌&8dp1gVq_gp--ܿ/p#bk۸/ұ/pY ""ȉ3L>1d6>1wc XTPr^:L;|2&_3G.; > ]Uk7ɓ':Dx63z + '&5I^D&.IhL)KB JU b{~jUNC<?D>zf?^S{b7*3S}?yjpZ9s??ۥ ll+?[_c*FGn.Cɾ*|OI(^N-RoGjFQ Y;Vvÿuu&۲{*0~0s:>6q^ ަ'?(|+*fX;0XyK|yx6v \ΫHԡLB RU~n>TM=X^7>{#ǩ|?w5=W8KMҤ:DvX=~i~f ߼{$!;ޅ9h8tqى~F|\޽ǺBogT[Һѐf|-VR;ZOQ|iۅj ^xGو@|6o. i79?o]=^wڏ3jMDj/RNe<_͝y^qY͗V7=7O|׌*>?Mqzg[XgܺK >=_rkrŧ-R- g'5׶K'JXBO7& N4&<;v[aV !hȨ̽(DN2v8yCa(_B9t)!>;ڸ@#p_5Q /C1t23@|H(&CS'ihS7㨄£8eA' F|=N hsLloB0i~ 7\υeH~$ZLF,5p&CW)DHFG:H~3aC|||im59Ao{ &V}N U l U^%pZF/E(3*_ezHx`4yB5}";jAiFc,aME,K/B>xB♋:)$^kr Gu=GtgMV#M#W1brbB;`͸Ne*^!3R@Pxpi塚W EG]|B^C{_7ПSӵ_׋ץo &GraoA=42*G ˗.!==p}=d9!T])uF`+!C9>. ]C!\/KZEΘޮi"?H}MLUhw_=FȽ;xl+ mB62=L 1ۨC5Nȡ>&߯m?'!9] ^/"K_9w{YlӠ 1aCFI!)<1"d2+$N:|(p_%e|%vȀ煈_bM6^cE)3nQ J"9_o%bGX brGR'Z]'i򏎻E'ke'Vĕ#Å]i Rcu0 uCR1P^}[GӨ: E>1'U6:+Dy͏ĉ@ b&D*SbgN D]oAV|wq? "٣4$='9ђV_Kd.psbƕzu1^GyjV%T6_2lPf.@~%B|+KC]H$$`䚄fWDy٭?DOIT }YW ^2Fw'Q߽n;LxvB?D"9B󇜈n.D-K7WAݏ_&yPE*\%:y$ڎ[;~?ǯ?mV/e.CU6Dwe[%lトuM D?`р4dy]N& wʓؙh%G͟׿<~%r t|#>(3,!}'7~k:. "^=A# Zި"BDOΛ9Iٻ$YÑĮbk]Sz Ī]4Xhω72L;u[3ψV YDz yf܊9bcbbY5_GL\GL'~_N֝' 6h^D3fν'ۋ$:{KlN= xP"!Nߪ# ;UĴ 5j_8UD[UEp9.Df \'1HA:I iuA>oo"* {XN&&}e}xuiW֢/NTxlra8bFz!ԣw3 }[cDk!b3ְC7z0=x+B :ʢK%6zglӮ"WK l&f3Ia\B -WkF։AoKZ ^"WJz!e%j% x06 T?|~x;5tV?ڧ+J^Ou#)z&ɜE#IkɓONn-y?q$q%>CZzr'^[4drg%IP[)D:(%O V kkRnSSd&rI>Yۺ۱X=;$eQρ/ΒNEq $/::e+'&R"IOi?o_ 5& ;n>{wՌyςFM~؏HwnC1mB 5PI}f0jѡ8/;K=V5Zd-9 $ʼn`|hV%)kOehT>ԭJa:rITsDRt4hW7V")[ksIaV^ǗJrv8Nŕ!THCQR_!$c;.i7/ۓ!jI@/]I'[ΤєM:/SW~N|HHKv2߻I5Q7H.E]zDʔ;?qχd'CjfKDǑ)Ѥ|e౱p {$ҕI~zbIMc֫FUjއ7XF: s)UW*[+٣\7DG+f œB#OIp`O2iɥ$*DRI$S/sHLŁ_oAISþ/z H}^CrI=QͿ#*KHVIE"}t؅Fwu$i 'jH"]٫HUiQO|+=gJI~5E|RqR k;t̡jROk-:k)%_=ϱglc2iVrNGqgҦ7)q_7I_VI|d'Ľeun=9;QOH Gofn< I$qA+)8zl5! }_T(i?qhNR+\Z6&%J'笗Hp]z +x=f4rQA)to{t"4i4)gֳe{gI?6*TnoQ'>YYˠ-RcZ+XƅM\'1O$Y?Əx !H C/}Dɬ^KQMr &ٷ9 nXM(AgwZe]l}XxA8p} oUW'{+8@~]j4YHi2%|:YW兟*љ;Zdo_\P#WHiJ.%5W]!o&*>$+ZeO~޶J&aߦxL'6"9YM(ʊ|3"ųKfF^19(sߚ*-9r?Kc2̩f䡏';!HL-k8Z_=R u9Ő+h= }H~2]xIG&L6|!R̳o~TQZE$Gz䢱dCU_<^ZlJJnY0U޶(9bWrѩDԃ G~Ed>#9[2n SC[3ƭdOnMlU`qAП|\az$%Xz7Q9o2O " %ˬO:خ&G /ՒߟH xGFŬ?)! n]9(%=d$z_;2K[y ?9B mcJnv\C6 |&?+&L*2{+j}.2\y7Ֆ:{悲ʧm #+~b#iWg=3@&RNNsu#OO O}"l{[gdZYO_ ᪺)2=%CyWm[mhj|mA,zh~#ƋzTN%#_NϔFV~nC*|s?r*+y%Hi6ِ_*bt|xrDM el_÷f|<q`,T{y _+A TWs>bz=|,S}EG2CyBz!HQJ+@4e, ~FrGQ4Q-O<ɔnL <1]7iJă-.IʩJTeeE̡ڔY3*-%.Eq`[&EJ%$wZzKUب;hR:r6?%H1`ֻт(;;˫ߦϖvyRڝ~RJlDPXRxӡB;X#?Cy[َ;5w(_9)׭Z>SO7rA'Nퟏ(u(glO)*lt)[.hKO(^MX$Sϯ=x$CފY:\@1l>3y/r\EEk ʦyr1bJbȇ闔?/)R#BYYL2Jy{ʭ2a 7;l=Ps hl?=Eٯg}"BCy߬dQ>H%$SsCó9gw^l8?F2z)%`Y RjIB x~'{uԹ,;Km__ORr k%CUJYEº+l"'ڥv);SeJ%mI =,:e:eP0#LqE[FHwcS#u!jf0|QDQï/O5p2]HTMN*7EU\Yjĵ)jևNNSf?.KQ4%TzijhbE^bkHcj{R̋n4VQթbV9pl{2Ș$@ s{L{UL^-dKI]8N6|A݁TZp?}ng>:#ܔF-l󵋦^6OB8pR#|hK}Ԍ@PNCje`,Ukٛ(jJCf8u]SE)}LrSfu<[Wcj}~3sr3j *^"TE?z]>-QHWNʧ>]YB%:Tϥ?ܽQD}'kow7bj G_h#7 T7 s" agvJXceԂ#>P}cԂ2 C^%u;jOëήjN1uSXL| xC5};f tP7EmD}* j| - {L=s0B2=̾j7x0Lċ{As`h<&9N=J-=t_;pOa/P\ \=^i eQ кQzޢbiv PVz4wi?<4ٍkG!·*mE/ɔVwbwp!ɚ/}vLjrt*sh[~%,h]?ߛ|[mh//*Yt@<-qNQsn'(+Ds};m |xc҇/IğCD j/EY NiސIMdI9ɬ }$D%<ٚ9hK.p۸5[76wi^G=i O}sp4DikQr(~@(-9R!Lz@, {ZձiG>5xeӚ(oy:OhFi^Qi4I!GXkhw"`^ fV >5kZB|LB1m^U>ƈRϧ.s4 bܳi!JC\yuZ`MNğ@*}v$`V)jֺe7 b|GiF}1ejhfO#Х4VPt{Ͳ{NW4IWzh=ω7Ӗj?ЭNd^U+M'%x=%ͥ#oF`&8-t[}'ۍ՟FhLudEJBkW6Qq>Tj-i[1?ӆNj%g)h_~i}Řò5iG2MFvfLM]ϖi=Y mJiR=* U["uXxIvijiu!R/3hۧіziĶأQ|t»ߨ͊+:B{QnB;[\PL(=CqcEO.n;F7IΕN}QΟ;zǂ? *'a/g*|)mW=oMK=Áf+o4uKo'mVw4OuSX> S؂]KprDm}yPi!$o(ny_\wDv:E5^s,N8iPfy&]Ŝ}Bà K4,itXѺ_tD!LzgO=yf,~'$=ѹSV,!+t2.S9eB\|KWK".-Ԙ uλFg9oDgݡ/xmݢ_C/H>,Lυ~XoM!E?,Aoq>CKEҏ=m_$}s JwQzљ:Eﲺ9';6J"zg0){f[[I/V:L l?S7JOB6F?#ɹ;'l?61&qՁojoмjr?%wgr|?SJ{t_mUQgktO:;=A/Y`D3J J90۔cdJ 3FJ8IMc[L%1pO434pE ?f$xy超CD*PQAfbHA}Ĩ䯧H3ִ`EFK0Ԫ=0`lL<Ǫ3acs^2 _ư%i0~`r rN=ƍ1qvEMFg.EX-C$'(zA7Kobԉ$-\޷d<یY1\$lq8\[=lKd9uƌ2#,M(svPMQ5~,ǸWր1h2̰d!6Q!˸+a=kc\H?1*8p[<`^c\S`MdxN,FfC׌þ23^Of2۩Y/% LP̸m QXM~Q@^]K,cږ\I`7Z7eiܽVt)~x$QA=gֽB` aR]52;3zޑέQO᱕FƮ{6Ɖ^52&puG}`BUJ8NƢ6%0CJRsUvh28ΠRc}a7d1_>.Mb>k݆DARf`hۅyQPD=<8z&.{Ӟ9|,e:sF?5&Q>ejic7f_˕ըܺZ`kL0hns?f1̧1w9/H42_Xg2Too/d>IzSIwb,di||C`J1hWqwG-b(iHm[ݻv☁IRf̀ڪےy~ JF72re*?{L<ܒ>~$zb9?~TImČJg)=T/u;8Pjc62ay!oAL*/3"/]bwj/G5vn 0 '<3: 3DTftJi)*YdVL.M1eb-1gtfN1'3Ea'>۟Ŕ* sɀUfɶI =&en0M_c]nxb*S>f3*fd G0o/9cw)g]k](c=Pe%[0X,U1^VDۙcbKN BqVvnιYj?&I<D{dX˂ݖR,3ghS,ϏҦr,:dQ9AW='X,W Mf,LUV<[ Xڐ-kY0]hYߪaJ>hyp~݊%7tՇ5hrϗŅx NAVWMY"4&ZٲjxTGXHw,|0É?p  p@F޵9)8A9%;ILbVu%w.4x\FeT.!/tAd%Qfa;̪y=Gg6-nY ±5TV9'F>6kkvǃeu= r>`i͝Zl¸z/hhUV~\tUI(βJWub-]JuۼWigu el^ͪ\>ɲJT(/9nثڬa`:v-kzlWgɈ8Ě~qUŰ2Λd}!v] c]-kȹ2}2:2\/ulTz?y%joz% SZҐdi99ήJ&K|Vv*`D4ײXn` 65eשfxsKY0# g*Y,{7ˮMs Xdo Yu:ᑕY^tGHߒ1̚WU9ǂV:Ȃz7.aCZzYv/YfS>d-yտJc ow %)N5"-_T(ȸ{x"+Ԁ#M _Y-N?c],Lw泲ʮmKDp^e{Bm.j6YܠX^7Y:7:`+ bn'`s !łlЌAE'2:.[%0u썐P ayU*ΞW{)0f ljd7cI?l~J9vhzo [U`,t__IpeoT~Fc ;w1lmZ--v 㹚^.Bu], zV:0&P ޭξ'Ư®AudGnvKo`'V6 WԿcv>Xr=/'d ӐKFlMLc f!Vlo2lN[w{<;Kg !jc7UG #WkrA}|0^ [,M۬\֝p^wk@/Q4m]jx PA#28o-;~!>7]~`oc,5;^s =, Ma9zZ+ɝ ._c'n8nh;wDH]c_GgF]e/l ˕}**!6CdIm_Bhmv [å|%N+gػ^SjC~Xo%@rJK$8b|Ro~}yrHVƲZql|}r8"N!műGO;{ic?9n.&$VLr#G{(35{-P̡Jv^ܛJ62}-H9ŀ;xĉm[Ɇ}M8dG$&nIzo$" Uu'.}`Ϻv拤w2tMio5Y2q o{؍6f Evrz=7;?jz°dKOBy}NO\/[n&ݠt{{ߦ{7ŀ?38YL`T>m8&}{=^riȚf͎9'm=9`ef4G./OY^fw,<{RaW%!vאַ?Beי`ﯲc%>$'O_cnmÖwM7bj]o ʘ,)Ծ`FsB9ʡ^TSV3\!ʙ8(M!Yi##/Ϗ%N5i .A]{Xp'%]A&͙JvNVx]~ծVoL#=Ρjoߒt(||*[8#i\*P>yCC,o240-3;н:3w?xlќQsY@(aƙ|MP -#gkЄ1Dސ7|s)9gzzۈc2%F8O[O8k>huQMo,n|"cFisΜ;ZaD9y5bǺp#a`Nw1N3u^bMΞn`5P^bq;+7)b\Vփ!D\,V8i$#S#t{Bs릐Irj|ZW>g=8Hܫ+Z{WgN{@GyG̦#}۞=ʱz;ΟVk.QQLm'_mC[NF?skAɤ{s6l{é!}]W#qaõ8),4;`3*uQ7pC4PNBxϬh s<=X&`.ss$:IS\WD'{BY*MGe]o:8az u8Wzpqħ&-Ǎ4tV>˝נǽ wr7?=ܹ z:b2/f=hn,\(D3]~HXi6`պtW؂yaō{DXs?Ro5J>56xE 㒃$P3x;Z!r% \ܓE$coWc41\~{\*Kt?'~x#q\x*90UYL,/ /&r䳨PAnٝ;As2O&6PVP.5|)/:4䨭s}t^[ }.Mb.Y (s\7,G_ܭ;'b ~'-.$\b<oO&V0哯\ӛ\lMo-lvszp~ _wg.o }`.+t?JoەCU',Wru7o/'S4%VPO8&sw፾ή~&<>}Fɞ~r;3m~_Q|YaKy(ǻuUAf8Qg/pMUR{]+?]0QWn(2OL=^qٳ-C:ª-ݰ\ﲓ'L v3ǎ? W aqz/){ T# KR& A7ŏg*'$ؗ[%>Ns:i#7TG物~EΩNˋF,Nya)GxIlkokT9S>uJK>!.1~˚>}O,M<ˉ?|~kk<}V,6Hpi}KbWϓj9#c9Tح9^ ^e$x/~e8v9v_pOnՎ \dxO긼奍JSMSΒk=U52q#w*xcEjxY2*E_>vku7󮷗_Ky9^/OHs.G }l  &D.<=ǽc;3ӟ$?&x#_x{ᧆy6SDnay;wGyEUgDtyW yEûA?y7s)o]W* 9ʼnXͤ%'GnX>YU:xw{xvcyf?<˩}NWyqx:;<ƽ椹_*+?̥wή=WHy{rBv׶ODɞv:J_4!r0v5Eôv{LMy>;cX#v~ols9mlVúW[p +e)y^78m'Ò[0n?G 6̕cٱڥ_h٬ng #aSlg}þPNi'z;"FԭCvK,vQRjvV.]o4z0%qNvx]ba+|gn6!_njW3k7g~Ҟx0lzZ42-TֹU{ʽd'װ4seGϏ\Q/s5vFnw[vGeEfˣ(]`RvF;`S78ݮ"^"wn2>sWvF8,ʺgӮ K#6hgW$:%~!/Bqv)Wۙn쾯h`~*_%erUE+vq?ZO߶ӼT'e}zoՏ@Lq6oՐ7NGaRGuGsQD!dȐ$CeoIHvRI=ddP )2(;z=ϽϹ=gBᄢ7a W.sBN1wC,PwBmu;ͩap0?,tP^Dh6!!{;TyY?)t 3u#9t v84#tqu߻gTC5mTjn{dn[EԞ~6x=Wʑ>p0tԾE{%zB}/ m }. ~uhhޛP)uXuh#͡_jT]<} X^Y9wYh"j<4@(zvh%' x|WKhW/~mR&bM!A*͡vYCO^JZ;7z <+1-P,D KoU{x8yйݪP[sBCYn>LՀQ5B3;qR"ӡ FVP; @PKBmfCMա~(BJ"&B4tΆ_ 5:fsv54@/hs+t֛ CΓ4C{ƚ*x,^*6}[ 5?sU=53(yj`k-xmԒ8, p˻~Osz>@;uALOEdRW ["nU`x6[@i{v(@A{*9]"ݺq @rY %p:c$ 8ƙ/x/xA5g}P)wdvZ0}8X`>2,1@^$Diaum* /@&9' ' r 8(т3DwR2-\7fxTa0t 7l ]PԗtWo:@''\>4? 빥 tFYN"XV@gćշx6V3}w^UAG/콂m|j䂎_h4ǣCl GZM{k8; ջr~z7UǮ: 4Ft܀OGx%`ehХu3l P원@oQ[VBI@NɞF6>5^[|P#" Lm+JLJh.34kf_+vooN_W6wg{ < 'K<J<覀ڗ]68|O}J=(ߗ"tnnyPڀ&+'[^@qۑaR'ƚZE|3 =mGV:{ >`X̸0P$8=gxyop@4 zK9(I hmܦQp=DtX.YJ~P`cPIm}qIP.۠&>BY]\Jʎh"#>&] d}0Ρ9(C䋲HȠ7(ӥ4Z'5]܀XQ`paP!_zzּ||&OΚFЗ…z΀ڠs#n'@{AAQfWD],9u/%g 92m kw8xdwN"ȣ<9c) DH>$!r\4qmAwz؁ QdP wT}=\d}o/y ~QSD̎o^il%A_Bjr{oHQ )h2y{!#9nɆ@hb6:Ȋ_ghK] Qp)w%(=s yt d,A􄟑g.A :R^ 3#XPBO ԊKF~]7\ 惊İe 1޽|Ё(ۚR^…\!QI1tJѕ ܖfS ZQ_ ȭN_6͈/&f50=ipλ0X 0G[>MyEOZ ŴRfGEkt'OY{\*+(. =EZ~heЬdP@ ')MI@eb>;Z"9Q:К)Y7̆>7 hm@m\E! ԃ}9r_4ߨ))"*ë@/>>< Ty[qTAF'M]%ܯs*kÊqR.P|{(ԩ4,pT.XyEm[ڗfЙ;}ozB@]]ARnAL#gPY4 ̚~6icO,;c9{t#vKs ~^ v4;yM߮@q CA@R f@M637́}til U_&~(RԒ3,+wS^9Jz ]>wK]k bOAɅ xh,YӦb*KTA5U@rZ\|Tl~#QWV/L ]!+ﰯ/JxI^ﮦyjz)V,H+Mۼw Yq\} TKTui! [X#]_upX&q]m!4K.sd)$K &yxrbQcsp2.N<0R~؉Mmr7Rwf U s`)2xKHxJvku#oڂ]Mfp w4"vc91)ߪIxv_iBY`6APv,UZ#C!`|Qp8Wr^=l ; L0|534~HD^g,; `(c` S;0[nc;pV3`4 @@xd$B= :qp XG05+܉:vv- 8 ! d;0i`þ̔}Iac=&s'<:yWU0c4T)XZͿCx'ɂ^Yv9 @)7>5xZ ?rD(g74Kyfl|^CIyx{ NTNzҾ&XXlցʧ౩5F>vfqzBF'0qt>{04FޣJ`CCYϹV_9pح``,s)(wF9}s ,ʩ>/^7"3 )=,KW1د`YhH 8Fo08 x_ "NഭD/jt\?!w)^4Rf7P)=>mX1 h9Ks \G;=&j >_ᰰ >CZo|X,φ_<7 wݾ,;th]n 6(gR!U^m-~˾ A #DO7sb{cY};@bB0wEVBS/:6T!׎S,TL-SXٮ^{'IM Cn X\5! |!NDOhAΠ["*ChtqHg|}HgA@wH/Fӂ_*= sր }xBԃAR7f fCr~Bxd[<>b'j VpzJh)aC֐]D5$ sBTLb~ {A8GHsl!Xx'Nj*Z3:,pYt^x: ppT '*\u ;6YAz5!3^dp}! B9/Lꉙ|:B*bTI >Tf!}Ͽ0CT;!Adj2}lʸpҜg8ۇTāA/_9h$k̇lh)O{PcAlHG5rHK*O V;Al9#7K DCa`A7APGqĩ߇H.ufP 2S#X1GCnAXa(]Wѐ1O4'MgR*2 I݃xI]E΀Tn48=~{ 1՜HXihyAF)O~ԃǔNӬ N],JD^*(U#!ou%}uV˪ B, 56 16 ϿYiqi};).yw|bͫH(le ­ ;93> ypa,~Ao%&OBh_'~Fdǒl?࿐zb2+`[z;O?N2 L'ECO:=_t4%? n5Z <rPp4gT( {U=BY?\7rDeAEۊ.@? 4=i5x`AOzYHV]d(AOߖ/C5%r ~b]Ȱ{#*88Z|= ,)gNqZ1 S-Pk{%T%hoX֩7PQ1}%֏k>z^ - ]R ^>$u=U j*N34ЁЛ"GRRimP}+47/"kG+TBF: (d4ATZ \ OV9\şX A_On0zr۫_mw BǵyP{pʻ~)\m @wIxs{qWR%[Jq'hΘPڕYwy4הta^> : Ֆ}:g$ho܁5mCU۾K.rY4^sc\dJ3644LbV>)gqp?z@8^ϕhF2^V}(muAf;wKD濄;_& aXz 6dQIzˏ{ q~;c).-WkaIA0O=&_0AWXr;(=}4waWN0$Us8Vz3 M)z I;ucig[nq`e3u>=B<V[G%%Ȉc0v]a$v5ԫ06x)+ESyE.dG®#/4*}Rl#Ƨ'F`vDؗ3ywadU3a&Z`ցwa 9²Bq 6M_gߙ͗Dgm9ٰ W2vR޸' 9,8V,=r[ @6;UV0j’()lܫ]s1>DC _TI{5^0^@-hN%!=_o+AR쨆QFڻ| G0u䒷@@, 'vw?~kO39p?>.n5 N_Uu~z~H4St`nz2:3L3 6hizԅmF6Š*?mf/A$ 'a[21`OJOdm3rl`EXJZWM<,[B9f9k|+<=k9.Z؁ eSao2[)&arkIVU2uw`6s/-|`'MOlbAMϦ* Q?T]oΕFVmDL\%/@ӳɎRT'}p3N!8n20iQ8IQ9bU.++xnpi/5o7ՎjKi_;aOF2pJpWqpyf* Ge)'r) NOjv[Z$&1z&drN->9cOst~@1G.:{ߛku'XAsP#x0 VϖZC9?P~4 3L&JܭgJD]WnB\J|~݄ } T s5FR%¡R=oK)$"i;f5hIvtI{2tTL"\7rX,z~cF!bNr1|wekY `. 4C/k *#=U+~=@7p7/6Fp~~N="5?;[Z9N ~0>9$=n(6W-W.C7o=t.U?BBi7_Iɚ܂l0./;&v*,c?sb/쳭bC =!>ha 2l[gC$Lz(-&-k&0ܿ9ڱI.F{F) *Nd1=\ EƢ<$reIa?,%ݺ|挦"ڳ{j[~Q23Z5_ 14`we|ZԅRqV}qK)Dnj>Br6bY59=<ڃ,C9Yȉ qa,4C :#_ ;lf.!}h. p^@XJBXI1 *\'hz\r|aX+h@!]U=//wE^:Qvbؔ bGf_7D-57p3F*px| B#ycx^"LFbb2w'tx:_ FlŖ{SVQmЯ(-1 @ Bz.o 0MY0Bv' 1x@(i >Nkb6߲GTESdQsc,APcT*oP$Eqۮ @<(&p8 Q0tu'x-QBNF,Y h iT(Q KeyHqyУ|1>IA4{w15 |Rg(б5FOf"*#]C\E~pܟ?XN~8>:F;SC}ht/7r԰ Ԥf\?VhFc1_K9'*[jčCaヤoag4D#ec!t]{7 b|W"2;dj+ q Rz ֝FD[Np=Ά=#"V$b";D[Dn!S}MƢ/E>݂x>:;p̸+ɮ r# Xz"ƶD Jb(њݯ&AaR!K{o1oaS|rbYֈ pvVi)ĩٯZ_*KO,~ C[ ;XA. ~P7#WX(|o0Kh ?]A`77caEw_v@ő=ϳ9G!clqHa:^Q{o1LQq$䑡vXއ_DBС'"]og%w%5~m2i>Gޢ>d~f!e{5#GfҞ!lBQ!~eEWh AxdJCba$rE, @!ZZ+㭖pAƃL}1I&RfhfCFր3.0B\d;!'{q] eп̏: FfkϏ^ﮉA:X+XF$ ̾49p M[x4Q}j'{tqts*rLAMnjͦ#[J ,'U̧ !jiڣ>z&,{oD/{H5,l'VՈ$;KldWxCςReݾ21?~|ݭ]^6 -F**3%#~WBH|֦s [F^z.j.TU_e/R6c9뤮X,_ȕkeQsY#@zH8*nxs9we-#[R ֱ*UT=evdŜ 䦥T۳H/!/B6}NB-e~cHtV "QΛRCPtQˠAԲt^5;h1PE!.E1ʎTF"j^إ(OTy7F+LQƇnOU)NWpP{ @wQcwiWQ>yuƈೢӨ^Oض3<͞^}35})J&tjD~ #}Y?`:R#_eBYdL}0Sܡf(5֨u89M|fm!]mYu-XkRzx9!o- QqZSfأԿL̻zfdmQ5A..רv3:n/_krRL CU9#AcPwNWB}$<WZ#~+lN(C x/⍲;| Gmu=(ràMTᗇAPԽ˧Zuqv(P1Ld+$*.t`EܼrviA9uxygJ@^6")(˾F1%; jCzr΃ܥQWwPKxM:@?:*fߒr"d.1JJM+{esXTݭT~NM\ZB* [QScPNN(Sp8, UG  ?B )P撢-i(Kq}G)蝃lz"Jg(Pgս|bUQCj,Ae~&㍢Q!8(=lԏ2bԹY 9+?+P = ~*a#:/P?%>C('Ԡ.KS^ԠtUy$R^f&_@FitFmA/EF\,) s_Q~޲Tc_gO~DԌ7 eUq1rEBP~oEE⣖7P. ƗzQ=($V>ع,;svብhLat[zthMq;!E*NG*h B*)~8 z} 00Ntm)ߥٻ7֢dwM/}QAQFϝ]䧂McnGOԝ_@hBz^Cr}kĽp:.\&hK<'zEAK:&>dy?9#`2f=95nmS a% ~B zs;mtIʦgfRW=f_F` gFz:9W&Rh^i^mI[GM! hy*y3o%z^434XN-~+0!4b+t>ce-zzzw!#> Xv=ޢ?*]ЪNymhݜx+۽>=#qC~}W>!4'KC3!.) $t>ç:_>FnjNzѥjv{QQUzhg+}6~q{g݄0u68 -y|1^@x,c -{jwvݮ FwfnjWM O_]>wm.jo6kVY[[a+Dn$a( O6m0tЃ# #a:O9eY-*hYaLO`vpg1k:_8c&}c#\jQA;`-bK_Ɛ4ڗ/a QS+RjA^hFqk5@CU̹91?0~u|0ӞOnc.Ϲ!0'1y&/^40Z1kۖ'A*zPH ǧ͆hiquk}i]kKGQ17ebn~ `R*r YK<~!:4 )=6p?죞َ̿ww1>ͻ~`uM0L#WНh̹0"W}07gb|v9b1sH˥KcYN)8`q:fP/6spXv/3 ;U9/}hp1)KÄI O?pK|, 2(Đd |0a]|Gဒb]0RuֺJ1+}MgZ1r0A:LVZVΛJotkLҊ}O̵}Q/1ϡ,y-o03n%՘\H[ & 5ڇ0鯷0N}w1K:o2+9ЁIl S=ۉ$.)ۅ9;S#ǻ3wyt4{l FXdOWT=!(&qc= K!G1z5t1nlmbi1yLrEƾ3j º*,`m9bf.ن?qMO.c(+&ӘB^{1R-W1$i镜;ె REð'jՖڴ&b|UZ 6М3j i~Vsl2OsdzlpJ8c /=Q'-OF;cft6y-n `_U?X͂bت{y +}I'7TZ= ͷU\ǎLBbxF Hl܍iN;&} 4zTcŻgW'XGݬرe֞wW{AXնh,'ƻtL Ib󰋶~H2+V 7 vϸaO=|fbn\.EĢNncYkbE~UWx`u$`3`MV3_~%Q3'°F1#f#V37TFaX՜}f hmXC 6&S1 w.;k͗H ( =ꙟuB)wGA"'k5nU`Sٜ'\G\yU$?_Z똏u110,Lb׺';ʱE1jg#7UH`_va7:8H5p(8}u*ϨcsPϱ}MUR_l*R RWby?yҶAH:fDX҈n_+֦Fl|4},$3tBqk9F)_K;tG׬a vȊ~glCmml߱պژc'KQEg,&JFiy{-FnھOl$|D4;4vAE$vԑ_*vrb{la3b>t)/롇ό^ <ZS\k?cU* Ĭa{i^v9X%fȿa?4"v5ױ=leZd6Uք$n'3,Ƨ'qL:u1}}"- ܆ HROU[uTBǝåںk?#_g-)p>Ӧ]J-In/R!*'tqºq;'=Nᮊmم^J/1tqWL'q=bh-N=,8w᤭elH W!\?q.g '.\hac?> i[^ ]uƭZ2xchx$ d=@?p!<3}ևWzW4y^#WHkkBW`99__Wખ?n~JgUV w*nxN؜u [Q b3z3T|:iMi`Z!q[y$.0_(n\el%v N]oEY8tsE|\[-L}$nF^' 9:D)$5:c.(3%l:睈λE.ƽe2$7#hNN(գ1'r8/=#6Z&GK8Ԁ.N8_e|~Kmu!_>UPɸ?]"&q {!Ov\=Mfn!2ۜF\?]9%'%wG` Kq`vuMgc%VW(i4 :}j;k]M4}*}h/暍LyY_ U3sBwN`ַEiYzuq[*╸/q8$:w;8*ܐ = }em3pƥPc;S2sdWԩU{;ȌzVko!K9W?(qi: o+:׏{z?؏=1эK'h+ZHƼq-o}NW6r0?uo 1 XD_,8d}i"'1 < k~ce:xQF1=0h~Łm۬/nMPY'Fyǭ[)䧳g;Hk8DH&Q߮`]ss(/᱆kWɜźEFǿ_0Vُ_Yxi $R#:Cx _$?C~ӵ[cc)ziIQ^5V/E (3LCNQ/;O!ryŋI9g/o+g۝N*zÇ? {˴ŗ-ϝ 2u Okৎ@\uMժD9c|^w9+g6p5>Ľ꺭1{,Ux/4tom~yķ - pǷXv:ǥ5}@,<#>q)^Q#7V|[dd =8' qUn[lPI?i'{~E9)b4]O}a ;ttn Ӊ)x?‹"Y8aownb Zg+UPg"E'_oso}2|-z]Ti_(_lt=5h'~ů:~M}ÿ"W,~ agoOH2P#\^G#>h}o\ oc &߇OyIԏO?ck^co <:"|^rf˰m&!;YC?Z_&sjE*y1X~ӧ'RjeON5ffW U+PAAUMFqA->Ԝ_oXImS~k G$VI}sqzEVz(gK` *P{{肭be IQt+E"GW%<OuR$y\OwsgaB%9%Fen*iUٵ/- Snt[V܂S6&OBڄx%Bǔ!)x@pcIΜ&% |Z\si97#T)WƊvoؤdI o'ГpKBY8AnbHb]w;G>ǿ"a3,XcKZ6`x[2!싇-A_[!H/[BݧVgNŹ ]̱%dߧ~z5BN5_˜_-BQߜEF'Or !Cm]'4 | ٿ% ?ŠA0!UdleF\#;HlDDĂީ](޽:a'lb$o&m-0A`Q [h$|A=PK*m@i!\†V@TXuA߮v!C۾dWB|&"%LykSx~0`L_& &ԇhKJ=6*iv4=\g-K RL`cvDjox Bc(QKEzbDkK@\Ciqy{e>jlm/7^INiT ̗T:S@)AS&0HK^>Fs׽J9'},C7r%jg=#:m>kC4$_b'`ET" StvZV]:DȫMHZV'?u_F9JzyaΊXjSUXD>_1q?kb杘%ǍJ?1r0"n {Ќhq >K|cOliK$ b/mͷo{_ ӂl-݉:I'y C Dʨ'NĄ3uE?nPS̓>U%A \!NN14oT>}5Btʥ& bQzl>%71GjĘ8UFؐ8]8NġV wjO6]zHlGtC )Z Tb؋ d68AL$ ;|(jC&w(#֚G."~+shB渚GiK ?&/iKkOOĸ>!>tD% "g $i 19[ 0hr%qC[pˣ5Gdkjb5K;X^XubpX"dH~zi-Qx>F|tbY!-А@+j5T8ѳ T $!/A37G׍~Mu~#~M}&6^c(-%GwGĂ|wS>A21!5nQ:$ܒf.I"\4dqsyKRa*K}ji` [א}-aLIn8OTa\u2$M_$HRVYۑ~ H}L0WˉóLRyuʼn%3ņ"$PD[utx񻬵A:8MhCz!_=‡P5?D&(N!_G'+4wq!0Ÿ)X2ԛoW'H $m.pNRZ~٬Ic6nl,iYm'> @r;_!{UMA=osFE"$cS& kz3iH=67͑EAmd&i]A'2n?"".̎QHIU$\/0"t\>ڼMz?Atvqy< IFC"1n3Œ >jwd'g=d)MF!uj,zGADn[GZi*Grr$!O~%"$7=$#rïLcBIv )q(RU >"u Y,f\'L9MZ!l,2]LE6H > ͗6H'ygٛ$X=Ƚ'߰M5ps]pGy`z)PM)2*,$HNyq/n&B6[)"8oAHbl0yEK(9C>[er҈/HNihȒmηP";dz&@МGBk%ϞyELR9Lk{v~1rdC.}1&[%.=EַDϐ khӧ42d騆\jirٹ:?)u1~>u r,[8mHt|Mfu,q}[srY# Rs|;yW2fws SNN߮L>q21#]6gHƦjl#îgvOsNے- / =&,2E FN8"g~KVkq++46u<~yr9nDN dTyHO=0w.}"G/ T#sdcX28 NmkeV9̷%rU>f~t|+\_iOT)V?et ȥoLu+3yjK&D/mR/V2P[ߐ_z=>'[6 ߽$=z1lK-YEdSrMgrG5Әd1w$^'C΍xƮVу:WWgin&M" ybo:cOq___.̛#2@NVe,4a9B-p#2CXQa2M}\_99YY_H vWY_v y;cY)pNvk&͸5uWo/}ql%Wg|~y\l[F4Gl.ϝC6JY<#GQ`&Q._4W}!D)ʜhLж( ˧RuSӲ;)/VVPILHS+:Gi*Y7sr:\IӣRG'\)oZlч) S&(2ߎoR\D(Ѻ{"+zY3SGOG^zNqSo*Ԕ\2O=!aAĽpLrgkK V['7[Q ?o\LHH#OQI3Jf`+@kJ}7U>.PF>(kz)F"(WxBTycY *HLYËRRzZ6A:΂;f`˟?6M)][~# *AoӖQp}(ͷQnD]8ʉFI%;Puu$es\ F.qa*JM)`)oO?sPf:yp\Ĥ޸bgy Y7+ۂSP(wUQitʰEU a"E>苵22\zFIt~;D )<ç$He2(s3փ5x* s,ʞZ~n 7ZQpʁJoQ2fc)ʍϭQn\|;!H=cY<2qჂZneR=Mx봛焩!]VNrԷӟmR]Ce'^*iBPQܢ< ZqG O |SکR &ݳd+$/q-?W/SW;-#SĠ7U\`C/`Nu d\8Km3:G%l G[UC2+~WkRO:03/'[S\q>O+>p29/1MLcZ{j^^5=~!2BvWjcS W!󚉸bt?Bc;SJ–B/G 9;@UŸ^:` Q+sA?Z^Qa?3RFWBp`ӍCשs@Ԯ{; 54S7rD } T06: MU,z"s}&+9fūZ Ԉ]0*7G5o jfMO@Dk 8'Mh8Kq./EJ꽯roVY7!]gJoQEёԋN BjޟVˣT~MG-Ag"h}GxjUGT}=jr낢,*W_2K~D̈́R^ATOя#@XQCP\U/Rkޚ1OP!uA:6p6ःJ1Ucf1@Y<(<:L[p .i3 J!˙eGwQj?po[ZyzSvGgj vϩgj˿&Zꔴa#+jjXsTȧeH'FxnwRʪy[iI.piL#W#ȪYx]Om8P*kGm;i~nڅ}usCtSג:l.)q#[#^dQ*߲ *`2Wg𖯍З_TGc3Ԛ>3T; ϧ 1(̔9d,)>s I^~>oAQId٤-DRe%Y~`zy[uӿԵެc F(5E)aڶJt[!鼶$wjg]FSLPqCLHg Ӿ #h w"i .C¥hn1WQOOPzP8q9۵)*$-Uc4 vT1cウhauGhA/e|q q+ErVC4:;Yy=ZKeajI)\u&M>zdD\ ~>> 7֛$$1IՓhze=hb~4!{a[D__Ip.::KBd e|:ՅF?eC =%%}տ}pǛFW):aBU/ ^4p\PZ25&wJ7nw|V" %xa4oh}/ Z\j[ 60~MʻၣhĻZ$._ l4;!C;c]f$=*ecvIkJi#&_k}GcՅU~EimIO0>CZ:c+O]K_оEsIr-iAS'=zYڋ4`Զ\N5eLô|NfJ)yx.; ټDtQ4շI4'wiWi,+랥 գ͋iXZ!M8i -8 ٵi?*yiʦt(Z5MthV[y~6nDUVf?Iџn+G+ieAI 4Ծ /_2aOic"' /hb_B yUS2oi?׶TѤx?os,ߺBi%a iA'*decR3mqS}~?Vv/r3n&csP$GhWuu~f(}GV^st MbU wڧ"?i:bh1ᇎ)RhcQ4NMZ"=Ki5@hVOek-O|bfwЎ/>L3[Whw:hJ_ߗ^xu#Ku{Kv>\7r#lfJyzr4y:nί _B牻\roV':9J_: güO,LK}[]J, KkHZ5QY8z | f9[Gѝ>Gї2n~`hz&|C?@N:NJU~e2& ϕ<`0h-Wô NU&cNCmGF9)\cv^ qTr:%B?!6|9?!t9C|Y`NJR!w-`D}x'&|Tk>>pSa æ[: #IeZLG yc"PkF:L[CCؐ͛[mzpI/g(zS=] +Of3 nOH|(.lt?X9Дde43|2s-јό{tSG-:"7 Fe>_m_R݌kZ2= #cU3KgЃ']^/?}//0$l_B<w立V-2T2ǃ~2ɟssjWceg+eyvT4ef},8zvjun:*h1l:e^)<|%b"xcLL#p& 8:)t<{y'_WMA&全$ȻI1)bY#xGE(![[i\&2\O9tDPa")'ARhrL5L]*Ӱ-@Q&tjCt@\L)YxqI`bf:ԍe*]̓lfELՙ(ZL5't=KD Zr8vaz)’揸Z2E(mZ3TKeDMF߇g&/&4e޺ ?kʔ;3UIeg)g#Shsσ*sWe6gCa/~]g_c qX[CW0H̱0b`a̢$b/83 eŒ1LʯӖ7qL?țMK xXx'y}E3ɏ RX d YLQ"*)@}!3mkљ5vLҥwP:뭑^3c/?3OOD4ˉ?Lfqk7Xg[J{eX&L=BhLspSUvJƴtQ0 cP;0jVͱv$%TI>-\}3Օ{1C]=)Sz1e2&mMGc%3=+.a92{'٘ѴqɺIp)3*h 3!#T8OVZ󱭦%]oWVtzs Wƞoϙ40hߌ2R#>:Fc)u>e9}I~9S|D7zcG27V^~tvYN\Y:}0a ~94QzĽQP#Qέ?{ǎKŬ33¢l3[:^ݞb+a6`yfq,)%+Մ_L֥9fئQҕpּSL_CYnLSSkLWMf֑/K{i;*˯; 25m̞.ſ̳ݯZ{WǎdEY*/A׊$XO*$Y}֮ BNb,8 [YqJ$.]2mcyHHve!ȃ BxM'YRseϣ,1gaEojE4+Aґd%NJЪYQf^*|$*9hRtM5[MuuJ:jQ> Y?,}}[}nT4K%iD.W~ -etۏY8be3Vk֒VKV mY1b3Yo6(.({NH.DǑ5@5{~GĻIc6o|X6UWXQ W_eWHaϋ%6#:b/r/i|&8nmD{XyY_]Hn]ػyݺ`1^}Ɵp _%AX1yFP; TQO2/ ɬ'k,N_> âp:+>^:Pzl%n2Zy͒:;D`mn?YׁٖHV[\vq-AVHO~Xk-ZcYKk:3o(F¥=GBYGknouo'?`=>ŚٻVSJ {rE7l-ϽZU~u{,gdޝ%|K{Eyf6kR,bSUuϗ~)bidNf]x2+Z`1|rXy%R6v'[b,*Y-7ueYM>Jdah~)%G#*S%k~vpa,Ups%+^e`-+R)T3kX,0+1&]oKCFiDKJ Β.>q%`hDmP<ʺtd$VAC,_,qnY6ұo'YBk(_ ^ }f:WV͜0 ̥_F?XH5)yK, ӟD_͈/~ǓJY~R(YVg q:/k KoebT#`IM7\YewF+gvnwNFe^p$!jkOh ~ :ROw%ʌމ$5Ƅcy%V, MwJ/|.|u 9uC=~;wAlq g.] Vd2Tha,>0᧽ ۇdYݱ]ݿwA8L:Ş9QsIʩlqsZMϛ܏3F}1?u0q18ROYIO-iVwƜyVmK𣯏V͍^bfl~&lD -Svxsl܃}Vlsa=2zk<[4J6&:Z9iS𠒍y/UU6 }=V:F;ilJvRRTsoo>nbT<7嬿eCj*/53/ =ng{#[InDr#{i+=s ,Z}Y]mpgvջHl2 ~}ix~n`v@7;!v+cS-5}lɀ7~5添^b'! t/RmmIy;ŮPq@F/L`ˉw3^Ooߤ~?˜c?Hހӿla.qi\T6qyԋ-2%r{3)f&۲0|tiuM©$~Mc6&ek \0NpD=wyO嘆fmT rN)28[:CN8T8l]̐\~#>\ ƩOqRT[^vtܰ<'4BS7v%| G};Q]1 )qHϨr2 u8ypQ61j7XӜLBͻz5S9eI7Ƌoɞ6čjp6Fvkrot.au9Ï43]vkaMhq?rOy͵ wƜN9W]<M;aeŵ;rƒ~@C/p\? 2gr|QK!۽9+ (%:|ʖz؅<;چc#pc`vʙn~`ɖ<ՃYWey+\qSԳ:4s)'ÉWJ))XD_8 #}A`95AWCqŽ99g[PiJ|7j{ڽ ϹPAUphp^\=}L2Xyyv;ݧr ?אKI˻^!zdNz!.55`p-}CL1!0s)%rZG/b=Ź lk##^X]APG}bjm.g}6g?;T=ӥEQ*ï|3t*!p$.s&vst8J:!DM=gfߑK/98zNu*'o}yYɡ*9YKwULj9JQL%6SX큶r*R;}l';9~zNO};9SJIr]{-ݭ_nȅvKp|;GӒ@&N&pd8c6 q.F sW2~~$~U~`gK s}f_9ms8-°S%pGoΩSÜ'8;G}g8&WI8}0)膅NMs ca άI"׾KQ9^V8IUS%2'_ ߶Y7U @ ;ԗ9AEMukUZt]TAnJ m|a an;8'H#tzx,έ3g&⦟R%Yg|*Kʆxםdv4nШ+՘&ϥH E^qe^{̭yw ]D[ky65"͝hq OI%չwNYE 4H~<݀6XO3L[V,$W) HθX+B|jԻs:7pF=.q=q ~\ +JMA.3֠=p%rZ%RBYպ\Ves$7GrOhgb'X>\ Gn`4 sMOBi0E?sOe~9~N+~,&OTN_ru}s?sG QR(:J%2֭`-SPr'~ ν7Rq&eG7Es?p&Ƨ?6 \#mFqGG=q,{.Us*Qna.bH|ޱTϪkWTɔ2_h+lblWȓOZTmq[d&?N5~ |)kep]uy\aI8)24S1W׮ 75X}d[y%|\dXЩ C:g^sk֖ zU7\յ\&)h3n|U4qO{)vx0h}͐mą zm\r[+punUq<%N}|~`Kο#p^]R5{;Oo_I;˭Y_V7[<1՜LlS#Zr-5'WJK]iYݣ6k=v7Qn=:Wf3Ǎm6.. YI6#O7&}2Z9 os-E)s^ԓG>Aynύ{y%{Kgf^}+pƁP:KV|ًj1K"+r'ʇ7,=$,ˋ0pzxTS[=6Ydǫ+OQ4XwSLc7;#=Q*Xsd^~S?#ˉyL>]||d%"tx=I}\SŜK";Fxq.'b%䤧S5xAt'<y_xgc|_twoYb*.˻ >vt9$#MaGX-Oj g48n47{$U'g}Wjs͔-zp,rm~#uby /ck= _,`{A~^7?6 {gg;of]ġ77N}'w* *56ӱ7Kϻ5͛Eۍ!)J]nM/?Y+=uyO>,OP_^ٿK+U9@sWy񛾊wx7~~iC$o:+">Jx[K2//|*ɟ^GW/t7odϩ,f_HJF4' / `._{<f/TaƏoLl4cQyWO@! m&qE) f?ꨕ`~>ۢ~Hbe~ڠI~k'.|k`A iƗ; +H5$'%^jUviovZ_F6r:҇ѝ#9o%tR:xjOoGu$ ;;:a}+ gͣx:x oZƗ+6THjOxU|%.nRa"?lsYer̬jm%h߆A*6=/eosf[ e|ՎW/ YYO rG ~} >ޏ]~GU:۬Ѧ*PS/u|H 0g]gvb u6-g7YWu't=_1jdg(o?[1lOכ>7ɂ;%mw⧺Ʒo P !~Eag[Ӂڦ4/<㷾`;~YN/s{9'b͔8GDEfeM쒱E0>W$G,A;T JRHHޞlϰ?A%F ! 2^  PHTh R(TihW{Giqs];x%<?n/u>y(獒7`^K~I-867 7X)w`h6S̼Uu)/ĵ^G׬ͨf44fn9Q/}5G# =5 {k<:hk|#f4d85L~>~eFm5w>fAگ[HˏPh OV[μ|_@x@7C~s_E~"~P5O Cz\Y{ܟ7X :l0Xznw&haާt#%~S8iXfOZ 0J78g+wwSM,hSW/nc`dA[ 8\ 2b)%KԊ&җ[v 穭~ob̃J48>GD07/Պc'/fhşB'~œ?=hj?#0OpczRHwy7#Iʟju~gi Bxݗ9W 3I X];IOal] .X.RUw_3Վd[+zwa6]۳&ԒNvëkR`K`fԒ#))&I5<:qx=\9E8N.}w3>Tg߻BQg肰ɎBpƥ,FMj5XrN͂A¯BK:!f"kq?x& ۚ6ک~O^, m߷g@@0IKp|nk?y|߽*b_X{.oh5sˌ_ cCz u6Í 1Kx`K%[^lS-_-yxKs{|B7fis4I `7-Cr]: 4S\޾D+xŁF~ ^ia/|HYL:\.̼|7wl~I弅g])@bߕg}@r{xDUݶ NIŪv6 ud:77=XPjAfWaS)XQ P d2 P~v=6WոF{, ϋ$ [K{;m?ʿî3[MǮDAce|[ѳ >LvKя]r GPwL {UNJCi0:)" j{tu,wq)_WgT„5pgp_SO;P=BfSA1=/lʡNjk#P'n+큞3sjĤQ6ɵjloۢB#l0Xj \Ӱ c^])ꅕQĻrBRG2]E TOs[<dz5WjO(ſ#C6FS|K9IhcoK@l}ؚ?^]65$T#`{55/wmxЩsʞz1 S,Ȓ|Ia ԨD \m_jn*{MTpx{!Ɔ -}~HmTgׄ4kǃ ѽLTo͚5Ϸ>$5fx g}?z%G6n¡$ |jvc&W8)F!3wIdU7CEx>\&E/BfUFX ]גEڮz>b>,PNơȪg4n Axw&_P?€Tg7-O`Tǻob:i;W!?Avi;J/s~/qL,6TJ?S%۽8<@G?{v*z)ʋorVwzA=2K`3v]PWt~Ce*~ww gâ( LۘUCgi1@M5g k)k{pNT:.0D 'C$ab\I,W W:t߫M4X&}RcޅεhDP{k!)P&e~3b\;+~?l7Xi꾽44=ߣPzc B}B* qi%HƓRe7hBnj<)RLoHí[ m:^ĊeCo7.xhW U]w{qqQpdwp ^^(D af7@sɃmXB>^E6AzPյn}G}H))^kLs*JCA̵* z.owК L!9Ӄ#Ѿy>0&P>M\!OK~xX=;/Բۑa7h銗`{4,tNmQ =OA6.V[#xuO)inVM`Z)HniBDˊݸ޽`cgco9߫(&Onc=/atx| zqUn"R7$->\R|+S) :Yb<% #fugg@/r2.(>.pi‹v_̅/ 01Q=+ _n%B MW10IϳB5tom*O8P?_yo@KJg?9)6 5(6}A8zb7]8Y>V߯GК- wnk||sj7&hHQwc ̲ݶE ohrJ&.`y H[8&(nʢ@7`&#{>γC l.' `a;(òrm6EK`fD ^A;qZٰJǿF[6!U,YK3=_x sY+z`k )c`ߪ+f^AO JVPؾTk^HRz8d\}3f]gB 93"T٫Sr $JQ ?S0 jN.R}x{O@ʃhsCrI#s2gk9Jl Դ%X8}n.!y/ 2hR&52W?raOzABN 42h}>W 'b&vwڎpf} )rm>АBҷkb\pOB7̊gafd%A.ڮ( 9)5wW&qLY%2J0¾#jU}?q =x g҇2m:<F"峁G6Hdw;O~+*߅BZ}NuS[ }Og#wT 865ȷm]Vƒpk+`?`ц+L2 ܋U}:mO.&AG C*#=? {_K?@.&qtt )˞<6v Q6ZJθ:&XYyLG~;0ɼ 6ow)BRY轰Iِuӏ &Zԧ:qO_j1vzȦM"t+~|+H:ls N7sB,Gy1yZ` x`k:|:g1B)e'٤`O}!>=kF-X=츇 EmQHO; ѡm@.}IiTH[)6$~`m'e<=׉yld|h_dK|Ɨe0tg,Ovma|{0BsŗwbĊzwAW5B\F!w:wL6EZ%ŃuݷYҡ=6G"O.gְd' Cfӡvՠe1.V7no՛,(0t 2ڸ58B-Lsj7&Yqj*:x\z &%b Ty&HnB]X,\Rލ*& scW pnTaM<׮Iz)\LeȠ`2.RfAxe%꼉-Pӽ[9}T́30ِ:̅NE,xqĥGؠp|{,rS1 'Nȣ*TtX_tVtLs=bߪ7nEJkfJdݞs@%A>R<ۅ.O!DA˔v|dĽCJMlލg5fdohFBhH0}˅5zk] G,3Bl~ [CI.HZNPn[vlNd[Bc=$]7 Fc@j"XMhQy#,нv|P BZzwn G"uF4m@>uc#*\N3]xA?T_B%{l>6>;.p-%[7_伥 CL`6ZÇ0}eF\ l@/[hi+HcZ6y-zkvTSugĔq>emOhX;xy^yiA๙2Tod݆[;*G8yi[$ANK[:>NR;giYZL!y̌;ړ{'$Xn)&D/>]n2VIAwJ-^ '$y.+/M<\L(FІ/ZL\\ Ƥ3 o{]>_zp>tnJ^M}؍ OK8i攓T8`fvܺd'mB_dQvoíxSeU˯1tWFotH-ާ@,Uw;PR`I]=OkAnN\8m@]aqҺqeWOfh&58uc-kܲZA_y~<*U5Z ^<)4|@DUM`v_vo=J0a]v<8} )q ks̻Qo ;Sʆ/nSU.؛;O;k(xN.9ZGhkte=CXW!R*GuԯܢĺzK0gfL}7DY:=Y(-?8I o+e ;Dz61$œ2tս5'ppUcg7C]}ATay}f Fa G]lԻ`߲n }[ <\D{Pf/q* `@ۓBX zmӛ {Nzv ߳{֍Ҕh;t 6;7OVss3{hpտé PwH@ΣW\<6%'pSY cl,l~P5 ן8Q+䢔rvQOv^|幸#Q^oCdo/`QgZU32 T͟]iku ,_P$ur;8ƿ?;/@,p. N«k~͸PaE):$4ׂ8B] >2&xxH>nUβ{ROpWy?ӏ)5 9(!}G;<[!ہ!%"xCV9 r+/)xθe:_ͯf f(^9mM 킚CV9Y13h3Zgl呜&ߋaU}%M{F85wvwR=`XzI['xϸ  jpH0q%|[RH]M7m{E.}E eH䖔auhs 3| ^r G.Wn}EA= 2r..N^υ#]MNK6/܁}CkhYJVP"U }탮4\]>{.W$0\48/XmZ3h<,h!C8פpš{%B] ѱBO~~q6'0v[9qVӢ@;'Kul5۲nviϟ>|Q|.*ѕw`ᡞUKgy4bkS1,u(v3)pF!<\\߹I@g||zr{ X Pj8 76ڶÞ,x豻Úf|JgnƉ[oҽODϚ̱shp2c?ms]gk͵M#«;6lF;M~(q;y]yK@,%ʨh^m'p=/B;8ĸ &੊(SC<{P.5UjϿ e<} ~Kgk'\/]`}N|v^m&R& dg? w8R!8,Q4wg]:Vu0ї@J̓ ` ;ņɝQQ8H@~&S׺rtox[ NOPP0 {s@ȩأ^rw,Gx6ɠq\n:mwNŝ^|JE6p`2uǶlq8x]M V.q(pY52:`?G7q!X'pL֠v <4<^ږa>\p%^/ J"& q8%r Lk Kok{}US(ƿ]g9v=@{v-MQ'U.W I-uz[V/Cml땿BaO3󻺍 9z -1 pwъiGcͥBݯNT2@N"2nܸ݅}?ZN~#mD;>Y,_._`{R MCV`Q_i.|O#VjעWd~ J iQmOdPqgɭ x#g,hfC~M>xTe5᥶}PAJ|?w&oMl_H%^' t2#P CbGXlq@?< _&shV9*rԋ 7-`črm=\rarZ+4Ч3EK1\KE:SxBn1^x$:wSױ `G P| eU703_yXȔ͋!pq l@f]K yJ_޾D+NJ$!12|s*k-4S50]Z9yj Bb%Kzb@UesiIku] 8"T$g̭cCjZ&HD#A󏆀PwoyA!v Cccc_f$6<]rU ;މǁwS:ݭ?Ά gr ^Cgѳ҇YLi3>:-#CG\%,cI*١jc\kd & @@gsC0:f&qLQv*3cQɠeʙn("qaG {۶2q7ʭ|`>e͙-X2GFP6<h"YmtE T7ȳ~]{kYdW(!P플p^sRdfq/T,d%|9^՝rT,}᧟9/i@ Zn6\qhS6>{agovq`hɞҊ`F!@dn0F񏚿xG+LƜhR~1n|Ew P:ژ[sHgC2MV\jn|2Xp ӌۋw~~?^aD߱M&A ԋv [euKq<Qb-~Cfd2 ڔJ6j0-eme>T=;/`1?/ qnQ>FbJ%'iD}̖*0W5prGP-|Rl+X$~B5eslwȰF@"zd/&$eݔiY,? Zh\^wyP.v37b'}!Pf-- K0pL얝OCz=\=cY P`G56AA&kp9?*\JFV6Rypq -$mP=]Uju>(ˆn˿AWқ$U׽;kG%/twZFj,Â{@'}ʎ*K?T=3L$sHFaP0Eho߿.k񟅥Yh冺 _0 h&[_ Oڦ _K*Ƚ$_|A6UUYSBÖ}5 t3:}K+}S=kR%ƍKQtUA^V>R>pKk;=+8Lh>^OF'T{S³׷4uK#TaGBcOePۨ j%fm ZeVG;.̡8MdUJEc{e/WÆ;^P|!1%rOﯧȣn4C໐|?D^~HvǾNQ}8ف q 9]s[,`vNKrXK;yA <٫2>sP' "_б~^b}.(ה]_HǡƧi&V7 ]*zta#V" 48f-c$J\߉_"t2ts/nwѷCCl Tc[{|1ւ, .\bwa..oCJDŽ 4WU-㲔fH= R[nYN`h&~\:y&C GqLٽ$*?܈wK GKړK*::Eܷ4>Iq|cAX-@{q s"QVb Z87|P\|fYqC|,s\<2VCŇ)46ϮbBcoSkD2U<H-)Z; ,N﨩oXh *ۃ4 ,e,F_xﴁk*ʔi66Ph^D4Ӕ6~uiʼnWʃ貫F>GbBD>_$;icliw^n+F-0&42s+n/T;J \Ą+<-s(d+mG*ҟXIXu.-rpڱ[BE)6ϔX;h C4hyygus-Bf!9n6:Bݒ34|p Xrn?Bq_2~mWוuCGy=s]ohg,kۊ_+1LݞL-#o2[VEw!\,̀/[v'⿒_l͈8fCi,^WVd ]ʅUgC39pSQ/W|{vc蝎>~zﶇ{o7g@Ճz(?YN]>0[ ˇĻd.y56eybcr rpvs(g~;K{;Dh/‹$=ytY<OOox 0KZ} N\jo7q?^;ʝ#Now(ī rѶ+$ Y?|gCeFlY 躵J>#dw&  ʲ*Gzlc[__k֞+90:`FͣhܯFj6$5$r8úEG"ɡ8wpXBEl#jT jЛKÛ;Tq80}=fCYKU-q}s?rD5g[b%@I;>9QoTzQRgyq2|[@9ۏ>۾Q2rɵO?#Wˍ ,|moXs͟#cBtbܑҍ拏mSڠBe\'AMK+dքaQ%<)Č ]`qv亮ҝv]p pVfZJ'}x8)n :(|`E]A.;=J b%j( XvA{}>]7z?xL4|wІ~iKV=l; ;0t'iݽG gz+A`g CY'|1Մ$O&W\;z* d]j([r㞏xmr+.{ 'vp tiY 1ßO6Y첳ltO!-r>l+gp/wiP/?`ldz/p影!i'ȩ_)oA z|(h}C@ʮoB@;p>1 RL ^C[>/(ۿ?<\Egsdݸe%GYJlwA2VM8zяw]8jb% X 3vĽdBnqI_Cv:6!©I$D+Iؾevk%v~]v{&;z3,%ɥICs_l5,^ЖS2\jhbnYn9Y 5P%HK} Nw$@9SS. UV-9GحrP0w}  v~,!5܈zG!A_,S-5JΜwz kyF#k|J`cS_Bꛨ ⣊# UTXk>Ӟko@9FR H aLqB&CK1x64µvߙpSKIO_i指ᤕ\|ғ/Ҁ[kDQ\}^]{~UWy,9]fyT:B%rgH(ί>8ϸw(8n#Qyrjwѝ Wvh叜-w8`hHxhZ>|.'s [}獭}>R<]F Ny|LU.~KK c6Я9S@&ȅ1 튳UaM\'KQ:`hΪVr~8@o5+ul+7<:m.21 ~\k؎VK|cj]'q< ɫ0A}o\8wzCqGrb ܅YPT?TVf i78AŤງ;fEL) ]/jyBٿ_Ӌ[i߁巟c'fj[g$;Uvbki㜩 ™KGSV㣑 ZLvx1 =݅Lksl/N`C)-3;6ޣ뉔 f_~vL <H{C};`ЦU]Ǻ}ZAY (5C]ߩ7Z{@;kgXTl͆Hm;~gQ?r+Pш .-Ċ\4-9:I$P2SmqY]DpĨZc5$r=Ҏ:Cszl2xFG)_.~kMQQuiI6v,8Uf h}qM7޺xĽǗxM&6b4UJ\ڥ(&On4e=Azwܚ@ӷSlofHg}56 QFZ]f2r_>׌魜&vO s5^3`8߈'Mp|N\֡ }HcCϯ>f[zR_~1P9#^@\.'k @->lM18.DJu=~5Q&[dwI])$Г?u|<۹5<"V)31UE<ӧׁ`% ?8E f5I\sDړLVm0z`(X.&o'` kc } ק?%T!Ȧ Ϟz +>t ?0тyۣ1c 8L٥>ko[d+(ȧ&P#?Y׾z2,ƳQk)ntJHH闻iv}hJtvIlA-9s|3AIFJ:6lnMnǴ/$A ,l|\v9$R6ǩێ#mڰhOZ_ $=HO^.#@F1*u}'Tk_`Hdu %+ł`6W?h=dSv=PQ1Qm>-@9oE C@84D^V8̂ yZx1ȷa M'$u OB>ѱ<( \QA x): jU c\qS[.;ۛ˞ í@_,(_OD KnW(g-sYN&_c㸬1o.iFagye^$ oBn8|FH=+ up(>%9n??M raQf-oEѱH>k0hA/]G2ق+8&]p>G}{k77MMa,z0GĕǗ%yDιR0Ox9䮑) WeY+Xp>$dMw2Bfſz?= ںI~i  9^\Zsm!:$MN}HvE_%^@R%\U1}T2sqǖPי˓`ۖk/x9 >]ee~bq%]*adf#8oIU/6:tzWtIgJcHP(pEܺFhzp,؏{LC:wȜ G-abdP##:^94 UGzf H=i;/<Be|n=ėݜC͇Z ,6XyߙmUW??E>vCP'd<{:/ܱ7י€x;%$6qq~ 4#E}kVDl?e܅G:8+\ZoWZPĪ~mIa;}phӃ4KZ$oȏ|S꼪n">O\h^ǑZZ 'Iz0۹!Dt}ZS~' ,Dv[q 5m]Rg^\+%v%G16H9Jt· : CVOJVp<:PB` /vh̖{I}ۏ((Ddcu C(cK.}8\Z61C :<9o /Ҵ&a:L&dt@'"XR/#p1&1>w_оOA4o8FR0vC= 䚌3r߹|_G~/_q{~Y %A&_|sC#ތDߐ4WB#]_|&:1B֏U{5Sj qs}X7:z|/ t1]2 TMnQʶiz؏ɁC=KaQR \佛=6b/G? %`ńߞ^XX, Np1CJNs༇[.$`/e58HSr)FB* e*ߎˍx4'wbyj-20T򦤅3_B7q&wo5u*HR[Z.pfgh&:[N,4="σM4|;:~7h 6団¶hׁA6Ķ^.{e9+p0AuYw*E QT~X::.Ueº;7)m8`C9G`caTuKU%xM݊"|.%$j^acm<<\x3wl/iB~]~0 > njT0Q{_K6oQ/Mb O1pW^nɋj]DžO8ydzZ?(ب5C»yu/9K\jd4&wҭ|3W][:;K%o^-65կ!m߆P?W:oƞ}}ܽffBi"n&Iż,Ƅw)٤??ӆ^#J0݋Ш|:]^uq1[tBX=9Vi266H@iډuLxT6T z߷]DCF l^>T*Ӂ.6NP@HL\&;Yʮ-B pIw㶷%-xMZ# f53VdH9Di:GM.re\ cc&" sщ~ ڹ-Qꙝ J_fR-'K' \p-dmIw |sf e F(WdrYˮ Nx 7 n&lnQr9{  d>֎JvJ$쑞@ .o!_Z=E&ēI2eDYV<"#ǥv|OD/bټg \aHV7N n/'#󻳿q"!_=_/N$ J?-ZGy]k [g']<<2#&_5m^23o$w暍?4,Xc8Ej]t3-n# BO6h!x'A[HN֠@)jM8?tjkRq|D<T(]IbTn σ~Sl^rG\L 9_D~> ̶CɅ){B,؈D}Ű[vp o a/v+n0TNܾDBރ[P(cv5<mǭ){aA@v;fϳMͶ{vO_GC>K'xLϝ9痗!E3 ~mt4g⫬sҙH~M:Pz{x?0WJyъr $QvG܎мuTۃEM}pSt ^Mb@i6&nv`izxaxT8uNg|/ #%^X gߺ=Z6ӻw?d/cDEi+;ĀنiGGz:mִ9֡6h .V9rtyŽ V4zfj,%FCMf)CFF"5eݩ4S'5ZS m8ŀɖEց3&xu{v·hI^3IR+9-Y;CrX3 /%M󢨸bMe%YZЇ[(6P?Ʉ Akx{vPD0z,ksY%wi>ئA~??c;Ѣ?}e <05@ƞ㕬FܻJaڵEmtR.SuzF-t74'D&dLJ&WCIP ?vجr8FbB N]+' f]XvI] L'PSA%dbt\#Nw{C>~u\ `VA )'pjCG-qN @#ʒ `/cs|LmDɾx7O> )6W8X$ҊMlL& _hKñ[jNRl8 ܶc>Y` s2MA~ ~}m;}{A2nnN0O>n-|- U#@H"6~E&xK\l;"cE*bQ`Q)5l|Mzy-j‡~\'$0!AT,cC`k!9}U13/ ,[]Q3k&a&oνS\<*:JX(H ̯{-f/~cJ<,(Icg\a*Ja&{ l>EV]Oq@Ñ.j[N~1!̏^p^O: AӥWCU 0Q*?砵#/\Uuw]@hf(uCcvX )ۻ8w:=E aв}&1 E1C 8oߍ1x@lKr#&D@F%*|_"0Ip;jNʾ.N~+հM6^/e㮬nk7cΛ2r:= NI]X=!˅/Pa5d~.lQ*}# }_/b…cSC[O =L,Q}}jT<|8lj[l#-cIcz NF7]`%5MV;DYi0+֟X_Ub~O-iPaCM ZkMJb'gB|VKU9:C OU)APz| ;Wp1jֻ{ `~6Il6"mҹIA8r7;ّvȇݲ,6^_F@9\_<,UN ґ|]_;ِǯ_$E[wp]iCx,ŚaH30,i_U9{,QLQ x[Er]ƃƊlp+,1l"78]Ng3c8Hhf 9-T /nTkٛboEoLеAsѽG*q2 r_&obO>N' u9(%!0&/F\jMG/A8I@9\Ll7upp&ON:O}*?oN \[\ ]0~oKyTrc(LBB a6.xc&,#nɞfXwYB G?y)x+Er&XN7!d ~XqZt$K]Ȗ/ pPN3;' |woZ{ 3l {R޵FԗjqtPU5|wMhtts"6 v{v;$] jfޏfC\iiiC:ou!_ ŷy jv(y a^+1z+R*lҎpZ ~IZig])}b{}tk:&=j3$XyRT&8o^ .sx*J6-O߭nͥlIt}5/G2dj &cܱgZayF {X;z!F|M<&vidւ-Z*y#['/xkE^mW zG݂ _]5'[0RVkᐾT0PRht9~# TFZL9% Ǖ3 1;UoU.:dN_ý2<]FCl3gvݷm:p) P'JRz4 O܊̸khM|L nK+W5J?DQ$c`2Ofc@'QDV)@=ڰKi^۫tKB&s?8}ь?:PD괬;,U-BwM~2_=a,Sb>DunVF\H79O@/]=lԭ5~"ފHAv𤿢aՆ/Y-'0lCS\ .e_ PYuy,PͭGL<qndD ыNuyƎ%Eo;2~;DaYpts Š (kL󬶿؜x{aAX [dрTe~Z@4H|yy˾/][4|}hptFMW3X2R2)8 :aa;V77ڞ2:__6NM} q?,\|GڲWWBLpJk1 WVjdur"];6e/Fpx- EQUՂSm<0{6ԃw޼"H Y% _wBw取jRQp$7Ey1 ꕆNU(OЍvhF@bds[E:rGYpszK=G4:PVI lL=bpC H'SwMfw9ŸsY߸WC:q[۽dX}[ v̅Bx8[p7ĆWf`usՆ˿O7bRo>&|9 Lj_mB@UUG.>~c' d%/h[M'8@K+${o0!ߘVL7&}(wy[ٰ}%PMVMmȗ`@Ҹb+.+[?=8ty{0_J(7]7~|UՀr?$ u^os]9:/ ΁α≗xըē[~ 3br} BݼygvJ)VnQ{n uC0yK8!{g=O:Kb܉K7 br`zlcMno8b}6FpLR!Vb^B~l&ꁎ*s* DiooZfm8wx\[i+\ߏD/pBƈt.){пklD!qC*[.3!zkڟ'S%pzòF:H%i =$tN~^)P 9bPx-B Ϋ) >$'Iŗ͔(S6˙kF6ЂrvO˃wv=B}e(ط1Vos@sb0X]fNoYV[_Ľpsf],dG*,]|c\ !zAAo:Jkhgh5F>k:ʁKok>PA&x>#gVLNyOբ(F}ֳ1d:{R^&//*tn(c|)[wAl)>>t- Aeet6_("ύrt0>6w[F6qȳpf3~ (T!N`lzNk'cm%wxYy+VEe}h ~s1%Czf+|Á󅥚%]Gcܓ)i2~c :X^H\aj~7$h~3_}(9z!p^z_VSg Ey[lnN]_7iűgqZt=9nfx]w5K >|kc3Vs1ю xHYvʶA4U椾 [V.\a>:`LM3^c.w+"w$"ܒjlvR gw֠TeM),EGYs ([Ϟ"9k1˃gtr(pe,O6I/w p}hC5݀g 6(Mм_JYIkfڠ8|W ~\ulEOCăɭTxZ?}]KiPxa]]T7n|2{kKfOB{ǴjYGʼF-w~|Q6e@^;(ZD;Ԍj=Խ/8)as'ͣ߸K>;dž[W™]K; qc΄GZZ}ƱU~ri: yW/ruU3 af3lɮKbXb# r{e34XKdǎCJπ+M{g~l~:t}nwMb6Ԗ{,d<{)+p9{Sw7oWKwүwE %sw|`Dž>S IZpJݦQ]pu7W["GPbiv<% _s1`ˏ,;v_ uL=@Å]C5irK.X>/cckM2Ѵhl#j8́P߳v 29 N>Ă1͛w#YCc-$K?iDaB|z(B5 C VL\!-CQh.jZUd>/ @ } aȓs%皯q`:󉺔>4gջ\bʮIOdL|} YJ69 2C< '.R!&ـ|7ڥPEXGQ- 2%% `m,!ܧwGRˊWNh%FȆG).rp_5maC0q̱ =x9E+}/oKVu!1~f*n*#p*t@xqwS{ytq"T'#tg1!YnlXSV Rjps/~X3Ftpx? GmJ[sͨgc|qrD ]g E=<5e`cI@]?R1q`ԋZ;|dž/OլȫopN+ p~ 6"3 操\(;{_6(/=~PwgZZlBCUg, }PNÛ{ڸx4TMÑ;v 4= |j\~wI$^^qGtظQ :ZDŽW$搃8|"`mruL5މE54j55.ʚ%g<7?`z_S런G3gwqS}' c'+>~s'`u<*nI>e*/hx֛;WW nz8%'$2ZpG 3ǑnEV]Ʊm h߼]Xt+ >\? {)Ee^6qVkYg?QWn##lEryg#Vf<2\dn>U*|C4y@+_Ϗ) sK ]:C:k阧{*ֺ7Mu#ߪ_oHzXEf_@| t 6d A^96{e]RPK(ls>o.x5CMubCCKDò'šu?:ԉ/ݖ;ߋ#ދapl kw qA Npb\~# 9 Vc.v#p~]?(4c+Q7t(OK:$0-Qn8u;b]/axI3 S^x.E+޽ tyoa ?x/吿LyMNF)[_'8w/U?9 dL߶CyAD^l'oLCSy:7'`!Nzm~t =a`b5vHjuС37wru{v0@B^eW^|3I d7QTWB_pX:a=J w^7 x@ݙ>:Vթu&Ìt(͛c'{1Լk-26[,M(d,F6\sdTTߦkQ'>2!&عvK[.Qٻkl\TygQ7|x̲n?a . 儈Ik'ZΑs[訂=!))(2 oOZ5䏡_8pա7C*( >L޴ն l"YZOߞ_"@˄O}3t.P~RpL@@ƒY&;}i^!5 |nbEkՅqSnxv&醯Tpgjx1ՙ-s?4tj2 9:x@]'*EO5A{hRjk&]ym ʿǏ6 !xjي?[BNHl8](\}pSfg|Ukq-B~ !bi{ N oK{|9!lA60 *.Z}"3G?OF6lrS@ְ1Y֛ y}=Ane[pۛIM! ~p]s#7/r`g]^#8z?STǞxJK>IZX~Gj?fGX,?u6߽QAaqk{IY3h#w>xf< @Jws#ߺ2F .N,6EImMstTrQIAݻ}0υ'>2%X~Ƈ{:8p]a< MP˭pm}Jr8ol 1tN|o߾?DvzhB\|*ܒE@mS6qTBsyڋ,檭g \@ Obݳʐn0d:=gA{s)! #mfCL&T4nnk}Ç=*0_^ ~\-ƀg]Bva}QuB{NS,: |`Zwx=4r?4%-pG=ǜp ~T@=Տ#W(_< {`}%yί߽;$5sqk}gN@"ch9rDE:jƏ/PBН@M׫)Wa[ ؀L3S*,+{TH= Uw~5+BVp#aR8c.^aˊj* z `Lsic0 ϕ7U71`+k/+(uS*AZ!yPVU"td6Uˣتn[ -8Y["NMJ|xJG ߇X XR9j *)_xgfM,z[S+;p{`ٞP|@_qI9*?6M0p -D)f=Ɵznn X<ٯ/6]AOϜ;g 2Wo~U|?6$/۵\υdYG;<1^}&ⷮqvէII,ڑouۦ0!"b#`@/K[ 8y7zjy$u l>Qp6gbP=F?2u* x'M,ڼǧt֞ kCRb(~)BWPsr"iXqP4,<ڸ^?[GRrYbF^ā f^~YEk֥Wsdٿv6wIt˗YeZ8MQG4 B&)dS7?J9wp xMQt.4ܔ4:4|_n ӁƮz7's0$`ʋ,44MxFJe6lƷQ.Ȇ1G׭3LL~v%iʚw7NLKhH@*y(">li|l.`opub ^0)Γ }NqQ HhP̅)m̩FM+ {  9װW>iֿ}7\qP_Â[]94.? >)#rqEl)LFp]/,xn\8V8&o6ꇓQEyr]m}Ru[k= <\}Sˆ0FBo)MCڰ1R@pe.ZPg^rx}_b_j?l[^X`_rTj7y 7~Q@; ڷ:0$LRtf&nsi2'sՅIǒ73f%^~-6:g>χ/sЯ`9$$:Q5\2hkFk8p*TAGw"*bbgOұ,u~O7p')QX+7~)s`uN~Px%&WK48{UR;:n6gm[5;MD^C^ZI7`)rLeX5bM5/Dž:{#z2Dy9B~B6" W]$0Z01-Ejl|z"(0P-6wW#nZ>tB֚2)8E܁K KCJ/ nܕJ/`R~|}]Bw4W[<RxC'<xC#j䵹Ƕs}ԋRz\ ɭrj i}7jH%6ncÊfP/탅 |:~m_Kg™wR4w98pIOig3aӤns6\uO ^o:sXPX2l<8y_& B_~a)lҹyerughLyk:l攤3plᡘrں+X(.ŬvյzB$<[\,#NWRpP }dCATܨ,mWaTb4ra}uB{x)(rqK"-k*Oܖ5ױ 3su|3z.m\9=c\yMGmׇl?$hfo%u]"O@ƹ n,_BK"ieE>uFܧAjT! Z[/=?g tآ!IBȭ(C`kiK= gڕ! ͅNGњ,6+ a@> wos adU{a_Q‡\):cZ_vlk{r[T0v4/Bd_hrTFqr-g5yْNPxy6JrGtS oll=ќےQr}JJ- gYF^U 4Qe׈ izEtm ߖ vǃF.>݁w089+WǑqya^WL.n->'N`r*o% rQdXqwbvg'\'.&bWijpK|\2'6F(&.P;Q: #ȯBH-B< 8>{QjBw}M4#7bX̝)&UOYOm > ߍ[$@ak j Ψ!@lr0v]?5>pexˮ't۶Awf(:>9,*xbm Ö{?(p.ZMG?*,gA[%z/&,1”f~]Ď1p,jJ`č* _ ! M22 aԯs>3Bo6$U-gŔoU8kE˝"t;!Np奛d} fJ*vACH0 td/若\,mjh L]KeLfxb~J.6T9 57EҧܓߺG g.2f2…u[hCkH l!n|_)X]gc3s]=i6t6VYŨIR.7Ia/;m/ $e* oe; 2= ,7_ xtCP[3>ˋب['Ԟ [Yֱ̆oOn*QOu¼d $?U&d1aEBz1? p],\"p!zߟ>qC`ŚB} v!JP8\{@0 ! tT0k:2Cx11 nv OҬR J;PIxL/\L?6UAژ`A6_T_{':e.| 65Yf&ATҋ@&R>8:j/U;X%J.8QI"œ%y >VRCehc'.M~OCODzUq'0y}3ACs닅U®a]6}K0ެF_cacŷ /}w(T(v в^/Hp:(Dl% e^sTRޡ&.1_ݭ=Ï_jYaAD'u׈ƞ l`挝=^>Cˉ0r8Apѹ5nZăE*K~c(^R[ӼbEaK.OLb9lj6/ Ù8q%eDX?1~B{W2\nQ_|F'kUxQrng~raq7V_n;ER/mٕxY\cb[>l<TA`񁽁U)r}șvU,hr? ڹv#pNW*FN=no̯%C #:7%' p|mG/Cڃ/b̡/u/IP^kgN2'^dm5sGmވ >Sbk/<\KύB*r-n 2Hβ T῏>Q >7o| \y*şyJ8)>@,KPZUh|MKdsVwN2:!@`eþu{С+$\Vt+oh:BOj(H9b{lh&=ñ^ 6S.*U˵~zGི:M4ow!r!Hز/]swҪ.G$99'bf=+z hd/M5R/8DWj ,LxutmOGt#OT5}' Um嚤c_ؒo@ΔCnն' <9|,{/ {tLؑ[Fl6<{Js*nxֶJ&0r$4)o{ھ̅]p,(E픿7&_}}QPGCIWxBm-^|6UO* L(:TEY|>$Բ sM\ g2<ظiKI(r0P+ &={> `唉 .96HUv1e`;$dnyV&UTL1Bs SHPwzZߛ{+Bz} 4n;gN}b>Il<' L>u$%6L^Z(uعcbALqapbC܌ :q EKIlPEfY[Op!Yɧx^› aCթ j\z\ֱ+&O{]!@M5~>o_vص.˂׺tODh6D3C*7bPnyu Z:W3K2gFhY􄴂íVbǾ%*r ܱڕUw;>Kg={6H3k5vHݼ7b1=pl2 P| wݮ]?a#M_챹u%i/Lk+d,2P{i%i+~_c0ҰjmR+«0eӈ˄ԥWݗNK |:aƉ_e?בiz4/gSkrAN2'C} C k &Cg/) ^95J!q0, {V"+ !T] 8DH6Q{u?jl,=thJTػBJN eⲝͣ*yR #`4y!Cؘ2^Hfe=zePj*Ҩ dc-\9=T1R]OX-:& ~ lu3O=?~twl`Q>(t ?ɰ!RΪy.V~|h:ӳ68)۰!0NU6b6FHj BTί{ ~:H sP12ض˞PW_ 켝6KtZݸxC}Ǒr.Q_*ՙBH}7xBN,9T {}|hŭ-OT>ZC0_D ]ǹ:MH&ە2zkokl>3kom@c @Hs5FBC9ijх7J䂚!"bTC# aPü i+Y ŕWߣC- nb9 S ԱQj{KDKyiwg-%aȢ.e m4/Nh@# oh#8ZC1/OٹVǏ$iLzÂi{V|߶ʂ[ĪǧLV4gs%,OkD`%<}I6r;y =-ja7 TSo `0e'%)xd:|Q+"ǏA+=$޸ߥb#2_UF*oU`Nڸ?P|a"ظcog V%׭ *HfؐĽL]B|xL;ʌ~^"W- X%@E0cϗে tP;R |la޽2,:X26_REg|OhYKe?u? f(vd!X*xh·<= y@C],8֣PGdW92ib=` Z_ڌgNt/*L[ y:Icu輕 z.Fe Iv˽c51O-ry n1M|Vȴ: Be4.[ph +_İN! NyvSfX[69 @]r*zS_wrq˔˄GO}ٓF4uƎf\v"2J8 _XX_zg9VN!p !^NGnglAG|΃ "|< T8r M䀦kdw֬@R $젒8Ttxubj7x#;oaҬ$!E?誥5{J0+p\&;xn#.]" "ܠ`'=xe`RӻJ8xl4˖*Y'>܅U{vV ᎄvݵB ; |&ӆ}})W{nYlQ uo@C|9+{XE3%%Nl'㼨x~sf&{]8=_ {!ǣ1s=@ %[ Tw8dr?}3T\_ )Ҍ |{/xޓ8S?$|6_ w'pgiUݰ+4}Dw[q̾ k"uRf[b&`﷝V3G[o!~y.Fj+ц?OUǜe0Y%er~IX߫bح˾AȶIOVȉF- Dcj*Zw`R'fvO'j<*W,a(,9hVP.LZ+ U y1^&>xMDǹ';obU\wu~Aq!Ӗ6L$oT_EOJWqrIx#DXyZ wH澓y:}mj~ 8wA<WI X_y<|_68,DQ׵^kʬ4o?:ueXe^ִ/*Li"TKgI-=`JUśsop[֛&`Wdׁo3 *Jl oRgqj z(Wqz1wj!πTٴbAm? @oҾޅAG!V=8yɹڛsㅹ4"L^ӂ^S¡y5o{(uC BQqu~ba&:˗R1g=p''hGq 7MWTM\G\ֿH@!0n۲ /y o+S|,Sfw+*W"pI54[ʩs@fmSk\KC: 뱞)=vxoon&񍧉Qr-I`ԗ"ǻpgcUCs!29rf:xlERۇ6ot; vҏˎV~ d▏“ Cnc.4&r]I@/>[ɢme||&TL+lt  &<42nb`\kgSm@bIk.n x\.jJ-౩PѥRƱQu%y%oaIMxoZ&ҎĽ.țuJnbcՉ; /7ߚn5si@R{#=s,)kYm$,\LdCM2"wx2! :}[>3PIۭ}͓@7U ~[䠾SѰ3 }=+:q$ᠩs nj0)@D_e.fl`Y+ rW^¬S#ϛrWj\!@gΏba}@#/\./j;^Ǐ xNe[Y;XGRpaӏ#g[~R@?].O>Q-V)]mXb[ŕ I]>u?p!5\tcW  ԓ^]CL=?5;V*= !_ڿl<贬ԅ:yqp%e06FQTِm|k(d]ui^SbhPpYSaZ]o#f?~]"/N)ywY8uGȕ^}GD=!Lpk'jp0y$ge2֭dahoG!oȭ--Kc`8[П!0HHL>ڎ?eAe׹ٰSJJqO7%ǯ`>0,9s>ٶ)`*^iGXt Yն4aAK.> p\v@l*A[4n?;9^dX486t.Υ,&a@e% $b(|i彳A%]. MY=:5/{N/xkի*֗ΛaoϲF54))G-2"dW^O D};W&A;Q} :|!P{T'V <ѥ&%)Ⓗ0l'^K@\}j٧(?[L_ד48f|DjbT|Pg8L)j12*>}ª~%\p ? RzDe-Ll;HJ}MpKѮ? lV+Y*L^hS3^BMI">q@|U)Po9C/9 ?>͠OېpHT!1q TUa]Q(A; l,6LГU*܋wm8&{?(t6BsQ0i*l\ߺ vJQ3/iyS;BZ_X}ׯ{{a: vYgW=Z A\WH_${$8ur=) ]kd)*Y7IϞR Tjj+ѷaoơ;.r?6} !1!БIġ܌f 6Ȅӱ\Ѥ#834eXr*sV& {NuՑDκw=y2\,X3KܳO@~uwC,o:?5Pzzh{^z=3vjpqejgc(DRfВ A𛑮͙&'z2ΰѐLt6n5ϟpi a. ѠWk/r'Έrq_//[C62u짃R>G.7j3.#(\\-UKo70@%yʷ9w!@3,變Z!ۜmcJx/233 "}o]ܩ,,]ky#H_H/l{!ΆZ)'Z4;7Jod\xc@ȒG?3*Dw k vX4)M mY|9Sn ΤB6woT~hǶ`QK'7KwC*x~ŷHvJ.Zb` 6L%t>uӌ6-~>FoY}N,Zt^]E;Sƕ(tf=؄_:06RYЂXr< BG. !Q^7l:2’wљz]}6G7҇U}[4ܤXCP]=(U濝 /I lV~=]6/u!4[>I;zא8l|Ckϔnk- *s)qkRtgMCʻӭxjsر̹ob/̿.ڲ? g#n^Owo羽îe Cki7IByW8xQn=|b}&bυffT 2B\" 7P.Rxr$|v堭͏8n'/dMدZ nmw[h; F<^hMWwzEw6)Oe,Z,IRIBͶ+oH?PN녎~yƿɰAB.^&aӜU{]}zA6GtC2v -Wÿ#@˲+=Mv^/0XxkCƕë0.??Iۜ˔xe;'%]vEylqAt0.uMZwОvB3ɰˈsT>|Yk1LNk&$N ȅz5&H-x؏f7qmItv8{+|CQZf "NJW5uS﹒jܻ1NU8oU;X =]=g,li`rIۇy[EK6IP掼fjeǴTXHH]i ViT4Z{\>&}Q4gۅYt̽!}36AeAtMӞꦣǾ=?ͺ0̽U >-{DV^pq@gLH{.kS e S۫Luk[6ӳQnҟبtL"-.4O%S?9Bͱp1`|ܭT^>Cj:|d~?&k6 8=\"F;p *n> VAPHYufb(\;ЉBƺ9PP8GBJR`q}_h] Mvr@DV_ eFm kC*hmd|f\}thK,x/G /ΐ# '_OPTh S4\ڐw 'R:;ECٚ=kn%w-z=ծ=|>F)A6gš?=L,DPQ=n {pkR<wee^ڌ<3m~|~i?XQb]7N>qdݍQԿMI p)[ h vHZ| V lͣk@;9_!DͶp}3VU^w$SƎZˁ-ǂrz #ؖ%< ڹ(\ݘt^m93M2 uuC^#"x xx᷌ܧE,YoMƴ'UJbQToF8+vjlutblWLJq`3A g.u(wȾ<NK^؋^Uxf3{ %M2?m; #;Cس$ րWň".\=Wr \F6<-ժ}Ҡxh />C\] BzAxk"LJ)\vd|k5NWOo_?x߅?mˬYSfv=[$@nxovֆc 6>mƼwwq8IB\a,tVL7Ϟ'l6B˳꜋4p )!jmQlң Z=u+ֆ.ږPR~ey7QB%~ipQ{E@zo=:L<#c߯6N]vXN-cp1A$鲨9\okj(K[eYj [.[~iP;3ETyz#|y +E*`y9ۑoQɡuyL<Ѳt F] y};fꛓuFX&3T o"Ra\*  gvO3.v?m8~jVBOC]/_e M&WfWE&$. ,9o>]BM!K'q{Qny._N 0~gVc}' 9zeBwRW&O;A%IUpV\KX|mΞuo]/ ]d_?s$j恴G@vno_4OjspkX+vK{tӘSlqv4釀UC6\\rSXɍW"i b3j!x\Y Gycm"!$/Xo93DƏGHx޾T=/8. Bv\>3Pl96$W镯n@ե])go_/0Nq(54ԼɞWcýG_(gΝBq\Ş7E(O͕Ĝ C-6&]e*f9ۍp.hY)1֍xu(<7HlW:ׄ˂87(xfʖ?b\A+_|_&^ɾelT;z"3 R3KĀK ~L *_5<2  Ί>ЋybT0"v+o]-,^cPAڽB٪ =3ws{9"QѿW,'h6W!ͲB4v mmimG˾\̠9 OHujom|\dYe\40 f0A|ŖACxq8U/0g!k)B'CCGjG0?PAR \4i:}kTϸr7 ' g*tXK#^ާa,8&ͤ6u;Q&u <}$p:s.0Nsa7B:x_ؖ _4Yh^<ǣV<6SG,gڂ70[϶ !O66~9XDxsy&,}g n1\y | TN:կY.WvÏ,w,;NΪ$uT-kC/Cl⽿U\0}-ٹ Xϵ 6r/ud⎋ h.$'.ZSZyIvmB~ 1M{ qfk*Ϩ<];\c>Wu][6rxШ‡Kjr塚X~_tA`RE u)TWxxѾ bx1(xpYf*?]e1F`U \BT>}| U$HF5L$@-u?.T\~t/y޸ 6=@Vq _h6o SYfXi }/3TZb*bAj]U B  Vu[ex;$d xrE)6jj0t'80-?ކx"ԹϋQmauЭz}>V\ё:G7FqC»2mav @s~cWLע1^̺%b`eT,tIٓdip˂=4 'ˆj 9>*vƶ/sCtzB#?dT 3U)4}꾓`m <.j?;z3yȐd=Ӹ@.`%W[d;+ɕ(K 7pls#Fhꤥo[i5tqNr)󏯵IT IG8eDMȚKbk lUA@kWY]F. ȉ'PITk`6ؾ+`K)ݐ[󴌸w┎댰aDR ە%]hٳVܜ"--GCڧͯ!&7@Xn<ƹI`◰AFI9w/;vi}*zS27\0 :3dl˔ҳ rWmk@_FM!k^]a6bD;r&h?lƲd#!o+4: N<JߗD ’9`v[zd=1w_u=h0s#ێ.Al!8%AjƝ'Hp/{ vosz BFSM&8jr 11Gb:Z kX g;n]j >\˵;r H;H#Ƴ^g[2W/{ G2(P &>)wTշD*gw*txH_7/ 7o'@1أm$}' Ɩ#ý%qI1'< +^޼Up۸@lth/=EU/!kcN8i '4e5%O¯xu[ا9{h"gXc j T S`;D=h 7'vaW[@ߤܳ&yy!U\9z`3h{ww8hWx=:=/EN0!4$ל p!`z.o>ւ!G4{>^y,BG<nqq рqjognWM"@7d91*tتqƒAFmd(~ K6 S.ӲƯ9ذ5w8GwyD?}2\qRf‹c+0:ոD=8,֏BcuP|3ikpnR8hIpt}DN,a v³KZl|80X%NG4%ٲ Ԇzi%w}0 F).kow=li:7eAU&~y7$|tsI /D1 5d̶1O41hv95zcy| !\.B.?`,xNc.WɒFj++pԹ\Z&򡆄{5uw7`Z?J<ټZ!dt0 ro.-M_E-ʹkGp,[A|B7.xשּׂ.IӚr`mNTM= /ԃ);%z1!*OYQ?^jh4)qaA᩺?C2LuC +e |bsY.R߇.Zٟ*,Jsޞ9_ʣL߽ s 4tv^'NE7ASڞudb1Af?/ ɰ I*f@V s9-n{qܽmU6$8@OTI7>OVe3ZgҠ@nՙ2^Xvx/I*Xu/K|B tp1m~7dYSs~vcw>F.xco˜F+g/L|>0=S#z+I=!0t\0ba؅ZN3n_^Bowݻ2-?VAS4 '_XGʭvk  Au$&ӏ  iJ$| sp]ZRmbgr揬Y J,"xp[nI C%3O*FQ0}j/7/1o5X1~oV g 3 dpk: ຫ\'pɥQvחIM~Cu!kte q ֶ82j p1稐1 koÙMŒU o-QN^"`сȧLٚ!l HhT ٘){|.}.Tq1}Ony HMK䡾i/'f92LxҊLMnBf> iތ"*jޢɋ¿OÚ}Md3ѭ`7H$³~||`2y@Y_:3Co+ޮɎ c2L#tиQIt R9-u(^0U,/K+)+9? סH~,| }2).$WD71$ xT[$ף5ۮ;\밉/<΀"G/6b i:~J7pg r (<'y.M֌'wv _cgs t"Cy6-_< V$MZ/<.xavm^ +Д5-}+|xbe3{BKl>csɊΏ}[{Hxyv*wéBo~G/0<.H 'sTLJ?*cݺ{ejwϬQ&q׌ZL%HT Xf#OyL`a`Zɮ+\5 : ^Z@H; |bǞlAqC5$4e_6lcurlIAi| ] KFn:NHo_ۢL Un~ niגɰgĎ|ѥ#ʇqә᭳piMjY?#3-?ɑDoAUhڮ߷ (pC'< б@`!CPsﭙ0V"6(,J.젰y.rWx/WL]e{aWD; p^Q: >빩m#mP* hqoja_m0,o^DC۶~+Cjy T /igc2.zc`NydzW~"8sP_~;oS!אcG[f~!,y<X:±ݜ_֕sǕ4MkB[c6V3J Nn^Tbr;raJEA{Լ!ɿ^챕N׮Qep]/Uo8}ԍ&G?e)^j)Ի!]L{܏@'+ ѱeqpj X}? " / ֛NwP$.<+?^ grc=TvrKRO5$D^*Awב.~9 Tí:I Y/΅­m{]v& j~ t]ѐ&ukuxc }\+)~>*g~hWS6hF dA@."1L8{[Zd^mtǎC@J.hxgo Sl\H3 2GlƩY~oG;H:V\JV fN}<w\E?eӾ0W/e%fݹ{}>Εă娌X(Ȩ{3DMB1㥆4pE3 }˟6 I Ipų\}hnd?6D6W1+A6΁(~E@k7O@K3P)1Ƿ 4Ml/7dlm%Gc ?]P,lV`Dbgڞ0ĎW8BT?meS9V8~%|^Иm 3>^㢍NFɲ=}z)]7>>aύ6CzS/j&԰9O~z_lnO;DkeW{\|VIvwr0+lfL";ousNm +b*E!-ƫwiW{p뮊sUWpX{e;&,v鵊6wVjj u=5ɛowC_F[]QEɁ["WpZ=ZֆK;ͻ zS#:MBO[+x%J268ГBLcQ6LEa{ſdc -q>@/{^> R'k l6ݬ+F3(fba\t ]a]Q,o?d;"e}g406~ҌײRw601bGWTjlLPft!p"oHλRcjhrW36h-"Q0s* o ᎖"{`/~@'2)0?PVq/x,ي}uBv:p_$,6i?h#_6v5䋁@fB_cpťyx0Ve8}YwY1m5EtQ}S|åQ 6)f@t\Ll( PtUH] 4.lZN;hjrn'nVk#Am,X Ҩ?ގ~f dC=f~H+C9,JݻvPGϙjVJ|NLuPp% %n7820Pbt-;* *2NQh:*J]hX.ȅL7+npԙPL5//o6#[6TqA"ai({!ܣO릝DZ1v\xxPXva%U-vs L8Kv` R9:H# SXtI9W"r,T/֨t i:Z@zfCJ:Pgw.olEGX}. "fl|,٪M)i'z.]SEʑs(W|Ac<5p}T <[@n^?nFQvWrA֝Ujuomd{sg)TJea\\{$*^Y6sGt]d@,ќ(֞wFZ6P1qx-^X-mlǮdr)jO?Dm9y[ddP[TG x`˪_r$:Pʗqu:'qq>f7J0 CV<[ZLB5َsZ$ypoD%A]t/R] 3 1aX¦/pun>cہۗi@)d m&Ǖ%9xRDH_-[5…G]:q4k_fAЫ([#| 'ŝ\؟:lfkͿmsKϏ…q%uaGD`@.ʉ!5ݜBWظ耑0[ww@uİ},xamamWex璦Cc8xe6VpAt>Eoݮ6 pYHcϡ$PO|4'r9X=bWܻG_oo+$}+kVУL3?>( ?|Xz Ъ?pmts17|;rpMcե ^Pb|G?JYŲAvOpVpYV͙pN/^\fzt8] ^j| kHXZzpkczYwh{˥X__٘ɫH5=m(8$`ڋ7q, b۞y4PZ2Ht^֎TȣXZ"p?!Tcp Ο6dO@u;,F3G࿇ޱkoTB؁O_@{5Z"@tbz|߸\ HKßחLƞ_T, #`6?B{숣bzC[߀:4w&,,Iuw?LF=R#6>{;3N2`˒BCr Բ<{.\{ODZ7[މ\GEv1 h(Y N4{r̀}B[p[L6zg9=Q%baVI{K{ (k2x3sJ6u}nxecꗋL*a қװĹ8uͬ$,Jy( ]P ?HbGU x`e6ʌN<#0d;N\(ީ^$pv!&8'uF@'|Grdx`5J8&@<[[*&|2o%n0r):7~`1tI',4|NAis=HoZW!- ;!ɝ Ԧzx1W7 J<0Թ+? s1}([n_qlDGiRQ'YƦ+uuqn*3&f̙(Zcl_G.V\8pwJ_/>)7{1F-!,Ŕ/43/^ckXRtB7{V}|Wçp ׻@O;d]].2៳_\-[|Hku# +@!8NolXpb]0JIF]|tIqBo~̐w\LM doKgpL{O2W{.X^g{AљwKÈ+ qHڜH@=6~2Nn+"Ic(Xفp+9 ;!m:Jl$a{F$ݮVY}Oz@ҝ5cItCG=fu%:oܟYes@zؤ%6Rҟa2[ezaP:dÖN&'ٛ=Ph%<>uerze]IPaYCoYnV͆OMH_ JI-)9@y׋"{C:p햵/zn5KUh\6piq5c2 /EraeN!U[_"@ʕK`vJDB(l&Hͪe8nFzTjmx N`)Atk,t}+vCR-r1Τ[ǐA-C|eMx܍lXOtbۯH!`UV샲AN.[ߗ SOViҵ>MGj/tvە ;NV#.X*߹nN7b5,|/[+iMg)hųN2Ƈ/?dkɇ 19l8/mv׿ėi×߰O@+=`@Զf {I2v5jxy어Ρ0YIiw/\֕χ :G)1PzqZ?xxںxu w%_V[XX`k'O},r1^^|1;A%p@kէ9x+!}׫5 (:,h33hqƕmK I*;Lp.HϹ}tl8Yi:DŽ;j2SxhsIS-H퇗ټ/qx#qa=v;2Em}xL<L'LGw!Mox҂Hj}4_AIܬ?sY(JOP!]6D}>#\Lªβ{hG+ r.11[aA`x:~7HO)wn Y;\'XMw7bnoBw3qo3⠺X&N\v`E6]yрtd%}t퀥C|^Q{!H6Po,`wk jt8Ϯ.ݫ 'mr3*}}ugtc;a-E+Tn^ v2{g>􅯌Ӣ䗇I(uhZ*f_Q"گh7>%N'\{v\&q{ o[Ky SX`h>\. rn`'-?b:\#g( gX)9ǥ1ˠG.s0ag@J2dXSizh^?: Lcͥ5?\W 'u< ѡ[&0cn'}nt=8Tu &*2.ʽ[^ ϰ.Vbg5Ry$8WL v| mw{R5LS'X89]U tKbuߙ:67cl`Br+lWjO.o3u[+L"0|vl H|"qU;h΂jGrQkKD<"Վ\莽Mv'kQur;eCSZ*6*u`2/Mu~@7nD#W<X_eOf3aHgNz^3cu(h!GLwlz~ԜlY}WjQe[}8#Ք0Ż YFXӠ䜿wj^boߙ\P^~et;<g5 >fw`/.KO.M<J`ٷ%G3_qgomx=|uk$}BO_@eYGy| RBvYa؝O90iIJ-6/GCp Y.o׀ZHJH޸Nk Su--!iEAzYHoBX N1E[w-b??v2 F-hSii-oφe0-WS?^iҝ(:ςghZ'> #!Z6a?9pY*woL;鳧 G0hs7ząJTFʳ?}L  4梞̓04oV47u(R/v9d-}%t 'ؗu L6- BtѕAluy6O>jYSN'0,:1 r~k@e|'/%LͳKLn=ʭ*$E{xX֡q}ia\OZ9=/##CCi{/s*-{%m(w,w]cKtmdX72K$ -UFߩ Ze#Y:ʧ*nv$uMé𭛿372RtmTTK-׋Kj'Pn >*v|ۀjn'5:`Z|;UjDgr TzhOV4tPbكq U' _9AqUN%T0p;@[{b [Y3{k"KP8+&7L7MދHKq`e*+s+<?[2qbܟmXν\3 =/T~ k ֟f@Up zvG3!d{cdh廍xh4/;Ky†:TpQ5 1?g ,>Ⱥ6y͊oZ=8l&rH2* /,c!?N:~ϢS ZΏ :Y^[O]=R9PSEYlBm0I:o+[yv:Tz羏nO |e'e.qpb tfse-#wǜK Մ\&L׎9RX0#P.\i?Ɲբ!2}{T[uYNlmNn(j֜bF)QV!m9} 38(wEg7v0&p,7۞L5e|^;WoMU,}_ߵ4nc i5+Mg /")8~m$$'ب7s+%fxb+K,U>vNTˀU] XX=N5 >\AP^.Ɯ!9(::sme%.X_bcc;h1nc@UG#n@`2u^]y„sn5ҧ"۲Z:e||gHY_I`t(5S" pcEI3~K`6 :%gOiOu0V"4-j爊eNs*DZ37dAO{ѕ;]qɦl䢴3*yT+d0TZ4C.[%x<H_sLW O"c7TH@joNU_c<ÞMK [D}i݈D&:vZ#4-zuS^^\GGU+95#*Me;V% O6[!Rf0]lU4>iXo> Rz5d[Yg*u?v,?a[|ҙ-|&JEb5Gqk;Z!fI,^b;p?49tt?wYׅ ^?RrZi\g6wrw1 f†/}Edz.V.&P ԫYyRZp|y>;]N N(p`cvXLs4JBΥ -k~ k{dzb >;aQdlM'bvaf:+yw5(󭓩 ᬻQ0ahrdHjŊ=/pah*6hnhZgy[!RLMT}H"cE(/Vx#wd熏¡q+b^4?j C<ܮ3G`̑Qʾ 0IBd5'ʅN"!t`5%X}e`<%۲BRiOϿ2:g+,ږsB Ԙnz"-\(z2fLMU\hKK^8kxr1pu^3jt1?jO--羱6bo"~~[b[G"頫V6ڹo?+s[I]A9S῰ Tz{z-yVOI`xbؕnI$1}=*CR͕(F=|.e`,a? Q{͑-?RxnxQ ׾eo_΁c MY*աBWh82'6>^  #w01tGW6h7J!nz w5l}x6^,(2O?bu ޔn)vR; TڔIlG+VA * I1z_&\x[X UO$tSl7wHJ ٝ%de@uL϶eC^?wiN֕wG=mDD@ҹ.0D{ =D/p1#mZ1> ]̧0qO.'P"VjmfZrp:W 㖜vq3U~Z?dɀ ŕLT̺|Bn־wRFsG;QܭR\(M$dr!sUPgkt}ym}G d%C;8N-_eGRYty#c- df\`" Uޯh(c"rNt0Lu`0*t m DVO~Ybu0YAݕ8C/ #3Q/v~ bEم`:k'2l)xMcg2Q߱,9 VtܸHZB|"%) bnNwh Qҳa&VY&$ GÎf/gmSCԥ%% C휢pJbZ&ExdKMBX=j;~i*y?m*t'UekDIjO'0*K[j ỨMz>prykj6sAwǹQ'VNN\ ȋzЎzK^1P'U|zfW+<=q)`{ C~1: *qt7G;mc.-ؼhBa?oP/j% oR]ra_Nc\HTLo~ ֒:Xq*:V,8&ș5:?߭rWƐ}*xߕqm3nX^cF΄ awms ;`d%*|UDQ&@uec!yH;cM -/+˄!)`V8cݱʚ+vp&)f\Ly5~W ݴ=ChWt,G@-~\pSp2D\>-~ā'=ˎ}̥-jtXq2kyvq_s,#phj䚾Q>Y'9XVknڀEw2Fk& j?{ Y|f<;Rm9P`s0+)M>טлI<)U0h!뛏B)9o+:b\ԭ=oRd@2z0ZgF#ϚrЭ/т}&!=6~N[?IX*Skлuŷ64Tr]pWyk+ò!Hm-vDEݖA@K.5[ؒ*]}<Ѝ/Da?ki:rsA&, 8{zSP_)6﫼i`Az']CH tѤ v5W F;zmK8|҉sa2IiztycܧeWӻK\QΛ[5j[ L?tz nwALk%pwj!BjJއJ%qhզP)ݧ\c猷Җ1qos\&5g Nf!4mP•W f=z 5uʘ̪P1UJ^C01}mͭvj?}T.BǴQn}+$uU/CB"\XӽHKwޭ5u^tX-.r4'+ veӦ]0!wf\V္m\F^#{7Tjg`qŮmLPzIX,65>$߯w2y]8VBށ.[umԘ_Ts[T(8JrCa3cab zo(IxMv7JDǟBI/*H hmA`^ՖhPV0p=_pmb;\xp'hq4PF1݇Xѕ#k˭Xa :YT=/{Ky| LB/>TZԮuuC|2 j?S{9mJbњ^&ѯ|$%uOFFXvTܰsV7/bkC5}xygolJ,3Cq/_6^W'oakn2!Xˠ+M~b@%LΑOC3HR&<ݻI+-WN^pjϋ GryTQ{O{sb_Qa}&U0tMN4x<:6"!=ƿ%Ƈ(#*^MrhЭSYH!vzadUGй\?w{,gIN>^A\8|& 1v 621T;u_wkQʏ->Sx֬3n5 9SuU{P q>{6'G-ʿ*\Oa6J^ArS&mD@^DV}JjJ`qkΟ.*mB0R8 ĪOx'Э |QgKZ@r+pk K7īst}e0g/,8ɾ2?Q֙Z|ߙƅrf$upzfdh|`V:,6[CWlK,-D'IzAK0ogT $FUX\`[>fӇa[?D{ y[Ch,Kܹ nr'g]usBaǟxQTB,:;ͱ`~V쑗l*pqe 3E}p׮G?yIRN,x*`P7Ib( } x8Oǜ|?ZNAPoPmwn6b`غI9r@Pv,kvgGnoakg)q/C]Z*h=#_F&Q\PN?y&6o_݀;l]EtRc5ȓmɅxO97^Y?4ܲN-a 3 esj(۷\L\P;{>pO9Kx׎Tא1)+SКmd UCKd`T*/E t v= aTJbBu/=˜b"Cčط>nbHSET@L#w6@!7<[@(U?]<o>pH+ ̾\%mo&<3v s;aGYz ]#U؇o qT㣃SS(LKO^)3 m.̘|Ufd=`ՅAOjM}$;B e l]zX҇cB:4AK|xxx>}T1njRBs(aΝA.ozɂ/%wdeرvwFY~>+$d‡V}Y50*߳i ?ˀ]pwbFlBww & ;#>75܆.Β3H{$w 3S5Lk׹}K]a>F\yǞKEE ѕNJ XHwVֻ>'=)Cw1Ir*&"$|tE~H=Vsl&f_;L@-hPP5OŬHYënk ־j3Icmo ,8Q@!`yk@˩O POU3{hj \IZhHL#f}?E1b'ylX'tziViA!p gGA Űxٳ^sfǃf[|%)G YB3|H0=2W*\I;6]z ֽFp4Uv`Q;Q1ʻ'g;MߌM0^O:Bю Iw` 5S zu1 T:r_buԿ\h;tU!4 ^ ՚tv֍mpqAvZ]fc][=KFp7pMY?4O%j进ijS߇*ĚeQ  #Ae f͛S!L nZ$'̆4Rݿ^iͿ 9rnS/,{_XO+F{#H[5 0{tl4$MKf?DZ1BOZ?^@Wtyw_]-:ҹl ryn7{;_sV;fR+Vl׻pn^Y| һT[ॵ(F)職OchJ,/&3kIƹ7_寯b^MC&*3 ~5bDh,ro_]Xя:~u&0ysl/=r³M;Xuɡf4w iW;b\/M}d;svTza86g$p5!?92џ岙Pr{4:*xAW.rU5)(P8j|;y/V(cB((!Fxu>V+6rcJJ{ d`6ƗqqosȲbdw\7Vذ'bJ_ t/)H{ad9,B@IqC.,m{^9;| 6T5J}XX <]2{e/dq^]lN2N ᤜI'[8|#au)R,8oV`cc >H[byGbn(O#WQMs*l\<9A\CWW>Au!@'35Um%^O ?p1`ۏ*^GB ,M xqϱX9HBtҹ|@uo+w€׷ ):ig )XA_O hr1ck]$l};scF 45@SO 7 h:}^]<>xqBZݹ=\U\7VyH߽4.O >mBz%q(ݵpy.[dN5/81Rv+KpVCF- 1R_.$!M&vy~̩=ꋴHS<'bًM-ڴJܞZvZI`c':o*v9{\"`+v^Q\ Ldd(nb}F&`7YXL%FXut,i}-mx(*TϔWݘJ=bЍ>Ľ">}ʽ=-rN24H{'<}/d^UfŲ&ez{l!3+cߤ.H$.!˜Y[RyOf0jX+3(QPXx Nt &7V|CZGFfR _ooЋ*<+ظie\ǿF،B+8z1Ae{\LQ2qȤzi[=x b3s7v<!Eo𿧓b\\CK*}ѕ>ԴUF 6+e#/őWs0bxXuz޽4N(0E:N3N8QT 8 Gq¿ AG=tжѥra&tdʦ8BbJ+= ~^z|k>tPj-ĵ4,:UtJG0>g[erg. 󼿐@Gzڱ6|f\[&,zvj %wx}o}ߒQ%-4W}B"Y[ήi"} | z<l>Okd.Yq#-rΖ7Wҽ;Ye(ma2-4ډo 8[O *Um8-|#VsW\?۱wh}&˵k%=vHF.7/nojOun}tV><R u.6#8vC\T{%%_ SiKPy7'>I VO+PNpcxsYd,ə\}B]?O%%r!\5y*گZ.k 7EįG)ꟑ6§_8.sӭ$P{ـsgf*N 1䎮%05wʙf@5j.no™7ʆ7j>7398=4M/%Cy 3ە7wxZzo^#pCӢ1Y]z3sYqIJ;bx5h Ъ\)idqWJ:9N.uUb^Ab.N7Eߘ~bnu9_ ,ȅƄӹU;`[4gm7lf8m#oP'оMwv ?xjc U $ʫMXODNU0P/3USh[PU6zbU }7l&0Fh]W= %/ج5 3A+|>?"6hTZ#ہe޺W:+އh$,W J;uƿm{{L'h~sPg-'lx3rڻ_խqn_)&El 8ǺDUX;!z,7yv+zxk#SLD3D`ϣ4,ɵr=qZw˄T:'Hρ:[ltZEq4~Ζßߒ';bWЎłr |%թx#/5M?M,%B1hO|c#no˾-+`L7dhUߞpVj[Hg∂f0\ݰA~ >  ۪2yt:$˿8wt?S~aäJ"|+/wA诣$x?'?q)p̂ܢُyCJZ D=;F㱞VHl{.D* `}WSj 7P!-4 F[O\Q!Ws0^@1EYXڸhH. K\\!Ӣ)qLC },W%@urV\(3M _:䂩m\*Z#=u4p HhA==4x|*Jő80UI/ K{DEDQEE ((AEDz()ùw?ܜ3drIsZkcYlO=/!8{),d]E"C\#:!ky."?!aQ}_x|rrt}*6?0F1H.ШW5m ?8sMaٸ_Cy:Ǿ͝!xO P"_z"…Lgߦ+Ӵ>[.iddX qzoT_4;mɤh92=ej$7g/:ZaCOʽ2ZrxjIT7r&4[`O9`MJo[jaYJ0Oq@]]n,tTf%uZI,#ոKfùY$d^ t+̔ ܵG&V4KWĕjj]#sgxL)2ה`b=jWSK\6^܊1zj[w\6yc2`%];t+QG˭ s"ɸh3'3*K yܯ>y=1C XPh󏎟B:&TQd cS]$>:2[`~'/^I:k :65f{שKpޙF DPi[L$:Ou*?~YD{g<ӱAG$M"o$;PwZ;˧,~2 -du$oj%ӌp lX_{pT)lYD=$_W?A', n"KJhoN89^YVʿnTnGo8[CsRfRUG#=* "6}4^\/@|]?q-Kȭ49U"yT9Cl2z[(x\[m:*ww v@Cq\d!vhnɍ)ָS%%l?1 n?~{mt菡o;^(xhBS{džz NH*O{e?v+s&xWRNȱqG-i^:*ȡPG+ߑTOΎשL*dU}k~u޸Y+<%WiGQ]֌,/fW^s_5n\?ubNybuD+طÈ"+eGJ\o埐9P:NZMM%Wk䮁nY4# O"RQMr,clo*N$HvTTQ \;Ҭ6|:R4w*aJPڳ GΐeDy?*rjF-"Dq:9KT;o?HbޙTgnOKKFd9!V6R[Fh3f?NuCuܧy ˋs.|s iKQq 4'[ %vzc;93z:u:ZGԦ;ӟ=Uj=jwG,r6#'X0"MӋ/\^9]T;/׫Ω] ;Xkj FPWhQ+uzUy.jZ%FڥwuV_m #8a/ZmAW. j &" jʺo_DcծwP~P[R ٛU6CPSCڮ9_*/3_ Y]ټٛӂrq1|D&B߄#.F!}p'cp3ɏoѝn1!O_3ma4=׶o׶O2m0*m[/k׶?juŝn?}ot {_mZ!dr[>u{*~nm m_>m¿}IoB`[mlXn=z`_YۥFvxP:xôN0S-N~D0&4A03["x0%%ҿ%%nL"`["$6L"&aA>&b1 o a"I9DID IC"$<1 0 1?$%-L"["xDD0mL"`$a"$%FL"$HD0IKK̘D`k6xaEWp`*d\9f>tC-K> #y#ٴeDX,=މM}aj-F<} ŗPƒ8Wdw >Uk^CGx_h #eyDAxӵjP>^=j-sv uSKAZN*F[ۜ:4]N հ#xA g4?ϨuIS5ihƑ_ e Y,zNHc jӃl/ԅl3A:44)oXF1sD,{'"Q}VRHDҁ/#X?PUc1Gy-^˗[!}"'1^R&Nٌ?hbQ_#t1Б?6SюzыQrʵcf D6`gq O`Ȓ$hj?7d6 ,8N|dյYX P *wKa[RՑPmU-lɋP*zF)=Q%ɋ-y3Fy,9%p 꽻=I ~ɩ@BBiTRrp 6"h0*ddo=u3r|A4PgBG-`:}u.BSF }8F'X,!8ZG!j+(Rʝ Kœ0z,F :_Fy'bХaȋBUʍ< KTՕ:#҄v*) $Ɓwm!&1ӊ0xt|DMoB^d)t.l^tH (춿_2d2*5t@:lHnL 29x+pwA$.v ͘V5 F^U5Aï?y=zmhGݝR$C7$@xºEtv󹪝tݕz}U@/EU4~^3{)~*H~0V;\;-_%M b" Eobl6RKM@~&WP_Gݨ|Ub]B$OJӀ=<zY*3EYv,VζbLԋRu/8cgNg>O]qv@M/H pAYyOqxP^;wKn@-(#hd f<8P~N3ʣBjO~. MUH}Do~ +}q>>ƫ=1}.)H~?g .|ty=]@'Ĭ2O1(]HlF^?#3o}=σaYug=#*|w[ XybXUEMr; n!đ)2L Go5E{3I6chVx2\ePTd..0}B>?"ufÑ%1aȣ(1?}G^^B޴CNg4>p~Pn).M \]Rj,ݛrE uVXThhBd |0Vpu~!;~m"!^NA }՝ 딻Nȕgw:%TM9g_mq3%Q^@ WǘoG6E7Q\QOVVPI=< \J{!B<:\{ldP 8`@/t|HD%ΥE#!)ڑOO_>]_vݙ\^_#AK߯Vw9 )lP??rGSY% s1PCv| Ym9CEg$cu +৯%j7I¤ [iTO3{+dCt^,QØ?u5 FJhv;R0v~#pI]:5O [ޓ=&UK0?\`-+;)&)oW)b.I9b/nK% +@aLY%t`+s=2C~[,hx4$~}x|}M7aWa~vLTRy|tG0.ߍ -*B; (PzWGcY.uCQ&q#(4[A]N"rVSurx~=^;+3RP7ZlT[]P7гTy=v;? n[\2MXg4/+WpdJYn7f랴Z.r7B[1MEpѲި٧lj dq!uF|PjKyMބ$:>!&}hU:MHKC_奥w"{6V NOϯ}U[n"N]D ˿V;bѝKApQTPl),)E8,kaRLj=*aX`֎cICgBt#K?E {bJ~xE;Wi/!ڋVg–DG/wl Hڧs֍858BHY'Jɢy _6M򮗉EYn o1&p hh6`[2ȫk_+To Ui򯰉@t<݂ gX/ =̶?6^.*mUB#_=A⢚_(I o?9-Q=5/83ʿw(±k@={=RR6\ Ρy1V^ҷ =~?I{;.ݶB''6 yAk39\/nB҈tUPo OrNgpb&$\=b#f;8N/kXb:3A U:rT_I_ӨA?pWKz#[v($ "Ş38L84yǒ?[@|Εxć{J?[]j|kGه: DZ2ܬ膄F+uʴSQ0}z=?rySM}PPVwIs?ŵTg_VԏnD1dĮr 7ݾ3!9ğ iSx8vR_G?ej`=t4J~mEY4\D3H剚ٳ&:SJ7{v\_~}x ^'x2{7~o\7=xja:LY}(]]$,0Lk_,v_nOf_3رE!.\4֩ v\QOrsBVuyߌ~̛WI^޻:VOߑ -bNW\ҿ@y r)w4 Y exTj%-:ՠe¡3D fP۠JQ|c!"?;K"DqB`m/jϳczdwZ"]<㋧HqS 5sCfqvR }ȴ ̋(λp"Ӳ^0zI?SsyL穧Q.pH˼MXO;!|f} Ama͆ |[R!mv_S{^[)'OwD|6gȣw" , F3XB1O&\MDӵESwܑ]>Lcg'?W򿮨eX塪tخ՜G gH[IO.;= DEtvV͙\-UH(0|h⟪xI- Rv <@M?|L@lr6_65M/ī ğ"v"jZ[ފ[Z^7ۮԢϙ_[Ģ.QNA |@3JSP7we #z/ pXh*:ky;˽ҮF׫#-}q7D[q4Wϲ՛(֞'/W C_%ӯܘ};kД=s(+8V 3%ۨS*G"CÑiȒ@/ȓ{OGrL!ufH/9}@#;ou4%]l|nhb4ޝGhfK l_<%]{)chq=@?|h2s֐NZđ3/ty?zuEdesOM@x{Cq##(:Kb\:Hp0%´Y}.9}1P9FTyms*qA"A!A)$ *KM_C^(j:28ԋ%{|秱zELNu-Oe-kºq7 1Lפ\%ΫPC$MDV _%(U6Ρ?%$8 #0U'2YLrB-#|In Γ5:~Ezϕ3j V!#Ԯe`7AME'> "O9m"| ;LJ&djG\p.o-g^8>ty0^O~~5ّ | =L"r7ݑW+J1ɮ?9ۈ0!z%:{_iqeV`QNb iěe{!}۷O kg-t'h͋2VsV2UAv Mˑ7`=—IEiǔ`mcg<9OG~4H>G2z]ҭ@nQedJ9H :?gov[+rgJHg'uʗHKꬨ.}l8Yq;is)?ՁkƜIx"7Re }SWSXbbFsg[CB=t!K1 _:|y>Ύf (^n@< igNsc1ib3ݕ5: b[ݟ=Cs} u?*H` hG4b,W ԛ yy6/pN T#G|Z62&:G DlƁO1/D)|{Pe$VZ; %5Nn)K`ɘUFr$7Q*qpj]~l|#Gyf춝O +:@nlh}ׂ7؞H3YysT aі8yq;K-HhwaRİ:3W:r(?]EX$Q%|FOKoA#. rg9R"ӢP#$7892և3+.+TXLokČ9[Ddjx! /yY(KzqcG&v$Bҁ`()߇ZOsB1o'Y~9Shg3/M:IW |E3F[ieO"G6P)+a}8OvmrzH;l9W2 eCcVBrGwa%BqD!=ykǩ!n? !k覺^Y-=-C<V 2/ EsJ޳@> Q:O\r>?592=*p. 19RiȻ24{ux&_ݓ}T&UwL2ry^Jwq--?8wu(v T% 2(K9 7q,y;d=*Mr߉*6(w>O0ixX!h? g9ud~!Y!W%ݟ|:OwAr|$''\ܸ;V>! E.&{#ȸē(wt$;|t $ )QmC?;@owJ;i$F +'(ڇv٨~16 R^C?8nh@.),YȀ%9k:Pvn|舘Y͒u5{7_Tދ8?p..U_qE\m3g|ryHXNtT}8kU&N4 Bُo`sW=Ak&i8!xs=A6.Sٞ>Z.# yg<ѱOE#Kg?}F(7MBUZ U|sypH %O0j(_ 93#Mkw"p$e[}9˱G#ZHlczZd`oK(Χ&$?tP|5|;۸i'Z}! >2;"J\βG".{](4 x79QZ/ e[KJ2߬XwlG HZN?~>)^M8Xp39pyuQܽ 8k]9clE#"@!;破c_lZ%}j?vX -A'Z8HҚ*MGrt9n#ͱi1&Zpɶzx,d#Wk耭2ͷyHs~ '/Y,DJ*=DnV12' z jCpi:5\Qufړ1uł o}<׳x- ^1OiI+&ZӘ$L󯘔q_1i1)SG[U7~@R\=HF;&Ĥ~LLĤOTI(&&Ti"?:3{eHX:Í"J+Hyځ &80'$+.GP[~PVh6uOcR2fg!h +& +%!]1fky-.ӂiLJpWߊ.ImOC!_1 7(c.iLh2ylV9sӘ$q(,Zv (TdeF)+,13u0iLf/ T{!c!\xUq1vbZnP'D- q>XT( =9ۺ-h뗪+1i\ӘGOƢœBLJl̬ҳFbLE M5@Jލ$V6:?ИPrl/"t=4&Q.SIb-C $r^)[F%1ɩBɂlDshHf1xNcR{ZPQAfXQ*hLH( e'H I!W> opu|E,Ң2/Rߪnuvޥo2Uے\PWy٣(+$"{Hg$'`~R#COhT|4xMAT~wE (>\WTHYԜN5yB5A 5ף21IK\.ƤyvvOӘ7Г-u>@6b.x%;:ǁP֝Z8cC1'RTԺ d"..\p=I̛vSusvc XO$*wU̗K)Օ*w*9I^~Ƥ{苷G+_hXOcqen 4zux@<[J /AYE$ +R, 5xv,~piL6]Kޡ3.q T]gܯwS{L|?d~Eh9*ƤkG E݌5t1uBJm(mJ;Ә;vǛ94ˤg-yԎ'a9Ƥ_I]iL*dSVŏt)z]IVl@ +$"fgd'{,[g|U": 0gm(-j"r$sih8IO$''rƤ1iQ($җ]8IDn"OAkQ"UkR-y0åsU8[c4&9|ԵYY8 t8O~}ZD®011)}D,?)2K]E`gL"Y^x].b*vn;7"$ LxQiU(d&:4&E7hNO$u e+=.wc n#JQYf) v7K.mwLSn#O.wtTQ|{,h2m*EmhƤ!ՒI*Ya z.i﷫Fi J_.aJVn?H;qPm <˺YYd/^5'*AR}+S.,kR;KU_‡;uʧ1&۰I[8 q7nS6&wp>Y]#>3AtvNmk7#giL.5 8IIf\j{gK[UѡK6:Kl}TiLj1zSZ]ծ a xupWS=/ƤezӘ2+%T8 v!W5+!g7K kopݣ-}ƎӘ$B^ $fL%6畠=wD'CHrHWda1 ./ED&PjL&!ϖS- 8yQ^%QQ%щQ1J"$z0J $0JB$1J$1Jb $v1JB$`+FI( 8(%Q%Q!%Q%1J,FIcFIDcFIcDFI8bD6FIa(P`(P( \( I(Q1Jb $T1J,FIaFIXa,FI<(e (8( ( ( \xQ%q$r1J"$1Jb$h0Jb$T0J"$0J"$0J#FI<( Q%!Q_0J"$0Jb$*0J$1J$N0J"$1J $r0Jb$cFIbFIbD:FI<( [(J( ?`(f(AQ0J$L1J$1JFI|(Ep( ?(<8Q%Q1J$1Jb$40JB$0Jb$ 0JB$1J(( P(%Qv%1Qm%1QS%AQ6%Q%QQ0J"$~cm(X( 0(|%$0J$ FIc;FI8bDFIP`)FIdb9FIc?FIlaFIcW( ( [h( a(( y()( ](|(( +X(p(%$1J$b0J1FIb4FIcDFI4b$FIcFI`K(%aQ%Q>%aQ%AQ0J $l1J$60J$0J"$p1Jb$r1J$*1J$1J$1J"$D0J $1J$|0J$1J$J0J $|1J"$nc{(v(%Q3%!Q1J$z0Jb$x0J$^bFI<( wQo0J" $0Jb $0J $0J"$0Jb $bD FI`D"FIb FILc3FIbFIdac( z( {( Z((%Q%Q%QE%Q%Q:%!Q%$1J$1JFI(c7(( lP(X( Q( Bp[bI4+HKڂ%䦓19+e:gNj}g|YmZ01Hq" 0  s$}{YdbP0$BfFw~ll]wp|aᤚآuݥY- Y Z\ZP^60y )}x`'Br*#W&bQ<&9`sϫ&-!r4g1]=G8wdÍOJxtG-4!W NQT&M7~ٓ/GSH{ 6o GEfޞg2QocJ ?S9ivމ0f^J56ΰBh,㍺Mۑ.)d ~~$TunL?bA\k1)S? qQ}?>ZLĵA\u0? A\bz? A\4-0or6oh6KqŔqA\b-㿷6+qqim?aq}[L0-&h1Oq .? 2A\qĵA\f>o-&ZLb .4o-&h1^? A\o1SqӻaZL8-[Laq?iW? %A\k1OC-{qA\KA\0+qi_a?bZL_b Db 9pPE %)masthw׶Ƈo먢!9'5cmH,1$!þB[ˌEWv0<3f#yͽ?'imES]qu4Q*LxXfmֱt9䉩ԍO"bX7{3W}:q(7\w]%-8ސRQo},IYOҾiT)EP6^SW:xo[FhEWKz¹.nPko vJ+(7)|%$|Yə˄W?s_<;#Pɯ![9cG-ߋb zI=Onǟj>W]ḽ\,ٌH̚G}}1qC^> _lwlד?(1r ͽgΦZNnImdb<9^3*~h35HJ/tkWzutC,=Lv63B->zޖx)Wt!nK.2 3zm=VGjn%[ p41AyUNG< CaZ4JZ-@a# O[S 8=c|þHI/VDDd{:-OL"=R<~m/ܝ(Z EʣW6~qbmgSϴmmZnBٷf7i 5mԙO(RAf.Vm C~,b "a'UY5$MT$/7V-Nj %_8dF%q~{O^?gϬcҭ]g+"\}"UR  Ho +_5g/ׅ]9Ͽ3aeW<Ě+;Ma|NO }63 Y ˊ>Mt)\DĴ;#ք\MrgJ'GZZsC6YM9'q%2ỵEd(oqS6 (}wp6\ROxzzr${'~@S%دnjЃB7gGu_X tfN԰ldvRf]O8IaGe 4@ dX>3݌<$]V0nw`7F2<᪼%g~6|$:J>~ nu"Fa'.H5}a8LA0~j2 uV^>D2)?(m8Pͅz#PQpc~5nx|_)mAp@b[Nq'س#x@?MDG#wr;vzіm5GLcCo^z1"!r_6XDp.9 j7-S3 D#]1M]`ͮVcma0.;3=G<4&N ߔS>DC,UϘsOL)e!_D x6z7QէKG2g%|`W ahprU#!Խ210@6E?H# xCqX@Nqn8;vφ Oч&B@4;3ڋh&]$+YnZ%T70 hivUBls^'%l'~n}y"+jt^ "37%&ŀ]ʉ\~J3Om=0G[e ў.Ҙ dk+K$1{ī(\5D ϕDR%ɟtTw{a3ʭٸ5%n#k5 y]Z72a8lm11UebNDn~;Uh!ۺP\}(7Ȑ׳4@8jp% s^\tSmAN:#cյhJ'Jy3zɥjQzx"oZAF u$ Ѱz?h1G9cgRu5G/i)t Zۄ57n?{. GGșw_Q CztEZF'9;WK}Z*[垼EpO'ytM(CKÎ81x/ѹ8RUW (9'pQWB^G&](@pj"klwtaz:]3+yhs#;B\ӘA;u~F9ny֩وFٽNwy'rD.zUMr^o3"cu\(_vxm Cc ƃ{Pz5?6- 9tYqzs1G[M V=3->Lr~uu o ,8/?iBC_p($>b4jV#JԜD^q3x4*A|IxAo^asN'0Jꚾ4O mW^J]D9w՟P!߮|$)D67CIa{3``ɋ>T91Q8,<+}~8'Z$e"=YN(xXudYgЄZc<t3ėqSȈ|l Z2?S=zsMt]FϦ_G~(;t%SAmu¢5;6+#<3~x\E.hݳ[b0Bڷ}L^5=6Q>Tm Ce.}BbVOFR/:Р,A{h{JO1ǟ8B#|m=Udp A&Z<&nip ^m z-94XBE~Dd$7gqiޗ=L!z=g$. nW]iB=|z̡^WY`b<(~W8![1rZqd %w{lm?u@c fF(J쭳Un!)d='=[#b)d -szxݪ :ܫV;U_C W(N3hӯw VO9(I;$jiV`zDjZ eCAŸBDH\퀛;E{Y%*x5n0Y@ Y>a:C3b7.D\__kL#74nB'98_u|%HNG(<'`,q9lH ٻYޑ|WM g>D8ndC1Q@P8we%B m(#qt펚AR)_xdȺbUZTxq-TKt+LjP6ĩ=WՠӨި w֖ ?s,Wc?+[:] W4y_Tk:xow!&qtߍ+@~m?GЌ[%ȹ;Φ!<"fx"}IA4,S~H: VKrOF8k琇*yF "U7#d}cH7p__EhD\LI??D^6Q+_ADF 'l}y}=>>:{ZcEr# H~t9S:VVoޞ[Ӟi5tRc ʃgmi(=vT{5WYf*Շ?wR.wk$ND_5A诚.KWaSZiWEL|ϘU5,]<U/bW,W]ִWYW=)n(N8Z!]_"M_UƿjBWc"FWk׌w8{пׅ|"eS05'٥zIgC( !oc#)Vg{O e0>ٓs[S~x*VC|G6-afn!_ۢy3wz'MQ>܇g I[DK.vq# ^$9:p1?gTf8^Z+J +5f(.g .:4d_َ]\ ݎ"yQSaؚS(*WQ'&PɗFaFKT\iVWY񸬪W+CAO8, ǔ\f T}` ]Wh (#t[*e!;ҚG!7 tfp2;*WH_mk9b'kljK4M(=ie,,x6-G45pyD}Yc=O훹mCcc{oO{?#S v~^D]G p7/_ }QtL"yȪJ@RNGdHq9:s3\7SPBb3I'EaqH9b gce=0;ӯaDz$%i~'/e-k.J GElJ {^/ˇ7fhy6ZbԤݡP~rޚbIRH_E$CJX¯-SX6: ET6h]~VeP\zhvI9N VTHg`{iO6QE eBG;w&Nv?>מ'nr?/+UFn_^q+d TZ9얾OEzpfs[|WhPge?\)ZA[muo]F[k i3q}it32t d9/wW>V109J[мݱdMW*=fazqP4omRO7vIJ]s8W1r܏AKqK=a|ppݽ~\\a>e[z[#W@ɇ(`K_3M+}<55 3o\O+5TKjyP;gp8}z϶+= lC\Vpgu|ՆlsLu;U[ŏm'V\=) >Ӓ?]D"y^F~=6-)!,-zn+:=V51Wx ׀SGk iQek@ C}ėhɧy9G}$<$w.RshCakm}g&χ? xN2dݕfyKQG^lwc~[L;h_h{ߗ=OI[gzg˻E?=rMCʔi׳7AG]Zl,TU]is8Q,@wġE<]-{!.Oj_ѵ34(j!y'Vt*WBNqӦh(ZD=9sWOFXώnz7!Q>RʇϢӶGWO*)ꖍSc¶92knr-,Yd.a'7"B&X;<[:J?l((!Wr~ l/v1\+6A2Xi+jh̰2S&-}q4{0"ۗ <=,DK/Le5d;W]ݟo syG5너i 'xyUp%wA8C‘`RQo~jlSF*@].kAh|"b~k$5Đ|7w5p:wA^\&$@v8r;vz(a=~b*](}|yAy = ZU2D7cӛ[jE|2> OK¸qh :!I\"Xw߇\ÖN/H.MZzeV,u6n9Yjx?;F[ onä~s"?lLJS@Zm*`(ӑ͟5 0{*|->ͬO!/>^j%{%vUf]uHef,hqY^\y-Pw%wK-ؽ|_Bģ'Ղu,PX&tNܶ,C|2/Rπ7Xѷ }4DW {̷kȝ+DX|lFNJk7"6 ǁxH1_vu_Kk)\҂7ȵupP(1DSSd:%U"-/+G\Dv"jU9-㯐8y4/\(^"dH}reo'ðhc\VUNecZ5+"@LFTNFkߋap;.;4PF/8Į`>4U#/Py>P<-\f)N#{L^zn;' (`5ɥ%[WpА3~8iLy~FWmSMp>[&K8).KB8(wR\i n1pRs>y45/F=@ =a 5a࣒e0*!uxs0EuqaP|ђĄ׷OdqsC`JWH{Raج0`a} l j9;:As(=X B6PpyhY(|MDS6Tp :NBOWP^xä+*=k]~ZͮOyCsIKh> +0 !! ~O|sZZAr` Nn0h_< ~v81 w%'0и-<k"gǂс xUȿ`_ɔp6.G+7\@aL!iAW,(ww-\@@vmcO [ޛ@p6=)i ɔGAfa}U PdV_&R g;śB1\Nd'/: LD+ )>gx,>lf|o[c{*ƑE/;R9m{VBv4 |lJ_~?`~8FGc'ETJ^ƖgFK.?Ȭ5\~Xew:t~ bsc?u?sUf(&^cV-wΉ^O5Tа\[=]W{G}T`a`ڷH=׾9C7'"}KGxie4Zf&|_._s/@<9X|?,>%fp!.Ol;> "g^׻c|N1s'$_t珮? (| j9Co0C g|x7f{&JRUzyoqlo{/8}zsd=Ŋp. =܁zKwqd)JPu2ɺmj>w4zf; |qt(9措|e7@1WU<.uTYQ7`B=\TwqUoﻁA!?Q7(gL܀_Zc10LtpFn`>G 0KHt_n^i ,w7\AuQ!W~x.+hY+ ]AȰ+̏&ǎ_U(!+pLPLwoFr뵠.K0|xNGEєZ/{ݝZtyL +HN3˪}`OD4:E|g0jm3x* h>vL+Ft*@0U ~#vGcN5ԯa'a DL: )N@ؤC" x߻@p _nWw!@ ARqu=GPq3Ljt@_=#gA#&0l==Β#XNq(,&O8_s։Mvoʖ:\%Ȋ0w7*3R38<S0}5<@$]Ytk]$ǒ/{tk,;al _OC-O2[ a(.OU_ ]:f#t_]*x$e pʳقtK$Cr>rTH^C6al]+| }QZ&2 ka25v6!ƅ_E :_e? 2NΤ:ڀ*W =k{+7iDYyQ X4k =][iBRkS5h "EoL:J Vm5Jɮb rί Z qѽx28>Ֆ?5a2M{Db(9M( (%d$Zg=YF:+o|bf޷Ao Mx,S :u$V^0ڷ[-AoN%NlѩE2o,AKpD;>j (,Ya9Ǽ@Ү%p 8HTB?XB %p|mHj RxXe,p~.|H[λ/-@T" =~q>Khlž]QW.YEMd= nโX'`9,"ѯ7TϏAQs.ns)'9/5s$_>=]?2qcx3^9λcq:D>ot573/22AgA|u9H-,7Қ^_|sq T7[0=Cb/5f`iZׯ =+3c eN9f`7g1 ]~ |~_&x 3N؏yٍؚ͉-}3!ѭl6ֹD̀^d 82%݌fl~)(g|k ({wM`Y#Snuz`4G]66,8Lo$`֪ Z 4FX6ԪY&х& sSp "K`i? V4eVe&BM6ٔƠ13*7MA@6yucu5e,E؛'rƠGz410B\ԟ%#`Fs׬t9D#p:k1& km 3;T@Σq%# (Fj= (V*wC`wzLJW`Эu!`YHcMtyk꤆@Xc\h~+c6Y ApP`U# 5d0dWcߋ 12[^00sO>eKwӗY A7·wc]_V}`sTk}啤q+>8Ojj#Uw UK*I#>sB*qFᝇz5k~=5|uG\a}~Os?!){fz5{FIL-rV#zbVn.wf_tA"q&]p}X]h| 6˦1.f(.^MttjwY]@\B mwTt@g4 9HԾ٭d~7jWu@=$(WuIR V:8{<$^TpVJ"u:ǒ`&tJW$>yN5TXkڀ46(= o;k#?ZAz\5ͫ ~GwhW7ű5-ݘ('!xn擉o .Z`fu`48l.h~ ZW-)@sq*!S,nHUHVocIe{g:'-pR/6Vm#7bfquL:8xkJ433I _8/[P|U q4F1:1 kbOЈrW}Kiqfi*֥=Ue@M 8>tHW|$҇E!>m5)rpdST@4v_ t !`β3 /Cm#lˑFC6KACuW NTvP l#o/Ufgjj`.O $O3QOn0)ʨZ=&5|:Qf+ ɭ[>H*cw*P5 x"3\6CU:.^, fnyO2!ܣcp%ϱkV |:yգբ_ޚ,#+w ^\x/@D^(ٛ]ֶFy@*R%ˮK7'Cakʀ* ǰ27ڤ yT?Wu\>Q7ٿD)K;ʀV|@DG(D_S?Gc]%p:m^ d17aJ`x^ <>uZ@Vy._|{աޅn)Zr1F%Сs>[ DU)h/ܕ%1qW^y`쿥X/|]X l+X>Eh8PkTO&m4Ł?̻@i?{Q .js~AN@JKѴW@b\鱀XIm"&:fҊ zkBQp$1~TD atQŐ4ZT7_gE ˭QB @#  /2Q"MGGRpjH^.z6:}22Dz]KepB\;`oq72Oﳼs$ϊ?m"hf\}$X+c@MɻY|y[xK#N-tGƈfaT="n y/G+ m{wGy'Q^tTJ}+fwܘ>Z wM^C& >ر#R^qL>t<Z6pKiC}*@q/l+$ӝ.ٻ<`Y+: a 7êbB\ԛ4pH`Wlsr* ipD xx;mC:k@[<:eWqŦ{Q~~0%67wtHCR"l&,ɓz[WŸA"Ώ~L[I,+` O]uAQ~<pN_b97?1/օ_ᘘFO4(|#ٷy?,oFnz|~q-w/4V6P]Dx|a7m-_'=YU@٢\)\j'||NkLVhP#}>pѢǀ> (M;p<8xn\]+j L<9 m'o[—0Lb:W* k~>3^?,t;@ʑ(|o=zYmʺ@eQ.0'ݵqn IŨu73u!xp3̰x#3$:9 r՜'Qmgȸi:c} }nwNjtN6 2-1 r:cNgI'5: Q uU:”MP'Iu#lr#Hp?R.:BA+p+!I#v#?vqRC>6eRHlwB8I&QuA{m~qmLѾ@ڱ=|d~pz+.GLvq֋!vg;ִ68σ|RABY6Tս+e#;}2X ;_qL%hPg4vmo2q[xv[T3Qj sp_9?g.¢4O[HP9Ji[Y}x?}qwb_{Vxփ60l36tVgJ j]卲9]60Ks#$G*h\y8]Hƶe#!ų_ְuQ5z|W3PW%sC>LR>Vv}>q`以<чCIJ{)ZtߍowzОgԦc~G #=(%_ЃJQ aSF[v=HҘ@"+!Wu1./Ҩ b$B.طO|Wf"taej.]Z9Vׅ_X+}ԅ65T0Zhv|_r_#'ҁ${:0Z~ yNDe˼68tLV:Pra#SURMcW:PU;{D)mGmmVFQ<ӆh?pI:=~c6 'dganͺ6rӆF? mKz0Ет9q[`&N$vP lׂIEBAZPc}F [f|WׂY IۍsY qv֚&{M 9zЦ ;FUjB+<O5aƳځ$M:'R:k]sՄQ̆omV^rskBV:²ޕ?0<׀5CɅ`bxؙϷIpE'j@kaSjP@)h!0րQw4`Is~ ըMCS5@5u$Q1}k x[k̫) `l>8ufFeT:Yl-\IuS@~ 3ğ@Bd ]}=wF9 hW^‚Vf?nj^ڼ|JLVQ r Z?U9 v鄓IOpRUojE_ﳪ7bQuǪ( uE@U'#4^ #7Ky{W[_į 6 BqteڭIWyi*u +$l.T*; U _q2l|GuRZҷ)ÄǗad-deN*D V՛+Cwk.pf8'2D.b)A!JQ1c 23}Q։DJp|~<5TVw8 9_xJ:Z֢"캫OC֧ӦiQVc[+n"]]C -qEKYHQo'`R Cİ\?u){.)@W- 0KL&/`+d6#yX{Y2D~%LuZrȟ%]Dͺa+r\Myގ=c".,+@%bD! )H W椡hҐY?g4g~WX, 4>n TqI`rY4.a+ edމДwΉKդdfix8,ZC( i ޖWOHAc-)t,R-V/9ϥ`FqYt)s-N ^xc9P |:VRШ(%o|gB~dR.IHkz^SE.}* ={TVFTwġF[gkqhi./0LK\?dk?SC6 1zO o+WPё-^fb0%QR ~Tç0,CoK`Ѝ&>(|zc=CF+E+]w\ۉ^~\\IH6, }(K D`-ޔS^zEz_vh,8"p܄({|?&wEE'cSJ%*Hl[ ׆p=gVSaخ-N8ׅx C|Ia>MHm >'[B0?ebX>ެ )6<"LׅB9)~WHk?kd䅞AXrPS|Vm.S!Ej=AB9A8~EA(8R=Jm^AH +SqtS3 $m5 )+ds.o5=|}jp?S9~(qFZ)lynEV~8 %?4J >KaR+?|ܮ_g?{%~ba%>v.p+%A0i.EpMo:D<܁ B>b"J^{W+plf 1haߍW?@ōKV5ᄪ*PMlS2-3rpS!N~si»!Z nAX[>߯t7>|HGCH:aO\/*)fqLa@Sv(1{cKsV>NY2lP: [a%n+/6x3KreؠM+D[:Y]bτjY౧ؠcwwE 9s,0_F%\XF,0}9fx ”#3 S}sQJ'Nc_鮬c\YB혡S2fXGHe7ϟ1%BgܽJ /sz19x7# ~!"[ҳmtth ܋wJ%0s$tn0v&Ⲍ6R&e24]V%8.CjAƥeMs`X$t enV6 m=58vWݖ s3=vaƓg)PFеJnBya [p<>wЏR^fN|H57=<. v4Zi 1ct6Olu υO;G)<<JĂ킴==@ui^78>lr{= ˜tyvnP0<~Ջ[ l$AK mn*%\cq1etq*[gnpڊ97;@qSҽR>}]Aqn\7:o uuvȸ;s8_.ǵ^.LrxEn.P>r+  m{jm}.F}ŭorϥ;\@v/8 }?BY@>\ ,Ă ͆LrI翩pF+^R\`ę <p w9ڼ, t!'{A :G^s+[c(/` }w:9fIQ`'(iܩ?'sjgފr}N>4xux |̲o> ba_'XzYqۍH,</jK 9ǽc9><'ȼ%+ F-599t!rN0nt6_k<>R{op6s 6xmp_q:?pq"Xձspӑz%׸<a{8v3%pN1ey0.hrn c%s׋2&?Ҷ_3盁({C-7С:|_SrWnDJjv@|Xz('N~ag߳8 Hyη*l?8s|ygx[+n`wM`ocOX؁kg6.Zt 9 lh8%An|zKY\kBRY ד@x䍿Ean>bBc5ݫl`|ю -9+ⓏB/K YV++x#(tT pykXA8i~QV+r;w#%T^e\Ο) CY _W<3bUf)flBF,kN+BBVn %, ª>(go"wYoyy,@}l.MeMJ7.DZ_BY@ hn2f甗TXAM3 hh1yCC5’%fp %w7fPNJ. ;2o+`ru130e-ĒyϾ =}C-3Rϭ  &g ̠)Qc>ݳN>Ol,K|,0< cU^םO跊iJ/o< /]< 6ߜ0? Fuς,;gէKKg +̧Cq,X^?bTƪWgiMVcj-](PkLi*ckbbә.u&ps9&z8ћ 6Lྫྷf.-uS Y6dƃgкK6& 1~ k@G,kOFOgFhMQ{,n2.fw3s`ϐMSׯv[4#'ʜ^sfd #X2@7OtBnF#@H.<1#dy@?:&hT@S&xK ~ vj mtJ?v&(=ԅT@m+ -4gM ""wz\e օ,|WY_})HE&Ѓ#`~.zpS++- ? lԊuF<45|=NrA )7&lŅ-G3TZ >@<=ndi>mVzƃlZꕛ*҃DU?:`G&+`HSvx)1}t"V: ?ClUCVSUm_t`!]=:KQ5:)J}8_~Oēt;7!.I3:1("WM2耳 #!|NE¸+Ӂ{ 3en ->A _r|&m%u҂uт4 Z`ɁIʇ@$%TppB ^6GЂ2>ϲ[ & 9-0 Hl-%;pTPӂ^_N'#Ce\1P[l44quPQЀ寕< XXuizC:M^ҀuήlPc;Hy.q5)0GTe%р)4ٌiE΋FuP.wz-o Ӏ?8FҀ:5bprD )3zR{yj0Ԣ3F ַש?Snb0jN5лSI ؟S-k,j`5$xiy'P;hjp,P]M[ԀwBiL l&h5y.3WjJ߸V?#5pgwf@r*"qN#l_@P;>QcS^Gz*PeLt sRR T@8;aX멐;Ij+w_PW9ǎaT@\%H>0.xxTE!JIZp\O*\enafiC6$T`b0C /\[#IS`WJpڌ̎6QJЏ|Pyz\EOX,>>%%sG ~iw(tlyRֲW\)%-֦v7T(N5PSv)^S!]IzJ&*JaG1hdnSIk&`' PCXZWLBo3eP*2)`0 PIB^O?46cW)@"熷|%ȁfVP"ur0e&9>_`XqԓEU^\x9`1ZFFWA8=qξ9)si)er0m*HMPÇ G>9.E~ekaL6~2@᭺+[Es姧7ۺڞLp\KpӞ/("oγ!{Vd`2mқZ %"^/"->%aȢ3 cy X؎tR:5igG\:g:T>xZɽ#;fulπoϜRu3`}5Kt.t P PRCI}Ct 4)8LBHwH+)#""9ORHAk4RZO j?J-,7R#!eF p38Rp*BOqJR󊋏:%)?! 6"n$`)z @}3+'v ~FVEZ1#l^-OH8!V< 1 qɞo=H@ % x/p>@|!+r2yHQ xeCpt!ӄǞ%## C|iŜF|cٯz9>HCbl˨x>8cT>VSx6WF|`x& >/ ;>uOX< iut}׋:wŻlx@1󥅗x6G>DK`LK;ǂa7@\M40frn cgOO-muYO$*7ED=~xNua mq [b<ޟ<;ޢ.8&IlpA?}W'.ϺD]=\ jn)Nq ;tZj<.<.z |ri]%.W3̯oD>KLJ &U₧Q  nt2.G{ҭEKJ+S87FXk[ڃ4BjqSWJp@ ˹8jۥj at;>>|Y;.kQ9N+h[j\ Lrgq67ه{D8`\160mր`Hh|x?k܎` $cCgW(M]&~6qBݱwq@hA7a eV3 `/Q }КŃ ?޼rPXSbWb`f!Pğͱ@齇VX հ̦ ݥ p,\8X -ݫG, IzUNy7}ߊ%,po鋜.a/>`N}0ĿͧB}P}:fi=}pqg5  8wڇ9LŰa֛{ չx1uvҦȩ{ =и1Ǘ\߃w"m>"{`bx$+Q\WXhE]=~|>=hrS!];#" ? ].';vƏY컂t.D*~mXEBAo')5aDY]"Z ]8p@|3zLyv-&v\l퀚Mw4 _P1>üXK܁f*?@k El ydqYWhsr8w@+xE'/箍 r@3g;,9rkZG~&Oms3m 7!fx6t%LM܆v=Ar xIoxneED6}X1t/oC/m = 2y{.Hx IQU[i. qoKlʬ!nKWa*2UʽJ ÂBz+8 ,Wꏭqջ&Z[kOV+g?,,&? bVDZI.pԬ2+*jxtnU+٤ 4}_yR EeV@-HxlϿ?γ$6T+TYt U!@:ji6 3od0 g2h=qP }Qˠ5v` mtv/Cԩ< iњq a3Iɛ%^fyet .s B{e*ːrQ; '7,W'k2H_ĴԠ'$r[K~X}a +I2G4U{ L4,0.o3罥J|Q\[eOϖdKk ^o9,A&qT%:0-3^3'u=%*WX0Ka׷-D|y%ؐ^YeqDK8ͺϩYa\$"U^.w~K6.J$׏-2;ٟ/g/~XWOO36jN>NU ^Z uNj'm/ar-,z!"8\ĢtE]atME=Lu"x_{#:TnAE8b`zu,p^("53?' A ~/iǨ]{[hg pOL>gm3s GF._IkyY'[@c<(|O98BoY7,} iVf\t JX4gDfnCt+ElyȺ(v|>TmrCy9((U-syjL󩯶>A Α'!sk ߝ]/_<9a?3qc9 :K<#ǹg!1Y`P$j_hN3BӗЦkb ם`RP_ U9^i0> kSLCۇ)H,ʸG&Stf .O3ΛoS$ՏNLe{>Sei?MYܚj vSr#)~;:R6O'ئCSU}}kkc'A]V]mg>P7 dKw 'a=]$\e8^MqyϧI4F: ntm&!L$[z5&r]I.H>u^|N=r$ᝄK^1N3=/'!SRLWbɎ]Rp6nL΅l&uÎ FfVҌ-+ʃ1Ⱦް<_ ㆸjvy2Վ Vcpy 11l;dvǹ^A+1`'Ҿ8F2YOkcv]1q-?5R\j ~P <wJJj@7`/E1h8=bm^$955 ėl/G'R/TǩG|#9idccFAem=bU\ k95yQ %8%`_C-FAɐ`N+U_.)>:RP(XrqsQm ~ЉxkUv~58VWZG௔nT@Y͂UvJHR4#0l\)W0:c2}&~#pR=0Idy;</oRsF ٗF`sq^dL=~,94y6?19LDl %acYJEa8>x~i Tr0R0hI]/V}3 a/tA@ݞvuT=fpYk0xv0PaðT02+6 -IawgvTXp]`l JB>K>48rOe !R5Cp$}&>V oڤ!Pxbexw^Avko!ndN/&/ A*{oxuܴ Hd' C* &_=%4lXV$ˡ!*|_8u?̒A 2 Bn <,Oa!vfC}@aF\ ?xe2)x෿\9gsa@qh (=RoҜ;9Gwl^&|6RuRAp_~{[ylw7UJ)Lbj_>wTRSÃOAHLL!u>`l~h,dr^Yb} AI},lw(N!NmpLJU<=!'{no=,ϛ'Ax~K1.>_/~Л׷<HGÝG~جzoC~`Ѷ0J8 M8Gʎ0:]#WC_Dn| ]Ϲ}PjQőq,opȳ>XE}0߸if)4}[!C1w?m}It)}2p`c?PWjמ^'WUCY hbq!DJ^˓7a NJ-z!an/ѣJM'uHŒt5*C/9߲gz`ԞQR~GZ z2Cg-'B=`E2ë)++o=rrD[k8iԆ{@;;C=kxc5nPXO?kiM4>N{!qkH7>3ʔ'w=w&Л,TEst ?nH2c!д c7=fw ,y;Nt -]mu: rJ2`N.{, d ? ]0@$p X1r|`"`. y'WOOo,:w[0>!ߔ*wuaX֏xtG";z;Z:[(FK@E];\x*?ꎖNR`\;ǝx'\&ڡߗ4̻"z.۷9QѢ}j9~tRCA,,Q>u]2Z&uXK`\v&]kk76QRoi3>mJCN6ʫrs)sEug6*Foih6DdY Oo\{jm?{GH*M}۠;}!H/X]a6۞ w/^[lGn{#[7 54 jO ~Axus8SUR[aVxOgFh+4jV?i"AVX}ttnPIn=n+RBe6VL}+* j0c:S76o-p"o?8f -?1@@SaJ-dQ]D=9Q-qMï<}bӯHZOa^tM 9dZIn5 Y -pK-o5^_x_lƨD-'EӴ;fO ^Rz3lM43f ahhmYU NqGa3,NFn6t`% ޽jffY L4-Y7Svf3ViJnG* _%A9=CZR̞p7ʼn PY3&[4A5&z%l2$X{٫s P]yy窄/7ӥѶ&j7OFj>=nS&=W7385/k&x´ j]k !FuFXݝ4Ś`k_&hhՙo,-M%/UWHޔnMqrV#ܔ [h?AZzO#>p.jj+Fl~rp2e4sUU&Be,?75׍@T~iܒG#kY{4ZV0ԺpΨJ_xe46.6EuȞ4~~L#~Hx#L 4qοSSeϗ3dVZ=qVQ4+alE pfqJfťD7##~%ѵ%[Y4zN,i(4G >DWAZ׬WkNH-ܹ\ ~jZsjHZvtcT =oҸW 1IRF=N>YwrxBӧAwZP㬅/Qւś5pd |Q ?,+j`_8IҢkup"Y a.5 xh3٪_Ol.-gj9R;Zj .M8lV 9ǪC[5_Ue /,OǏa@Q u54yY5x[5%`S lmJa5H=X Yз(XpUC1rs^=5&;Upo*)񭤷 z3g].Ug_U`]S4}aU0Q mU,}X[ ,rTL vͶ UPzʼt>0Xvchrq !Ȇ[9<}OCqFmr.9!o'Nrr8sܼH9|]ϗh+!U٩&rxx:V bxfl #D?nwA%{2+_T#Y6eY>{ m_áYReod Z?g:Qe ;>2h(k*߫wU>%WɋA ~ V5ʠ嵄0q(sj|3p"nLM)}+j.)3b9S T;u?KeE)K)do&͢JA?(1R0Y\.-4#x`Y $w7 K!Lgr)88m(Bc+tgJƶ\R0|E xfnY2Ba))XU%EQW]7^s^/[jJ@/+Ɵ/ۉ%?c^O{b.hs+P_9S+g;Ӵ@ۓxQh(0bjR1|nOTbJ1)f(+{\b8x5nF /~-W./-Wjs!`KFJW [&a 4X^1&. y3bx޶yd3f)|$e/'~!{1P}1s.KC%" -PB"g-5(k&Į"x\5Fq|*߫*҂#~A~7EP,m2 -76Kh3ģEPf(iY_^wMCC"jZ%I$犀c({T\C[)\CCwٷWE@ux/ex_p97-5ثyL2ܾ_ہ椅ë:*"Jp(STC_8ԵueA4HQp8dZ wtŜ| 9﫟`z .}c89PCkZ q K]y pt,a4(:~1VL;A %4^73G. p%A`k`r)E{Qtb#HyiE}?zι U5cB𠜠Gg { ?Yɠ3=UrqsFœ̖o!tݻ_r3ƅ"FR!'ꉢp!\>dZlb^ą`Z&\Y" Z}齽UPc7; uvH__kOF `i[\1i]5[ @Sa\L3Ғ66逯 T= o~>8~z.GgC'5P'LMoX:?m>,/K~AB|,· {2ZqBuA&Q<S>|sn!0<07ʃ2+9Íy:/RAxRlkouL|}܃.䎣|q &y0d7z<>)ffYxL=Ƀ:!@<~'r?̽qO~\81aP h \Jy\ :g_BWo.(6!*[K'k6sᷰ/\xR0O1|f΅_.ʼn@ uM怿D(0 o7A9HXV>_q/nSn=Ԕ8Ok5 ;24$,TQ+O2(zO>NN ~aVVabuhL?E O$^{g8FAmfy S}4kũ.*rnZÝA7rҘs9~pl 9wL9#Ier41"rquv+Ar|38B6<$:N6>R*dxlT׽D2Ŋ5_Q FW} )I+7T%%RdxυV>2\DDCGp3"ϤjrI_)^QJ&ŕ胵ޑIսtOϥOwkHT8K N*>uFTQ$Ϥ'$8[$' )?dz?I#9EI,)$eG7) +W~'z쐜4L7C{۰{6!b-뱇j5=LP] {( :]$vnsUEjie(72$ym( D]ՍgvG!%]e.bn]T 6`oa·Fww-tI;dP*}8'巃fA&uwз/r; _AQ'"+ۨⱫ}6#Ҩ+FQOgŲm쥨e潍쾜ްOӪ2}I>(R߼FkE{Sn#(-TOGݳ˶~wRҞYÛ-tg,Bj1`|~w CZ䦿 S+l!_O5-u_q =w6ї*陒M4ݰδ(nj &dU|Lo"dw-6&z&>>x^pqM?8DTln Q#h:~)u9HgoW^?Ev5t=7Pqɷqqz v@7^n /TZ,Hn- t3uDzXstc>"-YGp):L.:.$'t9YVcuK'_^GD79ju䤝>utF0DWkhÜZJ;۱F! Aikhi醿5+5t#} UZCS%۹kH{:!LxHR ZCği(] u* o/bYEB(~E*:vXE yݽnjnL"_ \V@IJP[K:K_#$N[/[Kh7df 9pƓ,!vPҲK(kK|Vl },s-!HQ%kC<5Q!~EXf2$ѸvE[-"ݠETtx"bъZD̑"ztgպ.W^^D Oj<Qe]8""2tI.`^DAo!]DZ79`g7}~35Y@%w-oV-> dзAdC6NQВ+G)KPS-HF<"EBzy=Sf>xg'Gsi%~ީ9us|?^Jf.Cu'\חPMusHrr$,R|-rtklұ΢6~"ݣo)͢bY4[9l3=F?f=1gəY$Nw,2: EtjgfPM6z pE3Ⱦz c ~폞Ϡ?m Of]SK3'TRWA)ăEg/V36:4eonFdoHWOա\Hl3G4ZS7cvӈhy4}|x4Ih}VF]bz}S(jt>#[3SeLБSHf*=:b?ύ)t(E\e PV..BneS]F72qLDߏM'2nh $N"1/w"'Q2zItfIӢr>Oo5*L!]Iԣ#Jw^rb{wjɲoEN50+46%N S䭉QHޤZ˷@<*it &wv 7#Bk1|ZC:w8viygZD~q$C6s^9e Vݐqbk01JNY# mqD6{UaFn(zf`Gk!(R:zo eN?CqI27_jCSýЕ%wPH;`Nza dSՔCfqc 5"?3G= 0aEF{ Q$z(6m9~ibLI~87|nb"!ͮlQdK{p" S#>H:޺.8;W+FwWwFPq\kvg?j>5RiAj$ #HCSG&K{K #(&HeA3z>gFWgQ gV0ZNH[=֝"rэ\ HvU-0j78o0ʩ`~9|[m 9;CՅQbLar0$ZB>MJܻ1V*Е, CD#@kw~7#I6!cs幣CH+g!T!dKzwڱJ+Bw>.Oe+CȂTv` mn, "23A{کAND*Dw%>DcN>tUlc߂N ." 259/c:N;dj"vUוQR qӃH]AsS6}9zFPD]ȩ{[8iz ?ֱP4BDܕt&A?EjI*p ݻh'0r^ɶ.GjWZQ|nX?=nҏx8؅~J4GgܴPfu>4ׇn ҇\w9! P{}z}9&;\>!C|nVd}hsM_l/Jl-[zQ^;Yn/DG^G:,8zpκsyU5q \ߏE'vzzQ=HhJTW6e*AG~_ό5zP31{p"7A-zPƹ=M /-nF B^4v9)(8:ޗnD!w#CJݨm7eJ7~Eu*xu#]hP.mԅT}Bv~v2!]%.d0X`օIjt3|,R]Hآ](jx.>Y@R's,*ީ.D뷦vuʪ[w"ݷv3:Ȓ ,J' D爝9;QPa N$ZKνЁvRuw7.Ҕu\YTF-%<~ց?u@nŌ;P=ݣ/vS@z'v wר F; onG՘oG VqsQvt]@vdy\v4Ζ^Ojێ64 6ȉ/[LvDGh| m|a`jC*ZQ(\+=u#龽VRيlg"ҠuU|ފ=4{i^+z(mzSފͱԳ(,ymK+:qQ߱CKb 1?ЂL:ZLѬÝUHԂfZ;޵ %a{WDí$[nA9!Y ˧K*-w~|T  gZб.n3ty'~+5Ќb$woF.TH̗Hf݀kf4oOo׌~MlFp7][pwfԔqfWMyI݌Ӳu4!;$[3M0doM_mBO0&TUn' 1d| | mBW&/>jB\%~Fe&D[,] vUlB-Ir먰1r6:Y"&qHv }4$CވsV&jxFGƴifȾmD^4InJ}lD"C66"F4IˡK[4o&"ڈD;ۈ_G(Lj6"+FX m#rtao@%75[lMFh#Ll@gC͇Ǝ z\j-wwobcb&GҀzE'g9uhAKcz=zM=:N)٫\TU,q#%k"(>jc=j-FrДvyq&pQH7G> Cnu(Z Fr?ƚ!-BuȬEaB_E3_hk˽x-K^T[O_ E6R.Q-z{墲r-+VCkqkf gi8$=XYQT3A$WJ{_נǟ/||TNe]fё{*Z5q[t 2VA'ljGW|5%>I9^ďjjDnjԨ.[+o $ϹW2)/E/;ý^Ejd4 OZ}":_bO:JO)^r&VQu*C.w n]8$ПwdPnۙ<*tp&? 1KܨD59QCNWM%ɰbˬDϔ^\2cpJT|gù}P1D/W ӕhYPkHibjL@B-h|[U45\k׬U %[vD*R @ԧVR >n933"1Y#wZˑuOJ''noQdMhn6rDKru.CL9r*/G4ʑ򡏌Ceй,p (TSEeڱe6W}z#·. 9yv.C7kݼU=zOJsչ2k)C Ҷea/C ?<%)CB˥hc9jyHו⓹SHrRd햡`< t,Eϳ*JL6SRt,"\)B$JBG)_H^ J>L:{( wQ _%ӟO%WKH ,AO?/[,~]/A?F~XpӀ┳%JgTb[ä%(Ej16Rs[zsoq1O~[=_Q3_ȅ|¬ַߔu/F7hVSŅ.F{}y=I}n-Fǧmbj.8Xi,B_{PzӊN\ۗ"B'Ϋ"DGIxIʪw*B'{fX,PJr"4w4-B+]q"QJ)(OmVr܇ӽ8zzKܤG" q4[ Gm8D+,xk.8z0moA qt7L:]G4o_\.~ϥ+Tw8"}BR:'!j.N5A(Eq|B #4'jG/ o QA|LN!oTR td9ӝBUEKttޏ*D^řV V~Ѭ5-@#DMQ=Uh[ztk+/ĤwzxO*@M ˍ=Rv?|G^GIdTrK)W|48g3QXL磯fG?٩|G#] V.:CK!UyH"F}bqjCQ޽yH?]h2a$ H!өO"!{Yӂ#y(rjM;ANiuur1MGeH+C)a׹h(9\d.>iO3'i~M'{1`u.*^]AR|IrUּXy"DA5wM6¿3__K̓L^ɤOz@*lNg "/@I~GY6 A`֢`9-%wP~&5zHpq@- W f 5kN==C4@^C\=E@ ;?9 {Y 4iqR~<f>) Ta-߁ VoR]p&pn+0JR7 Opp|85<:$~jo߆)&v@ `k49쫜g@ŝ}V{b~9tCAo[xU^l7=x z[cuw@O )??W[Ea{7p8SsIJj\#rN3/*Ęt4D!ǯ'}e趚e$." k,\ة@/U?:Pe3ѵ3l(so@No!# Wm$*Uev|?XUq2}K}( 7ϨM=7˚yy'C[+Yt>Tk逆Ӊ}=t*?a{HZ9B4.{e Q.4VL^?IXC+ݷ0/٫NhK_9_LZ]R',}rI@ .8-p$oH:5a,}ه: jB*x95(ĜJNB̪}oYVdm~qYD*s 瘜v{']@ Qi,;tfO[=HGCgpٯ>-hSsV&,$Ӟɜlwm*8 t+|)+es㗾ӆxXAv&kbۨ ݩf+9|eTqmFf:˂ٰzO봷S(xR` ;˦6TysYmQ g!qT򭣞@)_~ߓ͒[«YDB|o)bWoUܐ [,P c~$r\϶Ō>J}!P93g2;[CSLPg2G v1o/8m篦3n&R0'Qv&umvEHÈb tS2S"KI~}A$N}ע/ !93IV,H NiV:>+0G :(qg;Zyש#%M59HV2{1֓a86cMDII 3 с{ 8>TG"FК5,mDJp39Kb2`/g}N H}dn:deƞ-ߧO ]n3E¸Pۏ]^H~D5}xWnuv@ 1PMu;njkR//jtfl-m;tieYר4!Lv^H0 <5{Fhߕ]ͪJDGazcLڄS |? ;r3{̌ĞGqTaf??:S۾,ᶁ9Ga%77\Q3h %|h?8 fvNGzK Mf+z=2`$nd$ͧn_CG hy&Vj8чK~yX ͷ W!VW"J$ߟU)n-;D=v3p3EgD?Cp\*{!N'/~_8IY 9KVQL ɋijkÓK~A" ^Vi49(Gw}oR<9zPH2-مЗYt og )sdgղ?Q;{R0*ͦcOf#l-gA;Ss#2n=6D^TIuܣ P"yv?GG^pgN`r[U}t22FunwP`Gɼ 0>ƏCH=V&;[cU60`W*0'-y hz7׊pPz-ci~s4ߗ)TR-H?JxVp7>>?7eЃ6N)eKaRY?Ʀo{wQ.02-zIm)gna; ֫6W+ؾ}YwW!~e̍(Teo*Ic 9U~ kDs!XaIQEVfnjK4YYhE*F{z6~Yf~UM:RB m4urQ/Βv` 3H'7~R4^Ekv <O!wK($yˋ]H$q:zcdynqꥌB|_ F,\݈;.Yrs «OkP*]/GA`o]JP`Xf $SőXm`ė) >|gTaz 7єsþzl({@^o3ԟF-7=%8MќC_2 (OTh^᳅M(+jm/ԙ΍MBGOɶVϠKNhp,ܴ|ÍEY.hg7τ K#g0YrUXEJD%8"v8T1&ò{bBFO}$&@fͅ21#P=YU4"3;k_Fg1 ސXD/VCבKtJ*ЌO C/O*uƒC?bbr3b)\b#M.0z5S =UYk':#qpFU;ȝpaG4k_̎AGudBcW2쮻1[4Y!0y~$xz|C;.D~rܴ#J<ҵGcI莃eiVou+\xU)G^}I T#,D@NGR߃Y#O;P psgYEAC_5j+]a0"@FΫ+ο,A`P9 OwD> 9[9ό?]jO2"!ZNÆQ$TB:77 `(ʉ}Bׄp.Nhިh]ţWdOF?|67!q2+O ^;c?uޘ:8>tw=ƯSO@vϹ5LUي~{Bs`}zdV/z}*J)ĖPAс~J='Z[!I1&5c3}k(F},4{Mj~ǹ_`or:g!T]RBm:=VCCRhGgNhc(:6|'|^kXu+#N À DH,RkW ' de*G2\*,kQ-jzfH[+Fwlh uk+i77b߸4!OTpFNc|gsŦQ41{̎%{ L͒UQg\e%RCvh=|0 "8ED E2ǁ(7"ZdyQ,]6|\P_Ep";\Pn}Gݢ3rmE jfx?|˗uKR=d.7TUU\] ui~H( *? mFlYsAŦ%1eWJJ֔Z-vtqLjY L]wNblDU|M8(T\M[EFbtag}Ab%$?[4~E^$U:ˎ9Q+W@OyĦ _E+! ,Rk5P3ty-Ouzo=EZX!<. V'?*<WdNGCg${h+O^uHGrα^ɦ.C5Q 3h vJ'Xp[&ucm-5*܆Nzl$$.#T츘و? 9ZLB)G đw[J ]C3B7_ Aђ4d^MIKokc M]^z p1Gsy\M]o="nw#זVxwYnbdX.t:,}H4ةnFT"Q'N˝Gg’|?\ju~/;!$(O{#~t3_ȒXڃߡb':Sk\_Zuv`4Z0>Sbbƀ$? \Maܔp?{LTh:v\s5X؋ GdHH0QFYqWH%Aʠtw=$" O‚+{~aSa4s/^C^WoO.K0ˑ4AL#qBas˺U]O{?4jurl .1 ε4~!1W>&7FҹLn~H_x }Iy44O~ <-3B/лA,ϣ"xm;uߤϩ>)*5C XͷB #_iHɃU{%ǑYrS2fVp7ۉ\{6ڳ9̽pw+UiGٳD3駅j9EH(GJy1zPAKiu/Wj&߱B6{̀rR}*XraZ6)ۭ \QCp%9bP,p̔CWQt/ /rΓB-1V'9o|  @Y~B-~ZRFLRQ2KqagoZ1Rb8Yj5x.Q>[9qi`};''NZ٬H`Mg.pٲi>s6Kݫ9]\OO/`f/=M&++Px@OCH]6s t:T|CE쁊yԡo*i} itֽP8ݣc^܉/B?z.*#Zꏧx |$Toӈt)ʜ8D #~ELaf.,B%Xf= QOV`u;B/g, +l '#ƴ0LoXy;Sx<}&2 8k&尗ӷ| 79ވqz%&?{r^Zp1{WO{| J sݘd:SIqvv[' (E 쪛}4Tq|qtKz4IP<=:,6vPe:}|u:(S#>8{QՋvI|vR:Tӄbg4r''Q~{%W\sg7=&5yB)+wgM lI˨3?۔>ĺ#j_^Xr+*c0"|^[.6jFߠPu~.!CˇlG#HN2.G }׶ǿҾ'{J+a o7OnCX[w(@=Xla Rrvga3;rǛ\)@ jg4B#qtb=q՝1'5bIJ&@xVw"xfr1}XH+$1]Jœ0_x#9[ |Gq2HnD`2L⅘=h|#V`W%bAipD̮XE^GPu#Fyɑ9-=gX t7~ EW*^1ŋmeմScMތ ]G3 ,!Nu[ڦ`n$6nչmYd6upToȈ[NGh7I]J%NTxRkqK\8=&+%,"ћG֑;h=#{>X4ˆS|aꮈ辩?Ϗa(ih0 ͵.ei0 cA>P3dỌV Xq# ].d{QW/}r.d.!tc76L/3g=7!.oiאN>ڻȷ&( pLsh@.flKu !&OGDbl߾lW+201Wu5h&m "mKP̲'£(T{Rt>aT" }͌m.(^!veO'-)~l&ڕpހtpzN'淶ek==ۺ,)Qo'p(~[ .UqDq^$uXek)7D Qc1D-?m-*f"/f Cp>G~V_ǭM ' bAo혰} 0;;)<_%%hnC#Ulc 4) y~ _b <9 lcF)K u/;e!V%E9*CCM(T]أ )*okDZ!us#QXIl{l jtB? 5 pomH39Uxp{yNc),j\@A1zW-$-I{^~ 0͖}KQl 'Bz Վe| B}4(DEu .xUƷ!"}1 J:OTtz-, M(Ո J9z1$>O:ѷ#&PkNY$giq y綊$3oGӆ E0W1ߨ"Dg8q]GD1))X_SkEO0քX4VO/Cl; U/X_7{^<^w/]\nR>8{\T*/j>`u[2wv\ݺho^j"D|vːUZQ%FY¸/,Ћlce14m4h-VJxU<=V TcJd]w+H~\ߐpߦmFnt Z}Bgnڏ"mdC@ʱdx~x-˹x=#᧵_CʲWe5v6d!mi{F3r<$izOS;:JL^ 8)b{+6NK|=՝ؓ[f֟uȌ).VL~]H,xW[> gvR6۵fLzb RSlA%G nf.(!jsKplGr pXj bP䘿t.''. ܗ HBMؘ3(-" ]zBr]IKwiuaRk5{&|6Z<[UH֌:y#hz45 Qt JM'=]j8PN=?KEDX}%)w:`Ę-:WCK%@`;!Hh6S]l#_!{(=oN,x8wF/’M7S㳊 b̸Dx;N\k*WN^|)<^u]*Cv>]S0)ǟd noNUwS⏢;(?sXz?OVܝ jCMձ7,7{MTy(Gn֦Hz@j4$IdP-*r^P/S4֛Z\B$chDxݩ\E~\Q6䶛Y^y&&iF( CIf~4~inbcJ WK'S-0>=ߎ-tg|[uo/"[ Y1mܜAzӂWCܭEYZVQTgv]-Nl?;1"c ]Eg#(؛WTQbw .#VN !% C,@Dn /ۋaoBSlnzE߼TUa ĜXKr3⧮Չщxm5aa#e|Ǒ\8r9[wg>37A0e<_<<<ԄʻMȼc6^:L:i?j`cyl_7 ѣ룇ݩRϖ}>w7AGza0& ݶٵGň,8s4*&3yHc6]]h[șKlBo2a*̔o߮!&*!?0>\8cfPݧ|@4}i l`1%c6m>)Ufa)pߜ#(O=?^-'sy;ݨT"݀v&oHvcJQWۉp9?xn nO#†~6+}ӥ=75}WA|5W;qx @t1䵹Ͳ0;.,”=YۖN= 923.BwI5@Ϟ=ݍ"^Ej?WOMm}=Nv(oŹѴ Ϲ1fo9C\;膈m$qzx\;<sD6T0s|C<6c4oPoYg!JA"֪Ѐ? FC E$/,^-ˏwF>|`1ۉS7z$^C *nZ=Τp;aBn ߲M\Umf\MHzey't ބϽ?}#HK|Jp赜~޲Z9mEu߳XuZ n1:e(dڡ\&vG|-vv&VpB?ETO]s:^ɗpO.bxէEf|-ҤIm) ҮE?5wm ^a5hYeeԗ;1J4ՙ Cq-$X#k0qANM@u2jފ|a i:@inl6F:R0V.7BU~U+)+s{g;M%SB~='H3vxp`‡~~$}#fЗЍJwE xN:v^ =q Xe~.Z+9"Zh|.bւ̭ĚݣQ3i/pT6l%pw9nMfIFcْIn~ (o$Tn3IDw3 #IsŸXy&t#P5(efIoLq4_wY\+2,}B6. (F>n%oeV +x2̭gW~|P1\r u!SAq,Y ysU;0#fZG.a/oĥ4(n¼1z@BQҮG5ix, @;!v'̅XÔDL<9_,Jn'܊v(*\]V {@{ؾ(Y:x3~*M/dƸzLFutAǣaq~5Bϋ]`{'lL\)Y8s`r#Kcl?G@_P7q?7b&|Icwu pU KڲM8L:&}m.ёЛWmskHa'VY_Ot#– (v$fZئ ~eXYV?_!ʃU5\ 8n{Oh$ts|٦v]N8 YJ-h7inЭ=dun׏e¬ ;T^-5͢) ݈"O‰oh? Y+t\j#Rg>QkY/!]ƀNt#;Z_>ח{lD,": 3H* cXp.BOBTAUwð0#b Z#L:S$0oRDn"QdMIT3j>U~-kZE#~iiBƸqլ{r>Wc ;QQYװX'v1%msκv=ԑj187Xe7d4F_PN:MMQ(PAGWࢥN1ֱr6sQ+Mg&'EkQnF9zI[{AAg/93*; *zpǢ&.xsoR.m"VJts ?֖E8)\GNyRƻ9 4pYD[RQaJM _DQzߗ,&%'_N|mM^D#gwzћ\ q%&ҹq\~ TxGc"\ރgt g>gh޸\5ۈU#2la{nn^%5K ~IgnX6Gpk u"෱"#=[yzJ o5zm>Bx pqʌVM8hM 1zHv {fτEyX+aM-Ɖqt="icvѹS(J|"*NI:ӆބN̋sY__+=ZHȼ+$ĎAs\kRA"Aݺ3fyH]ٝcgG_=ٷm!W;KHߍp=p Xm$!yGedv䉛/Жr9Eql.Sa)nmd|cH@Iȶpz j{77UD#!~w0SwGKݚh 1%5nbe?Vfa1Y)?{Էh5Eו6!v_rєY[Zdii7;n$Bnndv-k5JfO(XԷ\.B~baYEr"Vv]\s!}w Ȗ X7 W#&ia{&sa b).]@l䓦ڹSH渮ˑA3^NTk)KބTY;먖"0Hbc^OBKmd?7w[LiHhќ-4T?#5 ccч3]zI,T ϼaƁGڠYkQ=pc0 Q^1N@ڬ2\/p̓z}%u)v ZnAc3g0?1&P\A܉K Gԇ1G$1[ᔁ% ߘŊ[Z,I۽4贈)).x4O7kbAfC6PO_0I ں6QO?艞EX髓ȯ iņЅKS^SZ;T<6҈ E]4@o,&L-ur %}W"dt*9@|!$$䩌7C0P8T: Y&E!pS\߱]Y::|WڂH&%%2q c?wc]ݳ@"?[c6, Up{fԋ@m`:_+a?,MH=)JQ/n&{Vl%^l"+R}eFJ;%s&vT_iܝdFg?iʐS)jaęfT=ץNW ǏG'swv^9ЇǍ[Hzna[EL:"c/-܀b .ElrSms[N#]묘 "'ךy TY-f#K(n "=^Ʋ泞N:#rv+zԓ1^DB*g.cEKRSB-yj,.Z.+q h^Po&PC*+ߧA9a0_7o7WSϻ-:>lc3OfhNNC aܻc]?95c[<lsj|S < &`d⃇(@>/ ҙ%X} wƾ~[AENԭ7j[@C8]QT%D"DU`K1Xωq_jBE!h(ZƈuP`'F$481NN>X "=t<])-C0HB2ٍ۸M⠠<~"؍ʑ8 >??{4p͐`p_{8Xʝg${;?/"K'Wv5C ip-QįnD)JB|n>h=?a^,[BɱFV鋀up(r &o8,;ӌˈj!/w =u:z7owdoPl}sl=0Ox;UJrf \v8j:uyh ];|xq& ӻGCZ!1W=AԸEe]znzaC-⍄vj_@Ӡž̓hF/|kDK5액A?7V#ƕpA[4r5l B46gKb݃sSbew,^O^PWc4?F@S/Lw?QG#Rw;TeHZaU3z6oɪm<|[Lc֘Zm@e^P9rU }kM7@K#0Uᄃ; 1On1-8;\Uk x$|6Y73Z²_BT{{L}\XͯJp] 5%bteZttW`<UFq^i |a sp?[v{;v5(l\zڵ q~21i4)>ǩ;j&!qEM"S1ƒ; Rp b`Hx%s@\ӨbT/RsG)W iOA8s@hmTٟ=ӽ@뉖w7D c-yt{) CAP{M lO#hYo+Rjs?mJ 8t- ekF`~5 <υ\J_G3@E=“! ӻct\ ;^(0OԤPu#컣=Ejbf粐!J5cL8Xt|׻Zb< ?RL/LܬB\ٍ(VZ<Ok؄|ڒ4ҭ$~wzt$;7M]؍+5u/OPaUd4~B%G#.홄a!%nu(5~ADvyy}?ghN Ar}{)f4ʯo9:)$С|ytp)2chھ^w\BN5sܳa!Ne*.rn: +VPи"C^Y{o֑(CT$jvuB՟۫Q6]TPsSfbMGQ p_|{mj;[J/q!%-1qs$x/1%qΪ_)N"*<3ȕ |<s<΀Γ3) .v$[ v{> J ᵓ9%߭S4ӹx=qm)0=<ٖe3ظwQUm'uNS'f1e&o(f=( V ѣE )ZlfLpbNy0cn|ٗx  d퓊6:I7(<>KR]I~Es`2vcRL_U p 1ԭqo# [8;w^F>"\#g?23λPVZf*tm$@a"Ap|?lޓ_IZv xW<|2r>[cz ;|Sʺ` f$&aHHīČUީ1؅C;@aLj9t3 [T!~Py!+d34_?}i E~h=<#pv{ p3jY7t(gT}}-ޝpph[)_$/%nVnMp^/Z#<Oi~qu"[_@g歟w9,J<^-_)OQ `F9kt?-%S}1П }e!8O{9?n|UW< ܠ]rk XBCo"mE (5QYX*6.?ef,tzύ+,&Fhyշ<{y&t<7pwv",}B;b]UǾ.KEb4[,"ʮ0/JnLT%4'Vg.{;nkPyWd34o`Ƅ~`6uLFԹ:FL#7#2V8vs6c2{9KMH[`-Qcڱ"1TYo$Qb؇U٤erlK>=X ?)w o{Oe|g!it`w& cˮ,ÖXWo%fsCjDB"*d*!p㦳b}AyLf_c"ny?ë oIS{p!B`MvbV_ޠ4Yz33 O6,WÛ-غ]sv ^q?X )`&Mj y @H>C :ʶ殁yV=b< b>зSȽ [\c+pe[`vk?XU=UoJe:"{} F.AMKí:q8vO-H!"|>bc$>.AoWhFVEs pqtN=ވ2 a30諔 ຎoLGFynsa l:4<@7$A_'A>u3I(X:+6Lԟ+OУk4k7骪6ǁӹA8׆KAJlE(8*$.4TvJ;}y, @yv0|3yz/Yt A­>C LyoMh7V& >f4T>+42z4酋}w^/>ձQC#1tM ?@S;ۜsJȃv i#m~#!*rmp-V8+n W ~3gshձ&Џz v#d>45B\bF解;q<|S=s?l]TMnqU7Wû/d @k|%<}.WEj=O-O t)P-vzbh4xct|p0Wan3/Dջ6J#.AR.z g\[?rme$^=bwNLiL)78`*/aEXU+ntHt2m6J@OD:ԉd:'غUZ.&D3Hэh\5{ҍtߩz5>\g@_N"BduTv$$ʿ.s\q }!{2=\cFor Q塖i|k *c g/Z395Y,jg3|SIQ! ›sYP[~d9R>I~ͣ3dHiN۝IBՓ-;~R L_6[Dۋ*h7l"I~3pQ\Bky;o/.ŠKHDhKRq%s5!yr=Hv_F}j{(ۜe2f~9Ҽ痛 VČt$D&ko8Aa UW+he|-:*Z>V>X(rOWa'~XC k(k}ry>S^GMwLV'/jQyT(3P(heZ@o8ܧD7lfM-sL&rєͳ,3yDWź-x:r譴6V`2pz$,l#X,v{;(&y72v/1E wQFo2߯]D01M/ 7Fa?ЪD~;>kڡ5G^f#v"k2z8D ۘw>E܅!Ѳ҃>t1P>@a&JV'[k |rUW[a"kmESQ $RXw }β*D׈qW~c]W;dO..`[ kmNLYHp~fNpLfE܆w5 NA(xR"Ijk^[wp^~e r?<;p &1z*/cRK2؟ɷ/(#lXs ؙ0o=y&ͧhtvx'(F1朁 ؟ TǺi.,Y'N,k! F;-Cr29v̕9˅{Wy ;!Ɇ}9Է&ʆ .K*a9bŸوX'66,MaMMfla?q̘ɒ̘/%3-Oz0a16ãLXAB8x5Ew×>U`zYSmMOE5ݻ= %;j4 K΀pNb Xݕ$*n--? U(l*~aا+|0Jr>^:L8Y -6^lr3@aPCefIY`"W21`(=m3vtLSc.8RaTEK王̗mV$T) Di׋ Ē3OfvlQ`Z7}r)0[G(0odj09b J*r̭R!+g)4 i_cd?Mɰt}L23{bݗ 89U [sMLb62wrHLcEI 7H^2X$y 9 y+l^6`?eIa?{#J%1_LY$YZ"?`aDX: K;@2y0K1彄S /ƪR>b=5 #!M1& Rfb'x 1CӍsUeS? 0Ḹ/KR.ؤy guQX &ǥc.w%~^^8ѪY$?>ז!~n˹O燇zpKՑ}`rdao*`fU^ϺͅAJ{?^Ƕ|Rfvf]3*x a{ئ.<2 r\pRxy殸V;n7;;-$3 "& Atwpky6|l6@o6g_)a}bMqn˷C_Ӭiw@c|.@vh O+ Va z6!q%w7Y{P&TŶEm6uM`Pͻ '4k6lb}ݝ V0} Y6zxGYHq`ɾX]:l;ԭu+@} P2xH@)qLڡ|m> :Ϭ.Cq0C`7ߓ^ \] RMeː\$b2}AK2 ;]|ոk$, Q"fUe)ĸ AZm>k۹%`Yr}޳o<-ZJWTK@4r]m]ZvY!%p'=oʢo-egۯK DY?TK@=@zr :dƳ/}uh⮮"|=s"iP.QEP 1"l%/jpVB4dk-ދ e}oҡ"8u"q{=0˓X Gf7"|A8"ZT궵 +>*k1W 'TeLə.e֤ UĻ}9w}e&8eю MtS7n ?|sl(քBa3Ym3ɛQYy",0(,09Bb,l3!:BÒ,(L? \oe[6f@ՁZ|yrJ݌L̀3jt.Rӛf` 失 Hpn;~ZY4L@r|egXNu3|>cm1`]e96"JM a@\#B'>k8 8!v'Բ99Q.Ю6q-+3^-!'|N*=t.^m=lc~$9caFUsj H"K񏁥Э^1Hv ў?ˣ (Xv$e1std\(?bz7 {{Q3l_;ۣJx(Tv`elC8N8VM0]ԧT!rzζYX0 c~D$!DZ zqD0Pu C^ag0Zٚ fz9=a41IaJR w'i2!k5dtdM///db^CpYH=(2 u J.Cツ!$3/\<}M#3bFH4t/. N妋 Q0!X}Yx̉pAY{!H/  _34FydvZ>OXwr}fkjTɨ |]w D4: MA+JAZfaO%wo(s0JµjS/ BiEl}ܹc{ :4sb8b"w f @<HԨ<, pF0W|zy_vYc̒ @Kfa&>cuGa7Ŷ~D^CGw7y~b+$KU_aC{?؜l'c7W`kGw0)8>hO}pwH*¨D31&3,tÍ+}`_|BnA˘"kҴw&e^j9 ߮SGk nU'ޟ uvAv/{WKP[mvp|QP}J#@򺭈en3J-pbB - VUprvhͻ, Mz{՛ۡrsmvH/7o(CzL;~ /3l.0v'l .N|LF)Cm#]f߱ղ6S8 D,ۀХ/CLvllf|7ǩ :,n Zi{6&kjŝoɜ +*!m&˩Ǜ X\) n6s`gO1 $;7V ݣiX[a4#^lcV_yҽϔ_m;~&Чm M*[[rLokQx[t334%χQsf&8y3T4Ǐkr1M}8 FKƓ9MvP:( Z| g|Aw3V4+&ܓ&LI@- 55A4톟yDu4AUfdU#&vp&É&rha!&a^ h5AFK f#v56F {G36K= ~5һq`nn~P5w5B@\c#pFn<AF szIdQh4©&&LQH7ӛYZ@4۹r4svFUR$iKk zPPG?\g^}ߓC7NNNDd%:e[mtnPW;oDl#f:_6@!ٯz+ʐ[v}Q=̖|JtUzHyy=,~ZfM-"O┌N=mLPJcq7K͈2#p9.up;VXu'ׁ:H{>PL~ I:(֩StcuQClӸCuz%?zNU  &jA m0d%RZ ^WBЗZPv˿SQ-hSlo_m 7kj(Zzuekm)"Z}1V UϹ慫5PÝP0RKV6p}E5 ǦZ:"kٸ\5pec̣.\Wwˎ)@Lҡ5yj@d́߱l"ᮁ̈́Z\T5l9tUCpU5|J7] 8*~TﳷPtU`5Zr0sJVI̋Q2q@H5?osj%ܪG/˵C̏]U |zUL>[rfUg;]NUͽ i^*X+и #@lB'G}*ird*oo_Qbak%9_V AJzVaJp@k;ʞQ*iW gW +ppjj*!:nJuw9K%\x8o$+pک hjU]V@{#PQuկ 8@K}CQzNO+@'Z4X0-kFWԿ\[[h(T5u !yEGnlonTNIC xca>1VLC~vo9wI7ëJϢrxyEFr/I}!'yHP9HyCU"k̓rpd^fZaʅJڳȖC]|/o9x03'T9$倭P_(je3% {=h(α_=eHZY}Aډ9e aZZnՏ*πs0ٵ){WoA\U?S,TD2HDʀmw4,rӕp"2xOzhz,(Z&Kžjo)_u+n(oΫh?x2~s;X /=BKPऴ^ )aJS7Rxؼݝb)*K?a̋"K`c$"y 8.M%Db]͍HդUeO++@%{[%ZdWWh/('{$x:Y)ȟ''~Oo1,^&=T 씶ke()/*GM7Bsbҋ=f^<)zzybv?6jW i *\kDܥbP NJ?:t1pX1~ynW KUdzPC<"_8(zkE Iyw'E0'ViOUku HeUƅωE{ōs,w * ~tE`D[oe\c}"<}H7@SHR˸y.KN;QEkmXv /S$Em0c!yq&? r~v3T/V%ZfF꩎qΧ`a_ ,@{^r8`V8H\NyK$-/PsE /qp6aOS?ss98Xǭ W$8xnFSgHkc,@`ٶ)ÅvR_>iա=1VZ$%" 5dFg,RϤ!(榲 ](߲ B0fr(.oF~.,&>ڣBe6 F=(ôGBDNʍK@yl!X}wMPZB05~D\oTb @'a@޲/۞W ˕ӟ 5=(Ը *]n8jgXeo>/,Kc^vhr4ɇ8|xj/Y|hStk=gAbɨ|Rxl39$3ݯo邏,N?bpJ{~)#o>$>A4}gTsy%LЛʢFj@I^|- Ĩ[ WA9z&uP7}UUt7=<`9t/bt2yph耽H,U&jqyoHi- "6&saPWS3 TB,i\`v#q~6#s%G.PrĒɅZs%j w]\P0u;*Qsax7uh67{ݗ9h.i<ܶJhOmp7|K.̄~L>&~nb) N_cfYE0 c H2[ J`ZpjgC(iJZxoF>Wgve`z#2khMȒ sڒ[aw $g[56zY0?v0pHD.U uw ǐNd,wc{:IfĬs^W p·{~ǚz/ TM~?pl7э`^HjF=OlةCKw>oʜtCņ0Y%6j #+JF1q꤅GH(T]ko'E:c0sJ(1i Bs q5=4=!|&Mf0dɏ+넙['Lok)3S?ru n, _= d:pYj |\=珊(e,42C2&ě,U]2+4`mv@mkF*i6\FWYG@¤tOk^zu4  XB%u]`ْudUGH7[M90ذ T{:ng1ס/[clH cIzm_5mTdE,/v`xs(. T4D̔^>Le6_gLu8pϚ3cs">*[?6o^,&Ĥ07DNWDeA ¾($luc!3#X1EL8D/\!@R,@wU6)F讶=VW{Bx XG9^Xk3EY{Xᗔ];]f%TU550@q}H4 OxSBBqIvc򝫮o0`ݯ.3` jXLWV#jńou c |!ȌQOZ ,ul ˊ,b"l=e6=*v,H*K;/^w[N´_f5r a=H̐5 ^AK2~st4{}1!/%lH 6`'1ەB+}&uUďa1oXV,צ%4'HꢥJeA* }fłv?>M)bf:lveecz瑋X;9ؕr?MF}80HG.˝kKC7ѧ욿~s^~=?Jԓ>gRBy$+GCyR|{=/R24)grT[i$]-a{M61s{\G#"c>6>ڜYC913 sv{(ų=T[otzJ 'A>oK]d?'g/6.?;hv42o7>3HKmFUGF<Լin|՘F dJ.BJ/El!3%f[zܐ-6puݷIgDГOh}>l=, [1o:?7tK :!t{bV @, tw6uK>o]%ӈXGmQ@NLx:륨8 -LҲ,>ո ' %nkHV:FbuIXCg:VQwKͫ胍LcU4D0?dHͱ]EeW4VQEDWQo˓+(=#ʿK.XA/*U|'swWK+HM+0t~XlQX^Fuό%ZyV`2jE~Y@ܭhqE>ҬЭ^@SGp}G;f֔ שJCS&Ww'%@ 4sra%F.Nޤm'P1M 9lz֦%㈘Ӱd8=rjd棎8 T`9vF]94/"q'$8RtKy>(nC"YFcNǯE1dc@|4b ]j+9GT},)к41/gQLth ef!ǘFQftV(p $P5U:g_cYA\h1ͪt|KC@${"mpA~:$ CC#'AIFHvc%Z #(]A0sU?W?ICT^ 22 HV( A0Xh1SF1SH0p0#1|W9:VR:1h9y%!EkY@"JӕtBG6)yC;ֺ !D_|NBLB2C.z dz=6m/6>MoeӇjZք'#}ȼ{gMӋ"Q%^$xNvC/hV̎E-QOt-{nɩMuAx/SЋ ]A=6v;{ЛrO zq>4_LA&=R24KQϪ AơJrS Ɂntt/6uӍ~9?F؆r,--nMg эηbFݔ[{]Ekp ynBwMҺP՚]([kŧ DzB'. ,]螢K.}iLDݫfmH1uuRSDaNr|B:тtM5M:l6N.>/d'{x Ĭc'D3WK,^ZU@gOu[v(It}kF߭t)RK;;oZ q3#@woЮI}(ב)v47֎\q~hGdSo# O'yfO7QFO ݮǩvdhP;q&oGzn"Ps6cbjC;-mDž648 1IrkC(ePFXVrw}#׆O6jCܪ_Rq~+'pdjw"9IBVF\,ڊÈ>"u[E#9k+*o1nފ_iEVgsϵ"ibV4zwr%iE~^jAv_~oAzk[/s;6}oAU-HqzI :y皵} ?84iAI'/ [ 6D:tL 걵8!$-ٮfdHPB<*zҪV7܎nFrO5#OKif0q3ܦ.}-:~knFE;Lȶ6s3~IQ3RKYjB ?~ɱ 5AM+#ބD7'jBubhv&,Qvpy Z\{c҄N jBn4 CDmMHIyPV.&TNjqЈFsB Qx߫FFԥ= O5"gU*ֈ+[6&FD5qǭTm{QJmTq5*"X/F=nʏV#ȁc%!A!;<$Y~aF'-q!liJmB?T5 *DŽV!+J*Ҭ )WBeO~RIUAˇPW*8f~UШ} DOFJE+Q;7K[R%2gT%&8dSHy$ TACJ%{|%YZ 1 2V"MCx5̟@9~UMUwy+ϫz5==+P!GN2\{ lHg WLJg>rsT93qm-GGDr/T*Bߔ4ݪ~׃7X#S7Qg| gj9x)Y4H{fyQ [#u92=tFz8C9RƭwJ˭2ļC= ȼ-q*C"=)CZ?,C*F'>ShX mze>\n)kDv5Ѭf(Eؔ iHtIbL):0q`{a)uv)&m~m0\dLNAGRm)N)A'W*Aj3%gy y5gQV=P}l O1Q /AE|JIGKձt=¯K%a\ I ZK?pW*%袩Pb$E{r}FZZN=.)FDӋъ- Sl1{G^~e #ǸFŨx7i1Ꜹ9YvɨSx/IStx_f[oZ!5)"t!EHi"yuJcMSo,BcR|Џ.6"tmkQY6ng)Bw|'-5"dM@Jh\~em<")B1k8S0#秴:p$|G 98򵪚4OQFx\H4Ԭ_?[mNG9p 7ÑF8ʸ2AG%e˧hxT]~.JYIEB!Ѓ1B}КxDc3W퇆EWg-_fI"$ĎolBy@!RDbK ^`B!,Ma)D}E1mA!"+D[O Q؟~BuLlx2Tg^*@> /'40KhU%+O)T ~7Ė:>܇'.iSNn*<>=dlGWZ~NL>:3^SP><읬Ll: ޝCR/ut3`V|ʱGKa>:>M_hSƝx`\Rt{vkS=jr|T>6  )guP&dC@{汲%ӽ͖fJA#ݿ^h%1 ҭp|vɽ[:h}K80PAM/guse^\'_r=X:|9~S?n[TKEomB=bbmc7W5L/l?7?;\opIG-G^OrSgwzͣ|R _nHӯLڏ6Go8]&U<'x|}WKɻ%grj5-ԄegmǫZ.U}EeD#9?>?R? X <&ףDڝG.ʲ^~St̝w}|.umNjJfw|Rf^j 4"%gMt,/?z*175嵹TZ.9&`'סǦdV߳5h=mM^,c'XpboP̯Ko}f-#詹mYќ[;zݸY,z-cy)Z驗yz7E2:u7ݲM}^nsIHXU/i$Gr#anS0wA{Nݠ+/{l/2 pkUN<8={.ZեOWT#4o) zʢ?6zU<oީ<֢V#5+^eW8O?Us hѴ!ލߴ+_/)1-˲>uKH`۶U?&KiK-rVWDԜ;=zGOk/Qqh!,g5JqKe5%O,+GOlU$IXlE'g 60m.ܥ\o1lqu=Χڹ4#ȽfX?>ջ=_}/XTް-gY|:\K!vEs|z"?Zw,~ڃnǡJ=b MwHr'UݦL'u-3u3qfvۺ$YQ%HG^͝?tvyiG>P==3'5EĮbw?+ڌL^+VyEGrRƽt^t֟o'f;,';x?)%Eh@u jHxw&kI= %[2OL873*Y;HbYox`jW*>;zkwqr2g#c8N375t7G(rI)HzSpzlXr֋xCT}_ً u֝Bۙjbl(TsDрAM#/kooerWepH3ɔrMEϮ;~1 ];Y~ G~ʜ&͉5oLZTqkUJ*cE%,킗4-wKiJMp|볧l} 9C\XY/%^##^FS]0٣Ŷgї͕=ABs~JDjɥXo]*VU|Oҕ[yb~(]wZ~Zv쫃}30Ra5$6jXp?zgͩ*bAn{u_&yl&jΙv17փ 暏.of~p"ovc~v?ᎡAK&{9®I@~_O|^uy/K_xE8|3ŝ5"3wCbw_X\v-\=Zޗ~l<;<{ZfGjAǃUpN:V#36Z /,'Н=7-]\׶/i9+!C Bi9|mwbirYKu-^QJװ:4G$,Z[E eiݯ|-pC6a[4ՙ]%߼)~uV̙L )/2g~urY|Sfg>~Y=/&/Z`XQ6Ql~$;K~!|c b[r |uY.%d0O! 2V{k;χs7Ȑ3vwDxdf:W|I(.c~٦wMyck(Ug2fݩ)RIꌄޯ%Wxq+VvOYd2b,錵fou%:c75\1S&)Ϧ?PaJ۪otDBw>pq0÷ÛMvlB$G_?]LXDhC 5dO.aی*U=VcbV`by0ޔL`̏kEJ7?<#~ȕƛFo2az'<ШT;V3jm^)D -N=ˈw'_j g}BLD3\db%ڎ#< u5 :qkψ6 پ='Y5v}}Xke,kcKl^CJkA7z} i 1I<;$.ƌy%@Gkߋ$as5ҖPG"dO{DW!oOMWvs74)zd^C6a nO864~9n+|xTyq~гfZkY_B t>@jٟrxJc^ƥƵex!C.76b> ZW(\[r)rq]xd8~pH/&]nj|ğFRRn_MJ5ð!BI:)%l}vrenHށ<V 4t͓g T0~LqQ3D3[`$_ L]g=0? 3@tq8z\[~vNzX,i*䇃aZ|ȉ'}sT2A :wꝪ!(Ɇ(D_<&I WH~x/\|!:O֠ΏOkꡕ0 )a+,X\S !o)ő-ߤ/pX? Kt3)P,K4gBń(Ō|_ރ~vB ^6o&o~a ohA6D'ȉp(6Ǎ vS :|{C4'6m+qx!Fd7LIɲ7%<{[+,-N菹%1>%] ss:2i$yӃn0@JP-(! |߮=9Jp~izDUDe aUGs(y=Oyڋߘ}܁ӮSv+=/ݸ-wP#v[]SbUV8KqyM! h~TC,\^y@;vUT_^h6:X*rؕ#G\ J8K?ݠw"q1#?w ziZT渇/(=-і3 ΦiEzVrc2:7PwM߭$BJv]##(^}YiwbGMUI[hǝlz剰+4<_QD%^$ٵ~ozl=;@yG|+t!MT~6F%5χ-D!'0^-8V 1~ ;MXUm YLИF'ZZ,ԩE1bݯx+/ LpWmCי&"ڵ&/}0طR⚇7"/WA:ҥx4 oG:#֟qU\FxD'$v#}*_]D}zԕm.i~sy>~='Aƨ|ϛOB/$P,\o}e tɬ1v>ɷ׆JpVR&uyNp {9}|M~C8g}WbJc/SyYHp^aB,9x6&|Y|}`{^qS j6|@_[.}uUQpb+3( zjgz:n . \SP:'(xn_\O/c8XJF)w#تRoBhZ烯oMQTZ1 u+1W VfWoz l'&V`e;WjW.Y^?75RJIS+_Y%zT2?VR6<_Yt忳rghr/l3XE3]''ٔm .s߄3MG7OדE''9O6K_w_f9/WD''u&пJ3߄1'IQhp[Soƺ+s ނSxO?SxO?SxO].<<NF=J{r&='vISivծ=vEjKռc]MvU6Uݮr.v;‡dոe 16n?jCNݮjvLcݮ.vNӮZvU_]Er>bC> u}<0@C7r%K{@?ny k|`tD+:Әy޲IMK Hz+l);.] fckBpKh ;فXS%o L*H[{}-qea7rGp"D"$1_ }aY~sMe[r$ݫ9OI+$~KeTx 8ĩ(7bšx8ާZLqfw`VB Iźx-NiEc \ ʊIB*4QGH U?!?^'!5l?%'!rؾ_?!o'f?} F"{V:(O`},["~ ؒ; !6??@`y ؼ؏X{'35 interval-3.2.0/inst/test/crlibm.mat.license0000644000000000000000000000172313316017127017022 0ustar 00000000000000## Copyright 2005-2007 F. de Dinechin, Ch. Q. Lauter, and V. Lefevre ## Copyright 2016-2017 Oliver Heimlich ## ## 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. ## crlibm.mat has been created from crlibm's /test/*.testdata and its ## conversion into Octave's binary .mat format has been done by Oliver Heimlich interval-3.2.0/inst/test/crlibm.tst0000644000000000000000000000676413316017127015444 0ustar 00000000000000## Copyright 2016-2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . %!shared testdata %! testdata = load (file_in_loadpath ("test/crlibm.mat"));; %!function verify (fname, rnd, data) %! assert (crlibm_function (fname, rnd, data.input), data.output); %!endfunction %!test verify ("acos", -inf, testdata.acos_rd); %!test verify ("acos", +inf, testdata.acos_ru); %!test verify ("acos", 0.5, testdata.acos_rn); %!test verify ("acos", 0, testdata.acos_rz); %!test verify ("asin", -inf, testdata.asin_rd); %!test verify ("asin", +inf, testdata.asin_ru); %!test verify ("asin", 0.5, testdata.asin_rn); %!test verify ("asin", 0, testdata.asin_rz); %!test verify ("atan", -inf, testdata.atan_rd); %!test verify ("atan", +inf, testdata.atan_ru); %!test verify ("atan", 0.5, testdata.atan_rn); %!test verify ("atan", 0, testdata.atan_rz); %!test verify ("cos", -inf, testdata.cos_rd); %!test verify ("cos", +inf, testdata.cos_ru); %!test verify ("cos", 0.5, testdata.cos_rn); %!test verify ("cos", 0, testdata.cos_rz); %!test verify ("cosh", -inf, testdata.cosh_rd); %!test verify ("cosh", +inf, testdata.cosh_ru); %!test verify ("cosh", 0.5, testdata.cosh_rn); %!test verify ("cosh", 0, testdata.cosh_rz); %!test verify ("exp", -inf, testdata.exp_rd); %!test verify ("exp", +inf, testdata.exp_ru); %!test verify ("exp", 0.5, testdata.exp_rn); %!test verify ("exp", 0, testdata.exp_rz); %!test verify ("expm1", -inf, testdata.expm1_rd); %!test verify ("expm1", +inf, testdata.expm1_ru); %!test verify ("expm1", 0.5, testdata.expm1_rn); %!test verify ("expm1", 0, testdata.expm1_rz); %!test verify ("log", -inf, testdata.log_rd); %!test verify ("log", +inf, testdata.log_ru); %!test verify ("log", 0.5, testdata.log_rn); %!test verify ("log", 0, testdata.log_rz); %!test verify ("log10", -inf, testdata.log10_rd); %!test verify ("log10", +inf, testdata.log10_ru); %!test verify ("log10", 0.5, testdata.log10_rn); %!test verify ("log10", 0, testdata.log10_rz); %!test verify ("log1p", -inf, testdata.log1p_rd); %!test verify ("log1p", +inf, testdata.log1p_ru); %!test verify ("log1p", 0.5, testdata.log1p_rn); %!test verify ("log1p", 0, testdata.log1p_rz); %!test verify ("log2", -inf, testdata.log2_rd); %!test verify ("log2", +inf, testdata.log2_ru); %!test verify ("log2", 0.5, testdata.log2_rn); %!test verify ("log2", 0, testdata.log2_rz); %!test verify ("sin", -inf, testdata.sin_rd); %!test verify ("sin", +inf, testdata.sin_ru); %!test verify ("sin", 0.5, testdata.sin_rn); %!test verify ("sin", 0, testdata.sin_rz); %!test verify ("sinh", -inf, testdata.sinh_rd); %!test verify ("sinh", +inf, testdata.sinh_ru); %!test verify ("sinh", 0.5, testdata.sinh_rn); %!test verify ("sinh", 0, testdata.sinh_rz); %!test verify ("tan", -inf, testdata.tan_rd); %!test verify ("tan", +inf, testdata.tan_ru); %!test verify ("tan", 0.5, testdata.tan_rn); %!test verify ("tan", 0, testdata.tan_rz); interval-3.2.0/inst/test/itl.mat0000644000000000000000000027275713316017127014742 0ustar 00000000000000O.I,K5a```LKa@891'H4(ęyiť88818()3H93<v;0k!GQH`1_SG a 8 4SB@`X@)gèibJ2@q4o]}{/iukUkyj2k%ޕ֓Qc\VP9yE.>4@Pry.Dɞ~v UK-K<;kdwA.<ɉD2 W+H6DD˴`4ZbU!9ōO2<#ה2K85sC 9i`U JAhIG[29v c̳K0 $w99V*YdỤ!Z9sgȍnyf(z!yW,i@2A]a#?JobM4v2ddY`P 'AKΞ6kZ6@2#Ɵq6~6rljÀ  C '@2nzc D,~-s߶# d \MӗZ\_2{ƩC7-P~, d`qd eT I ő , dSr"2ő dHbN_w9vb.W dlěMőAjIF RCdS!P!2Aj>Lյ d@!oqdO c鋟Sbo*Qg.{F8ũ@!bN;pI2p_vPiH G;seev~nk˧ Ґ~,~%  nFfz]#{I3o;8&O]+ėezSUwA}r@r$R2 k3bբ/HηA.%H.G.$9Y9Nn Hv sj#r2\Y$2DriAri2P"|Uܻ|P!cͧh'C]Ư%wѨQw1w]I^wK82D%o@FahJA d d |dTР2B2X\1 mBf(8'WgH}ʽKAƐљ瀈7tR~tJyc$#\\iǁ7!R'^"T)1US*Ȉ .F5oj>" -x 9I_-VoO#i?=tˈk`X"Ö #u.P.wusF_wq..]r=r/! R?>fԒ?dP$AD_fL*=WE2+q.!ZB.OKBH\K z.h oe+qȅ๤Bk'pV:98xDˢ̮=$%M:2ʖtw1A.4,_BFjllV[yIhQѱג^"A'n:k׃!"cޑ7eF WmԚj[*d>5 Si&\SjKY:,(+Zc`f5z˦5oRi/-6˾ Dj- >/28gn_4"Ȑ% XBJu*  ,b/ma\T]o3lQX̡dIMzlcؤ&=6eEpucWO4:BV,?:>yKV>WA~ylgBrV?|!7H?oTQ`G2,؄/]PS?gf7wRBmeYfb9x[d T|e2[[wUUp.m?~wa ]ų~H֐F4Dr$6?6uejK{2 dPO5iܑ꣉x;5]u!w'mK^>r„\s <s ArscyrsY9-!G0-D;9<PwysDK9%v=92--'Y]j5!$\dʀXHn9Scs,rDKDK䈖#Z씍9Y-ο/B Qɐf"Tăȱ*?}B~KBe+✝SL4Ahɪ92N r=/Ku8)w#9ȝS=?ss );cK+(ssn`i#E7^]=9UG 4='f-xSs sBIyDK[ݎlqArKsR>c؛cLP$;x΍r6RڡƜog/uOkDҫ{4*/[&c: /aDK_|=Z$Z6:mx(Pdyn]IcPDȭ߶`n<2+v혱I :vS߽-?xgϏWm掿_gsrjrqAxzgi=MWuU;'t9"2[=GyRpQ!/{,~۞*3Cn+lzk,/^Eձ}aj_ |l7, 4ճmשsI 4nR^JC.g.nzGj) s4,D:P o"/;{:V /`ļ_!cgvpqƽKȸJ4nņUNӛmk{5QkaMyzqKOr9џss'N9% =q9Arv HJ'9=qsR2 Gr-JAAϑ[R 91EU2=q=q<I:"\xrj2gȉdBQrkas3}]j2eB.DrㄚrE2\.-(Sߐ'#es%Y5QQnC]Y-爖scU9+ C!Z2AeVJIbCEqyDn}|SY:{6RK܀߾;쓳ci { 3$yWm{?OO#rWz =-"y7̲M"2U:{Ӌ }]0 Kt'9eHnxZN)Wuo?WV(u_G6y]#{?ZOB<|gigs HP~nd>->;=*O+_zuÆ =V'7hb5uQC!C 92Uxeynj{v,̯}( Aɥ*g̪#'ӐQ;X9rrܸ{c[DȽ1wޯ.Isy"Nmygv3xm.a{y *$~^픕[O^@N:;( ;ugN%2Y0ANV8j\+1sr5%_:z{ծ7{j2 _S#w_ˣY{MjI>e(O?g;47O\\zη9wDBߚxw?Usknfϸ纾9_<+&7O"A_sos5{r;9ɽ|n/BҪ}+W-}m}W4U;.,{{ ?r!xsȨ[ۿ wA.DrIArIn4EH rd(xu8-PeP GsIA%.{W{.~-qJ{Wc*_>r\hs?!gsSZ)CDsZWM NȻl39}rxνrRwȝopXFAk!#H d `SHFH IԛAλ3.ƛߝ8W1׶ G7n'n/6{LԑQUe]Z#+-`NŖ+põοP izkq?8쨇d<)9dAv`@yS!`JQ< Vcxc݄LJM}[F=nhǬOM,?*#`Q[~RK/ eZwjӐqk]wL{-rt%Gida\[n]kEJU{Fe~w"Ac?d,^o=92W5r׾xϷ,1_z"_/ZPF0;*Q#ؚ7X|I?A4WRad\MFlt:}x4d8 6'dd+[oT< 7@Ԥ!)r\8iܸk'μ{i+gp,?_T' {Nc AlkJA&)Ay3ӗsj2 | $e`5 g?) r2H /J9kAX 9arV J-!)ra8[933+ #9!?J!/rxN jyr|m],[+BЇ (b9o?CQ$Wl4Z⹦ȑ[O&ُE- ǪrTPdd9d(d(gN#ewhyq˯rRuNJoCc3 , "'RT`P1T|b7T *1Dq'1fu(ٌšMF6͈X\A6d[|Fm[]MQc+zS>p='sB9!U\ 9sr='sBhR9sr='Xp丞9yKA x+ ,W(Ar\\ OKA@#KAђ gs P ǥ xKAPKAxO/Tڞb48HE"RQ J~7۠9l4gPKR7hs!o07aU{_pTt"YOD1r%p΄R,Bs EG WPX0) V9vq}%䨡@NwcP [ 9Onyx\v  w"+qBg%T\RA2{fNV9wsc>@&CsB_ ~K}sfgP@ g{>`#++e o=@?2?"nVxhFp]G8)  9r 9$Cѐ8TXCC!'d(ch:AMnPAPALJp  r ؆9PAdU9PA [f+ q*ȪrSH Ṑq21AN_28j\_@r.C=~փ '*.5r@Bƙ-q 9ArJ,|[9QfpE2]ev1'wd҆9{4!Z%_5:<#g׳T' wWcbN6OnJ\2c_5qs7/zu!T7o_|+XЏ易˜?ۭXANq|d8=( d0.cNn7ݤs <?,LÜ=H>wf0y5!/9{\r;WD-Ŝ^ ldc+dC WŜ,yuD<~ʆ~/zV,78\srn +x 5 xiDEh w |C1摇9+2V1A%+j.O..ĜL_ A}*`99}j99;5R^ Fזvs2-F9D]?YP׊2-'q:D9y:BGךsy5Ȋ,YYsL]>"RpOYP,t,0'qV&ҧ"%>X>2E>ffJ#s f4^(pLÕihWCL5@Uf8uɩfPrG=rg(WY\l8CN)zgߘ z;K TS->t$_58pF\ I3|:X}NL B0ڒuy.Wxk8C-"FUyE]}4r@ߐg0a"9Έ>gw( c84zg5f~7y! G"8_űT 6_@8M'jJWaVKTNZBo{Z#~Fϕ<!m#`/z2وsW̬36㛪l0'-ȗhZ A9(\VsVҴ!U*aNV۰G \)pUWՈd:Bɇ^d(r擂8A\Vzɷ89׵ ;"TK/@,rh56sj!ȏ{ 阓g"ؘߕ j9wk;Y#NO_f AvY%-TFy(#PRsr4-oZNo1''4\;x&G@<œY易mKñ*  Ȍ8򵷾=9Csh=p͸>]bx+ G-Φ۹bNnN#eAVouHݎ9u8RKˏjaNsLke!nbޘϹ=bI(yCmBϓؘ\$lrWƦDŽre>ߤAW% sfx!j 31'y 9pZ\KAKyR!ȿk3lW !w\]q UIaN)9r ȃ1Ÿlr09@N dr01kΥLԯ,)Cܾ9PIx%Yut/dֻc~eΒAn5R!\d702/룞7*AMb7 !6|gg=i;5Ah3!cL$A0$jiZi-Jőm7~`/.X" E~]lc#`FbKjC0^k"`n999cr#cG捣*rQQJn:_ 2Ec@Kk>zy [~U -Of s͎ 7o };XQG51i0qAwWW Lj `yf\q.U.݊qqYm}ۓC0Fd{;@0<t! l/W4F7i@Ə2d*}WA06zns[}9 K+j[Z9C08fI|%U`eJmzeݟ04ngO?y}ޢ(xzF@`)Ok4H 0Y0HgJ1: ka4~W0QշȜ;XP w=  31Ĝedi<a( aO?7<$$rz}{^foAӣ)@SL ywoQ jܝtcg5/=CYE60zKcZ!VwYF_ݹrd tI2Y=G$%&G\r$I$GìI$GfK&5#ɉS32['IZ}1Ir{]Β{w.re]l bw^cdb " F*Iwd FHe]ff b8ap-<=|yg~|9s9昋3sqל-c.]s1'RpLpBaΜ[m%svK7o։5ǜ5T>3ْ9s9sn ̹̹̙s̙s$9Wߜ9ז9s9s9ׂ9s9s.C'1ǜO1ǜJ"s̹5ǜs-{16s-̵[26g}Isʤ[2\-cNߒ9sk9Isd E9eRvKIS&eΚS&eNs9sN9eR̹9eRI3)2Lʜ9Lʜ2o~9"04ecNS9|*`9ԀSvBaN 95`eQsvKԀSߩ1xQgmLf6 kamÙ*K0`޼5|͈7=T*6\ sʵ0} ^Ne[x 0` 0`#2 ob1,qTCenx\ s-<Fah~ȯ٩,  ;UF60F<k#5ͼ5 o F† #{Hkĭ 6\ s-K30` 0` 0` 04 0`õ0`P Ïv7V ߩ1xFէ71]60\ S ὸZ_/͟wH%6ka0` 0`  0`  0`F*Kz.y7`^mcx9 6SYư6F҂{ORNK\QA֘@crdyfg!^N/cL('f>vpscߝO9 {@+}/XTt[_d+[[R('5Vem pJiɠl7d|`dџ~'VK9YAqFま6Cã+ܥ;;7I9_&dr d$7lmVǑw_HEEi˾yA|Al;`G{?SH=2eyO4ܚ)k !DŽ ?ә4=II9/t8/u _p"Ů#2_1e-8ڏ';YW&_:T2p8kI&ݺH{j0g۹~>p?ˈd8rQi4֯MeB06߮tIf`wQJ3c[t҃Aǎ߸v<ĢYW,PXMn@g5'y\?pO<㝲ٳD"'U ի#N*E1b4" r#آBU. ?~$1!AG0 Ub nKQޔp /[ÃRt'4+L d"7$0vȱgٴ@w&flxfO .bU4R3oWvOn+֪M1-ꝬV4"'e'? &gh+-+-+-+-+-+-+-+-+-%+-B A_y<0a6˥*Y_EFwДTA|2Rhʬa1@& 9==k!J } $C$c]HNa r ~2{k2d$w%̉"H~w~w~:N![w~'cdw$K1bJ _NcY3'.E E/E.I`nqQE[`1-:d- #_f%QMN!A<o +-0+-pob  xO$؛4߿@ 2" 0V2E ҒJj&xԁ7A~Q8s!M8 *.ﱸ;SG~!4=??JJi7:-G5іZ?,m⚢wu)٥9qIoQNN(BUv/wT>5"\9ަPD9u%7@B,͖ 5{B9y[dĻqϛ3('*z= AMQZ6Ո_AziUvrS}n6yx o唓H X6IY{D\p.|Cuy`Kuo KrC9yzьN g M|7z"o5(r7}Q A.lȰ*I-VU^ˆ {d×4!Ȣ̥<1=g0#KeVV[x)2cMt_('; L?AbŔ/]6V Af˽fa%`1 -l$e1)'ۤL^d_ |4)OuB2/d$c<`4 Wqd1dɅ2_I0Mϊ9pBה `r?%j&2 g0ppЅ`TJZz}OB('.tm g vN9ɲ!2=]}ƴ_[=PѠA,SK^{"*&]tRN㣿p+c-u^: A;m=ڔ ;#!ZW8D9R/@YMr~!ȱ+SXƢ|faFd הW~;nO.ThddGEV1Ǖ;hle MՀ x澍7l:;;<9>֐o`"x2SĢ Ⱥ<U('[T]}lzZA~bQ-7ؿr׉"ƇhWleZl(#-z#r !J5މ.릙Ft@f a !g$sN G"3KH<$ɜ|+~h/'('{=ȓ6y2†h+/i8?@dDJPNve0ڋ@%%)K;LPԅ epfRNs+L¾ɵu#'L_Z}Xosmu2Xs?Gxm<_lgFW06&}=ȢZeM%E[\ヾR CrILY0W{ bWg!10X摪Ib1e3Ull@^i2D\Ր^ Ӱgynlp!r3 hg44-y dgtz㷀A͉oJ n ˆz,Rø3HNf+?>b9EU|Mw'Ƅc+H0_ (Ű!$Nrd~Fbcn0`:ce7`0%/#Qcr`y6c $Aw Q@24zu2A"ϸF[@\$3<+4 'ZW 2 =$R(*2NSILy#gSr+9/G,fvX ៱t磅 {bx #MȫߩoR-nQ!13KoԪ,*O"<t,2QFe$tHHHHHHHHHHHHHHd,#A2HH8` k*k*;;9Si5?g Ńڳ{'D0XME$Zja:3L"1Gvabz`^LY׭19DyJ'y7Ac pzɈIա ^`v .5˜D2# _|Ws$hR?>\mә"j֘aI]A8 zt1+qEe1q^$FZK~$Y3Oƀ0zX9XT+3+:d<Ǝ4JaL,E14 LOYTXv l@v6 )Ld?3S0gXTyA|Aa;`G{?id o<'UnMb'gD1!t& hp[%@sU|N6->jF% '՘nyzL?+Y|}|}|}|}|}|}|}|}|}:ɘ6d D2s"ɘaH|}ᑯ/#{||} X)AJҎ<u!ȵwe7YtEӢ- VE,Z!-%^$02E3#2Cfl_V$2aHf.9ia~¨8,M$,ccVLɐ܃Y sjc`pYraiml3&sVTx-#LlR EnamMbNQuahN/wXCH&Ja@o ۱W d۰ ]Da^ct#zǤBdQ4Y%: "+0ᬒN7Ko}6sÜTGJ}nUZ~p2.a?ީpk" \Sx `wV\0&X<0}S6٧DW_di!ٙ4x.,e﬒$Gl_j ~TĢw"*Fc$7mFvaL:RĢtn~7SƱF9p =\9{fԩ$ix}Tn6 XYF1uh07'آ0TSlQYd c((LDߏ 'Q+62_آ`0坹?!Օ:kl¯,b[l-jΨfy1LE՛_}t,[C,J]!d g{q+CtZL ]4X<}Y@9Yqٹ~~Y-9ILM= AVfdɲokL4he[(ro1:C '!X}f) Kmk2Grvۧاnoy?DZ]c ȏ~~cѦ\bf_v֣(';.0춧PY+ff@]GdWI/&BUA6rj ́JA&Ol~K%Y}ҫXoķCG|J4A9y[s_Sաr`{ SN,THLJ dXknCuYAK:²Gvp6An8wu"ҭZ٩*<[1YԮ< A.9u\.dj1`bN=D *R8'"^yPՀh0h. 18GƈC92Q" U`L41C/vZSk{+_v9kIO(h9x5{@6Ȓܬr) QѶNoă˂Ldk@h]ǧF9H6A!{YB@&\o_f Rs l,"D6Ùd) SG R&|d/lApDd4 ^ETS#Sf%qa#8G42Gx2"2"I _&|)O~ BNNzʗ}7YK e ތdW-t=dGDk߾p G5el r" n9'Fe2!R6Aj +`/ё%|d#>YGRKYG6#%|dW1$ٌ,# z|d>EƗ_ Utd=>و,A6;$KF|d>Yl×/eYlG6A6;$KF|d>Yl×/eYl4cÓ%|d#>YGRKY4p“%|d#>YGRKYIPftd وlG#-2=9A /qp5#KF|d>Y' ߅ 3XL'Jhxy*%cIi<p\']I6s!7B?x)mF>p`Wf (~nf!q ޵ Yl*'/;(6 zq\6ðHAޓ G]lɂ`k|NT k%vρ`$'ll%7ìѬr) ѶN`w w5W0A boae4|ʜ/*b 1lÌ>]2B0Z ϋcoWjgAR J.)h. 1,)b9qVŀşkOA-N EE 7\J`ϠʼnA|Sԙi7@^gVNgijz,x{ tx˿AqsgPF[; ?7\n,1xcн0i6S"8c[;A>nyBXaƀ"3N9AZ-p02A bڕ>(V"``cL*{xoŒwˋEgZba 1hP`~ U?3 1A.v?ghS) Z9 W;~4l!72A <VD3=v*bĠaDL<чZĠ 8=Ici% " 3 vbuK$˞Aծfc}_y +bT w*`8SZGGD !zo@2|Z GE_TCE~`ih#1bc^TӪh|'O|颓_ҩHl빔sikCf!m8'K u-׏T!ȓ4sT/!Vf&.҆sSAnbs9շ srS Qz9sWP]ADo_Z5s?Ali힠/$'k8'?tiDٱ,H*vP?\_7|Swr۹N&sNH>dλp%pNθ\|)-ݎ>cT38w|̺+/pN\hF=7xz%8 AqVsN>7+uάT$=i%r"IN }6Ӹ9'0U9=Nk7>Լq[`3i>QBëxkWTqN^RZw#;A715ljsr.$9 ЏG?^qӿmd¬]y]5$qێYхUN>_w|~X{c7sNK!N=i9-Y݉jsrAs MZsNnV9ioz}h[oKvpNnYx7{d] y9] LdeS&5 SY#l$ KȐ,Dd/{F9H6APwl"# L YM @ˊF`d>2|W8l"2m"*)M)_˂MDFѝI"K#,U$ل/e'|!''xb)N_fZ20)/;Uufft7'oAG@`9%+t="2XETe 2@r, G!2;uU.eo1f8b]UtY{KYG6#%|dW1QK_/ F|dI qK_/ F1|) —/e|GGjEƼZ+VߦޮCi 1 u (go1A b 1A b02QM bG mѧK暾 ;؛,`kg7ŵsĀ A b0?NtA b1AgtDg4kӶ8JdֻuI`=>\)󶫭Z0\zqv-,0A&IwQ ꝅl[72jn mT˂1\ RopǠ?I 1QU[7Dg\<-jyYpK+1$81:ͱ˯!^Oc~cx迎A.1OvA 0*=Z;M:{79Kf u !vr}ZirXk-ɺI=}IBқ;C5yGKV6%ZBԨDk-Ҙꙟ!G->Zs.-n dGZߝ~$7XƧUB{%Hk-9-ց+sHq@Ց΍'r e ܴZsr^-W{52H-Düʦ HuqEDta7'S/ 2%ud $YJ7kdZ/?Aj!ڱ߾f"2xRj_t [#cJ9_9RֆD I6A6Kل/۽BNNz<|1=,Ѧ9 9V {%=tޓrUёLorJVV"*Y$ё%|d#>YGRKYG6#%1F|gRd وlG#-2uRV𥬢# F1|d وlG#-2uRV𥬢# bflHlG6#u_:|)+RVёbuNHlG6#u_:|)+RV= Ռ,# z|d>E''#HY,E>ـG#r!Ȍ I|d=>(۱!> ߇m_d و,T_/oaK+Yj-# ΅5<2`lm] 7cZK΂oa4Yp;ǂa}m*p}, xXH2oV`pDFbi)+ ޳#eX1wSL=x,~2{kM<7e+ j֍HOȡŢ|BvAA=~Jƕ,8]r q0>'7C)\QB02(Э) a뺎Iyœgdho 0;Us5cT<{At5|Ef85=c^FGkZ>wa1S=|A6jRj밚zkY)Cر_` 1ɺiM<k i伻eR\>}nEeFٸ~ԙɠ>e؞ ;I_y}gZ-.e{Gn^xp;F c1A 80[xz/hqHŀ1.N@0i8.%3ab/y[^_s ű1ʼnA b 6@zAr1jۯ{Xv|`[9SfU!OXAOlngS 1ad^?ƯOzcG@t9S07|~9C%3`,yϿah7A b 1d̽P~Waw4%zYp̒-esZ 1A bB2kS):CB̜NtzpO[kqN^tmGu=@#__;g/өCAׯHR43k@!jx'-WBvX<,V|}C5#vm3k-ɺ$?r9=ݘ߬8'5xN'׬x'߮vy=ySϭ8'lvN!7 Wd99P{T`܇LwVElf3b()xh$TUڶ඼GhS dYg8'߽T^XױyeSP>)ȴ AtZwO+A.zZ3'IσTb99-J!gZs1ܒw ~eZG-Zp0H_}" 俧c99ɈrUIiq\.\yh>ˆ߬x'juEZ>嫳 俗50 8%Ik-<wx9Hu[e9y> \Pu`^doqU1:r| ۲Hr#[td]`/z3:r|d"|;l`}"†$BUnaa" L A` K/}&~/Y B}Qk"cc^Y跬&/g|P# 0k9/o:csfT`4o|vѴi͂bm}0͓1?0F*@. >xEkJ;OYݨB0NdOڴlcH]] ߓ^xoNLZOfé2 B$J73GIE2h6!T"J"J2dK4D (s! ~ss^\׹ZO-빟ֳ{x°iO}q7^ FuI(!iYqhJ\ E*Lq<FR0B Ȟщ@X~nYe#dm/X7(8+#SYyJct6L4=с/PD#j^Jg#kӴu(=!; Q%}9jݪ 0M#[CqEK0{/94B@DL:YpzO^4pV`Lx*䦪 n4AX!}, c9(z-ЛslՕ $zzL/:n:p:haa wjӁ"{ݼxdm:T<E4LqDoZ`^6fm|2i:FA2m6_eҜ1"j\>69zi F`A` dvM:w O AnK,]T*n9(1MTJ/`l_1 I#sFd ~nw-PKvr'ރt 7mr= svQ j|hwzj*Kj8䅆};A|99YYDid0 `NTdEC_h9Y6rgNurV)ܺbKv-6N Gs߯i}tsr^Qir^psbNVoQ  kv;<9y9U4mաSp?Zl"8u[VaZj 7P-A>§a"16J/Ck\X9))" sַKO@=w89X*ɳG*]!zO9YmeĜg/Eǜ'-4 `3ES!)FbN0'տ[;-mrzn 8r3G?^Ι( 60)|s0ݞ/#c0ak!.Z`}]wB!%.[-̻`.%ra1Ü\,{ᥥl;srvgc{&KWcN>4V$Al'9sd;W4LHjZcwv^!ȍNW`Nc1 [ƹ`NvOِU$ A.!$W99XP1@NWSqsrdu+ rseqfn1侹c. K%=5OEsrg*dk2Qsg{BlcW@UMr=a99Ǻ3!/%o3iVǜ|)toHu"omyLɂ}SG% Ny׋{N.ÜkhX$ A>Z(4!s2F]߅ mKk7aNv\ӿB.ι"Isf9I Ot~ĦmÜhͥq5wRV7uK`2%ɔB&HSBF2fΣ# T> Mgrۗ/@&8˘I3uB&l}3Xpd~=̢ǔ2 F `2!eE&-ȊL86=,(utx?5lCC"vUi{`r5h'3$PTllJCɮJ ;`EBFr߱ⴏqSVcTU? }4P5DUBN80>b?0H4+2nZ#Lp+7U `Bk n` BF+_hYB&~X6' 6`A33 oSDTnٛȧv]T p%w&_H;79"@@獼\>`T8vF4d0Lr:߬ŕxA&Tt3o2 S B0bSW;>ۇ 7_DV3~-KC0d'`!aP/?~}=n#J12=/dMBtT丒>}I㧧FvDBZG>v@A(_ l>~LJ% 6co@$$'8MssP&#FfrO/ r΃ o:t(ԃ6 rC|rdCKDe r$g0'ol<ȎmyXy {.| &-X99b履Ywo'C#bHJÜW68~v`N~3(r_9;*J Z'ބ X}}2.Zԫm!EQqwNaNlX"'1'׹[.HzA7'JsXkQ UBc:> ĸI Z]~.{A3M*͹A80g}v?c'$>A_($H9sr  ǮSWĜߌwTY?yr xfC^z[ICTśd/.bNnR_?:\zR}P(SwtεK oVj8z3JŬ2 a6 `D\u<:0jPX~1 H6T `(IPe%TS l(Q@†T):P<R0ؐƏ JG8Άt{7R)SilHuGbC:F3R0m4s(9 $ LAL4#㋥bPi6^C(#k>cV]{x旴3DҟE Nύ:ME6\2NGDdH8[Qz6=шQo+YbmܰMÂ`F}\ےO[?Lf.{IڿhҮF&I;iN&I;iN&I;iN&I;iNK&MIvҤ4i'MIv<ɤI;iN&I;iNȤ3*!ΨM(!&I;iNs4i'Mɣ!&4%&d-&I;-ȊL{s_z#" =&+aaa\ @" 00~f2kgz?S kg lPI&afM? 0>c /=Y.o~mT.Q&Bp>:L?x}YRʔ0#?ݞakAIŜp.NX\"kɼjR f3RJIA^Zʦs1'zmw6ֺg {/_m9KXsX* ɒM2\3#/jq߱;cۅ{͇ 7 :_m9Y5OǴleCVM4pt_*`B99q'_}NKɑץT͕ǙƘzO9h,<<Eɝ՟bx!NG͝1' ]AvW5'zṘ KͤYsн!5VvW11' OiH ;]/9Lsra2Y kЄ\#}vq D.ݨ9q]O <rX8$}' g$=Ɨ. ?! sr5ܥK![9ZE/Lz2iK2iO>9I{}^<2iO2iO2i)ׇ /~<`\{6T `V Ft0~M%;u:ΐASV dc&S+TVU$8E0t+82 22PiDUO%3+D!6* 0FC!#0a _dÍ̬G`G'~Nz|;_tvߦnGT6p97P3N Mm8T,='T/},qcޮC#˄GAu*C7!3E9L?o/ѣ~ǫCg@F/i/ƜL" q0'Ovk,:uOQ5sHs26oSdws*t/N1ƜL͗Ɯ=dLT}mdm&Qd˗9Y)CZް&ⸯeme`N^:cS}JrO:fYA!._kkJBgLs26K(2廄9إȍOA}p_s26Rdwsjyu|dV\`Nf E|0'_xu{},rJlK[5ۼO!.99OtZOǯօ 2Lf30'So"C\'GOy |xKG 1'So"C\̄ h7焧 )%)(x1/i6tHn`)QuA^=ŀ$4_8siS3050~?FFS\Y0DcˆKy4$eNu` R㊀Atŀ$0F4ԋA03'-退At3ŀ$O䙊At1Y$?e4Y^1"9z `(ӛ Ɉ0w n5g(H{s\_Id_396\,k,,NDME=-30b_p2A?ޮ{o)=]V"X'9FsfF]Coc0'7n^ZL 3ԯ6ǜ|ĥiHB,NsFdIgFR3_coXuJsGF丑Urh% {l~*2Zǝ?LQo9Yp}Lkwq5 ?s#|FWSqsrdu+ ;vseqfn1>Ǎp㼪]' 0'g7nKSf_ݖĜ,8Q)zqezc a-k9c#rɎzW@9W$;Y`Ndpd!~oLX ;)<3w&)" Ȼ{yE4P!kü#nziv\8 :w`H<4NX蓵wW1W Q6 `dCAƽml[fmOv g^jb89`4N825;{P0PX2,QX':&Ct;$g6 `L$ƵfѸ͆Db7^XR E4 0~;= F `QO'5{-?|ϴy3sh1D;a`G 6`A2ة*b@0Ba"`h\RgA0d'd4e!`|] )j 0v39ٱ,rnxb+:ICDdH8pnnsJr@ ;D[ KY68+5t o10+Ȁ`(lld6?ܷfwDkuILߩ`L}T Ys2޿_LFXDbޕ6*t'fW'dɶ#,!Wj)؈9a"wӸbc>=srӪ w6o?xt ANީjh9"}1y K7aNwS< Gݠy}9z,,3œ`e.sf>GƳ|ľ2 rk7fub-e(//Jٱ6r`N^5p|P,}7uo+$ ̘uqU䐱k l0 A>׮>new;F 4\ QQsI=92B) ;U)o=Le G4q7BU79YiSK&Ӷǜ\to)mŒ;ƺ)''!rL?d-3ȔLG~0~.F L=? 2~8GA(zd&y{.BT )970 5ac-_hfg<("yaZ y{G`h&w?=+ F|Ք#N &߶Q0-ȟ8MaCLF\E/\~k@!z0FznaT,\rG:#QViD#vm,$_ IgU^0z!4r7 ƒaAfl.>0jM9o?fĤ=ax@J}1/` n97Nۣ`8XW]遐AWgv ee;`X>h0X!oӤW0;ٴo- A(10Zŝ 1'goQz9%\III]}ǒWaN=U" A0փPZm+G^@%ט0MEY0:R,5(.2&w ZRiXTd%n*ԃ VKnKd ޲*G८ [  2 1Bļ>g9ſߺ *b@2x]w+]vѥ]]ڿ2>vC\1 [ocN|I_3|$w8~- ҧ J}ۺP'La|X+%\byZ4 TQhi0$;=Ghz|NT͸ҏ ;p3H x4)A/]|˜9ng|%=,qx UmUowv/@̥Gug^WvNb[1'\"GbD`N:e"Y#cɲ>f$ Ia )ɾٹg !z}~=gZpYl U 0';obTIs[^[ 1'ߐyy%0A<ӵ<Ü|Vnש|䦯T-<ܱjukoǡjZm m҅ ?3dyrg koՑWZ՜ A4y#Cv/tҀ o sƜR*q%]9Y'%_vyt7`N~%R, A.uKeӀ ]xT̆ @s\O=d:%Jkp?}"CF,9 ջs?< -']LWނ9e_z9l̢P=FC6΃ MYLs1C5xe|\9YS5qޅjZݬ߸ ￶~m+F!ȃ5ێtbN^gDwxCrvCզo_xĖ / s p\/a׭ AnO{Y'l.Gʨ 4cn׏Zŵ A.nU9yPT$Mgы5%\t̀91[t20ِ炀10weN(!Æ|_9 ^27QDcz\ikiP0JsA.~ѴCqXGuK F*r60ؐ|z &#j %/5<#W}t (cq Fױyq ,ɵ:( |v6`Fr 0v hqFyhyܕQްdK ϏDᖱ|я5S[D(>GC.-ZÐ ߥ#`~?38r[p{[P04Fy0!ת&9F/wȣv瞅@(g9^0z j.je:;3S6.TYNWf"`VclB8f.NAwΙw Eb"(\e"o ]PZܴjQЇHhDB7.B >wVs90>{>sgGL'm=kg+Uv@ ,}?Qh  1 ۶=d=%(dkV1EFYZ Xu$0 xx$bAxGjygP8J%Hd:p &g\&1;Z1'ViTX -T8T&w]ąђr_*w,qP8G%@ԩ@d C9zٹt&isDZpѿ ;.YK8db͗p+PN칸@W9bu %llc{le~C\~Rm7 eqQQ's-k1 3.fлG&m~ᗏM)H>HMF'+UӁػD/%-Ѩw|]Q2a/q|4p ]uݻ0iaJ5vO֤ծۏyPa4 `& S6 01Ԇ0_jxT4WRҖ cG!Ǝ#!~~FU(l!8r k@2rX#W\rY [e-l!\r) [%(lZfaW4Snp6%x+L"K7;79V`֥ L!P!4CY^X% 7\N'CEl"8hwx=-e/9C9C9|s F>i䃜F> r Obrh䃜F>ic%9F1G9qFș["gc#|[2g#|F1G.Imߢ.<  dбbei#],pbR"'t[woĜlYO2r47r{' % Wd \ri>TZm!WW&CTBӕL?;Fb)nRɊMb9% % % *PU`ߌ`͚tCNi84ox9fce9iq9"r1GdsD#2GD9"rę#"9ȱb%r91GD9%sD1GdsDZbxvy;p t?\Yymeu6cqU;!YW1 T1ɖ>q(Y!WA?nouo#=3y!׵D5! sɖ Y˖ C׵"["7)rI sB;'˖ɖ/*"'["'[6M-o\tA߇׫NK5!;&: ׈'2K@.s:.r b.A4\8g3dKf@*NΕ8rPK_qH@Ne5\ ?rjWV2/r b9>wC.WM\\eK|ATAl\l\!17zVvnPr HF“/=prŞ0&>zV{d$ 7hrȉ˖Y r9GO'/2吜,.ǙdAdAdAdAdAfu$"ya.&24c9tBCl$16ed ڭDȸ^UA\}֍lOΈ؈7a2|IFTC&ݖ8=ow۸1|jt If(fFϪ Qi_d<+\_xr彇Z7=AAr䎖\"}s/leTYFH.j (c;|2F2ɥl2?=_mȒ#7&Wj}kٜ5"dAdAdAdAdAL$r C idd!62Ntl 2v88*PCƵ[ë߉qтGy3}iџ+7~DD~k_瓙v$/Fwv MWO'܍̃@b$l圈QೡzH#PMw{#W?hih ' 1/''~D8nϏ/r1xʵBf7_ ̹Sw˓'%{1 v̍9j ~Ι0,y@?B@L8`{}07)Fր 1@1 :lD jBP&@5!jBP&@S0 c#@0 &@MjBԄ&@MjBԄhd#@\ aԄP F@5!Z`p mD jB6 jB&@k@Ԅ+&@mX @Mh h@M`@P 5! P 5!g@5!hb&@jB@MOۈ@Ԅ`&a8w`X"\F#: #0`mDw.@a &4 @5!F#9Zw]@dրZ}@s  #s@DZБ|4H>ր(Ch@MjBԄ&@MjBԄΉ06@chBԄ&@MjBԄt5!ZXH>t$@k@t˧lD jBP&@5!jBP&@wN06@5!ׄ&@MԄh  O6@5!h@M>k P X  h@MچP`@MԄh  vp@Ԅm 7! йZ  b jBP&@5!jBP&@S0>L&@m@ Ԅ@Mր ~ ܄8 Y#`Cl0#@)@] @t@m Y(jB&@k@Ԅ܎㟣]@( ր9H@=G! : z @@# h  b0t؈@Ԅ&@MjBԄ&@M`F4`@ MԄ @MԄ F4&@m &@jBۈ@Ԅm5!Ԅ@Mր 0sW @MچP`> M(&B5!jBP&@5!jB44 jB6 m@MԄh    @MHYKX`̎1F@#0t@k@L`@6 &@jB@M*n=0ϑ.x{ 95 g 5@#@@G0< @G#Z>e#@P 5! P 5!s@P&@5!jBP&@hTe#@P aԄΙ@k@jB4w5F4&@-eԄP F@5!Z&\1@5!h@MO`5!ZP)@@9MԄ @MԄ pqg@5!h6b&@jB@MOۈ@Ԅ&,a8w`0;\6#: #0`mDw.@a &d1 @# P{zб5 ˻RNl#V`Lx}Wō\pa6..\Z??+vuwC 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1C 1؃/=-1C 1Lb 1J 1ڜxl1<b!fq1ICV?1cn!gcOcC 1C 1C 1C 1'>y7ĀvpF݀ c93g,.b!1Tbx6zF1C 1X#aM%b!/=ca *1<fq1xbaM%`0[SCA_z0oxYC 1>Y\ jV?-d[e+0+U-~e3i'6c=XHṫ H[щ·}\uH[щNc1뫶"F4щ #: 1 Na1 YDG :B=ffaEtDYљ|hԎ9 ѹw[VD(:S>_,hzu_$:88!HDQ":щՠ``O`st p0 +3G9|tF}#`F=!]":D#CF=!P щF=F#Dtp0p0BD9DtF!F#DtA#:(9:8!MF0G&MF0G':T6GtMFnDG :䉃q&OaNtD:щՠpCtp0F<ك*:щ@tɓ=ndF0G':TvFtM!:8M8D:щՠp'ơF<٪_|ml iA4``VLdVAc-)DL[07 L[1,tq0H`az=1n8h;gp{~'WƎ9Y(B.N7]8ionphڲ}ks$0:p[ 0WVxդicuo諿"1fw wU뛎+R0*PAB ?pSS!? q8:o񶓖#Rmڲ1t˒bŠT`PGו\10m7~zapoNȴ+hJ ` WnZZ"Rᚶ,`\Uߞy I- u u u f0_q/ wݲA 7]~j]{X~Fkڎe k_4QPiSNx0: 7cZ|묷f%0M[0\|3ʹxo*8`qտ;qQKv͛_La\F^7}l⚧^ѦឥGL?jQҨU$V,`'[^3HA.`4Qpc{mu/Sm?s0:NA"ug OS%cq ?3mY]vM[v1 |L1bڢ/#]oYrبp5lia@cv<-B?j1 uØ;T$SjڲѣַFXN#eŠ> :ncP<y\P[xR%wn".Y u Qg4}˙D3mYXh1&>%ĴENNNFt//y=eB=p ۾}k&){yޏk++Lumi&ܑ< W9LA>M!ꢯ2@9Чr? 2ȮO#mUfBW*(jl< oKC|ӛ:`ufST9۳]Ey*mm- [z˙Ani)XGnV_@Amc%9$9q %;*8/+PYUUͭ'ua=#I'z+ z+ J+ Yi`NK6,&m=^eWmmm֦m^1zAb6 m0bByŸ́g5{v\.ܸܸܸ rrJR ,_b+Z34,߀ }"] t,aH@nA*8+`puYSf:92 }PN>[&q]{8gӗ@9C93rT("[ Ȗ)g>VC93-13$恁7"t)#`Ui'8FӶ)Wm_ld`}Ed}p:c J<-(lA![\ʡ9ʹ۾`-8"}C|h;PGcvWe3'TR^= `s `li2ۈs('?021%ʵ0PwCvYF9}q΢D9}YXޡBA9c88(r8.)LcqF9gcqF9gqfC9gʭhk֧qQpUǙ>8r8(8r8(8r8>3828-d9gqF99gqF(;Όs(bqF9g8}dqF9g83T((r8ΌsCgqF98sc83pQ= Pp'78(lS9gP[38}>8rr 83838pQDQpPPp l=(rkKqF9gqF938S38\s%_qF9g8pQs99gPPpx 38oD9gqF938odVr8(lRǽ:pQPNAmr8(r9gqF9 pQǙqpQǙpQs8(r̬p#VUmVqlC7O7 fӽ| }r敳lżTLtTt.jpA;J 0Ha^wo턋`7T8`pI`STtq0 pͮoU `K\ "L^CJC0HҐ *(mbA@  8j湿'5?5!Saʶ`AB 0 FP( *=$  0 0XvM)>Tזf6ץR̳}h=9'k+PΞrȻ(gˁF93/ (19fP[FfYPPNXC9gpQ%pss8(rs8(r8Όs(l_5`4388pQpQpP~qF9g@F9kKqF9g83f(r8bp+rQpQ>r8('S383α{Q̍m(r8(GgqF983+@9gq8MpQBmr8(r93U((r8Όs r8(nqF9gEF9gqBA9gqfcV083ʅ-QpQs8(Lr8(rpw掗|pm*rjKqF9gpQNBA9gqf.8(r9pQs8(r9Y8IrqF9gC9%83pQ*qF9g9qF9ggjKqF9g83q3qsl[UZmڲ9_Q 0-lKQ 0`FNߠo````````qG/s[_ 0Tl oP9```pB~\Y 0gKߠo``````````WBdW` *w 0 0〿LNo7ȍ7mr<D=1Orflcd}d#g۪4?Ւ ͏!ei?֏ƂzGGc02^^c% 2^@ck1/|))jh D@G-`*ʯh 螃/ _> YȞ> Ld2t#ƍCA'X|EQ9&֥qqA /H= Ї3˯xګ9䄽} EfR=L[ylLۄύAt+*E>tžEDm5֖%2Ce{6Z]j VN̒,l])ۄ@0$Ѭ#uɡU'%Xd7Uf::N 'br }'Њ#s0 Ń,` g7w,m"np"``9^N>m\)WFӃĐK!xɸ )vP'9AZ8+A ˛ AvÃăt qQ} o$duƲ'_ͣk%gK{w1ʡ\Ȗ(rԖQ-cʡ1,`s(8WF9\ s r(88(ܓlrx((b0dG1Pn>/P Łn(rdK Qd%8FC91P 1psm91}P."\iLsfy}.L;bFfva߿5wdVU^UeNkN7TejW_])ՙ|̔ʲ+.ie5y[FjL>9ejZTen_9,6!MkEM~W%TM[5:27MX +Ty*oU}}*{J9aoBrSlMFsҭ)*ĢUU4?u#/ܷ=,SUt֧;>31I ~3_Z~O"Ȧ-Qd$AZ}[v dQ,;I݃]?E#3FF#)M)9c;9 iLLazvNfϴgCt;3Ӄṅ!;D51&֘EtZv0Np`;n_&:5;7Шs6>ƏO/<n~#iY32=1Kj37s+ H[щ·}\uH[D'WLtDڊ\t6NVfD':dD'::?^_HVi+:]vYoڊZjEg"c"+3[{N~ږ%^t3aO;P?Oevz{,8Ƽݡ"c֩DGohDtR-谞@tF̈n?:By`u_nI%щμ%wn"sU]zLtي9z0 %:G7Mr8=L[щEk41),1mD9zst<fDy)/3o Nt}6MX)2G{y?~d6s.5_3h0x.nv  iƇ}\ui+WGr0Oc}@qcnQ;,q=1ÖU606}%0YsOӦf08mTGd;޴#ii˳Z,XSY 0e9'aڲq`ihJSSQAi!ዂ]|5UcPRRRqח)Fv[޿=+HӖ կK`\ob]~L53"ԓ7ڸw*8hn{ȣ7(W^AYuu&y[M=K'gkTN B>&"S]# E~&X^EBP_Kt( )BE^dkOpjW: gUmc]C>tMmO#0( R|3P.NPe5p3SXjFʸAG 0@2S54{F^>k4"prLrܷlgdȶ{H ˴eO `^W0Д-.C% Y"%V?Ͼr rNW\-ٲh~rF;aĈ *wT+grD1M#qn{dK1LUSZ+j|ϖ_R'>- (gϡʡlr(':)'9+%rn3q f^*l>@xRGNG�mL1׳Iٶfu FT`|i&75yoq[gDR:‹"zm~mq\f('VrncoՎbĶ!0xJaڲ9gǝ0C%Zy=v wkZ7! ,`3oKZg۲q~Z2umڴ}KF"pT m+HZ$fJKD?"OGp3y\W! TkXr'C-C=ԁB!v*k F(n-3B Ӗ<ʵXߋ71^~(Y-Thpd9-.{v^lr!JSL=At^M'9`0Gxc#^̹_ٸN.vZrdK:F>zA "/̸^ZCvl/hZd`:jlC(؆ u9rO 3Yp4<2=J`#u;h?UNo^|g5j/k$!9õ s V_r]y&93C9 s1gaZr99V&.9cc>ga% Er PM(,Z"838;3}qpQqpQǙqp-+wigqF9gGq18318383Ρr8('r8(g qpQqpQ.38;:pQ,9(gpQs8(, 83PpQ=؆r8(r9qF9gc3qF9g 38M,Ԗ(r8(G18)Gr8(8Ǭ=(r8f@9gqF9QdqF9g*qF9g9f>q38\pQpQ>r8T((r8(yǜlxɗqQ8(gD9gqF9}qYN9*qF9g9r8(Ǜ-QpQ>r8(Ǜ38qo+gqF:Q[38}peBA9gqf=gqF9qD9gqF93883+@9|ȶUU9զ-{9ucaӍt"FRgwy-6Lżs(S1Q bpQd*2j 5wpQ 2U?.$\} B |*2.$\ua._r4T`6JC. SA@ ԠA[;{ xP~Wk3B+ 2jLEB 0 FzGPOLZr\ȸ՜ klOrJrRrBr\rLr}Z1}*Tel} }I})73)u)}I} }q}1}i}*S9З!'!;2JN+!!'!'!!!קӧO@_ևȴ".ZcCNCNCNCCCOsDʾ>ݬ1тSrJrRrBr\rLr}Z1}*TԝR/!!'!'!!!קJEʾiRDrJrRrBr\rL+F'9HCNCNCNC+@vt{dև҇ԇЇʡ!99ٕT夾חS씾HT_W$`F0|1hvEj4Z0LGoA 0 0 mt< O.~{Osco`T9a~v]c҆``rRi``0~pC&˞7.1`yA1r9s8FWS@8Y7 08h7T0Y/mtq0op1B eG/2j/u>_߷(Aߐ8cC5櫝 @`cÛ]B´5Lumi&\4W`Wg,ƒ\hC֨r~sWtcu QrS\~A D.Խ`c@ܦ,w[|HMC*vL/ܟ⽉a̟ٮm_k]pߚvNoA_ag1Lv!5 Yw<׳7up9LTi "]ݣƱ^ϝ6{FUsX <:J`AW-,uі)W) 0!P*rtkue˄A ј#[F~$L]O9iq+L<%XYQGnD  b]A+}̟ n4gqE=GGi;Ųl<$\0Npx1Wf>go8;?GD` UV׊6Vpdu*s}d +p+p@N.;CNCNCNCCCOS9Oe_ʁ999rRt&99999>O>}}*2>d3)!!'!'!!!קӧO@_ևȴ".ZcCNCNCNCCCOsDʾ>ݬ1тSrJrRrBr\rLr}Z1}*TԝR/!!'!'!!!קJEʾiRDrJrRrBr\rL+FKe!!'!'! ;=F2cCNCNCNCvАd҇҇ԇU*rR__N)}vJ߃]$roEJ0 0'|ܮ_~:j 0 0A]w2+mx8x 0 0XnR*\*0 0}|9qP[ћ,`\zS4Ǧ-`aPSŏ_yb`71 09״`sWs.`py`8#tq0O&} rZCA2j Z>z3}@ԀZ&d0P@14Phk@5 F'!j@` Џz`'!F@ hk@7$ր` F4@Skc '!F@ hk@7L4 FPh{րj@mwfCTwloԀpw4$@  Rt@4` &@5 ր(M_@ hk@ԀF45 j@#X Ԁpߕ˹jZ 1CBEC 1Cfb!RWуy{xj<'ٟ;pp5C O]b\<[x#ƃg˛ F W(Hƀjjl8"b!b!5N8OjƟb!b!b!b!NC 1C KC1pfV Wp5\ &1B~w5C 1 W 1C &1C 1l^\ 17C 1C 1C 1pgD 1C 1C 1F 1C 1C 1F 1C 15C 1O 1C &1C 1lC 1pJ 1C 1C 1#5cjeR1pKA 17İ4,g*W c\!F 07L 1b)Ɵ憹!b!#b!b6!ba$baaaM%bba!@%!57T X1ơ TjjV/^z7p5\ Wո/z\@ W#;e>F㫑lLÓ?hOᓛԓS }ONhqgP U@K(-Lx:u 4 bn؋5P`>m~v VրFpomBlB܈@(FxրF0F0fϑF}sYF0>G`lqF40@ P$dЀ>x q6pw.| &ٲ.@ րj@sWN/%h0xna X @k@Ԁt"@'t圈pRD4ր: `: @RP8n@wp3 ҀOui@5 P: P:Г#X45 :`k@ԀFp@ {@5/k@t;a Xs/e  7#Y0j@k@  7M@1lBP #ؕ844_9#@``@`hh F0vzC ]0  wD_4 @#@#ɼ%@`h[<hh[RԀhhۄ^ԀmB4 j@<@  PmBԀVMZh[hhl 藒\9``k@  F0Ft`44DP #؛܈@#@yk@``4݈@#@74445 F0Fp?44t#@`݈@#e 7.@#@#@`k@7Ѝhk@``4I`l?R#@``kv16a l   N hPZj@Ԁ6!@1lBԀj@5 &@ oل5 F5 F0F0ր~@``k@  F0Ft`4,@#@#@`oFp#@1`݈@#Ѝh44rba{IhF5 F0F0րnD l K@#@#Ye 7Ԁ5 )~Ϥ G0!hh[O #@``k@``` F0-bԀmB4 nh@@  PmBԀVMZh[hhl Ԁhhk@W@#"1lB44f7f@#@#@`k@7n@#@#@#P #@k@#X 4`15 P a4 ?]M@ hPڄh*t `k5 hA8E@`#4@ϰp P~  5 z@OBԀ:@ 05 h^R@:<>NW.C 1`GC 1ó^r5r.OM\օ뎺հ4M#VWۥ1Ƶ!F U QQ.Eiagưµm:oc\k*+\ WG\ 1C 1C 1C|qm/SPAe1"'N#TPAPATPAw1r5<$V L5T *MTb6k*1>~ Mـ * * ** * * * *D\ 4T *MjޟJSAgC CSi*1|}6 * * * b * *Ā * *1QOb[XTJSφ~C ^\z1Op1}\MA7{4qPt?\^߽I:4ڋV*`كPB) RgyLB_IJϛcMTJoB]/mncCTjw_Qh*\*`ᾃk%d"!IH6| {LjQI* _IK0X!۩<,+rXl4=uRzc,ivsk]1VvJ5@g$g1JwZoRB؀^uL$.$ S"sc.t+5h oI1KP l4,1 I1.)ʱ  EO[CPγXòtW8QE8,93gA88Aa%Y@K 6*pXp>GGT}NO`(mbm`[O"E%+Gh YP-Lc񰲿?e}١avĽZHTBnDo,۝5.fU&VEX'T0wncSC]¸4 ѳ?twq~uwJo7~?7s̕x7/X?2z`]x߸M!I3[c_U;2W?'s/6ICn^#d{07m=ίliB3} }>.2yܿͥT -22d& ZǢlOh )Cfv̦'d&3l䪠f2d&]v7ّ9+dl $3͖K˟}'e%ާA[w?{BYovK`iųjZGFhViܼܶ=z-*74dFs|aȪ+_i.J#Tf4iȼxzG|2}9ϻbI;os_So/l/6< ~IgXSim,~_='ߓ]KB!BfCY\HlEVHHIt eR3Bؗą$DHDHkI_9;q'_4禺 ~ ? ?Bb3`m!ax҆0555+15!15Qk>!h<0?]c;@_8vyKMW2 Q-QSF<<ٿ!_H$#̪l+#^Nɗ6.ɠ|'ɬڑtwKvDπ|3d._xHT*sj KYG>|;{z%\P1]r~}wҸȌ|~L2L>:OHf#_'ڟ=@k|V!G~R2;q@f|MMJwڑ`p||u>-pdvmLboA~"r>jv>̽hm]λn"3s$_|'~>/#}ŕ\E(Y|?lv};}{SAf!t}Gh7:ˀ|2vT;G/vO_fmT;gA@>Of p8|!3D|!!3dE~2#_HȌ|!QTA19mzz d5KKF!9|仏Ɍ|g90D>Ɍ|䓙oȗ˖Hɜ :_'/$dFdRZ#G5.'/,~>su򅤔[$>G>]8p2vϷ|έڟ=Վ#Lf#m9G>]݅|'3ҺWQj }p&ٹnMq܄&3~e|ۓpTwa2#_HȬ0%9=dF||Վv>8 I 5[w|/!B|''$V'EeST"_H꺚Vo<-?if |"3U;GA/3^_06#_wN !!`Rd&s^!9\]K<%cE/ VqpԖ,d>ӠTVHXH|#ȗȬɗg8&UBBfLOf9_!Bp<@)>r~Z#C&kr>|(!:#_SvO̥p`, jw:=F#'q$G Δ,JVc V!_||u>)đBVC G>s6٫vT;T;w.Pei5>8C O򻚎ApX| |'Yȏ= gO|#2ǿX|2|o(Q#Xv dl`7&NQ2#?_Ϸ|^MuP^7íҊLr/>f]ΗJȌ*jGPH/-~CEini2CI/$dVXɬEHv_*Bf3tB2LY gxYz/>'3Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2Kf2dC9/Ys [֊MtͿ{Sp?$2wsr>򑯞mJ0%,u9_{ ڱB~I!QH0#fc#ҊȷRh4#?jGҪ1bv̫U W|v-'SW/r>C {۟ǐ/$kx5lծrSbp2/EO|Zmv20 K 3ő K_qdCC(*?eV'tXwXHAsς|G&oAHFv_YQ2dT .pݫY#sϹ:?cl;O2\<3]Ϟ,NͣJw\rɐ/ubg4K2/!?DFg#3򑟧̇|P9_2BjG2"3S ɚb53"3?;e@>xų|Te^S< 7ݐXZO0Mkr~F[b?I!fϪ=γZ "Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2d&?&P#d&3ɼmn&oyKe$s4Kr3w$ 49L[i&LfIy'x%o̝ҼP-B"s4ص/>&WY * 2v{I 43w,d |Y(ˠy Sv5\ mΞY6yҙɭrcnaKJοN ].&—/`q5X,n^9(^_Ќ]%=i&s4Wyq* MsnE}'(]߭_w:?d:tiH,խ! J#x+QkHCRU IBk$, IBsFHR^%hA_//pe3ʤϒIo"|&{<2؟dPgPgP ٹL!q} !=mt2 Ij\H2$+k[4?P q 䖕-ߵe Q*ԿVv֬VZz2 wY/Ef{f ūCH,3e%&s12ꪲ9e-e2f':򑟾ȗL?yo|mD~?'f[c9\~e0RDwYWV& =Mqd62`LT;lZwaZeZeZh,lk3DɜYu1ڶմ.v`eֳGiOf**2Vd6"ʂ|*f/X2;[Г۪F*ELޞݴd!͙V8y3}+2O杩jvcZEf*!Ai*agOH^}EZJΐ5eՑپ܍7epӪdns禶L_m^Uc^U |AJ}z!I?$!p)i4 PXK E! I\Y^ 6.w\rZ鵖b9rJe&y8QENznsJsJsQf3VHDl~C{ ={==!#sMV)A;=_no(U9hPdwOTRyj!qTqEr"3 4\dFs6m?qLcV8r;mU}u$5 F̽/~%ss F!Smj> R *OoYGg]7>YEO_JCY D;D^|۫&=g;T-ie=g2ޘ̙ٻԜ}u%6ݕ5OCd~QrZc41c ^J2[{Kqٕ;Cd~G>{?Z.Xk__6aٜ=EY@|G~ux.B+7N;*CI>/W~#3Zí| KF $jGWdJn9w(]V|mvU|;w zSK,u>򓖹X=)?p)#_π|N9E&k$,ʜVȄ a|N^MW 9Vf,u%c7UM~)_TL>ߎ3YA>Rٽ^ȏ|;\9iDՎk^,c ^p>3M0dvȬw2^@בqeJ$| vAuϫɟ|5vnB:_?ލȫ|9?ߛ#FD~CgF`Jc͛#oQvLvA|vr);^MՎ|N2{&~)3\^M9Ivӈr>rvJofQ c 7%l\RvߎގӈN#d6í)dvߎBr~$ r>zC+>cWg=C2̜|f8ϒjUuO? ?=m͛;eUyw!2ǿ0_YG -+9' ւa TiT[S",By_h"O~"-^۞X/1=?ze~b LDfW%H#7gzb!4_qn>g_j)MoϒCe d> _|Z,a;l)qoчRf2[Lf2̓ohbsWvh&3Lf:uYY:?yl-7ɬ 3-''G. ɬ#3Lf2f'hv.й@d&3MOLfC*Wِd&'̫^ LK+d&3Ϛko-li6Zzِg%g[x ~FϾE7p8dk9B{sfˑڞ=rݍ?Z%U<}˷mx?겺?~xө/Y]gY].}oz]Nl]o}':{M>֖c-]S4aȆ$,+ͯx cC_}붽즋*o 40 5ų* JeUEY *I=eJw8|VDѢ-a_'ʠپ7[; RϟF㢓_sxVNK̪gO:ey?Y5 >_6͈8|F_V)EΗXUY{WBTUUJ] 8-WRU]{UOzjU: 9g{䙸G3.$~%EujB>0$#BbyR!1:^$Y֒cBԐq,~%BBb-Qq $kIkI^!XK>گZ~%FXM ,C؜OW^گZ?u\퐐ܺWrd!W *׿g;>јܱ/.=?;kyħg&3Lf2{eF{?]< \}?r !Y#%kkꕊr/?箐/g_8N͖@2d&3Lf2d.6_F3,7#'/Yuۺ]w>yͶ[2ogo~#An g_P'{N>^QQ|./&&$|Ӄ}F9ڥϾю-?n$sI~&xќچsgnv̛2/o;ߡm+m+m+m+m+-qJJJJͫ[{iNK ^!Y~׿tcTVگVھ CZH!_^~ύj8IɶnV[ikqЏBt+l|p,m85-tK^G.'Tf#_6n#?|!dF>6|[r~|2ǓlG~|u~яeM>Cñ!cMHppG>ӐBb|9֐A.XCjo#_ocX]ϱ dXSfB"#_oiEd$ _H$w!WSG$p94T;|;|;\̱|K+̱|K+]fKFWK0G>9֐ϱG>ǚjkf'3&-r>9֐|5;\sOf,u>U;ȗpsXE>ǚ/#WX;\u|!XCjcMñ7tP#_2R#_# 2,pY%cM|53\yW+*/瓙cMʱP9WT| DG.%9kz;vW9T;˰.|sXC>>ǚ:fmN W|u>/9/$ȗ`|K0z;ȗ`po˷|w!k|,5]Mu>ǚjGc+"_HT;W"_Xu>ߎ/$|5!QɌ|k PE%cM'3| "oGG~v2#kvdvɬAu5y5|9kddiX jr!'~>̱|y̱|i vg D>vG>9lp9|5jU;-z;ȗ|59_Ϸ#ȷr!_ ȷr9|BXC>ݱ|E%SK0G>G>v8֐÷|#_Wk'3\f#fϺpWf2d&3Lf2d&3Lf2~Gz|\xV=y'C$3L%d&3ɬ_f/4k f2yɬ{RlYLf2و̙VR4۞Xьf2ZG6zd&6d:B%h&3ɬudAf2lMf7ȣYl $3Lf2jAf2lMf#4.H{R,Rd42Y@g??!Ky~ҧd4LWxǞUi<62k=w>uW@f#2{S] Lf2Xd&%dZGh:6d&3,* 2d:",rsҖd&3Lf2*ɬuy#\d&3좇n8YdV7YAf2kiYtr3Lf##4f2iִ,^mMf2;I\[Gŋ*Srsd&Jdh̛–Fq-+W)]($% IuX~%18cȚ=su!9"?.]7mܰmf]kuzl핼߾_YOt$R0s/bMfSF{!{wV:)/_V̧{x{} 53FfkMsdƳ>cS7$B`-ҳ.$!' Ut#-ݯLf7~V)2ڧ'>wt! Rk 0Odž'$#CBW?;MkxP`HXKB,yI8!+9tj2!)N-C5ːϊ /"8ːCV~^v3gyL]Y5LܜZh&3"o#l4,ks:;;:և+t+4#WW(Wտ?? 4WHÂ(qqrt ;s8yB%AqwIH`Lfɻ$[29\poMX#InlB{mI1!0m ɽqT/$*Ӗ}pM[BŽŽbywI8!eh6vULf9&W5xG߹م6OOoxL7q}x*oaL+y(0$ I1Ę||8 &Wzv];tMԻt[&ڭ~Z$Cœ.$+q|zZRqC߾hk٭; keKs:*^y~njӪ)kI$$UǺhlh>_ rM%D%$f =Հ8iMmeUeNm`d4B2+˯4,iDۦ17pn0j?Jn6(6'E+4^cw _:X^1IZAJRF.z&WGGG mǫ3 zr>7V'^OUgwI-^WMmH CXd,]d`|9:yQv$9_'_=M2zH+*xA/';BܿZ$ˌ|78|:{;dF~5;vMv߿wSpv $wϱډo!c ODZ|s!kG>ϱ|s!kG>ϱ|s!|.kwqӃ9֐|w!)8֐|5#c XC>9֐|5#c XC>9֐|5{[;2(*ϱ|sˌ|!A>u>A>|#_|w!XC>9֐|5#cҊ|5#c XC>9֐|eF>ϱ|s!kG>ϱFfs! t5ϱVGs#kGkG>ϱ|s!kG>ϱ|si#c-^f#9\ z;GGkdF>ϱ|s!kG>ϱ|^MeF>u5| dFv/$dF>ϱ|s!kG>ϱ˟o֐ϱ|s!kG>c B±|!/$|j"D>򅤓|2#ch_k`ϱ|s$39Ȍ|52#c XC>9֐|5#c XC>9֐|5#cMQ|5#c B±|!XC󑯫|G:f#c X#39,!c XC>9֐|5#c XKGf#_G>ϱFfs!kG>ϱ& c-]|]Ms!kdF>ϱFfskdF>ϱ|s!kdn?kvg.#ia10K2dd&JdOS-yu4 E2ŧ[% FonYal(AfJme&s5 :4+LfY4iVid&3- :4kn\Cs2̆TghVi9mLf2YACxF(Lf9#J5^fLf2C.*F3@f4*3S ?vwn'(J]GZG@2 :*Kf#dJf2shV7d&3l ūn.2{O2ZUUh:R7[,7f :4Yf2rJ#mѬ@3Lf2[thFs%7ds%ƣYf2d^mt :4yCdry6hVi4,d&3ɬC3y,ir#>hVi4Lf2 :4yh~&^Q/'k]uDf2YAn}֑ܬC3Lfm}2dF3Lf2[ ILR ݦQ#)Ȍ|9$^[w?{dqgiF[w3j ?U+9ucsΐ9e՜A>?.; dV%E 7k9֐kG>ϱXC>9֐|5#c XC>9֐|5#c \;x5>/s5s!XC>Sp!kG>ϱ|s!kG>ϱ|s!k wePT"c XB|{+(/$|;|G:XC>ݱ|s!kG>ǚkG>ϱ|s!k ˌ|52#c XC>9֐|5#cXCk#c4|p/$G;֐|!!39֐|5#c XC>9֐|5#c XZGsA>v|9_|!!39Ȍ|52#c XC>9֐|52#c k%ˌ|j"_oA>Ɍ|62#_HȌ|52#c XC>9֐|52#c ?߬!c XC>9֐|5 c B"#_H4E.򑯫| I'dF>^[,! c X+IfskdF>ϱ|s!kG>ϱ|s!kG>ǚkG>c B±|!Q#_WSoȗ|u>u5p/$G>ϱFfsYZ?^C>ϱ|s!kG>ϱG|52#cXC>9֐|5#cMA>Z2#XC>9Ȍ|52#cX#39Ȍ|5#c XC>9~BYZ]GҎb`d&3\IHf2d&3\pAd&3Lf2B*,ir3Sd&3Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2|~ƣd&3LfkK,iYҐ4Lf2d&3Lf2d&3Lf2yE2{!fh&3Lf2d|t,7d&3Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2d&3Lf2d܏Ud&3Lf24xKfI#Vf2KdF3Lf2d&3Lf2d&c]1~Fg:Ɠ{+WGvq&$մC:O?$i$p^)6}UIԉ}L?&QC6?BBR\3 v*ϥY`/+*}bz;G:?;v||2YJ#A~f2vgvg"Tv!u5Y,r>K0 %:|vvX{Ub .Nnq!8vU;]":<gR35HVF%ԪȲ0*Y2 L|pVnwwClG e#s:lRwCMm|~_o ~I2O*BUX߱$&ץ-3V'屸Q̶/GB'E_J#Bu~K!((bJM( ̄!Cd|9~Z&FkjH ]56FcrEt9O%Y7JJJ@$=* BؚH%O8,JP\Pbh]KKmB s=@Iw-.5TU^huSnnr }SC#sCh!5CyoF%c) ܓ=CJz4R5~J)Pf ,(&Hl  `Sr :Jh'A K@<%TTԐL3_*_7%TSu+J#YWa.[$sٻ(%e.{xFȺg sܘ#ƺ{{W5qu ˺==+ X`uP=y {}.Мf׊4jcs^#XXBvV&}w枉-,0 s +>ܗ_G ѽMdO{sߣ3=`OM[^ELs̰{6[=;sZ{$nҺGe~IMh"qҺ![5tB+?ZJؓI$)IhJ?Js`Y" ]W%=L WZ'%(.D!"5k(Aql|Ip3I6`<3030FV7`5}(D|5u LOGM#cW%E^>rN'1O4QmGm:<=X M`|jP0U/`/`%"$_DHaK1Xf<|וrɷK*cƮ<ѯ#M7%cG-%4T\3].D⢈D. ˻~JEO 8ܤL4`VTRo4g fsYKKp30ci䩤m7>i ݴ(BuOz|y3:d;DSӀ9#C,HmGJ<=YOEfJ<(»6:7bte)j7{^?2GGV챏<ל؜bv,{29h洁qt"K{̽n4!=tǺךw؜"cifZ3c<{xx 3).%'i⁉׎߳>;4q;GH~Cs=y {hNJ\V dX؃oԛ?2^ j,4=3q݋Z14'1cċ"q%9V|}6{"\`y=Z=Csz;܃=?6쫏Ds/C}{穱X̏RP<{X-īM5ٱ>s}GDO?y=X RМ&Z{͹ڊ'F^+RK{̽O-` WcGc[=:~0`oUc/x6͹}q{ŵr6М3+y^Il<;j]C!"S#Cd2{td|МcʖcƋXcݵ]z{XGG4"c%[5'9؃=4g~wg[ ~Ú+>fiX W=e6Мw>Wc"RZŘ#CdD& ``]=؜5%Iӫ9aw߀sEzFXcDvξ6jj,j^ܦ%4asʣ?1o bX=˜ЫeKGڀL֜j=s8's9kޝӣ{5.Мy2|_XhN#ec:a-[ǘhs-z;cLu󷎟vMeTy"]}æm31ܚ0=:~:_,I<K{̽M'<1,!j,9sb-9hNm)e=5쑝u+{{`݃=r 7o}9 bƵ|";_l #{F\JUReeG|rXsK{hACLjsE{ 8gɥ{&F{Vc{.3bK{j٦{+XhNs nfQj{D{G?XH(ǰz;o}4A{u"9ACn<Ȁ=xǮTE`֐f`Fi30303Kie030N]W"cs'h>uKlN*ENдXlM t"K 0sf`]If͝YXaKE׎߳>;CSN$$`x١6ew f`& kWśsxfO{4m5Yf`"0`91 5Vil3031 `fBGfBG,;LL :"tDqͱ|A6>d/8hL Uc46f630a /Pj_ PcC $ B30%  o(x&eMz`&BL@(P`&J %Q ̞mlcaбĄLA( `fmmm@m`6 f :@if6]c:6sKu^l(C7 QfvR3;l3:RBiLð%KcGLQ0 Df`f"tDǛZ̘%KCQFwBG ̄o6:72#0!9x2n z4[#|탻G= ́to5g=afrXdLƲEAMO$,9/ bn1IX1\SOZב.qW[L ^uXtXISU a6x Wq8-2IԄc%at?G& > H>b-Ff Szt$4O|ts [Y& {ċ"-ٶjI(p\]?MJi$Dޛ$8Y~%$ᓐLܪe0IȓMT܊7>Iw~Z8qܙ$؛y^ɫOGl<;j]IUUUD%{œ;0W-@Kxj3IF1A'm%a4mZNƱ㓴uM+wȅ]o"$^c4o/SҫemP-[lMf4'IT> I$LiN%^2w`.;2& ;I0|$qaf;ݝ-& ;(X|$a~>n~ցYp1`Fi3030s`&6@i3} i&B=;K30I)% `Fix'0#,,( if`@iPٍ4#͆o fYYf``RH}5rKgtkOj v>]\sP<\c$'(L5uvU10_Э 6L>բ|H0*mt~^P.GT(O?+~- JB#)|yoAɒK>:o|ye䳴jbAEsX;d8P'E&cm\)GiI&c RcsW0O?>L&2d,k,`T_ߘ4̓Y@Y@74O 1Jif?JCJi H3H2ZAR$E'I0[J )ڍ8H 3,703 N8fRa$ۃIAR, FU8$|$vw'H> X4wO"b c2iD50s)M~%ӐFH]ucxRDETx2֎1OTWiD0<\٨ı  QMJ̗||%"vEI$wҺg}=Et~u}:t>ggbͩ^@P B9lݿP܍|+CE8NB|5V QM2fzMH>:%t֡ 030sق#8?cڍƷf,*DO44Y|WBi4DEYD``khL܇^[l̝^!l0rWwt fQ&Փ&HT/؜TwN:NVX\4V 6(J@ ǢUqq,9锻p030s^L۞ו?y]XKUOx $O(E GvEȞ2Qj,$w?%*>)8WfN-ڑؽ.J=%7el5X;o޲8}|`|y2Rv|ۢ|(d(y}(uU }{ht29f)0Nh}e.ᯮa%Z f:{k-"l}w״=p ( 03q{`~qOIv輦HSW޴چ+P "e7-|$J,`Ɣjci xZtfbW1ebX,kIJ:'a}TS_ z@[,$8XQ0|t>03IC/ Y${| ,uIA{4L#[H>]E$exa, I Fft>O+_;#o`.4̻gmHt >03kZךsP& `6 n/?DP7!:v|fgaV`ɢCP&*4,`D`%dJYZ 3. iYf\$\$SJ7$0ӊR "aX#~W< UQ5 /̶5r0iȄ5D!4d5$G`*oaLYQFBn\LfJ8@GD֐|$J)SFN`f7f ֡\ h}EusORVz`=Py,T*;sn^RS睺8<~J<2-}9͟|'B3tnUdpJ+̓~)Kf,eHYI)?.!)ZRIXn+0a~O,*3VJ}90委p`GuII{V7QWw7Aۜnߙ١p$4{Zm(Vnmq,ƿvsZVJ"5uGˬ jdLM @- Z5l,!c .Ż/LP0~b '\])X3O9/jj} gzBB x8rUT6K ˦ KF(-l{\AAF<.6ܙge=Is/TRJLi3Ss {R'9%ִu- ۦ#o6#J$9J|l&BNKQjH@>0303030303030303030303030300V$iL+El{p$>ǪUOP}BNl VX3ھbU7;T +ԓTR K%,TR k[9ckkkka~ :5/܃NxtCY[j_C#{x ^C599ĺצo_iEú)˙q`f`.#vW$2f>m9P=<V5*EB?3kܮ4lMT|uZ$']vhi XUutn7Z_EFainterval-3.2.0/inst/test/itl.mat.license0000644000000000000000000000356713316017127016352 0ustar 00000000000000## Copyright 1990-2000 Institut fuer Angewandte Mathematik, ## Universitaet Karlsruhe, Germany ## Copyright 2000-2014 Wiss. Rechnen/Softwaretechnologie ## Universitaet Wuppertal, Germany ## Copyright 1997-2000 Institut fuer Wissenschaftliches Rechnen ## und Mathematische Modellbildung (IWRMM) ## and ## Institut fuer Angewandte Mathematik ## Universitaet Karlsruhe, Germany ## Copyright 2000-2005 Wiss. Rechnen/Softwaretechnologie ## Universitaet Wuppertal, Germany ## Copyright 2013-2015 Marco Nehmeier (nehmeier@informatik.uni-wuerzburg.de) ## Copyright 2009–2012 Spaces project, Inria Lorraine ## and Salsa project, INRIA Rocquencourt, ## and Arenaire project, Inria Rhone-Alpes, France ## and Lab. ANO, USTL (Univ. of Lille), France ## Copyright 2015-2016 Oliver Heimlich ## The static interval test data in itl.mat has been collected from various ## sources with the help of the ITF1788 project, see ## https://github.com/oheim/ITF1788. ## ## Unit tests from C-XSC version 2.5.4 (original license: LGPLv2+) have been ## converted by Oliver Heimlich. ## ## Unit tests from FI_LIB version 1.2 (original authors: Werner Hofschuster and ## Walter Kraemer, original license: LGPLv2+) have been converted by Oliver ## Heimlich. ## ## Unit tests from libieeep1788 (original author: Marco Nehmeier, original ## license: Apache License 2.0) have been converted by Oliver Heimlich with ## minor corrections. ## ## Unit tests from GNU MPFI (original authors: ## Philippe Theveny and ## Nathalie Revol , original license: LGPLv2.1+) ## have been converted by Oliver Heimlich. ## ## Other test cases are original work by Oliver Heimlich. interval-3.2.0/inst/test/meshgrid.tst0000644000000000000000000002037513316017127015770 0ustar 00000000000000## Copyright 2017 Oliver Heimlich ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## We use Octave's builtin meshgrid function for intervals ## (there is no @infsup/meshgrid method) and want to verify that it works ## as desired. %!test %! X = 0 : 3; %! [IX, IY] = meshgrid (infsup (X)); %! [XX, YY] = meshgrid (X); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, infsup (YY))); %!test %! X = 0 : 3; %! Y = 7 : 8; %! [IX, IY] = meshgrid (infsup (X), infsup (Y)); %! [XX, YY] = meshgrid (X, Y); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, infsup (YY))); %!test %! X = 1 : 5; %! [IX, IY, IZ] = meshgrid (infsup (X)); %! [XX, YY, ZZ] = meshgrid (X); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, infsup (YY))); %! assert (isequal (IZ, infsup (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsup (X), infsup (Y), infsup (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, infsup (YY))); %! assert (isequal (IZ, infsup (ZZ))); %!test %! X = 0 : 3; %! Y = 7 : 8; %! [IX, IY] = meshgrid (infsup (X), Y); %! [XX, YY] = meshgrid (X, Y); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, YY)); %!test %! X = 0 : 3; %! Y = 7 : 8; %! [IX, IY] = meshgrid (X, infsup (Y)); %! [XX, YY] = meshgrid (X, Y); %! assert (isequal (IX, XX)); %! assert (isequal (IY, infsup (YY))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsup (X), infsup (Y), Z); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, infsup (YY))); %! assert (isequal (IZ, ZZ)); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsup (X), Y, infsup (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, YY)); %! assert (isequal (IZ, infsup (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (X, infsup (Y), infsup (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, XX)); %! assert (isequal (IY, infsup (YY))); %! assert (isequal (IZ, infsup (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsup (X), Y, Z); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, YY)); %! assert (isequal (IZ, ZZ)); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (X, infsup (Y), Z); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, XX)); %! assert (isequal (IY, infsup (YY))); %! assert (isequal (IZ, ZZ)); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (X, Y, infsup (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, XX)); %! assert (isequal (IY, YY)); %! assert (isequal (IZ, infsup (ZZ))); %!test %! X = 0 : 3; %! [IX, IY] = meshgrid (infsupdec (X)); %! [XX, YY] = meshgrid (X); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, infsupdec (YY))); %!test %! X = 0 : 3; %! Y = 7 : 8; %! [IX, IY] = meshgrid (infsupdec (X), infsupdec (Y)); %! [XX, YY] = meshgrid (X, Y); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, infsupdec (YY))); %!test %! X = 1 : 5; %! [IX, IY, IZ] = meshgrid (infsupdec (X)); %! [XX, YY, ZZ] = meshgrid (X); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, infsupdec (YY))); %! assert (isequal (IZ, infsupdec (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsupdec (X), infsupdec (Y), infsupdec (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, infsupdec (YY))); %! assert (isequal (IZ, infsupdec (ZZ))); %!test %! X = 0 : 3; %! Y = 7 : 8; %! [IX, IY] = meshgrid (infsupdec (X), Y); %! [XX, YY] = meshgrid (X, Y); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, YY)); %!test %! X = 0 : 3; %! Y = 7 : 8; %! [IX, IY] = meshgrid (X, infsupdec (Y)); %! [XX, YY] = meshgrid (X, Y); %! assert (isequal (IX, XX)); %! assert (isequal (IY, infsupdec (YY))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsupdec (X), infsupdec (Y), Z); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, infsupdec (YY))); %! assert (isequal (IZ, ZZ)); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsupdec (X), Y, infsupdec (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, YY)); %! assert (isequal (IZ, infsupdec (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (X, infsupdec (Y), infsupdec (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, XX)); %! assert (isequal (IY, infsupdec (YY))); %! assert (isequal (IZ, infsupdec (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsupdec (X), Y, Z); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, YY)); %! assert (isequal (IZ, ZZ)); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (X, infsupdec (Y), Z); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, XX)); %! assert (isequal (IY, infsupdec (YY))); %! assert (isequal (IZ, ZZ)); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (X, Y, infsupdec (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, XX)); %! assert (isequal (IY, YY)); %! assert (isequal (IZ, infsupdec (ZZ))); %!test %! X = 0 : 3; %! Y = 7 : 8; %! [IX, IY] = meshgrid (infsupdec (X), infsup (Y)); %! [XX, YY] = meshgrid (X, Y); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, infsup (YY))); %!test %! X = 0 : 3; %! Y = 7 : 8; %! [IX, IY] = meshgrid (infsup (X), infsupdec (Y)); %! [XX, YY] = meshgrid (X, Y); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, infsupdec (YY))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsupdec (X), infsupdec (Y), infsup (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, infsupdec (YY))); %! assert (isequal (IZ, infsup (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsupdec (X), infsup (Y), infsupdec (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, infsup (YY))); %! assert (isequal (IZ, infsupdec (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsup (X), infsupdec (Y), infsupdec (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, infsupdec (YY))); %! assert (isequal (IZ, infsupdec (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsupdec (X), infsup (Y), infsup (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsupdec (XX))); %! assert (isequal (IY, infsup (YY))); %! assert (isequal (IZ, infsup (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsup (X), infsupdec (Y), infsup (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, infsupdec (YY))); %! assert (isequal (IZ, infsup (ZZ))); %!test %! X = 20 : 22; %! Y = 78 : 90; %! Z = 12 : 16; %! [IX, IY, IZ] = meshgrid (infsup (X), infsup (Y), infsupdec (Z)); %! [XX, YY, ZZ] = meshgrid (X, Y, Z); %! assert (isequal (IX, infsup (XX))); %! assert (isequal (IY, infsup (YY))); %! assert (isequal (IZ, infsupdec (ZZ))); interval-3.2.0/inst/vereigback.m0000644000000000000000000000730413316017127014730 0ustar 00000000000000## Copyright 2008 Jiří Rohn ## Copyright 2016 Oliver Heimlich ## ## This program is derived from vereigback in VERSOFT, published on ## 2016-07-26, which is distributed under the terms of the Expat license, ## a.k.a. the MIT license. Original Author is Jiří Rohn. Migration to Octave ## code has been performed by Oliver Heimlich. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{lambda}, @var{X}, @var{ep}] =} vereigback (@var{A}) ## Verified backward error analysis of eigenpairs. ## ## For a square complex (or real) matrix @var{A}, this function computes a ## vector of eigenvalues @var{lambda} and a matrix of eigenvectors @var{X} ## in the usual Octave way ## @display ## @code{[X, L] = eig (A); lambda = diag (L);} ## @end display ## and additionally a vector @var{ep} with the following property: for each ## @var{i} there exists a matrix, say @var{A}[@var{i}], verified to satisfy ## @code{max (max (abs (A - A[i]))) <= ep(i)} such that ## @code{(lambda(i), X(:, i))} is verified to be an @emph{exact} eigenpair ## of @var{A}[@var{i}]. If @var{A}, @code{lambda(i)}, and @code{X(:, i)} are ## real then @var{A}[@var{i}] can be taken real, otherwise it is complex in ## general. The maximal value of @code{ep(i)} is usually very small (of order ## 1e-013 to 1e-016), which shows that Octave computes eigenvalues and ## eigenvectors with great accuracy. ## ## Based on the inequality (3.13) in J. Rohn, A Handbook of Results on Interval ## Linear Problems, posted at @url{http://www.cs.cas.cz/~rohn}, which also ## holds for complex eigenpairs (unpublished). ## ## This work was supported by the Czech Republic National Research ## Program “Information Society”, project 1ET400300415. ## @seealso{eig} ## @end deftypefun ## Author: Jiří Rohn ## Keywords: interval ## Created: 2008 function [lambda, X, ep] = vereigback (A) warning ("on", "vereigback:complex", "local") if (nargin ~= 1) print_usage (); return endif [m, n] = size (A); [X, L] = eig (A); # A*X=X*L lambda = diag (L); I = eye (n); ep = inf (n, 1); if (nargout > 2) for i = 1 : n ll = lambda (i); xx = X(:, i); if (~isreal (ll) || ~isreal (xx)) warning ("vereigback:complex", ... "vereigback: complex eigenvalues / eigenvectors not supported") ## issue warning only once per function call warning ("off", "vereigback:complex", "local") endif ll = infsup (ll); xx = infsup (xx); epi = norm ((A - ll .* I) * xx, "inf") ./ norm (xx, 1); # main formula ep(i) = epi.sup; end endif endfunction %!test %! [lambda, X, ep] = vereigback (eye (2)); %! assert (lambda, [1; 1]); %! assert (X, eye (2)); %! assert (ep, zeros (2, 1)); %!test %! [lambda, X, ep] = vereigback ([2 1; 1 2]); %! assert (lambda, [1; 3]); %! assert (X, [-1 1; 1 1] ./ sqrt (2), eps); %! assert (ep, zeros (2, 1)); %!test %! [lambda, X, ep] = vereigback ([2 0 0; 0 3 4; 0 4 9]); %! assert (lambda, [1; 2; 11]); %! assert (ep, zeros (3, 1)); %!test %! [lambda, X, ep] = vereigback ([1 2 3; 0 1 2; 1 1 1]); %! assert (max (ep) < 1e-14); interval-3.2.0/inst/vereigvec.m0000644000000000000000000001623613316017127014611 0ustar 00000000000000## Copyright 2007 Jiří Rohn ## Copyright 2016 Oliver Heimlich ## ## This program is derived from vereigvec in VERSOFT, published on ## 2016-07-26, which is distributed under the terms of the Expat license, ## a.k.a. the MIT license. Original Author is Jiří Rohn. Migration to Octave ## code has been performed by Oliver Heimlich. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{evc}, @var{lambda}, @var{As}] =} vereigvec (@var{A}, @var{x}) ## Verified real eigenvector of an interval matrix. ## ## For a square interval matrix @var{A} and a @emph{real} vector @var{x}, this ## function verifies @var{x} to be an eigenvector of some matrix in @var{A}, or ## not to be an eigenvector of any matrix in @var{A}, or yields no verified ## result (unfortunately, complex eigenvectors cannot be handled yet): ## ## @table @asis ## @item @var{evc} = 1 ## @var{x} is verified to be an eigenvector of some matrix in @var{A}, ## @var{lambda} is an interval number such that for each ## @var{lambda0} ∈ @var{lambda}, @var{A} is verified to contain a matrix having ## (@var{lamda0}, @var{x}) as an eigenpair, ## @var{As} is a very tight interval matrix verified to contain ## a matrix having (mid (@var{lambda}), @var{x}) as an eigenpair, ## ## @item @var{evc} = 0 ## @var{x} is verified not to be an eigenvector of any matrix in @var{A}, ## @var{lambda} and @var{As} consist of empty intervals, ## ## @item @var{evc} = -1 ## no verified result (data may be wrong). ## @end table ## ## Based on the section “Real eigenvectors” in ## J. Rohn, A handbook of results on interval linear problems, ## posted at @url{http://www.cs.cas.cz/~rohn}. ## ## This work was supported by the Czech Republic National Research ## Program “Information Society”, project 1ET400300415. ## ## @seealso{eig} ## @end deftypefun ## Author: Jiří Rohn ## Keywords: interval ## Created: 2007 function [evc, lambda, As] = vereigvec (A, x) if (nargin ~= 2) print_usage (); return endif x = x(:); p = length(x); [m, n] = size (A); if (m ~= n) error ("vereigvec: matrix is not square"); elseif (n ~= p) error ("vereigvec: sizes do not match"); elseif (~isreal (x) || isequal (x, zeros (p, 1))) error ("vereigvec: wrong data"); endif if (~isa (A, "infsup")) if (~isreal (A)) error ("vereigvec: wrong data"); endif A = infsup (A); # allows for real input endif ## checking the basic inequality [ac, Delta] = rad (A); z = sgn (x); x1 = infsup (x); # x double, x1 intval Tz = infsup (diag (z)); left = Tz * (ac - Tz * Delta * Tz) * x1 * x1' * Tz; # left-hand side of the inequality right = Tz * x1 * x1' * (ac + Tz * Delta * Tz)' * Tz; # right-hand side of the inequality ## inequality verified not to be satisfied if (any ((right.sup < left.inf)(:))) ## verified not to be an eigenvector evc = 0; lambda = infsup (); As = repmat (infsup (), n, n); return endif ## inequality verified to be satisfied if (all (all (left.sup <= right.inf))) # verified to be an eigenvector; Rohn, SIMAX 1993, Thm. 4.1 B = find (x ~= 0); denleft = (Tz * ac * Tz - Delta) * abs (x); denright = (Tz * ac * Tz + Delta) * abs (x); num = abs (x); denleft = denleft(B); denright = denright(B); num = num(B); left = denleft ./ num; # left ratio right = denright ./ num; # right ratio lambdal = max (left.sup); # verified lower bound of lambda lambdau = min (right.inf); # verified upper bound of lambda if (lambdal > lambdau) ## bounds contradict: no verified solution evc = -1; lambda = infsup (); As = repmat (infsup (), n, n); return endif lambda = infsup (lambdal, lambdau); # lambda lambdam = mid (lambda); # midpoint of lambda ## finding a matrix with eigenpair (lambdam, x) A1 = A - lambdam .* eye (n); AAs = versingnull (A1, x); # enclosure of a singular matrix in A1 having x as a null vector if (isempty (AAs(1, 1))) # no enclosure outputted: no verified solution evc = -1; lambda = infsup (); As = repmat (infsup (), n, n); return endif AAs = AAs + lambdam .* eye (n); # back to A if (subset (AAs, A)) # AAs part of A ## (lambdam, x) is an eigenpair of a matrix in As; Rohn, SIMAX 1993, proof of Thm. 4.1 evc = 1; As=AAs; return endif ## AAs not a part of A: no verified result evc = -1; lambda = infsup (); As = repmat (infsup (), n, n); return endif ## no verified result evc = -1; lambda = infsup (); As = repmat (infsup (), n, n); endfunction function As = versingnull (A, x) ## VERSINGNULL Verified singular matrix in A having x as a null vector. ## ## ~isempty (As(1, 1)): As is a tight interval matrix verified to be a part ## of A and to contain a singular matrix having x ## as a null vector ## isempty (As(1, 1)): no result [m, n] = size (A); assert (m == n); z = sgn (x); xi = infsup (x); [Ac, Delta] = rad (A); oeprl = abs (Ac * xi); # Oettli-Prager inequality, left side oeprr = Delta * abs (xi); # Oettli-Prager inequality, right side if (all (oeprl.sup <= oeprr.inf)) # Oettli-Prager inequality satisfied, singularity of A verified y = (Ac * xi) ./ oeprr; y(isempty (y)) = infsup (1, 1); # case of both numerator and denominator being zero As = Ac - (diag (y) * Delta) * diag (z); # construction of singular As ... As = intersect (As, A); # ... in A if (~any (any (isempty (As)))) # intersection nowhere empty return # with output As endif ## with As of [Empty]'s, but still verified singular (this fact not used here) endif As = repmat (infsup (), n, n); endfunction function z = sgn (x) # signum of x for real n = length (x); z = ones (n, 1); z(x < 0) = -1; endfunction %!test %! A = [1 0 0; 0 1 1; 0 0 1]; %! assert (vereigvec (A, [1; 0; 0]), 1); %! assert (vereigvec (A, [0; 1; 0]), 1); %! assert (vereigvec (A, [0; 0; 1]), 0); %!test %! A = magic (3); %! [evc, lambda] = vereigvec (A, [1 1 1]); %! assert (evc, 1); %! assert (lambda == 15); %! assert (vereigvec (A, [1; 0; 0]), 0); %! assert (vereigvec (A, [0; 1; 0]), 0); %! assert (vereigvec (A, [0; 0; 1]), 0); %!test %! A = magic (3) + infsup ("[-5, 5]"); %! [evc, lambda, As] = vereigvec (A, [1 0 0]); %! assert (evc, 1); %! assert (lambda == "[3, 13]"); %! assert (ismember ([8 1 6; 0 2 4; 0 5 -2], As)); %! assert (max (max (wid (As))) < 1e-14); interval-3.2.0/inst/verintlinineqs.m0000644000000000000000000001463513316017127015705 0ustar 00000000000000## Copyright 2007-2008 Jiří Rohn ## Copyright 2016 Oliver Heimlich ## ## This program is derived from verintlinineqs in VERSOFT, published on ## 2016-07-26, which is distributed under the terms of the Expat license, ## a.k.a. the MIT license. Original Author is Jiří Rohn. Migration to Octave ## code has been performed by Oliver Heimlich. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{x}, @var{As}] =} verintlinineqs (@var{A}, @var{b}) ## Verified strong solution of interval linear inequalities. ## ## For a rectangular interval matrix @var{A} and a matching interval ## vector @var{b}, this function either computes a strong solution @var{x} to ## @display ## @var{A} * @var{x} @leq{} b ## @end display ## (i. e., a real vector @var{x} verified to satisfy ## @var{Ao} * @var{x} @leq{} @var{bo} for each @var{Ao} in @var{A} and @var{bo} ## in @var{b}), or verifies nonexistence of such a solution, or yields no ## verified result: ## ## @table @asis ## @item ~isnan (@var{x}) ## @var{x} is a verified strong solution of @var{A} * @var{x} @leq{} @var{b}, ## and @var{As} is an interval matrix of empty intervals, ## ## @item ~isempty (@var{As}) ## @var{As} is a very right (“almost thin”) interval matrix verified to contain ## a real matrix @var{Ao} such that the system ## @var{Ao} * @var{x} @leq{} @var{b}.inf has no solution (which proves that no ## strong solution exists), and @var{x} is a vector of NaNs, ## ## @item otherwise ## no verified output. ## @end table ## ## A theoretical result [1] asserts that if each system ## @var{Ao} * @var{x} @leq{} @var{bo}, where @var{Ao} in @var{A} and @var{bo} ## in @var{b}, has a solution (depending generally on @var{Ao} and @var{bo}), ## then there exists a vector @var{x} satisfying ## @var{Ao} * @var{x} @leq{} @var{bo} for @emph{each} @var{Ao} in @var{A} and ## @var{bo} in @var{b}. Such a vector @var{x} is called a strong solution of ## the system @var{A} * @var{x} @leq{} @var{b}. ## ## [1] J. Rohn and J. Kreslova, Linear Interval Inequalities, LAMA 38 (1994), ## 79–82. ## ## Based on Section 2.13 in M. Fiedler, J. Nedoma, J. Ramik, J. Rohn and ## K. Zimmermann, Linear Optimization Problems with Inexact Data, ## Springer-Verlag, New York 2006. ## ## This work was supported by the Czech Republic National Research Program ## “Information Society”, project 1ET400300415. ## ## @seealso{} ## @end deftypefun ## Author: Jiří Rohn ## Keywords: interval ## Created: 2007-02-22 function [x, As] = verintlinineqs (A, b) if (nargin ~= 2) print_usage (); return endif b = vec (b); [m, n] = size (A); x = nan (n, 1); As = repmat (infsup (), m, n); if (m ~= length (b)) error ("verintlinineqs: nonconformant arguments") endif if (not (isa (A, "infsup"))) # allows for real input A = infsup (A); endif if (not (isa (b, "infsup"))) b = infsup (b); endif ## the bounds Al = inf (A); Au = sup (A); bl = inf (b); ## matrix of the system; see Fiedler et al., (2.89) Ao = [Au -Al]; ## finds verified nonnegative solution of Ao*x<=bl [xx, y] = verlinineqnn (Ao, bl); if (not (isnan (xx(1)))) # solution found xxi = infsup (xx); xxi = xxi(1:n) - xxi(n+1:2*n); # interval vector of the original size ## noninterval vectors; candidates for strong solution X = [xx(1:n)-xx(n+1:2*n) xxi.inf xxi.mid xxi.sup]; [Ac, Delta] = rad (A); [bc, delta] = rad (b); for x1 = X left = Ac * infsup (x1) - bc; right = -Delta * infsup (abs(x1)) - delta; if (all (left.sup <= right.inf)) ## Fiedler et al., (2.94); strong solution found x = x1; # verified strong solution return endif endfor ## no result return end if (not (isnan (y(1)))) # Ao*x<=bl verified not to have a nonnegative solution As = vernull(A', y); # Fiedler et al., proof of Thm. 2.23 if (not (isempty (As(1,1)))) As = As'; # Ao*x<=bl unsolvable for some Ao in As which is a part of A return endif ## no result return end ## no result endfunction function As = vernull (A, x) # VERNULL Verified matrix in A having x as a null vector. # # ~isempty(As(1,1)): As is a tight interval matrix verified to be a part of A # and to contain a thin matrix Ao having x as a null vector # (i.e., Ao*x=0), # # isempty(As(1,1)): no result. # [m, n] = size (A); p = length (x); As = repmat (infsup (), m, n); assert (n == p); assert (nargin == 2); assert (isa (A, "infsup")); assert (not (isa (x, "infsup"))); assert (all (not (isnan (x)))); z = sgn (x); xi = infsup (x); [Ac, Delta] = rad (A); oeprl = abs (Ac * xi); % Oettli-Prager inequality, left side oeprr = Delta * abs (xi); % Oettli-Prager inequality, right side if (all (oeprl.sup <= oeprr.inf)) % Oettli-Prager inequality satisfied, x verified null vector of A y = (Ac * xi) ./ oeprr; y(isempty (y)) = 1; % case of both numerator and denominator being zero As = Ac - (diag (y) * Delta) * diag(z); % construction of As ... As = intersect (As, A); % ... in A if (not (any (any (isempty(As))))) % intersection nowhere empty return % with output As else As = repmat (infsup (), m, n); return % with As of [Empty]'s, but x still verified null vector of A endif endif endfunction function z = sgn (x) # signum of x for real n = length (x); z = ones (n, 1); z(x < 0) = -1; endfunction %!test %! A = [-2, -3; -2, -1]; %! b = [-1500; -1000]; %! [x, As] = verintlinineqs (A, b); %! assert (x, [375; 250], 1e-9); %! assert (all (x >= [375; 250])); %! assert (all (all (isempty (As)))); interval-3.2.0/inst/verinvnonneg.m0000644000000000000000000000770613316017127015352 0ustar 00000000000000## Copyright 2008 Jiří Rohn ## Copyright 2016 Oliver Heimlich ## ## This program is derived from verinvnonneg in VERSOFT, published on ## 2016-07-26, which is distributed under the terms of the Expat license, ## a.k.a. the MIT license. Original Author is Jiří Rohn. Migration to Octave ## code has been performed by Oliver Heimlich. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[nonneg, As] =} verinvnonneg (@var{A}) ## Verified nonnegative invertibility of an interval matrix. ## ## For a square interval (or real) matrix @var{A}, this function verifies ## inverse nonnegativity of @var{A}, or not-inverse-nonnegativity of @var{A}, ## or yields no verified result: ## ## @table @asis ## @item @var{nonneg} = 1 ## @var{A} verified inverse nonnegative, ## ## @item @var{nonneg} = 0 ## @var{A} verified not to be inverse nonnegative; @var{As} is a matrix in ## @var{A} (always one of the two bounds) which is verified not to be inverse ## nonnegative, ## ## @item @var{nonneg = -1} ## no verified result. ## @end table ## ## Based on the result by Kuttler, Math. of Computation 1971; see also J. Rohn, ## A Handbook of Results on Interval Linear Problems, posted at ## @url{http://www.cs.cas.cz/~rohn}, Section 3.9. ## ## This work was supported by the Czech Republic National Research ## Program “Information Society”, project 1ET400300415. ## ## @seealso{inv} ## @end deftypefun ## Author: Jiří Rohn ## Keywords: interval ## Created: 2008 function [nonneg, As] = verinvnonneg (A) if (nargin ~= 1) print_usage (); return endif [m, n] = size (A); nonneg = -1; As = repmat (infsup, m, n); if (m ~= n) error ("verinvnonneg: matrix not square"); endif if (~isa (A, "infsup")) A = infsup (A); # allows for real input endif if (any (isempty (A)(:))) # matrix is empty interval: no inverse nonneg = 0; return endif Al = infsup (inf (A), max (-realmax, inf (A))); Bl = inv (Al); if (all (all (issingleton (A)))) Au = Al; Bu = Bl; else Au = infsup (min (realmax, sup (A)), sup (A)); Bu = inv (Au); endif if (any ((isempty (Bl) | isempty (Bu))(:))) # empty inverse: no inverse exists nonneg = 0; return endif if (all (all (Bl.inf >= 0)) && all (all (Bu.inf >= 0))) # verified inverse nonnegative; Kuttler, Math. of Comp. 1971 nonneg = 1; return endif if (any ((Bl.sup < 0)(:))) nonneg = 0; As=Al; # A.inf verified not inverse nonnegative return endif if (any ((Bu.sup < 0)(:))) nonneg = 0; As = Au; # A.sup verified not inverse nonnegative return end endfunction %!assert (verinvnonneg (eye (1)), 1) %!assert (verinvnonneg (eye (2)), 1) %!assert (verinvnonneg (eye (3)), 1) %!assert (verinvnonneg (eye (4)), 1) %!assert (verinvnonneg (eye (5)), 1) %!assert (verinvnonneg (eye (6)), 1) %!assert (verinvnonneg (eye (7)), 1) %!assert (verinvnonneg (eye (8)), 1) %!assert (verinvnonneg (zeros (1)), 0) %!assert (verinvnonneg (zeros (2)), 0) %!assert (verinvnonneg (zeros (3)), 0) %!assert (verinvnonneg (zeros (4)), 0) %!assert (verinvnonneg (zeros (5)), 0) %!assert (verinvnonneg (zeros (6)), 0) %!assert (verinvnonneg (zeros (7)), 0) %!assert (verinvnonneg (zeros (8)), 0) %!assert (verinvnonneg (magic (7)), 0) %!assert (verinvnonneg (infsup (-inf, inf)), -1) interval-3.2.0/inst/verlinineqnn.m0000644000000000000000000001226013316017127015333 0ustar 00000000000000## Copyright 2008 Jiří Rohn ## Copyright 2016-2017 Oliver Heimlich ## ## This program is derived from verlinineqnn in VERSOFT, published on ## 2016-07-26, which is distributed under the terms of the Expat license, ## a.k.a. the MIT license. Original Author is Jiří Rohn. Migration to Octave ## code has been performed by Oliver Heimlich. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{x}, @var{y}] =} verlinineqnn (@var{A}, @var{b}) ## Verified nonnegative solution of a system of linear inequalities. ## ## For a rectangular real matrix @var{A} and a matching real vector @var{b}, ## this function either computes a verified solution of the system of linear ## inequalities ## @display ## @var{A} * @var{x} @leq{} b, @* ## @var{x} @geq{} 0, ## @end display ## or verifies nonexistence of a solution, or yields no verified result. ## ## Possible outputs: ## @itemize @bullet ## @item ## Either @var{x} is a real vector verified to satisfy both inequalities and ## @var{y} is a vector of NaN's, ## ## @item ## or @var{y} is a real vector verified to satisfy ## @display ## @var{A}' * @var{y} @geq{} 0, @* ## @var{y} @geq{} 0, @* ## @var{b}' * @var{y} @leq{} -1 ## @end display ## (which by Farka's lemma implies nonexistence of a solution to the original ## inequalities), and @var{x} is a vector of NaN's, ## ## @item ## or both @var{x} and @var{y} are NaN's. In this case no verified result could ## be found. ## @end itemize ## ## This work was supported by the Czech Republic National Research Program ## “Information Society”, project 1ET400300415. ## ## @seealso{linprog} ## @end deftypefun ## Author: Jiří Rohn ## Keywords: interval ## Created: 2008-01-05 function [x, y] = verlinineqnn (A, b) if (nargin ~= 2) print_usage (); return endif b = b(:); [m, n] = size (A); if (m ~= length(b) || ~isreal (A) || ~isreal (b)) error ("verlinineqnn: Parameters must be real and of matching size"); endif if (~issparse (A)) A = sparse (A); endif x = verlinineqnninner (A, b); if (~isnan (x(1)) || nargout < 2) y = nan (m, 1); return endif Ao = [-A'; -speye(m, m); b']; bo = [zeros(1, n + m), -1]'; y = verlinineqnninner (Ao, bo); endfunction function x = verlinineqnninner (A, b) ## inner subroutine of verlinineqnn ## finds a verified solution to A*x<=b, x>=0, or yields a vector of NaN's ## additive and multiplicative perturbation used [m, n] = size (A); ep = max (1e-10, max ([m n 100]) * max ([norm(A, inf) norm(b, inf)]) * eps); e = ones (n, 1); Ao = [A; -speye(n, n)]; bo = [b' zeros(n, 1)']'; # Ao*x<=bo is equivalent to A*x<=b, x>=0 # additive perturbation bo = bo - ep .* ones (m + n, 1); x = lpprocedure (e, Ao, bo); # solves min e'*x subject to Ao*x<=bo if (not (any (isnan (x)(:)))) left = A * infsup (x); # interval quantity if (all (left.sup <= b) && all (x >= 0)) # verified solution return endif endif # multiplicative perturbation bo = bo - ep .* abs (bo) - ep .* (bo == 0); x = lpprocedure (e, Ao, bo); # solves min e'*x subject to Ao*x<=bo if (not (any (isnan (x)(:)))) left = A * infsup (x); # interval quantity if (all (left.sup <= b) && all (x >= 0)) # verified solution return endif endif # no verified solution x = nan (n, 1); endfunction function x = lpprocedure (c, A, b) ## solves linear programming problem min c'*x subject to A*x<=b ## x should be always assigned (unverified optimal solution, or something else; ## the result is checked afterwards) ## placed separately so that a different linear programming procedure might ## also be used persistent GLP_MSG_OFF = 0; [m, n] = size (A); x = glpk (c, A, b, ... [], [], ... # 0 <= x <= inf repmat ("U", 1, m), ... # inequality constraint with an upper bound b repmat ("C", 1, n), ... # continuous variable x 1, ... # minimization struct ("msglev", GLP_MSG_OFF)); endfunction %!test %! A = [-2, -3; -2, -1]; %! b = [-1500; -1000]; %! [x, y] = verlinineqnn (A, b); %! assert (x, [375; 250], 1e-9); %! assert (all (x >= [375; 250])); %! assert (isnan (y)); %!test %! A = [1, 2; 3, 4]; %! b = [-1; 0]; %! [x, y] = verlinineqnn (A, b); %! assert (y, [1; 0], 1e-9); %! assert (all (y >= [1; 0])); %! assert (isnan (x)); %!test %! A = [1, 2; 3, 4]; %! b = [1; 1]; %! [x, y] = verlinineqnn (A, b); %! assert (x, [0; 0]); %! assert (isnan (y)); interval-3.2.0/inst/verlinprog.m0000644000000000000000000002215313316017127015014 0ustar 00000000000000## Copyright 2007 Jiří Rohn ## Copyright 2016 Oliver Heimlich ## ## This program is derived from verlinprog in VERSOFT, published on ## 2016-07-26, which is distributed under the terms of the Expat license, ## a.k.a. the MIT license. Original Author is Jiří Rohn. Migration to Octave ## code has been performed by Oliver Heimlich. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## -*- texinfo -*- ## @documentencoding UTF-8 ## @deftypefun {[@var{flag}, @var{x}, @var{y}, @var{h}] =} verlinprog (@var{A}, @var{b}, @var{c}) ## Verified linear programming. ## ## For a real matrix @var{A} (full or sparse) and matching real vectors ## @var{b}, @var{c}, this function either computes verified optimal solution ## @var{x}, verified dual optimal solution @var{y} and verified optimal value ## @var{h} of the linear programming problem ## @display ## min @var{c}' * @var{x} subject to @var{A} * @var{x} = @var{b}, x @geq{} 0, ## @end display ## or verifies (in)feasibility, or verifies unboundedness, or yields no ## verified result. The respective outcome is always described verbally in the ## variable @var{flag}. ## ## Possible values of @var{flag}: ## @table @option ## @item verified optimum ## @var{x} is verified to enclose a primal optimal solution, ## @var{y} is verified to enclose a dual optimal solution, ## @var{h} is verified to enclose the optimal value, ## ## @item verified unbounded ## @var{x} is verified to enclose a primal feasible solution @var{xo}, and ## @var{y} is verified to enclose a vector @var{yo} such that the objective ## tends to -Inf along the feasible half-line ## @{@var{xo} + @var{t} * @var{yo} | @var{t} @geq{} 0@}, ## @var{h} is empty, ## ## @item verified feasible ## @var{x} is verified to enclose a primal feasible solution ## (neither optimality nor unboundedness could be verified), ## @var{y}, @var{h} are empty, ## ## @item verified infeasible ## @var{y} is verified to enclose a Farkas vector @var{yo} satisfying ## @var{A}' * @var{yo} @geq{} 0, @var{b}' * @var{yo} < 0 ## (whose existence proves primal infeasibility), ## @var{x}, @var{h} are empty, ## ## @item no verified result ## @var{x}, @var{y}, and @var{h} are empty (no verified result could be found). ## @end table ## ## Complexity: The algorithm solves at most four linear programming problems ## (independently of the size of the original problem) and uses a verification ## procedure which runs approximately in O(@var{m}³) time, where ## @var{m} = rows (@var{A}). ## ## This work was supported by the Czech Republic National Research ## Program “Information Society”, project 1ET400300415. ## @seealso{linprog} ## @end deftypefun ## Author: Jiří Rohn ## Keywords: interval ## Created: 2007 function [flag, x, y, h] = verlinprog (A, b, c) if (nargin ~= 3) print_usage (); return endif b = b(:); c = c(:); [m, n] = size(A); p = length (b); q = length (c); flag = "no verified result"; x = repmat (infsup, n, 1); y = repmat (infsup, m, 1); h = infsup; if (~(m == p && n == q) || (m > n)) error ("verlinprog: sizes do not match"); endif if (~isreal (A) || ~isreal (b) || ~isreal (c)) error("verlinprog: data not real"); endif if issparse (b) b = full (b); end if issparse (c) c = full (c); end # verifying infeasibility yi = verinfeas (A, b); if (~isempty(yi(1))) # verified Farkas vector found y = yi; flag = "verified infeasible"; return endif # verifying feasibility xf = veropt (A, b, ones (n, 1)); if (isempty (xf(1))) # verified feasible solution not found flag = "no verified result"; return endif # verifying unboundedness yu = verunbound (A, c); if (~isempty (yu(1))) # verified descent direction found x = xf; y = yu; flag = "verified unbounded"; return endif # verifying optimality [xo, B, N] = veropt (A, b, c); if (isempty (xo(1))) % verified feasible primal solution with basis B not found x = xf; # previous feasible solution outputted flag = "verified feasible"; return endif AB = A(:, B); if (issparse (AB)) AB = full (AB); # only the square submatrix taken full endif yB = mldivide (infsup (AB'), infsup (c(B))); if (isempty (yB(1))) # verified feasible dual solution not found x = xo; # candidate for optimum outputted as feasible solution flag = "verified feasible"; return endif c = infsup (c); A = infsup (A); crit = c' - yB' * A; # criterial row (dual feasibility) crit = crit(N); # nonbasic part of it if (~all (crit.inf >= 0)) # verified feasible dual solution not found x = xo; % candidate for optimum outputted as feasible solution flag = "verified feasible"; return endif # verified quantities # verified primal and dual feasible solutions found x = xo; # x is a verified primal optimal solution y = yB; # y is a verified dual optimal solution if (nargout >= 3) h1 = c' * x; h2 = b' * y; h = intersect (h1, h2); # h is a verified optimal value (duality theorem) if (isempty (h)) h = h1; end endif flag = "verified optimum"; endfunction function [x, B, N] = veropt (A, b, c) ## B is the "basis index set" of an optimal solution of the LP problem ## min c'*x subject to A*x=b, x>=0, ## x is a verified basic feasible solution with this basis ## N is the set of nonbasic indices persistent GLP_MSG_OFF = 0; [m, n] = size (A); x = repmat(infsup, n, 1); B = nan (m, 1); N = nan (n, 1); [xopt, ~, exitflag] = glpk (c, A, b, ... [], [], ... # 0 <= x <= inf repmat ("S", 1, m), ... # equality constraints Ax = b repmat ("C", 1, n), ... # continuous variable x 1, ... # minimization struct ("msglev", GLP_MSG_OFF)); if (exitflag ~= 0) return endif [xx, J] = sort (xopt); B = J(n - m + 1 : n); # B is set of "basic" indices, N = J(1 : n - m); # N of "nonbasic" ones AB = A(:, B); if (issparse (AB)) AB = full (AB); # only the square submatrix taken full (because of mldivide) endif xB = mldivide (infsup (AB), infsup (b)); if (isempty (xB(1)) || ~all (xB.inf >= 0)) # verified "optimal" solution not found return endif # verified "optimal" solution found x = infsup (zeros (n, 1)); x(B) = xB; endfunction function y = verinfeas (A, b) # y verified to enclose a Farkas vector yo (i.e., satisfying A'*yo>=0, b'*yo<0) # its existence implies infeasibility of A*x=b [m, n] = size (A); y = repmat(infsup, m, 1); ep = max (1e-08, max ([m n 100]) * max ([norm(A, inf) norm(b, inf)]) * eps); Afv = [A' -A' -eye(n) zeros(n,1); # Afv is (n+1)x(2*m+n+1) b' -b' zeros(1,n) 1]; bfv = [zeros(n, 1)' -1]'; # bfv is (n+1)x1 # perturbation to compensate roundoff errors (so that A'*y>=0) bfv = bfv + ep * [ones(1, n) -1]'; yf = veropt (Afv, bfv, ones (2 * m + n + 1, 1)); % system: A'*y>=0, b'*y<=-1, y written as y=y1-y2 if (~isempty (yf(1))) yf = mid (yf); y1 = yf(1 : m); y2 = yf(m + 1 : 2 * m); yf = y1 - y2; # would-be Farkas vector A = infsup (A); b = infsup (b); yf = infsup (yf); # (i.e., should satisfy A'*y>=0, b'*y<0) alpha = A' * yf; beta = b' * yf; if (all (alpha.inf >= 0)) && (beta.sup < 0) # infeasibility verified y=yf; # Farkas vector outputted endif endif endfunction function y = verunbound (A, c) # y verified to enclose a vector yo satisfying A*yo=0, yo>=0, c'*yo<=-1 # under feasibility its existence implies unboundedness [m, n] = size (A); y = repmat (infsup, n, 1); Aunb = [A zeros(m, 1); # Aunb is (m+1)x(n+1) c' 1]; bunb = [zeros(1, m) -1]'; # bunb is (m+1)x1 yunb = veropt (Aunb, bunb, ones (n + 1, 1)); # yunb is (n+1)x1 if (~isempty (yunb(1))) # y satisfies A*y=0, y>=0, c'*y=-1 y = yunb(1:n); return endif endfunction %!test %! A = [-2, -3; -2, -1]; %! b = [-1500, -1000]; %! c = [1; 1]; %! [flag, x, y, h] = verlinprog (A, b, c); %! assert (flag, "verified optimum"); %! assert (ismember ([375; 250], x)); %! assert (wid (x) < 1e-12); %! assert (ismember ([-0.25; -0.25], y)); %! assert (wid (y) < 1e-16); %! assert (ismember (625, h)); %! assert (wid (h) < 1e-12); interval-3.2.0/octave-interval.metainfo.xml0000644000000000000000000001121313316017127017113 0ustar 00000000000000 octave-interval www.octave.org-octave.desktop Interval

Real-valued interval arithmetic Reellwertige Intervallarithmetik Arithmétique d'intervalles à valeurs réelles Reellvärd intervallaritmetik

The interval package for real-valued interval arithmetic allows one to evaluate functions over subsets of their domain. All results are verified, because interval computations automatically keep track of any errors.

These concepts can be used to handle uncertainties, estimate arithmetic errors and produce reliable results. Also it can be applied to computer-assisted proofs, constraint programming, and verified computing.

The implementation is based on interval boundaries represented by binary64 numbers and is conforming to IEEE Std 1788-2015, IEEE standard for interval arithmetic.

Das Intervall-Paket für rellwertige Intervallarithmetik kann Funktionen über Teilmengen ihres Definitionsbereichs auszuwerten. Alle Ergebnisse werden durch Rechnung mit Intervallschranken nachgewiesen, wobei sämtliche Fehler automatisch mitgeführt werden.

Mit diesen Konzepten lassen sich ungewisse Messwerte behandeln, arithmetische Fehler abschätzen und zuverlässige Ergebnisse erzeugen. Es kann auch für rechnergestützte Beweise, Constraintprogrammierung oder verifiziertes Rechnen angewandt werden.

Die Intervallschranken werden im Zahlenformat binary64 geführt und die Umsetzung ist standardkonform zu IEEE Std 1788-2015, dem IEEE-Standard für Intervallarithmetik.

Le paquet arithmétique d'intervalles à valeurs réelles permet d'évaluer des fonctions sur des sous-ensembles de leurs domaines. Tous les résultats sont garantis car les calculs par intervalles permettent un suivi automatique des erreurs.

Ces concepts peuvent être utilisés pour prendre en compte les incertitudes, estimer les erreurs arithmétiques, et générer des résultats fiables. Ils peuvent également être appliqués à des preuves assistées par ordinateur, à la programmation par contraintes et à des calculs garantis.

Cette implantation est basée sur des bornes d'intervalles sous forme de nombres réels 64 bits et se conforme au standard IEEE 1788-2015, standard IEEE pour l'arithmétique d'intervalles.

Intervallbiblioteket för reellvärd intervallaritmetik låter en evaluera funktioner över delmängder av deras domän. Alla resultat är verifierade, då intervallberäkningarna automatiskt håller reda på eventuella fel.

Dessa koncept kan användas för att hantera osäkerheter, uppskatta beräkningsfel och producera säkra resultat. Det kan också användas till datorstödda bevis, villkorsprogrammering och verifierade beräkningar.

Implementationen är baserad på intervallgränser representerade med binary64 tal och är kompatibel med IEEE Std 1788-2015, IEEE standarden för intervallaritmetik.

interval arithmetic interval analysis interval computation parameter estimation rounding error measurement error numerical error scientific computing result verification verified result set arithmetic finite precision range interval tolerance uncertainty preimage constraint enclosure bisection https://octave.sourceforge.io/interval/ https://savannah.gnu.org/bugs/?group=octave FSFAP GPL-3.0+ Octave-Forge Community octave-maintainers@gnu.org interval-3.2.0/src/Makefile0000644000000000000000000000702313316017127013720 0ustar 00000000000000## This is part of the GNU Octave Interval Package. ## Copyright 2015-2018 Oliver Heimlich ## Copyright 2016 Mike Miller ## See the file COPYING for copying conditions. SHELL = /bin/sh OBJ = crlibm_function.oct \ intervaltotext.oct \ mpfr_function_d.oct \ mpfr_linspace_d.oct \ mpfr_matrix_mul_d.oct \ mpfr_matrix_sqr_d.oct \ mpfr_to_string_d.oct \ mpfr_vector_sum_d.oct \ mpfr_vector_dot_d.oct \ __setround__.oct BUNDLED_CRLIBM_DIR = crlibm LDFLAGS_MPFR =-lmpfr ## Use important flags in XTRA_CFLAGS for OpenMP (workaround for bug #45280) CFLAG_OPENMP =$(findstring -fopenmp,$(shell $(MKOCTFILE) -p XTRA_CFLAGS)) ## Auto-detect SSE2 for configuration of crlibm ## Ask the compiler to allow cross-compilation SSE2_MACRO_DEF =$(shell echo \ | $(shell $(MKOCTFILE) -p CC) \ $(shell $(MKOCTFILE) -p CFLAGS) \ -dM -E - \ | grep "__SSE2__" | grep "1" ) ifneq ($(SSE2_MACRO_DEF),) CONF_FLAG_SSE2 ?=--enable-sse2 endif all: $(OBJ) ## crlibm api oct-file crlibm_function.oct: crlibm_function.o $(BUNDLED_CRLIBM_DIR)/crlibm_private.o @echo " [MKOCTFILE] $<" @$(MKOCTFILE) -o $@ $< $(BUNDLED_CRLIBM_DIR)/*.o $(BUNDLED_CRLIBM_DIR)/scs_lib/*.o crlibm_function.o: crlibm_function.cc @echo " [MKOCTFILE] $<" @$(MKOCTFILE) --compile -o $@ $< ## bundled crlibm library ## ## Note to redistributors: ## If you can't compile this library for a particular platform ## or `__check_crlibm__` throws a warning in Octave, you can safely ## omit the crlibm library from a redistributed binary package, ## (you must keep __check_crlibm__.m). ## However, please inform the package maintainer of the error. $(BUNDLED_CRLIBM_DIR)/crlibm_private.o: $(BUNDLED_CRLIBM_DIR)/crlibm_config.h $(MAKE) -C $(BUNDLED_CRLIBM_DIR) CFLAGS+="$(shell $(MKOCTFILE) -p CPICFLAG) -Wno-div-by-zero -Wno-unused-variable -Wno-unused-but-set-variable" $(BUNDLED_CRLIBM_DIR)/crlibm_config.h: (cd $(BUNDLED_CRLIBM_DIR) && ./configure --disable-dependency-tracking $(CONF_FLAG_SSE2)) ## Wrapper functions for backwards compatibility with old Octave versions OCTAVE_COMPATIBILITY = compatibility/octave.h compatibility/octave.cc compatibility/octave.cc: $(filter-out $(OCTAVE_COMPATIBILITY),$(wildcard compatibility/*)) @echo " [MAKE] compatibility" @$(MAKE) -C compatibility @touch "$@" ## GNU MPFR api oct-files mpfr_matrix_mul_d.oct mpfr_matrix_sqr_d.oct : mpfr_%.oct: mpfr_%.cc mpfr_commons.h $(OCTAVE_COMPATIBILITY) @echo " [MKOCTFILE] $<" @$(MKOCTFILE) -o $@ $(LDFLAGS_MPFR) $(CFLAG_OPENMP) $< mpfr_%.oct: mpfr_%.cc mpfr_commons.h $(OCTAVE_COMPATIBILITY) @echo " [MKOCTFILE] $<" @$(MKOCTFILE) -o $@ $(LDFLAGS_MPFR) $< intervaltotext.oct: intervaltotext.cc mpfr_commons.h $(OCTAVE_COMPATIBILITY) @echo " [MKOCTFILE] $<" @$(MKOCTFILE) -o $@ $(LDFLAGS_MPFR) $< ## api oct-file ## ## Note to redistributors: ## If you can't compile this function for a particular platform ## or `test @infsup/mtimes` throws a warning in Octave, you can safely ## omit the __setround__ function from a redistributed binary package. ## However, please inform the package maintainer of the error. __setround__.oct: __setround__.cc @echo " [MKOCTFILE] $<" @$(MKOCTFILE) -o $@ -Wno-unknown-pragmas $< clean: test ! -e $(BUNDLED_CRLIBM_DIR)/Makefile || $(MAKE) -C $(BUNDLED_CRLIBM_DIR) $@ $(MAKE) -C compatibility $(RM) *.oct *.o .PHONY: all clean interval-3.2.0/src/__setround__.cc0000644000000000000000000000516313316017127015231 0ustar 00000000000000/* Copyright 2015 Kai T. Ohlhus (Original version for C++11) Copyright 2015-2016 Oliver Heimlich (Compatibility with C99 and different parameter semantics for compatibility with the Octave fenv package) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #include #include #pragma STDC FENV_ACCESS ON DEFUN_DLD (__setround__, args, nargout, "-*- texinfo -*-\n" "@defun __setround__ (@var{rnd})\n" "\n" "Changes the floating-point rounding direction for the current thread and " "any new threads which will be spawned from the current thread.\n" "\n" "@table @option\n" "@item @var{rnd} = -inf\n" "switch rounding downwards (towards -inf)\n" "@item @var{rnd} = 0.5\n" "switch rounding to nearest (default rounding mode)\n" "@item @var{rnd} = +inf\n" "switch rounding upwards (towards +inf)\n" "@end table\n" "@end defun" ) { const int nargin = args.length (); if (nargin != 1) { print_usage (); return octave_value_list (); } const double rnd = args(0).scalar_value (); int mode = 0; if (rnd == -INFINITY) mode = FE_DOWNWARD; else if (rnd == +INFINITY) mode = FE_UPWARD; else if (rnd == 0.5) mode = FE_TONEAREST; else // No other rounding modes might be supported // (depends on the C implementation) error ("__setround__: Unsupported rounding mode, please use -inf, +inf " "or 0.5"); if (error_state) return octave_value_list (); if (fesetround (mode) != 0) error ("__setround__: Unable to change rounding mode"); return octave_value_list (); } /* %!test %! __setround__ (+inf); %! assert (1 + realmin > 1, true); %! assert (1 - realmin == 1, true); %! __setround__ (0.5); %!test %! __setround__ (-inf); %! assert (1 + realmin == 1, true); %! assert (1 - realmin < 1, true); %! __setround__ (0.5); %!test %! __setround__ (0.5); %! assert (1 + realmin == 1, true); %! assert (1 - realmin == 1, true); %!shared %! __setround__ (0.5); */ interval-3.2.0/src/compatibility/Makefile0000644000000000000000000000142213316017127016566 0ustar 00000000000000## This is part of the GNU Octave Interval Package. ## Copyright 2018 Oliver Heimlich ## See the file COPYING for copying conditions. SHELL = /bin/sh ## To be backwards compatible with old versions of Octave, we use wrapper ## functions around some core API functions. ## ## The implementation of the wrapper functions and other backwards ## compatibility code is split into .cc files for respective major versions ## of Octave. ## ## The needed implementation for octave.h is selected during installation. OCTAVE_VERSION = $(shell $(OCTAVE_CONFIG) -p VERSION) ifneq ($(filter 3.% 4.0.% 4.1.% 4.2.%,$(OCTAVE_VERSION)),) SRC = octave_4.2.cc else SRC = octave_current.cc endif octave.cc: $(SRC) @echo "Detected Octave version: $(OCTAVE_VERSION)" cp "$<" "$@" clean: $(RM) octave.cc interval-3.2.0/src/compatibility/octave.h0000644000000000000000000000167713316017127016574 0ustar 00000000000000/* Copyright 2018 Oliver Heimlich This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ // This file contains wrappers around the Octave core API to support multiple // versions of GNU Octave. See octave_*.cc for implementations in different // versions of Octave. #include bool isvector (const Array x); bool isempty (const octave_value x); interval-3.2.0/src/compatibility/octave_4.2.cc0000644000000000000000000000245213316017127017305 0ustar 00000000000000/* Copyright 2018 Oliver Heimlich This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ // Implementation for Octave version 4.2 and older. #include #include // The is_vector method has been replaced by isvector in Octave 4.4. bool isvector (const Array x) { return x.is_vector (); } // The is_empty method has been replaced by isempty in Octave 4.4. bool isempty (const octave_value x) { return x.is_empty (); } // feval has been moved into octave::feval in Octave 4.4. namespace octave { octave_value_list feval ( const std::string &name, const octave_value_list &args = octave_value_list (), int nargout = 0 ) { return ::feval (name, args, nargout); } } interval-3.2.0/src/compatibility/octave_current.cc0000644000000000000000000000150213316017127020457 0ustar 00000000000000/* Copyright 2018 Oliver Heimlich This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #include bool isvector (const Array x) { return x.isvector (); } bool isempty (const octave_value x) { return x.isempty (); } interval-3.2.0/src/configure.ac0000644000000000000000000000322613316017127014547 0ustar 00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # ### Copyright (C) 2017 Olaf Till ### Copyright (C) 2017 Oliver Heimlich ### ### This program is free software; you can redistribute it and/or ### modify it under the terms of the GNU General Public License as ### published by the Free Software Foundation; either version 3 of the ### License, or (at your option) any later version. ### ### This program is distributed in the hope that it will be useful, ### but WITHOUT ANY WARRANTY; without even the implied warranty of ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ### General Public License for more details. ### ### You should have received a copy of the GNU General Public License ### along with this program; if not, see ### . AC_PREREQ([2.69]) AC_INIT([interval], [m4_esyscmd_s([echo $VERSION])], [Oliver Heimlich ]) AC_CONFIG_SRCDIR([mpfr_function_d.cc]) # Checks for programs. AC_PROG_CXX AC_LANG([C++]) # Checks for libraries. AC_CHECK_LIB([mpfr], [mpfr_init2], [], [ AC_MSG_ERROR([could not find the mpfr library]) ]) AC_CHECK_LIB([m], [floor]) # Checks for header files. AC_CHECK_HEADERS([sstream]) AC_CHECK_HEADERS([fenv.h]) AC_CHECK_HEADERS([mpfr.h], [], [ AC_MSG_ERROR([could not find mpfr.h, possibly an mpfr development package has to be installed]) ]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_INT32_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T # Checks for library functions. AC_FUNC_ERROR_AT_LINE AC_CHECK_FUNCS([fesetround]) interval-3.2.0/src/crlibm/AUTHORS0000644000000000000000000000017113316017127014575 0ustar 00000000000000David Defour, Catherine Daramy, Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Lauter, Jean-Michel Muller interval-3.2.0/src/crlibm/COPYING0000644000000000000000000004325413316017127014571 0ustar 00000000000000 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. interval-3.2.0/src/crlibm/COPYING.LIB0000644000000000000000000006364213316017127015201 0ustar 00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 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. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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 with this License. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. 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 library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; 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. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! interval-3.2.0/src/crlibm/ChangeLog0000644000000000000000000001065213316017127015304 0ustar 00000000000000Summary of changes between version 1.0beta1 and version 0.18beta1 ========================================================== Large performance improvement in asin and acos, now in asincos.c Added asinpi and acospi Summary of changes between version 0.18beta1 and version 0.17beta1 ========================================================== Added atanpi Summary of changes between version 0.17beta1 and version 0.14beta1 ========================================================== Added sinpi, cospi, tanpi Added power, currently unproven Summary of changes between version 0.14beta1 and version 0.13beta1 ========================================================== Added log1p Added tests/computemd5list.sh Documentation updates, added more worst cases Interval functions for exp and log (in the CVS, not yet in the release) Summary of changes between version 0.13beta1 (never released) and version 0.11beta1 ========================================================== Added expm1, acos Corrected small possible bug in asin Summary of changes between version 0.11beta1 and version 0.10beta ========================================================== Added asin More Gappa Correction of a serious bug (found by Paul Zimmermann) in the computation of rounding constants. (Fortunately the bug was in the proof, the code was OK) More Gappa proofs Summary of changes between version 0.10beta and version 0.8 ========================================================== Added log2 and log10 using triple double (log2-td.*, log10-td.*) Triple-double versions of exp and log (exp-td.*, log-td.*) log-de, using double-extended, much faster on IA32 and IA64 Cleaning up, autotoolization of the new functions Proofs using the Gappa tool Summary of changes between version 0.8 and version 0.8beta4 ========================================================== Cleaning up and fixes to improve portability Finished proofs of trigonometric functions Some cleaning up and documentation improvement Fixed bug for large arguments to sinh and cosh Added crlibm.spec (to build RPMs) Summary of changes between version 0.8beta4 and version 0.8beta3 ========================================================== Added crlibm_generate_test_vectors Added test vectors to all functions, including some of Lefevre/Muller worst cases Cleant up the accurate trig functions, now in trigo.c Cleant up cosh and sinh Added Gappa input file to assist the proof of the trig functions Added AMD64 architecture to autoconf stuff Improved timings on x86 Summary of changes between version 0.8beta3 and version 0.8beta2 ========================================================== Added crlibm_blindtest and automatic testsuite Consequently corrected quite a few bugs in extreme cases Cleant up cosh and sinh Summary of changes between version 0.8beta2 and version 0.8beta ========================================================== Rewritten faster trigonometric functions Added crlibm_blindtest and automatic testsuite Added crlibm_exit() crlibm_init() now returns the old processor status flag Proof for the trigonometric functions in progress Added crlibm.spec file to build rpms to the CVS Summary of changes between version 0.8beta and version 0.2: ========================================================== Added functions : sin cos tan Added function atan Added function atan specialized for pentium (atan-pentium.c) Added functions sinh cosh Changed Maple files from .mw and .mws to .mpl Added FMA support in crlibm_private.h Added polish to some of the proofs Improved performance tests for tighter timing, Fairer speed comparison to mpfr: We now compare to mpfr with 53-bit mantissa, although this doesnot provide correct rounding if the result is a denormal (double rounding). Previously we compared to 150-bit mpfr. Version 0.2 : exp and log interval-3.2.0/src/crlibm/Makefile.am0000644000000000000000000001411113316017127015560 0ustar 00000000000000## Process this file with automake to produce Makefile.in # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA lib_LIBRARIES = libcrlibm.a # shared libraries need libtool. We'll do it later. #lib_LTLIBRARIES = libcrlibm.la # Note that at the moment, asking for intervals disables double-extended if USE_HARDWARE_DE libcrlibm_a_SOURCES = \ crlibm.h crlibm_private.h crlibm_private.c double-extended.h\ triple-double.h triple-double.c\ exp-td.h exp-td.c exp-td-standalone.c expm1-standalone.c \ expm1.h expm1.c \ log-de.c log-de.h \ log1p.c \ log10-td.h log10-td.c \ log2-td.h log2-td.c \ rem_pio2_accurate.h rem_pio2_accurate.c \ trigo_fast.c trigo_fast.h trigo_accurate.c trigo_accurate.h \ trigpi.c trigpi.h \ asincos.h asincos.c \ pow.h pow.c\ atan_fast.c atan_fast.h atan_accurate.h atan_accurate.c \ csh_fast.h csh_fast.c else libcrlibm_a_SOURCES = \ crlibm.h crlibm_private.h crlibm_private.c \ triple-double.h triple-double.c\ exp-td.h exp-td.c exp-td-standalone.c expm1-standalone.c \ expm1.h expm1.c \ log.c log.h \ log1p.c \ rem_pio2_accurate.h rem_pio2_accurate.c \ trigo_fast.c trigo_fast.h trigo_accurate.c trigo_accurate.h \ trigpi.c trigpi.h \ asincos.h asincos.c \ pow.h pow.c\ atan_fast.c atan_fast.h atan_accurate.h atan_accurate.c \ csh_fast.h csh_fast.c endif # add all the scs_lib useful functions libcrlibm_a_LIBADD = scs_lib/scs_private.o scs_lib/addition_scs.o \ scs_lib/division_scs.o scs_lib/print_scs.o\ scs_lib/double2scs.o scs_lib/zero_scs.o\ scs_lib/multiplication_scs.o scs_lib/scs2double.o include_HEADERS = crlibm.h SUBDIRS = scs_lib . # Add your compiler here. Default is assumed to be gcc. if COMPILER_ICC # mp means maintain precision. Should be useless with std=c99, this is an ICC bug AM_CFLAGS = -std=c99 -mp -Qoption,cpp,--extended_float_types -IPF_fp_speculationsafe else # default assumed to be gcc if USE_SSE2 AM_CFLAGS = -std=c99 -Wall -msse2 -mfpmath=sse else # GCC's -frounding-math is needed for FPU control AM_CFLAGS = -std=c99 -Wall -O3 -frounding-math endif endif tripledoubleprocedures.pdf: docs/latex/tripledoubleprocedures.tex cd docs/latex; \ pdflatex tripledoubleprocedures; bibtex tripledoubleprocedures; \ pdflatex tripledoubleprocedures; pdflatex tripledoubleprocedures;\ mv tripledoubleprocedures.pdf .. crlibm.pdf: docs/latex/crlibm.tex cd docs/latex; lualatex crlibm; bibtex crlibm; lualatex crlibm; lualatex crlibm;\ mv crlibm.pdf .. doc: crlibm.pdf tripledoubleprocedures.pdf EXTRA_DIST = VERSION TODO\ maple/common-procedures.mpl \ maple/double-extended.mpl maple/triple-double.mpl\ maple/exp-td.mpl maple/csh.mpl \ maple/log-td.mpl maple/log-de.mpl \ maple/log2-td.mpl maple/log10-td.mpl \ maple/trigo.mpl maple/atan.mpl \ maple/asin-td.mpl maple/acos-td.mpl \ maple/sqrt.mpl \ maple/expm1.mpl \ maple/gal.mpl \ maple/pow.mpl \ gappa/trigos/SinCosCase3.gappa gappa/trigos/TanCase2.gappa \ gappa/trigos/TanCase2.gappa \ gappa/trigos/SinCosCase3.gappa gappa/trigos/TanCase2.gappa \ gappa/sqrt12.gappa gappa/sqrt13.gappa gappa/sqrt-proof.sh gappa/sqrt.sed \ gappa/log-de/log-de-acc-index0-E0.gappa gappa/log-de/log-de-index0-E0.gappa \ gappa/log-de/log-de-acc-index0-E1N.gappa gappa/log-de/log-de-index0-E1N.gappa \ gappa/log-de/log-de-acc-index1N-E0.gappa gappa/log-de/log-de-index1N-E0N.gappa \ gappa/log-de/log-de-acc-index1N-E1N.gappa gappa/log-de/README \ gappa/log-td/log-td.gappa gappa/log-td/log-td-E0.gappa \ gappa/log-td/log-td-E0-logir0.gappa gappa/log-td/log-td-accurate.gappa \ gappa/log-td/log-td-accurate-E0.gappa gappa/log-td/log-td-accurate-E0-logir0.gappa \ gappa/exp-td/exp-td-accurate1.gappa gappa/exp-td/exp-td-accurate2.gappa \ gappa/exp-td/exp-td-accurate3.gappa gappa/exp-td/exp-td-accurate4.gappa \ gappa/exp-td/exp-td-proof.sh \ gappa/trigpi/cospi-accurate.gappa gappa/trigpi/cospi-quick.gappa \ gappa/trigpi/sinpi-accurate.gappa gappa/trigpi/sinpi-quick.gappa \ gappa/asin/asinAccuR0.gappa gappa/asin/asinAccuR1.gappa \ gappa/asin/asinAccuR2.gappa gappa/asin/asinAccuR3.gappa \ gappa/asin/asinAccuR4.gappa gappa/asin/asinAccuR5.gappa \ gappa/asin/asinAccuR6.gappa gappa/asin/asinAccuR7.gappa \ gappa/asin/asinAccuR8.gappa gappa/asin/asinAccuR9.gappa \ gappa/asin/asinQuickR0.gappa gappa/asin/asinQuickR1.gappa \ gappa/asin/asinQuickR2.gappa gappa/asin/asinQuickR3.gappa \ gappa/asin/asinQuickR4.gappa gappa/asin/asinQuickR5.gappa \ gappa/asin/asinQuickR6.gappa gappa/asin/asinQuickR7.gappa \ gappa/asin/asinQuickR8.gappa gappa/asin/asinQuickR9.gappa \ docs/latex/crlibm.tex \ docs/latex/0_intro.tex docs/latex/0_getting-started.tex\ docs/latex/1_common.tex docs/latex/sqrt.tex \ docs/latex/exp.tex docs/latex/expm1.tex \ docs/latex/log.tex docs/latex/log1p.tex docs/latex/log2.tex docs/latex/log10.tex\ docs/latex/asin.tex docs/latex/acos.tex docs/latex/atan.tex \ docs/latex/csh.tex docs/latex/trigo.tex docs/latex/trigpi.tex \ docs/latex/pow.tex \ docs/latex/fig_scs docs/latex/fig_exp\ docs/latex/elem-fun.bib\ docs/latex/tripledoubleprocedures.tex \ scs_lib/tests/tbx_timing.h \ tests/testperfs.sh\ triple-double.h double-extended.h \ log-de.c log-de.h log-td.c log-td.h interval-3.2.0/src/crlibm/NEWS0000644000000000000000000000000013316017127014213 0ustar 00000000000000interval-3.2.0/src/crlibm/README0000644000000000000000000000156213316017127014412 0ustar 00000000000000cr-libm, a portable, efficient, correctly rounded mathematical library. To compile: ./configure; make; (for options see ./configure --help) To run the selftest: make check; Beta release note: This version contains one state-of-the-art implementation. The log comes in two versions, log-td (portable) and log-de (optimised for processors with double-extended hardware). The ./configure should enable the one that is best for your system, except on Itanium: see below. There is no known bug, but several shortcomings are listed in the TODO file. Note for Itanium systems: Out-of-the box it should compile and selftest on Linux under both gcc and icc (feedback on HPUX is welcome). However, optimised versions of log and atan are disabled. They currently require icc 8.1 or later. See the beginning of log-de.c and atan-itanium.c for instructions on how to enable them. interval-3.2.0/src/crlibm/README.DEV0000644000000000000000000000100213316017127015014 0ustar 00000000000000 To compile crlibm after a cvs checkout, type ./prepare make or, if you want to perform accuracy tests against the MPFR library, ./prepare --enable-mpfr --with-gmp=/usr/local make (if necessary replace /usr/local/ with the actual location of the MPFR source) The prepare script requires to be invoked only once. After that, use: ./configure The prepare script ends with a call to ./configure, and the options to prepare are the options of configure. For a list of these options, type ./configure --help interval-3.2.0/src/crlibm/TODO0000644000000000000000000000372013316017127014220 0ustar 00000000000000TODO before 1.0 final release Serious bugs ------------ No known serious bug left so far. Exception raising should be improved. New functions ------------- Document the cases on which power is guaranteed correctly rounded values. Possibly write 2^x and 10^x (in harmonious combination with power) Proof stuff ----------- Update chapter asin and write chapter acos. Add the scripts generating the polynomials. Write Gappa proofs for log2-td, log10-td, expm1, log1p Check all the existing .gappa against last version of Gappa + set the paths right (where there are paths). Write proper proofs of the DE integer rounding tests, or remove DE altogether. Cleaning up stuff ----------------- Check .mpl with underscored variables (some versions of Maple don't like them) Purge obsolete .mpl Ensure compilation on icc9 and SunStudio11 Solution: check recent icc first. Then add FMADE macros everywhere FMA intended add make timings Autotest stuff -------------- Add worst cases for all which are currently written TODO A lot of the Lefevre worst cases are still missing You never have enough test cases. In particular asin and acos More cases around the various boundaries would be welcome. Optim stuff ----------- Remove remaining SCS: in atan, in trigo. Replace the current test for non-IEEE subnormal (on x86) in the code with a test taking into account that x86-64 is OK Minor improvements to atanpi as mentionned in the doc. Fuse atan-pentium and atan-itanium into atan-de, and add in atanpi. Or maybe remove all the DE stuff altogether for cleaning up. =========================================================================== TODO some day for a later release New functions ------------- Write inverse hyperbolic functions Optimisation stuff ------------------ Write TD versions of: trigo Write DE versions of: most functions Use technique in paper by Karp and Markstein for sqrt12 and sqrt13 Interval stuff -------------- Write interval functions for each CR functioninterval-3.2.0/src/crlibm/VERSION0000644000000000000000000000001013316017127014565 0ustar 000000000000001.0beta5interval-3.2.0/src/crlibm/acos-td.c0000644000000000000000000011570313316017127015233 0ustar 00000000000000/* * Correctly rounded arccosine * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Christoph Lauter (ENS Lyon) * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "acos-td.h" #define AVOID_FMA 1 void acos_accurate_lower(double *acosh, double *acosm, double *acosl, double x, double xSqh, double xSql, double sign) { double highPoly; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l; double tt1h, tt1l; double t8h, t8m, t8l, t9h, t9m, t9l, t10h, t10m, t10l, t11h, t11m, t11l, t12h, t12m, t12l; double tt8h, tt8m, tt8l, tt9h, tt9m, tt9l, tt10h, tt10m, tt10l, tt11h, tt11m, tt11l, tt12h, tt12m, tt12l; double xCubeh, xCubem, xCubel, tt13h, tt13m, tt13l, t13h, t13m, t13l, polyh, polym, polyl; double tt11hover, tt11mover, tt11lover; double zw1h, zw1m, zw1l, acoshover, acosmover, acoslover; #if EVAL_PERF crlibm_second_step_taken++; #endif /* Evaluate the polynomial of degree 37 Its coefficients start at tbl[0] p(x) = x + x * x^2 * (c3 + x^2 * (c5 + ... We receive x^2 as xSqh + xSql = x * x (exactly) in argument |x| <= 0.185 = 2^(-2.43) Compute monomials 27 to 37 in double precision monomials 13 to 25 in double-double and 1 to 11 in triple-double precision in a modified Horner form */ /* Double computations */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(tbl[33],xSqh,tbl[32]),xSqh,tbl[31]),xSqh,tbl[30]),xSqh,tbl[29]),xSqh,tbl[28]); #else highPoly = tbl[28] + xSqh * (tbl[29] + xSqh * (tbl[30] + xSqh * (tbl[31] + xSqh * (tbl[32] + xSqh * tbl[33])))); #endif /* Double-double computations */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[27],0,tt1h,tt1l); MulAdd22(&t2h,&t2l,tbl[25],tbl[26],xSqh,xSql,t1h,t1l); MulAdd22(&t3h,&t3l,tbl[23],tbl[24],xSqh,xSql,t2h,t2l); MulAdd22(&t4h,&t4l,tbl[21],tbl[22],xSqh,xSql,t3h,t3l); MulAdd22(&t5h,&t5l,tbl[19],tbl[20],xSqh,xSql,t4h,t4l); MulAdd22(&t6h,&t6l,tbl[17],tbl[18],xSqh,xSql,t5h,t5l); MulAdd22(&t7h,&t7l,tbl[15],tbl[16],xSqh,xSql,t6h,t6l); /* Triple-double computations */ Mul23(&tt8h,&tt8m,&tt8l,xSqh,xSql,t7h,t7l); /* 149 - 48/53 */ Add33(&t8h,&t8m,&t8l,tbl[12],tbl[13],tbl[14],tt8h,tt8m,tt8l); /* 145 - 43/53 */ Mul233(&tt9h,&tt9m,&tt9l,xSqh,xSql,t8h,t8m,t8l); /* 139 - 39/53 */ Add33(&t9h,&t9m,&t9l,tbl[9],tbl[10],tbl[11],tt9h,tt9m,tt9l); /* 136 - 34/53 */ Mul233(&tt10h,&tt10m,&tt10l,xSqh,xSql,t9h,t9m,t9l); /* 130 - 30/53 */ Add33(&t10h,&t10m,&t10l,tbl[6],tbl[7],tbl[8],tt10h,tt10m,tt10l); /* 127 - 25/53 */ Mul233(&tt11hover,&tt11mover,&tt11lover,xSqh,xSql,t10h,t10m,t10l); /* 121 - 21/53 */ Renormalize3(&tt11h,&tt11m,&tt11l,tt11hover,tt11mover,tt11lover); /* infty - 52/53 */ Add33(&t11h,&t11m,&t11l,tbl[3],tbl[4],tbl[5],tt11h,tt11m,tt11l); /* 149 - 47/53 */ Mul233(&tt12h,&tt12m,&tt12l,xSqh,xSql,t11h,t11m,t11l); /* 143 - 43/53 */ Add33(&t12h,&t12m,&t12l,tbl[0],tbl[1],tbl[2],tt12h,tt12m,tt12l); /* 140 - 38/53 */ Mul123(&xCubeh,&xCubem,&xCubel,x,xSqh,xSql); /* 154 - 47/53 */ Mul33(&tt13h,&tt13m,&tt13l,xCubeh,xCubem,xCubel,t12h,t12m,t12l); /* 136 - 34/53 */ Add133(&t13h,&t13m,&t13l,x,tt13h,tt13m,tt13l); /* 138 - 32/53 */ Renormalize3(&polyh,&polym,&polyl,t13h,t13m,t13l); /* infty - 52/53 */ /* Reconstruction: - Multiply by the inverted sign - Add Pi/2 in triple-double - Renormalize */ zw1h = -sign * polyh; zw1m = -sign * polym; zw1l = -sign * polyl; Add33(&acoshover,&acosmover,&acoslover,PIHALFH,PIHALFM,PIHALFL,zw1h,zw1m,zw1l); Renormalize3(acosh,acosm,acosl,acoshover,acosmover,acoslover); } void acos_accurate_middle(double *acosh, double *acosm, double *acosl, double z, int i, double sign) { double highPoly; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l, t8h, t8l, t9h, t9l; double t10h, t10m, t10l, t11h, t11m, t11l, t12h, t12m, t12l, t13h, t13m, t13l, t14h, t14m, t14l; double t15h, t15m, t15l, t16h, t16m, t16l; double tt1h, tt1l; double tt10h, tt10m, tt10l, tt11h, tt11m, tt11l, tt12h, tt12m, tt12l; double tt13h, tt13m, tt13l, tt14h, tt14m, tt14l, tt15h, tt15m, tt15l, tt16h, tt16m, tt16l; double polyh, polym, polyl, tt13hover, tt13mover, tt13lover; double zw1h, zw1m, zw1l, acoshover, acosmover, acoslover; #if EVAL_PERF crlibm_second_step_taken++; #endif /* Evaluate the polynomial of degree 35 Its coefficients start at tbl[i+1] Evaluate degrees 35 to 20 in double precision, degrees 20 to 7 in double-double precision and finally degrees 6 to 1 in triple-double. The constant coefficient is a double-double, the computations are nevertheless in triple-double */ /* Double computations */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[i+58] ,z,tbl[i+57]),z,tbl[i+56]),z,tbl[i+55]),z,tbl[i+54]),z, tbl[i+53]),z,tbl[i+52]),z,tbl[i+51]),z,tbl[i+50]),z,tbl[i+49]),z, tbl[i+48]),z,tbl[i+47]),z,tbl[i+46]),z,tbl[i+45]),z,tbl[i+44]),z, tbl[i+43]),z,tbl[i+42]),z,tbl[i+41]),z,tbl[i+40]),z,tbl[i+39]); #else highPoly = tbl[i+39] + z * (tbl[i+40] + z * (tbl[i+41] + z * (tbl[i+42] + z * ( tbl[i+43] + z * (tbl[i+44] + z * (tbl[i+45] + z * (tbl[i+46] + z * ( tbl[i+47] + z * (tbl[i+48] + z * (tbl[i+49] + z * (tbl[i+50] + z * ( tbl[i+51] + z * (tbl[i+52] + z * (tbl[i+53] + z * (tbl[i+54] + z * ( tbl[i+55] + z * (tbl[i+56] + z * (tbl[i+57] + z * tbl[i+58])))))))))))))))))); #endif /* Double-double computations */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+37],tbl[i+38],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+35],tbl[i+36],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+33],tbl[i+34],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+31],tbl[i+32],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+29],tbl[i+30],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+27],tbl[i+28],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[i+25],tbl[i+26],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[i+23],tbl[i+24],z,t7h,t7l); MulAdd212(&t9h,&t9l,tbl[i+21],tbl[i+22],z,t8h,t8l); /* Triple-double computations */ Mul123(&tt10h,&tt10m,&tt10l,z,t9h,t9l); /* 154 - 47/53 */ Add33(&t10h,&t10m,&t10l,tbl[i+18],tbl[i+19],tbl[i+20],tt10h,tt10m,tt10l); /* 144 - 42/53 */ Mul133(&tt11h,&tt11m,&tt11l,z,t10h,t10m,t10l); /* 142 - 38/53 */ Add33(&t11h,&t11m,&t11l,tbl[i+15],tbl[i+16],tbl[i+17],tt11h,tt11m,tt11l); /* 136 - 33/53 */ Mul133(&tt12h,&tt12m,&tt12l,z,t11h,t11m,t11l); /* 133 - 28/53 */ Add33(&t12h,&t12m,&t12l,tbl[i+12],tbl[i+13],tbl[i+14],tt12h,tt12m,tt12l); /* 125 - 23/53 */ Mul133(&tt13hover,&tt13mover,&tt13lover,z,t12h,t12m,t12l); /* 123 - 18/53 */ Renormalize3(&tt13h,&tt13m,&tt13l,tt13hover,tt13mover,tt13lover); /* infty - 52/53 */ Add33(&t13h,&t13m,&t13l,tbl[i+9],tbl[i+10],tbl[i+11],tt13h,tt13m,tt13l); /* 149 - 47/53 */ Mul133(&tt14h,&tt14m,&tt14l,z,t13h,t13m,t13l); /* 147 - 42/53 */ Add33(&t14h,&t14m,&t14l,tbl[i+6],tbl[i+7],tbl[i+8],tt14h,tt14m,tt14l); /* 139 - 37/53 */ Mul133(&tt15h,&tt15m,&tt15l,z,t14h,t14m,t14l); /* 137 - 32/53 */ Add33(&t15h,&t15m,&t15l,tbl[i+3],tbl[i+4],tbl[i+5],tt15h,tt15m,tt15l); /* 129 - 28/53 */ Mul133(&tt16h,&tt16m,&tt16l,z,t15h,t15m,t15l); /* 128 - 23/53 */ Add233(&t16h,&t16m,&t16l,tbl[i+1],tbl[i+2],tt16h,tt16m,tt16l); /* 126 - 19/53 */ Renormalize3(&polyh,&polym,&polyl,t16h,t16m,t16l); /* infty - 52/53 */ /* Reconstruction: - Multiply by the inverted sign - Add Pi/2 in triple-double - Renormalize */ zw1h = -sign * polyh; zw1m = -sign * polym; zw1l = -sign * polyl; Add33(&acoshover,&acosmover,&acoslover,PIHALFH,PIHALFM,PIHALFL,zw1h,zw1m,zw1l); Renormalize3(acosh,acosm,acosl,acoshover,acosmover,acoslover); } void acos_accurate_higher(double *acosh, double *acosm, double *acosl, double z, double sign) { double highPoly; double tt1h, tt1l; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l, t8h, t8l; double tt10h, tt10m, tt10l, tt11h, tt11m, tt11l, tt12h, tt12m, tt12l, tt13h, tt13m, tt13l; double tt14h, tt14m, tt14l, tt15h, tt15m, tt15l, tt16h, tt16m, tt16l, tt17h, tt17m, tt17l; double t9h, t9l, t10h, t10m, t10l, t11h, t11m, t11l, t12h, t12m, t12l, t13h, t13m, t13l; double t14h, t14m, t14l, t15h, t15m, t15l, t16h, t16m, t16l, t17h, t17m, t17l; double tt18h, tt18m, tt18l, polyh, polym, polyl; double sqrtzh, sqrtzm, sqrtzl, twoZ, pTimesSh, pTimesSm, pTimesSl; double allh, allm, alll; double tt13hover, tt13mover, tt13lover, tt16hover, tt16mover, tt16lover; double polyhover, polymover, polylover; #if EVAL_PERF crlibm_second_step_taken++; #endif /* We evaluate acos(x) with x > 0 as acos(x) = -1 * f(z) * sqrt(2*z) with z = 1 - x and f(z) = (asin(z) - Pi/2) / sqrt(2*z) f(z) is approximated by p(z) The polynomial p(z) is of degree 29 Its coefficients start at tbl[TBLIDX10] Coefficients for degrees 29 to 18 are in double precision, for degrees 17 to 9 in double-double precision and finally for degrees 8 to 1 in triple-double. The constant coefficient (-1) is not stored in the table, the computations are nevertheless in triple-double We evaluate the monomials in the precision in which the correspondant coefficients are stored The coefficients' values decrease very quickly so even with |z| < 2^-2.18 we can compute degree 18 already in double precision Compute than sqrt(2*z) as a triple-double multiply in triple-double. */ /* Double computations */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[TBLIDX10+53] ,z,tbl[TBLIDX10+52]),z,tbl[TBLIDX10+51]),z, tbl[TBLIDX10+50]),z,tbl[TBLIDX10+49]),z,tbl[TBLIDX10+48]),z, tbl[TBLIDX10+47]),z,tbl[TBLIDX10+46]),z,tbl[TBLIDX10+45]),z, tbl[TBLIDX10+44]),z,tbl[TBLIDX10+43]),z,tbl[TBLIDX10+42]); #else highPoly = tbl[TBLIDX10+42] + z * (tbl[TBLIDX10+43] + z * (tbl[TBLIDX10+44] + z * ( tbl[TBLIDX10+45] + z * (tbl[TBLIDX10+46] + z * (tbl[TBLIDX10+47] + z * ( tbl[TBLIDX10+48] + z * (tbl[TBLIDX10+49] + z * (tbl[TBLIDX10+50] + z * ( tbl[TBLIDX10+51] + z * (tbl[TBLIDX10+52] + z * tbl[TBLIDX10+53])))))))))); #endif /* Double-double computations */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+40],tbl[TBLIDX10+41],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+38],tbl[TBLIDX10+39],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+36],tbl[TBLIDX10+37],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+34],tbl[TBLIDX10+35],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+32],tbl[TBLIDX10+33],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+30],tbl[TBLIDX10+31],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+28],tbl[TBLIDX10+29],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+26],tbl[TBLIDX10+27],z,t7h,t7l); MulAdd212(&t9h,&t9l,tbl[TBLIDX10+24],tbl[TBLIDX10+25],z,t8h,t8l); /* Triple-double computations */ Mul123(&tt10h,&tt10m,&tt10l,z,t9h,t9l); /* 154 - 47/53 */ Add33(&t10h,&t10m,&t10l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tbl[TBLIDX10+23],tt10h,tt10m,tt10l); /* 144 - 42/53 */ Mul133(&tt11h,&tt11m,&tt11l,z,t10h,t10m,t10l); /* 142 - 37/53 */ Add33(&t11h,&t11m,&t11l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],tbl[TBLIDX10+20],tt11h,tt11m,tt11l); /* 134 - 32/53 */ Mul133(&tt12h,&tt12m,&tt12l,z,t11h,t11m,t11l); /* 132 - 27/53 */ Add33(&t12h,&t12m,&t12l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],tbl[TBLIDX10+17],tt12h,tt12m,tt12l); /* 124 - 22/53 */ Mul133(&tt13hover,&tt13mover,&tt13lover,z,t12h,t12m,t12l); /* 122 - 17/53 */ Renormalize3(&tt13h,&tt13m,&tt13l,tt13hover,tt13mover,tt13lover); /* infty - 52/53 */ Add33(&t13h,&t13m,&t13l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],tbl[TBLIDX10+14],tt13h,tt13m,tt13l); /* 149 - 47/53 */ Mul133(&tt14h,&tt14m,&tt14l,z,t13h,t13m,t13l); /* 147 - 42/53 */ Add33(&t14h,&t14m,&t14l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],tbl[TBLIDX10+11],tt14h,tt14m,tt14l); /* 139 - 37/53 */ Mul133(&tt15h,&tt15m,&tt15l,z,t14h,t14m,t14l); /* 137 - 32/53 */ Add33(&t15h,&t15m,&t15l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],tbl[TBLIDX10+8],tt15h,tt15m,tt15l); /* 129 - 27/53 */ Mul133(&tt16hover,&tt16mover,&tt16lover,z,t15h,t15m,t15l); /* 127 - 22/53 */ Renormalize3(&tt16h,&tt16m,&tt16l,tt16hover,tt16mover,tt16lover); /* infty - 52/53 */ Add33(&t16h,&t16m,&t16l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],tbl[TBLIDX10+5],tt16h,tt16m,tt16l); /* 149 - 47/53 */ Mul133(&tt17h,&tt17m,&tt17l,z,t16h,t16m,t16l); /* 147 - 42/53 */ Add33(&t17h,&t17m,&t17l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],tbl[TBLIDX10+2],tt17h,tt17m,tt17l); /* 139 - 37/53 */ Mul133(&tt18h,&tt18m,&tt18l,z,t17h,t17m,t17l); /* 137 - 32/53 */ Add133(&polyhover,&polymover,&polylover,-1,tt18h,tt18m,tt18l); /* 136 - 30/53 */ Renormalize3(&polyh,&polym,&polyl,polyhover,polymover,polylover); /* infty - 52/53 */ /* Compute sqrt(2*z) as a triple-double */ twoZ = 2 * z; Sqrt13(&sqrtzh,&sqrtzm,&sqrtzl,twoZ); /* 146 - 52/53 */ /* Multiply p(z) by sqrt(2*z) */ Mul33(&pTimesSh,&pTimesSm,&pTimesSl,polyh,polym,polyl,sqrtzh,sqrtzm,sqrtzl); /* 139 - 48/53 */ /* Reconstruction: If the sign of x in acos(x) was positive: - Multiply pTimesSh + pTimesSm + pTimesSl approx f(x) * sqrt(2 * z) by -1 - Renormalize - Return Otherwise: - Add Pi in triple-double to pTimesSh + pTimesSm + pTimesSl approx f(x) * sqrt(2 * z) - Renormalize - Return */ if (sign > 0) { allh = -1.0 * pTimesSh; allm = -1.0 * pTimesSm; alll = -1.0 * pTimesSl; /* 139 - 48/53 */ } else { Add33(&allh,&allm,&alll,PIH,PIM,PIL,pTimesSh,pTimesSm,pTimesSl); /* 130 - 43/53 */ } Renormalize3(acosh,acosm,acosl,allh,allm,alll); /* infty - 52/53 */ } double acos_rn(double x) { db_number xdb; double sign, z, acosh, acosm, acosl; int i; double xSqh, xSql; double tt1h, tt1l; double tt6h, tt6l; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l; double t7h, t7l, t8h, t8l, polyh, polyl, twoZ, sqrtzh, sqrtzl; double pTimesSh, pTimesSl, highPoly, xCubeh, xCubel; double tmp1, tmp2, tmp3, tmp4, tmp5; double zw1h, zw1l; /* #if CRLIBM_REQUIRES_ROUNDING_MODE_CHANGE SAVE_STATE_AND_SET_RNDOUBLE #endif */ /* Transform the argument into integer */ xdb.d = x; /* Special case handling */ /* Exact algebraic case x = 1, acos(1) = 0 */ if (x == 1.0) return 0.0; /* Strip off the sign of argument x */ if (xdb.i[HI] & 0x80000000) sign = -1; else sign = 1; xdb.i[HI] &= 0x7fffffff; /* acos is defined on -1 <= x <= 1, elsewhere it is NaN */ if ((xdb.i[HI] > 0x3ff00000) || ((xdb.i[HI] == 0x3ff00000) && (xdb.i[LO] != 0x00000000))) { return (x-x)/0.0; /* return NaN */ } /* If |x| < 2^(-120) we have round(acos(x)) = round(pi/2) So we can decide the rounding without any computation */ if (xdb.i[HI] < 0x38700000) { return PIHALFDOUBLERN; } /* Recast x */ x = xdb.d; /* Find correspondant interval and compute index to the table We start by filtering the two special cases around 0 and 1 */ if (xdb.i[HI] < BOUND1) { /* Special interval 0..BOUND1 The polynomial has no even monomials We must prove extra accuracy in the interval 0..sin(2^(-18)) */ /* Quick phase starts */ /* Compute square of x for both quick and accurate phases */ Mul12(&xSqh,&xSql,x,x); tmp4 = tbl[3]; tmp5 = tbl[4]; t4h = tmp4; t4l = tmp5; if (xdb.i[HI] > EXTRABOUND) { /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(tbl[23],xSqh,tbl[21]),xSqh,tbl[19]),xSqh,tbl[17]),xSqh,tbl[15]); #else highPoly = tbl[15] + xSqh * (tbl[17] + xSqh * (tbl[19] + xSqh * (tbl[21] + xSqh * tbl[23]))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[12],tbl[13],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[9],tbl[10],xSqh,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[6],tbl[7],xSqh,t2h,t2l); MulAdd22(&t4h,&t4l,tmp4,tmp5,xSqh,xSql,t3h,t3l); } MulAdd22(&t5h,&t5l,tbl[0],tbl[1],xSqh,xSql,t4h,t4l); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt6h,&tt6l,xCubeh,xCubel,t5h,t5l); Add12(tmp1,tmp2,x,tt6h); tmp3 = tmp2 + tt6l; Add12(polyh,polyl,tmp1,tmp3); /* Reconstruction: - Multiply by the inverted sign - Add Pi/2 in double-double precision */ zw1h = -sign * polyh; zw1l = -sign * polyl; Add22(&acosh,&acosm,PIHALFH,PIHALFM,zw1h,zw1l); /* Rounding test The RN rounding constant is at tbl[34] */ if(acosh == (acosh + (acosm * tbl[34]))) return acosh; /* Launch accurate phase */ acos_accurate_lower(&acosh,&acosm,&acosl,x,xSqh,xSql,sign); ReturnRoundToNearest3(acosh,acosm,acosl); } if (xdb.i[HI] >= BOUND9) { /* Special interval BOUND9..1 We use an asymptotic development of arcsin in sqrt(1 - x) */ /* Argument reduction for quick and accurate phase z = 1 - x The operation is exact as per Sterbenz' lemma */ z = 1 - x; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[TBLIDX10+42] ,z,tbl[TBLIDX10+40]),z,tbl[TBLIDX10+38]),z, tbl[TBLIDX10+36]),z,tbl[TBLIDX10+34]),z,tbl[TBLIDX10+32]),z, tbl[TBLIDX10+30]),z,tbl[TBLIDX10+28]),z,tbl[TBLIDX10+26]),z, tbl[TBLIDX10+24]); #else highPoly = tbl[TBLIDX10+24] + z * (tbl[TBLIDX10+26] + z * (tbl[TBLIDX10+28] + z * ( tbl[TBLIDX10+30] + z * (tbl[TBLIDX10+32] + z * (tbl[TBLIDX10+34] + z * ( tbl[TBLIDX10+36] + z * (tbl[TBLIDX10+38] + z * (tbl[TBLIDX10+40] + z * tbl[TBLIDX10+42])))))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],z,t7h,t7l); MulAdd212(&polyh,&polyl,-1,0,z,t8h,t8l); /* Compute sqrt(2*z) as a double-double */ twoZ = 2 * z; sqrt12(&sqrtzh,&sqrtzl,twoZ); /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul22(&pTimesSh,&pTimesSl,polyh,polyl,sqrtzh,sqrtzl); /* Reconstruction: If the sign of x in acos(x) was positive: - Multiply pTimesSh + pTimesSl approx f(x) * sqrt(2 * z) by -1 - Return Otherwise: - Add Pi in triple-double to pTimesSh + pTimesSl approx f(x) * sqrt(2 * z) - Return */ if (sign > 0) { acosh = -1.0 * pTimesSh; acosm = -1.0 * pTimesSl; } else { Add22(&acosh,&acosm,PIH,PIM,pTimesSh,pTimesSl); } /* Rounding test The RN rounding constant is at tbl[TBLIDX10+54] */ if(acosh == (acosh + (acosm * tbl[TBLIDX10+54]))) return acosh; /* Launch accurate phase */ acos_accurate_higher(&acosh,&acosm,&acosl,z,sign); ReturnRoundToNearest3(acosh,acosm,acosl); } /* General 8 main intervals We can already suppose that BOUND1 <= x <= BOUND9 */ if (xdb.i[HI] < BOUND5) { if (xdb.i[HI] < BOUND3) { if (xdb.i[HI] < BOUND2) i = TBLIDX2; else i = TBLIDX3; } else { if (xdb.i[HI] < BOUND4) i = TBLIDX4; else i = TBLIDX5; } } else { if (xdb.i[HI] < BOUND7) { if (xdb.i[HI] < BOUND6) i = TBLIDX6; else i = TBLIDX7; } else { if (xdb.i[HI] < BOUND8) i = TBLIDX8; else i = TBLIDX9; } } /* Argument reduction i points to the interval midpoint value in the table */ z = x - tbl[i]; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[i+35] ,z,tbl[i+33]),z,tbl[i+31]),z,tbl[i+29]),z, tbl[i+27]),z,tbl[i+25]),z,tbl[i+23]),z,tbl[i+21]); #else highPoly = tbl[i+21] + z * (tbl[i+23] + z * (tbl[i+25] + z * ( tbl[i+27] + z * (tbl[i+29] + z * (tbl[i+31] + z * ( tbl[i+33] + z * tbl[i+35])))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+18],tbl[i+19],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+15],tbl[i+16],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+12],tbl[i+13],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+9],tbl[i+10],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+6],tbl[i+7],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+3],tbl[i+4],z,t5h,t5l); MulAdd212(&polyh,&polyl,tbl[i+1],tbl[i+2],z,t6h,t6l); /* Reconstruction: - Multiply by the inverted sign - Add Pi/2 in double-double precision */ zw1h = -sign * polyh; zw1l = -sign * polyl; Add22(&acosh,&acosm,PIHALFH,PIHALFM,zw1h,zw1l); /* Rounding test The RN rounding constant is at tbl[i+59] */ if(acosh == (acosh + (acosm * tbl[i+59]))) return acosh; /* Launch accurate phase */ acos_accurate_middle(&acosh,&acosm,&acosl,z,i,sign); ReturnRoundToNearest3(acosh,acosm,acosl); } double acos_ru(double x) { db_number xdb; double sign, z, acosh, acosm, acosl; int i; double xSqh, xSql; double tt1h, tt1l; double tt6h, tt6l; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l; double t7h, t7l, t8h, t8l, polyh, polyl, twoZ, sqrtzh, sqrtzl; double pTimesSh, pTimesSl, highPoly, xCubeh, xCubel; double tmp1, tmp2, tmp3, tmp4, tmp5; double zw1h, zw1l; /* Transform the argument into integer */ xdb.d = x; /* Special case handling */ /* Exact algebraic case x = 1, acos(1) = 0 */ if (x == 1.0) return 0.0; /* Strip off the sign of argument x */ if (xdb.i[HI] & 0x80000000) sign = -1; else sign = 1; xdb.i[HI] &= 0x7fffffff; /* acos is defined on -1 <= x <= 1, elsewhere it is NaN */ if ((xdb.i[HI] > 0x3ff00000) || ((xdb.i[HI] == 0x3ff00000) && (xdb.i[LO] != 0x00000000))) { return (x-x)/0.0; /* return NaN */ } /* If |x| < 2^(-120) we have round(acos(x)) = round(pi/2) So we can decide the rounding without any computation */ if (xdb.i[HI] < 0x38700000) { return PIHALFDOUBLERU; } /* Recast x */ x = xdb.d; /* Find correspondant interval and compute index to the table We start by filtering the two special cases around 0 and 1 */ if (xdb.i[HI] < BOUND1) { /* Special interval 0..BOUND1 The polynomial has no even monomials We must prove extra accuracy in the interval 0..sin(2^(-18)) */ /* Quick phase starts */ /* Compute square of x for both quick and accurate phases */ Mul12(&xSqh,&xSql,x,x); tmp4 = tbl[3]; tmp5 = tbl[4]; t4h = tmp4; t4l = tmp5; if (xdb.i[HI] > EXTRABOUND) { /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(tbl[23],xSqh,tbl[21]),xSqh,tbl[19]),xSqh,tbl[17]),xSqh,tbl[15]); #else highPoly = tbl[15] + xSqh * (tbl[17] + xSqh * (tbl[19] + xSqh * (tbl[21] + xSqh * tbl[23]))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[12],tbl[13],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[9],tbl[10],xSqh,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[6],tbl[7],xSqh,t2h,t2l); MulAdd22(&t4h,&t4l,tmp4,tmp5,xSqh,xSql,t3h,t3l); } MulAdd22(&t5h,&t5l,tbl[0],tbl[1],xSqh,xSql,t4h,t4l); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt6h,&tt6l,xCubeh,xCubel,t5h,t5l); Add12(tmp1,tmp2,x,tt6h); tmp3 = tmp2 + tt6l; Add12(polyh,polyl,tmp1,tmp3); /* Reconstruction: - Multiply by the inverted sign - Add Pi/2 in double-double precision */ zw1h = -sign * polyh; zw1l = -sign * polyl; Add22(&acosh,&acosm,PIHALFH,PIHALFM,zw1h,zw1l); /* Rounding test The RU rounding constant is at tbl[35] */ TEST_AND_RETURN_RU(acosh, acosm, tbl[35]); /* Launch accurate phase */ acos_accurate_lower(&acosh,&acosm,&acosl,x,xSqh,xSql,sign); ReturnRoundUpwards3(acosh,acosm,acosl); } if (xdb.i[HI] >= BOUND9) { /* Special interval BOUND9..1 We use an asymptotic development of arcsin in sqrt(1 - x) */ /* Argument reduction for quick and accurate phase z = 1 - x The operation is exact as per Sterbenz' lemma */ z = 1 - x; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[TBLIDX10+42] ,z,tbl[TBLIDX10+40]),z,tbl[TBLIDX10+38]),z, tbl[TBLIDX10+36]),z,tbl[TBLIDX10+34]),z,tbl[TBLIDX10+32]),z, tbl[TBLIDX10+30]),z,tbl[TBLIDX10+28]),z,tbl[TBLIDX10+26]),z, tbl[TBLIDX10+24]); #else highPoly = tbl[TBLIDX10+24] + z * (tbl[TBLIDX10+26] + z * (tbl[TBLIDX10+28] + z * ( tbl[TBLIDX10+30] + z * (tbl[TBLIDX10+32] + z * (tbl[TBLIDX10+34] + z * ( tbl[TBLIDX10+36] + z * (tbl[TBLIDX10+38] + z * (tbl[TBLIDX10+40] + z * tbl[TBLIDX10+42])))))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],z,t7h,t7l); MulAdd212(&polyh,&polyl,-1,0,z,t8h,t8l); /* Compute sqrt(2*z) as a double-double */ twoZ = 2 * z; sqrt12(&sqrtzh,&sqrtzl,twoZ); /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul22(&pTimesSh,&pTimesSl,polyh,polyl,sqrtzh,sqrtzl); /* Reconstruction: If the sign of x in acos(x) was positive: - Multiply pTimesSh + pTimesSl approx f(x) * sqrt(2 * z) by -1 - Return Otherwise: - Add Pi in triple-double to pTimesSh + pTimesSl approx f(x) * sqrt(2 * z) - Return */ if (sign > 0) { acosh = -1.0 * pTimesSh; acosm = -1.0 * pTimesSl; } else { Add22(&acosh,&acosm,PIH,PIM,pTimesSh,pTimesSl); } /* Rounding test The RU rounding constant is at tbl[TBLIDX10+55] */ TEST_AND_RETURN_RU(acosh, acosm, tbl[TBLIDX10+55]); /* Launch accurate phase */ acos_accurate_higher(&acosh,&acosm,&acosl,z,sign); ReturnRoundUpwards3(acosh,acosm,acosl); } /* General 8 main intervals We can already suppose that BOUND1 <= x <= BOUND9 */ if (xdb.i[HI] < BOUND5) { if (xdb.i[HI] < BOUND3) { if (xdb.i[HI] < BOUND2) i = TBLIDX2; else i = TBLIDX3; } else { if (xdb.i[HI] < BOUND4) i = TBLIDX4; else i = TBLIDX5; } } else { if (xdb.i[HI] < BOUND7) { if (xdb.i[HI] < BOUND6) i = TBLIDX6; else i = TBLIDX7; } else { if (xdb.i[HI] < BOUND8) i = TBLIDX8; else i = TBLIDX9; } } /* Argument reduction i points to the interval midpoint value in the table */ z = x - tbl[i]; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[i+35] ,z,tbl[i+33]),z,tbl[i+31]),z,tbl[i+29]),z, tbl[i+27]),z,tbl[i+25]),z,tbl[i+23]),z,tbl[i+21]); #else highPoly = tbl[i+21] + z * (tbl[i+23] + z * (tbl[i+25] + z * ( tbl[i+27] + z * (tbl[i+29] + z * (tbl[i+31] + z * ( tbl[i+33] + z * tbl[i+35])))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+18],tbl[i+19],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+15],tbl[i+16],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+12],tbl[i+13],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+9],tbl[i+10],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+6],tbl[i+7],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+3],tbl[i+4],z,t5h,t5l); MulAdd212(&polyh,&polyl,tbl[i+1],tbl[i+2],z,t6h,t6l); /* Reconstruction: - Multiply by the inverted sign - Add Pi/2 in double-double precision */ zw1h = -sign * polyh; zw1l = -sign * polyl; Add22(&acosh,&acosm,PIHALFH,PIHALFM,zw1h,zw1l); /* Rounding test The RU rounding constant is at tbl[i+60] */ TEST_AND_RETURN_RU(acosh, acosm, tbl[i+60]); /* Launch accurate phase */ acos_accurate_middle(&acosh,&acosm,&acosl,z,i,sign); ReturnRoundUpwards3(acosh,acosm,acosl); } double acos_rd(double x) { db_number xdb; double sign, z, acosh, acosm, acosl; int i; double xSqh, xSql; double tt1h, tt1l; double tt6h, tt6l; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l; double t7h, t7l, t8h, t8l, polyh, polyl, twoZ, sqrtzh, sqrtzl; double pTimesSh, pTimesSl, highPoly, xCubeh, xCubel; double tmp1, tmp2, tmp3, tmp4, tmp5; double zw1h, zw1l; /* Transform the argument into integer */ xdb.d = x; /* Special case handling */ /* Exact algebraic case x = 1, acos(1) = 0 */ if (x == 1.0) return 0.0; /* Strip off the sign of argument x */ if (xdb.i[HI] & 0x80000000) sign = -1; else sign = 1; xdb.i[HI] &= 0x7fffffff; /* acos is defined on -1 <= x <= 1, elsewhere it is NaN */ if ((xdb.i[HI] > 0x3ff00000) || ((xdb.i[HI] == 0x3ff00000) && (xdb.i[LO] != 0x00000000))) { return (x-x)/0.0; /* return NaN */ } /* If |x| < 2^(-120) we have round(acos(x)) = round(pi/2) So we can decide the rounding without any computation */ if (xdb.i[HI] < 0x38700000) { return PIHALFDOUBLERD; } /* Recast x */ x = xdb.d; /* Find correspondant interval and compute index to the table We start by filtering the two special cases around 0 and 1 */ if (xdb.i[HI] < BOUND1) { /* Special interval 0..BOUND1 The polynomial has no even monomials We must prove extra accuracy in the interval 0..sin(2^(-18)) */ /* Quick phase starts */ /* Compute square of x for both quick and accurate phases */ Mul12(&xSqh,&xSql,x,x); tmp4 = tbl[3]; tmp5 = tbl[4]; t4h = tmp4; t4l = tmp5; if (xdb.i[HI] > EXTRABOUND) { /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(tbl[23],xSqh,tbl[21]),xSqh,tbl[19]),xSqh,tbl[17]),xSqh,tbl[15]); #else highPoly = tbl[15] + xSqh * (tbl[17] + xSqh * (tbl[19] + xSqh * (tbl[21] + xSqh * tbl[23]))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[12],tbl[13],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[9],tbl[10],xSqh,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[6],tbl[7],xSqh,t2h,t2l); MulAdd22(&t4h,&t4l,tmp4,tmp5,xSqh,xSql,t3h,t3l); } MulAdd22(&t5h,&t5l,tbl[0],tbl[1],xSqh,xSql,t4h,t4l); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt6h,&tt6l,xCubeh,xCubel,t5h,t5l); Add12(tmp1,tmp2,x,tt6h); tmp3 = tmp2 + tt6l; Add12(polyh,polyl,tmp1,tmp3); /* Reconstruction: - Multiply by the inverted sign - Add Pi/2 in double-double precision */ zw1h = -sign * polyh; zw1l = -sign * polyl; Add22(&acosh,&acosm,PIHALFH,PIHALFM,zw1h,zw1l); /* Rounding test The RD rounding constant is at tbl[35] */ TEST_AND_RETURN_RD(acosh, acosm, tbl[35]); /* Launch accurate phase */ acos_accurate_lower(&acosh,&acosm,&acosl,x,xSqh,xSql,sign); ReturnRoundDownwards3(acosh,acosm,acosl); } if (xdb.i[HI] >= BOUND9) { /* Special interval BOUND9..1 We use an asymptotic development of arcsin in sqrt(1 - x) */ /* Argument reduction for quick and accurate phase z = 1 - x The operation is exact as per Sterbenz' lemma */ z = 1 - x; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[TBLIDX10+42] ,z,tbl[TBLIDX10+40]),z,tbl[TBLIDX10+38]),z, tbl[TBLIDX10+36]),z,tbl[TBLIDX10+34]),z,tbl[TBLIDX10+32]),z, tbl[TBLIDX10+30]),z,tbl[TBLIDX10+28]),z,tbl[TBLIDX10+26]),z, tbl[TBLIDX10+24]); #else highPoly = tbl[TBLIDX10+24] + z * (tbl[TBLIDX10+26] + z * (tbl[TBLIDX10+28] + z * ( tbl[TBLIDX10+30] + z * (tbl[TBLIDX10+32] + z * (tbl[TBLIDX10+34] + z * ( tbl[TBLIDX10+36] + z * (tbl[TBLIDX10+38] + z * (tbl[TBLIDX10+40] + z * tbl[TBLIDX10+42])))))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],z,t7h,t7l); MulAdd212(&polyh,&polyl,-1,0,z,t8h,t8l); /* Compute sqrt(2*z) as a double-double */ twoZ = 2 * z; sqrt12(&sqrtzh,&sqrtzl,twoZ); /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul22(&pTimesSh,&pTimesSl,polyh,polyl,sqrtzh,sqrtzl); /* Reconstruction: If the sign of x in acos(x) was positive: - Multiply pTimesSh + pTimesSl approx f(x) * sqrt(2 * z) by -1 - Return Otherwise: - Add Pi in triple-double to pTimesSh + pTimesSl approx f(x) * sqrt(2 * z) - Return */ if (sign > 0) { acosh = -1.0 * pTimesSh; acosm = -1.0 * pTimesSl; } else { Add22(&acosh,&acosm,PIH,PIM,pTimesSh,pTimesSl); } /* Rounding test The RD rounding constant is at tbl[TBLIDX10+55] */ TEST_AND_RETURN_RD(acosh, acosm, tbl[TBLIDX10+55]); /* Launch accurate phase */ acos_accurate_higher(&acosh,&acosm,&acosl,z,sign); ReturnRoundDownwards3(acosh,acosm,acosl); } /* General 8 main intervals We can already suppose that BOUND1 <= x <= BOUND9 */ if (xdb.i[HI] < BOUND5) { if (xdb.i[HI] < BOUND3) { if (xdb.i[HI] < BOUND2) i = TBLIDX2; else i = TBLIDX3; } else { if (xdb.i[HI] < BOUND4) i = TBLIDX4; else i = TBLIDX5; } } else { if (xdb.i[HI] < BOUND7) { if (xdb.i[HI] < BOUND6) i = TBLIDX6; else i = TBLIDX7; } else { if (xdb.i[HI] < BOUND8) i = TBLIDX8; else i = TBLIDX9; } } /* Argument reduction i points to the interval midpoint value in the table */ z = x - tbl[i]; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[i+35] ,z,tbl[i+33]),z,tbl[i+31]),z,tbl[i+29]),z, tbl[i+27]),z,tbl[i+25]),z,tbl[i+23]),z,tbl[i+21]); #else highPoly = tbl[i+21] + z * (tbl[i+23] + z * (tbl[i+25] + z * ( tbl[i+27] + z * (tbl[i+29] + z * (tbl[i+31] + z * ( tbl[i+33] + z * tbl[i+35])))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+18],tbl[i+19],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+15],tbl[i+16],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+12],tbl[i+13],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+9],tbl[i+10],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+6],tbl[i+7],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+3],tbl[i+4],z,t5h,t5l); MulAdd212(&polyh,&polyl,tbl[i+1],tbl[i+2],z,t6h,t6l); /* Reconstruction: - Multiply by the inverted sign - Add Pi/2 in double-double precision */ zw1h = -sign * polyh; zw1l = -sign * polyl; Add22(&acosh,&acosm,PIHALFH,PIHALFM,zw1h,zw1l); /* Rounding test The RD rounding constant is at tbl[i+60] */ TEST_AND_RETURN_RD(acosh, acosm, tbl[i+60]); /* Launch accurate phase */ acos_accurate_middle(&acosh,&acosm,&acosl,z,i,sign); ReturnRoundDownwards3(acosh,acosm,acosl); } interval-3.2.0/src/crlibm/acos-td.h0000644000000000000000000015677613316017127015257 0ustar 00000000000000/* * Correctly rounded arccosine * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" /* File generated by maple/acos-td.mpl */ /* High order words of interval bounds (low order word is 0) */ #define BOUND1 0x3FC7AE14 #define BOUND2 0x3FD32E91 #define BOUND3 0x3FD9CA24 #define BOUND4 0x3FDF90B3 #define BOUND5 0x3FE23ADC #define BOUND6 0x3FE4781D #define BOUND7 0x3FE647BB #define BOUND8 0x3FE7BC81 #define BOUND9 0x3FE8F5C2 #define EXTRABOUND 0x3F500000 /* Pi/2 as a triple-double*/ #define PIHALFH 1.57079632679489655799898173427209258079528808593750e+00 #define PIHALFM 6.12323399573676603586882014729198302312846062338790e-17 #define PIHALFL -1.49738490485916983294350817710599200835275047616952e-33 /* Pi as a triple-double*/ #define PIH 3.14159265358979311599796346854418516159057617187500e+00 #define PIM 1.22464679914735320717376402945839660462569212467758e-16 #define PIL -2.99476980971833966588701635421198401670550095233904e-33 #define PIHALFDOUBLERN 1.57079632679489655799898173427209258079528808593750e+00 #define PIHALFDOUBLERU 1.57079632679489678004358665930340066552162170410156e+00 #define PIHALFDOUBLERD 1.57079632679489655799898173427209258079528808593750e+00 /* Indices to the following table */ #define TBLIDX2 36 #define TBLIDX3 97 #define TBLIDX4 158 #define TBLIDX5 219 #define TBLIDX6 280 #define TBLIDX7 341 #define TBLIDX8 402 #define TBLIDX9 463 #define TBLIDX10 524 /* Table with midpoints and polynomial coefficients */ static const double tbl[580] = { 1.66666666666666657414808128123695496469736099243164e-01, /* 0, accPolyLowC3h, quickPolyLowC3h */ 9.25185853854297065661561206416060845590588197735272e-18, /* 1, accPolyLowC3m, quickPolyLowC3l */ 5.13580782192052290146917464639635163327575367072527e-34, /* 2, accPolyLowC3l */ 7.49999999999999972244424384371086489409208297729492e-02, /* 3, accPolyLowC5h, quickPolyLowC5h */ 2.77555756156289150513347472120591902572823540679419e-18, /* 4, accPolyLowC5m, quickPolyLowC5l */ -1.43929408167863119589461549455410834291155585333144e-34, /* 5, accPolyLowC5l */ 4.46428571428571438484134148438897682353854179382324e-02, /* 6, accPolyLowC7h, quickPolyLowC7h */ -9.91270557701064540788749549275225920938048550224136e-19, /* 7, accPolyLowC7m, quickPolyLowC7l */ 3.33748090721822991762574824757600091731436462508019e-35, /* 8, accPolyLowC7l */ 3.03819444444444440589503386718206456862390041351318e-02, /* 9, accPolyLowC9h, quickPolyLowC9h */ 3.85494105812324030564107341625454073114449944250081e-19, /* 10, accPolyLowC9m, quickPolyLowC9l */ -1.43865090242821346711405668429425189868490718470116e-36, /* 11, accPolyLowC9l */ 2.23721590909090918553037141691675060428678989410400e-02, /* 12, accPolyLowC11h, quickPolyLowC11h */ -9.46212831143868745925658651601400487408631908148174e-19, /* 13, accPolyLowC11m, quickPolyLowC11l */ 2.71756033709005426155900473576766627205226477546134e-36, /* 14, accPolyLowC11l */ 1.73527644230769238775646812200648128055036067962646e-02, /* 15, accPolyLowC13h, quickPolyLowC13h */ -8.00631194349979385750725428497500824341216859291999e-19, /* 16, accPolyLowC13m */ 1.39648437500000006938893903907228377647697925567627e-02, /* 17, accPolyLowC15h, quickPolyLowC15h */ -6.96640576418186252434826298980545123112053091491650e-19, /* 18, accPolyLowC15m */ 1.15518008961397068007359578700743441004306077957153e-02, /* 19, accPolyLowC17h, quickPolyLowC17h */ -4.10583074045422929898575008733550170923265860856307e-19, /* 20, accPolyLowC17m */ 9.76160952919401074534544449079476180486381053924561e-03, /* 21, accPolyLowC19h, quickPolyLowC19h */ 3.58257464358998522024321439568214748872569190564464e-19, /* 22, accPolyLowC19m */ 8.39033580962353364718353532225592061877250671386719e-03, /* 23, accPolyLowC21h, quickPolyLowC21h */ 7.09494992486164270601178799400238696830257336508353e-20, /* 24, accPolyLowC21m */ 7.31252587309846099200560942676929698791354894638062e-03, /* 25, accPolyLowC23h */ 3.10147942381298802750887889395221073583507364742961e-19, /* 26, accPolyLowC23m */ 6.44721034012319445943850482194648066069930791854858e-03, /* 27, accPolyLowC25h */ 5.74003646399263555560876781669321644585579633712769e-03, /* 28, accPolyLowC27h */ 5.15334845775329911110596015078044729307293891906738e-03, /* 29, accPolyLowC29h */ 4.65922376559379288613049752143524528946727514266968e-03, /* 30, accPolyLowC31h */ 4.25648267385331235956869022629689425230026245117188e-03, /* 31, accPolyLowC33h */ 3.70384206863821549560178425508638611063361167907715e-03, /* 32, accPolyLowC35h */ 4.76149788232017000255691385746104060672223567962646e-03, /* 33, accPolyLowC37h */ 1.01858540186370637827710736169938902993812548606460e+00, /* 34, RN rounding constant quick poly low*/ 9.99456520626465193846360776661410034560333454445527e-19, /* 35, RD rounding constant quick poly low*/ 2.42358565330489938993707710324088111519813537597656e-01, /* 36, midpoint in interval 2*/ 2.44796158322043572175275016888917889446020126342773e-01, /* 37, accPolyMid2C0h, quickPolyMid2C0h */ -7.80764437719474476036120943295127199090063761923808e-18, /* 38, accPolyMid2C0m, quickPolyMid2C0l */ 1.03072939530366736171629327145637944340705871582031e+00, /* 39, accPolyMid2C1h, quickPolyMid2C1h */ -8.85738929015520959086405013050480695702241994387953e-17, /* 40, accPolyMid2C1m, quickPolyMid2C1l */ -3.43332793693232296155057781643135490790330671255580e-33, /* 41, accPolyMid2C1l */ 1.32697384480218755209435244069027248769998550415039e-01, /* 42, accPolyMid2C2h, quickPolyMid2C2h */ -3.05519908299053827321743308736081906443885446585898e-18, /* 43, accPolyMid2C2m, quickPolyMid2C2l */ 1.84968471282800310046349200266639560111473343387153e-34, /* 44, accPolyMid2C2l */ 2.16675601140875473404889817174989730119705200195312e-01, /* 45, accPolyMid2C3h, quickPolyMid2C3h */ -1.09855192148394476119822843562855651270724326884774e-18, /* 46, accPolyMid2C3m, quickPolyMid2C3l */ 1.30965185306611444030805369954695892224998714815939e-35, /* 47, accPolyMid2C3l */ 1.16730419643667523987851097899692831560969352722168e-01, /* 48, accPolyMid2C4h, quickPolyMid2C4h */ 4.87619704882669077472238320833491156897798846867617e-18, /* 49, accPolyMid2C4m, quickPolyMid2C4l */ 2.44421677078199513698242322477237313066476585423275e-34, /* 50, accPolyMid2C4l */ 1.45667026718228842518954024853883311152458190917969e-01, /* 51, accPolyMid2C5h, quickPolyMid2C5h */ 5.36594969153474426628449995112694156468179831261122e-19, /* 52, accPolyMid2C5m, quickPolyMid2C5l */ 8.48516201835513020738766305454795330663195678132569e-36, /* 53, accPolyMid2C5l */ 1.22401266966440255834491779296513414010405540466309e-01, /* 54, accPolyMid2C6h, quickPolyMid2C6h */ -2.20822551943355103564859204431825679093840107651564e-19, /* 55, accPolyMid2C6m, quickPolyMid2C6l */ -8.07441439403117291580512089023909180599052269668925e-36, /* 56, accPolyMid2C6l */ 1.41642750696223979067767118067422416061162948608398e-01, /* 57, accPolyMid2C7h, quickPolyMid2C7h */ 8.52401858052517523392878261510621535534995050169401e-18, /* 58, accPolyMid2C7m, quickPolyMid2C7l */ 1.42861418735328621343327881731966044753789901733398e-01, /* 59, accPolyMid2C8h, quickPolyMid2C8h */ -1.33006668328318919665132697553096363383321713310227e-17, /* 60, accPolyMid2C8m */ 1.63718343060216098283632391030550934374332427978516e-01, /* 61, accPolyMid2C9h, quickPolyMid2C9h */ 6.13394557799256408251130704849071363459255390907063e-18, /* 62, accPolyMid2C9m */ 1.79592723769284340340490757625957485288381576538086e-01, /* 63, accPolyMid2C10h, quickPolyMid2C10h */ -1.30198260064097970981442998070110461849845662150849e-17, /* 64, accPolyMid2C10m */ 2.07951828711086583734157784419949166476726531982422e-01, /* 65, accPolyMid2C11h, quickPolyMid2C11h */ -1.26159975996932877835486818675875580593424383227469e-17, /* 66, accPolyMid2C11m */ 2.38247271379822073145149374795437324792146682739258e-01, /* 67, accPolyMid2C12h, quickPolyMid2C12h */ 6.62361216505959744828122635016705548667940611263800e-18, /* 68, accPolyMid2C12m */ 2.79893913215572998076652311283396556973457336425781e-01, /* 69, accPolyMid2C13h, quickPolyMid2C13h */ -2.24149827195062967543013296493616902343167004009288e-17, /* 70, accPolyMid2C13m */ 3.28958991769599307097848850389709696173667907714844e-01, /* 71, accPolyMid2C14h, quickPolyMid2C14h */ -1.05211249452308945191032281708802957418482198191124e-17, /* 72, accPolyMid2C14m */ 3.91766249806127564436764032507198862731456756591797e-01, /* 73, accPolyMid2C15h */ -2.02194096713130520849748106020797136930683180643846e-17, /* 74, accPolyMid2C15m */ 4.68246642053942785377529389734263531863689422607422e-01, /* 75, accPolyMid2C16h */ 5.64148787932559847568825261987512931227684020996094e-01, /* 76, accPolyMid2C17h */ 6.82488400757435664800709673727396875619888305664062e-01, /* 77, accPolyMid2C18h */ 8.30182127559316640486031246837228536605834960937500e-01, /* 78, accPolyMid2C19h */ 1.01367533043020308092252435017144307494163513183594e+00, /* 79, accPolyMid2C20h */ 1.24281078928695176699648072826676070690155029296875e+00, /* 80, accPolyMid2C21h */ 1.52877587404435177909078902303008362650871276855469e+00, /* 81, accPolyMid2C22h */ 1.88667637664635656769007709954166784882545471191406e+00, /* 82, accPolyMid2C23h */ 2.33494551765288571587575461308006197214126586914062e+00, /* 83, accPolyMid2C24h */ 2.89749244536000327698843648249749094247817993164062e+00, /* 84, accPolyMid2C25h */ 3.60426450740106130155027130967937409877777099609375e+00, /* 85, accPolyMid2C26h */ 4.49361107526955017021919047692790627479553222656250e+00, /* 86, accPolyMid2C27h */ 5.61406255377128715622347954194992780685424804687500e+00, /* 87, accPolyMid2C28h */ 7.02754870503224271516273802262730896472930908203125e+00, /* 88, accPolyMid2C29h */ 8.81280667340759649164283473510295152664184570312500e+00, /* 89, accPolyMid2C30h */ 1.10704407960507111852166417520493268966674804687500e+01, /* 90, accPolyMid2C31h */ 1.39282518419665830577969245496205985546112060546875e+01, /* 91, accPolyMid2C32h */ 1.75308292529565719064521545078605413436889648437500e+01, /* 92, accPolyMid2C33h */ 2.21169075633838900785121950320899486541748046875000e+01, /* 93, accPolyMid2C34h */ 2.93386309556562245859367976663634181022644042968750e+01, /* 94, accPolyMid2C35h */ 1.01683357072532350635299322879618933637376890680614e+00, /* 95, RN rounding constant quick poly middle 2*/ 9.05249299973766985475925981961240072045593429326050e-19, /* 96, RD rounding constant quick poly middle 2*/ 3.51339936256424290039745983449392952024936676025391e-01, /* 97, midpoint in interval 3*/ 3.59001896704258527392994437832385301589965820312500e-01, /* 98, accPolyMid3C0h, quickPolyMid3C0h */ 7.25234535377983806008993135801969933842904099082037e-20, /* 99, accPolyMid3C0m, quickPolyMid3C0l */ 1.06809311097735548656828541425056755542755126953125e+00, /* 100, accPolyMid3C1h, quickPolyMid3C1h */ 8.06569140638077604165107730077659782400969546746483e-17, /* 101, accPolyMid3C1m, quickPolyMid3C1l */ -5.04406564603486171676187418521136112402329884904383e-33, /* 102, accPolyMid3C1l */ 2.14054747447713134000935042422497645020484924316406e-01, /* 103, accPolyMid3C2h, quickPolyMid3C2h */ 9.76056255097027764696827253384241478483311533093656e-18, /* 104, accPolyMid3C2m, quickPolyMid3C2l */ -7.76857615284538540734861101748988881714638362963881e-35, /* 105, accPolyMid3C2l */ 2.88880884175958529969108212753781117498874664306641e-01, /* 106, accPolyMid3C3h, quickPolyMid3C3h */ 2.22181200821645624650165429361546283225838059740631e-17, /* 107, accPolyMid3C3m, quickPolyMid3C3l */ -1.14368045348414878337189405350442917783836545775590e-33, /* 108, accPolyMid3C3l */ 2.26134851489718013972662902233423665165901184082031e-01, /* 109, accPolyMid3C4h, quickPolyMid3C4h */ -8.04753534970505104224953947907869405284151781535028e-18, /* 110, accPolyMid3C4m, quickPolyMid3C4l */ 4.22557384286705919324956002465313457843707737945963e-34, /* 111, accPolyMid3C4l */ 2.75196923580072527748541233449941501021385192871094e-01, /* 112, accPolyMid3C5h, quickPolyMid3C5h */ -1.17338666986909136966078634618924264888220762222419e-18, /* 113, accPolyMid3C5m, quickPolyMid3C5l */ -4.68757737099062213529607300203132104484914350463871e-35, /* 114, accPolyMid3C5l */ 3.03044495521890500100425924756564199924468994140625e-01, /* 115, accPolyMid3C6h, quickPolyMid3C6h */ -2.27411416594910816511289518687103845115091724313899e-17, /* 116, accPolyMid3C6m, quickPolyMid3C6l */ 2.34762544350785348445971766662785127027332739123595e-34, /* 117, accPolyMid3C6l */ 3.77749573081396394780284708758699707686901092529297e-01, /* 118, accPolyMid3C7h, quickPolyMid3C7h */ 7.89247891096042648893247867692397394548591651092283e-18, /* 119, accPolyMid3C7m, quickPolyMid3C7l */ 4.68287147615184806692667507377336733043193817138672e-01, /* 120, accPolyMid3C8h, quickPolyMid3C8h */ 1.75668374099909928545987828472120658936175220036884e-17, /* 121, accPolyMid3C8m */ 6.06111063535901939403061078337486833333969116210938e-01, /* 122, accPolyMid3C9h, quickPolyMid3C9h */ 1.72730090011832304135009947489517024111046794620020e-17, /* 123, accPolyMid3C9m */ 7.92895790821915635859795656870119273662567138671875e-01, /* 124, accPolyMid3C10h, quickPolyMid3C10h */ 4.98295614974968378037947765656866085023078681863398e-17, /* 125, accPolyMid3C10m */ 1.05810730062141522545005045685684308409690856933594e+00, /* 126, accPolyMid3C11h, quickPolyMid3C11h */ 8.05577049603995800072512132781137905047707942749781e-17, /* 127, accPolyMid3C11m */ 1.42745521004660447239587028889218345284461975097656e+00, /* 128, accPolyMid3C12h, quickPolyMid3C12h */ -4.55985728468522936328504707804310204497673421624067e-17, /* 129, accPolyMid3C12m */ 1.94854789175488596342233904579188674688339233398438e+00, /* 130, accPolyMid3C13h, quickPolyMid3C13h */ 3.84783704422594121999348237839996274693704597202448e-17, /* 131, accPolyMid3C13m */ 2.68312408725385909136207374103832989931106567382812e+00, /* 132, accPolyMid3C14h, quickPolyMid3C14h */ -3.56068007836116005017028996147996121343986693197868e-17, /* 133, accPolyMid3C14m */ 3.72473732217660824517224682494997978210449218750000e+00, /* 134, accPolyMid3C15h */ -5.87298986037438700709055565377465605786708153319628e-17, /* 135, accPolyMid3C15m */ 5.20573944915823361156981263775378465652465820312500e+00, /* 136, accPolyMid3C16h */ 7.31989734855592644180433126166462898254394531250000e+00, /* 137, accPolyMid3C17h */ 1.03473141302088169624084912356920540332794189453125e+01, /* 138, accPolyMid3C18h */ 1.46964937699531184023271634941920638084411621093750e+01, /* 139, accPolyMid3C19h */ 2.09624579630017748854697856586426496505737304687500e+01, /* 140, accPolyMid3C20h */ 3.00147629377676423700904706493020057678222656250000e+01, /* 141, accPolyMid3C21h */ 4.31254748908798717366153141483664512634277343750000e+01, /* 142, accPolyMid3C22h */ 6.21591110441626426563743734732270240783691406250000e+01, /* 143, accPolyMid3C23h */ 8.98523523311889533715657307766377925872802734375000e+01, /* 144, accPolyMid3C24h */ 1.30228138287161243624723283573985099792480468750000e+02, /* 145, accPolyMid3C25h */ 1.89208159704443204418566892854869365692138671875000e+02, /* 146, accPolyMid3C26h */ 2.75520543663640125942038139328360557556152343750000e+02, /* 147, accPolyMid3C27h */ 4.02045721388318213485035812482237815856933593750000e+02, /* 148, accPolyMid3C28h */ 5.87814144421144646912580356001853942871093750000000e+02, /* 149, accPolyMid3C29h */ 8.60974558223577218996069859713315963745117187500000e+02, /* 150, accPolyMid3C30h */ 1.26323081508058703548158518970012664794921875000000e+03, /* 151, accPolyMid3C31h */ 1.85633061099108476810215506702661514282226562500000e+03, /* 152, accPolyMid3C32h */ 2.72831792235129523760406300425529479980468750000000e+03, /* 153, accPolyMid3C33h */ 4.02017366871190233723609708249568939208984375000000e+03, /* 154, accPolyMid3C34h */ 6.26169941241203287063399329781532287597656250000000e+03, /* 155, accPolyMid3C35h */ 1.01852226987326804088489911214053254620571040933433e+00, /* 156, RN rounding constant quick poly middle 3*/ 9.96061507703610851328544443284249848383807032724405e-19, /* 157, RD rounding constant quick poly middle 3*/ 4.48084712028450460330475380033021792769432067871094e-01, /* 158, midpoint in interval 4*/ 4.64621784296265272207193675058078952133655548095703e-01, /* 159, accPolyMid4C0h, quickPolyMid4C0h */ 5.46463478154141631687941857567549378870836612391668e-19, /* 160, accPolyMid4C0m, quickPolyMid4C0l */ 1.11857936563137916330390453367726877331733703613281e+00, /* 161, accPolyMid4C1h, quickPolyMid4C1h */ -7.52084787570938032181667127523977366268049041253541e-17, /* 162, accPolyMid4C1m, quickPolyMid4C1l */ -2.09600667283052949148765250630641631769479132030207e-33, /* 163, accPolyMid4C1l */ 3.13567137932624417917537584798992611467838287353516e-01, /* 164, accPolyMid4C2h, quickPolyMid4C2h */ -4.41710443385272069717070263863657699262849649693148e-18, /* 165, accPolyMid4C2m, quickPolyMid4C2l */ -1.66857777421172326251970639278136259133415308172276e-34, /* 166, accPolyMid4C2l */ 4.09066962553200574870260197712923400104045867919922e-01, /* 167, accPolyMid4C3h, quickPolyMid4C3h */ -1.77243968292023797220078441566237340174840093946990e-17, /* 168, accPolyMid4C3m, quickPolyMid4C3l */ 1.04993340346633219191766382762445818927028795922212e-33, /* 169, accPolyMid4C3l */ 4.17460970109683637829789404349867254495620727539062e-01, /* 170, accPolyMid4C4h, quickPolyMid4C4h */ 1.39418041407988360348752433713233257018150500547568e-17, /* 171, accPolyMid4C4m, quickPolyMid4C4l */ 1.44515287253394191526867297316859284672731580248765e-33, /* 172, accPolyMid4C4l */ 5.57995436127318722441259524202905595302581787109375e-01, /* 173, accPolyMid4C5h, quickPolyMid4C5h */ 4.36037702989507667583407786816694605825360677277616e-17, /* 174, accPolyMid4C5m, quickPolyMid4C5l */ -1.19172250052693786129959971158569652849573416545361e-33, /* 175, accPolyMid4C5l */ 7.47841169204912281642805282899644225835800170898438e-01, /* 176, accPolyMid4C6h, quickPolyMid4C6h */ -6.76313448015089834151929838334258544557222273487418e-18, /* 177, accPolyMid4C6m, quickPolyMid4C6l */ -3.47721914174083040302762713955940912153154957518196e-34, /* 178, accPolyMid4C6l */ 1.07444730844797153856973181973444297909736633300781e+00, /* 179, accPolyMid4C7h, quickPolyMid4C7h */ 7.55340134261966180374112563614849022138812950329448e-17, /* 180, accPolyMid4C7m, quickPolyMid4C7l */ 1.58041645549890685806815326941432431340217590332031e+00, /* 181, accPolyMid4C8h, quickPolyMid4C8h */ 4.80894355381610072868748091065730787867334028863435e-17, /* 182, accPolyMid4C8m */ 2.39169226022640657447482226416468620300292968750000e+00, /* 183, accPolyMid4C9h, quickPolyMid4C9h */ 1.26753183127964275508490032426937968441812593935712e-16, /* 184, accPolyMid4C9m */ 3.68572936227336489523054297023918479681015014648438e+00, /* 185, accPolyMid4C10h, quickPolyMid4C10h */ -1.41660589025860946857878120315437315934718409357086e-16, /* 186, accPolyMid4C10m */ 5.77285150262833735013145997072570025920867919921875e+00, /* 187, accPolyMid4C11h, quickPolyMid4C11h */ -2.16740363176565772841534018366824459554498708631527e-16, /* 188, accPolyMid4C11m */ 9.15766592727227646264509530737996101379394531250000e+00, /* 189, accPolyMid4C12h, quickPolyMid4C12h */ 4.37180613264180824186691777532090455983551321485214e-16, /* 190, accPolyMid4C12m */ 1.46862422532599090629901184001937508583068847656250e+01, /* 191, accPolyMid4C13h, quickPolyMid4C13h */ 7.89614550363306335166404831558856161121412865593061e-16, /* 192, accPolyMid4C13m */ 2.37692237950290667924946319544687867164611816406250e+01, /* 193, accPolyMid4C14h, quickPolyMid4C14h */ -3.50255834101571646092598176937562449597971181913456e-16, /* 194, accPolyMid4C14m */ 3.87753699929054533868111320771276950836181640625000e+01, /* 195, accPolyMid4C15h */ 5.67060321723933067329766411373458413340348986762113e-16, /* 196, accPolyMid4C15m */ 6.36909499334141528947839105967432260513305664062500e+01, /* 197, accPolyMid4C16h */ 1.05248620915111246176820714026689529418945312500000e+02, /* 198, accPolyMid4C17h */ 1.74851057791898000459696049802005290985107421875000e+02, /* 199, accPolyMid4C18h */ 2.91864013611726591079786885529756546020507812500000e+02, /* 200, accPolyMid4C19h */ 4.89259682748188197365379892289638519287109375000000e+02, /* 201, accPolyMid4C20h */ 8.23309003242859603233227971941232681274414062500000e+02, /* 202, accPolyMid4C21h */ 1.39025484827954846878128591924905776977539062500000e+03, /* 203, accPolyMid4C22h */ 2.35504246227568182803224772214889526367187500000000e+03, /* 204, accPolyMid4C23h */ 4.00090205201026492431992664933204650878906250000000e+03, /* 205, accPolyMid4C24h */ 6.81504309301592911651823669672012329101562500000000e+03, /* 206, accPolyMid4C25h */ 1.16369648030766729789320379495620727539062500000000e+04, /* 207, accPolyMid4C26h */ 1.99154708390699779556598514318466186523437500000000e+04, /* 208, accPolyMid4C27h */ 3.41546126991757555515505373477935791015625000000000e+04, /* 209, accPolyMid4C28h */ 5.86883344113872444722801446914672851562500000000000e+04, /* 210, accPolyMid4C29h */ 1.01027682393336552195250988006591796875000000000000e+05, /* 211, accPolyMid4C30h */ 1.74209975080082920612767338752746582031250000000000e+05, /* 212, accPolyMid4C31h */ 3.00874278784890950191766023635864257812500000000000e+05, /* 213, accPolyMid4C32h */ 5.19633023773909430019557476043701171875000000000000e+05, /* 214, accPolyMid4C33h */ 8.99866392232198733836412429809570312500000000000000e+05, /* 215, accPolyMid4C34h */ 1.65235977806337876245379447937011718750000000000000e+06, /* 216, accPolyMid4C35h */ 1.01865623563637326825520446919499828081810155036594e+00, /* 217, RN rounding constant quick poly middle 4*/ 1.00326570788492020170486150590740535840759810902416e-18, /* 218, RD rounding constant quick poly middle 4*/ 5.31445860862679642089290155126946046948432922363281e-01, /* 219, midpoint in interval 5*/ 5.60306504963744567149319664167705923318862915039062e-01, /* 220, accPolyMid5C0h, quickPolyMid5C0h */ -1.08630439217163180480513733763948654678554607776160e-20, /* 221, accPolyMid5C0m, quickPolyMid5C0l */ 1.18050895658762322604218297783518210053443908691406e+00, /* 222, accPolyMid5C1h, quickPolyMid5C1h */ -3.44936676454714048889716658635127499762917269870727e-17, /* 223, accPolyMid5C1m, quickPolyMid5C1l */ -2.49069456197248953275668118371299181194287558355700e-33, /* 224, accPolyMid5C1l */ 4.37156452058995781406736114149680361151695251464844e-01, /* 225, accPolyMid5C2h, quickPolyMid5C2h */ 4.12350542001181384975859432610288269290340424486530e-18, /* 226, accPolyMid5C2m, quickPolyMid5C2l */ 2.73553164822567581206451159459555826955342358406517e-34, /* 227, accPolyMid5C2l */ 5.97961581435785594074161508615361526608467102050781e-01, /* 228, accPolyMid5C3h, quickPolyMid5C3h */ 1.15786235462823532242451850040378867919657187923266e-17, /* 229, accPolyMid5C3m, quickPolyMid5C3l */ 6.70476163820618923333949946465040969013104876616743e-34, /* 230, accPolyMid5C3l */ 7.56654591443305823972309553937520831823348999023438e-01, /* 231, accPolyMid5C4h, quickPolyMid5C4h */ 5.63361768523770903650379304980880430544181403662856e-18, /* 232, accPolyMid5C4m, quickPolyMid5C4l */ 3.52518369310847108975654467573884198459173315811765e-35, /* 233, accPolyMid5C4l */ 1.15954888868330963092034835426602512598037719726562e+00, /* 234, accPolyMid5C5h, quickPolyMid5C5h */ -2.13088606479945404910718732635657047999226786224539e-17, /* 235, accPolyMid5C5m, quickPolyMid5C5l */ 1.01155988751211667735165829625236622533486662424891e-33, /* 236, accPolyMid5C5l */ 1.85057068266552660062984614341985434293746948242188e+00, /* 237, accPolyMid5C6h, quickPolyMid5C6h */ -4.13756595773451122099466439202037064387337671566669e-18, /* 238, accPolyMid5C6m, quickPolyMid5C6l */ 3.02843501360506226132120912500822054694900989592884e-34, /* 239, accPolyMid5C6l */ 3.11563743870884257702869035711046308279037475585938e+00, /* 240, accPolyMid5C7h, quickPolyMid5C7h */ -5.06302300821373603583774676357699499992045551579126e-17, /* 241, accPolyMid5C7m, quickPolyMid5C7l */ 5.40761322601296168244289219728671014308929443359375e+00, /* 242, accPolyMid5C8h, quickPolyMid5C8h */ 2.97487923575735998744301300115136435889001285861472e-16, /* 243, accPolyMid5C8m */ 9.62995354897343425193412258522585034370422363281250e+00, /* 244, accPolyMid5C9h, quickPolyMid5C9h */ 4.55607422255092503960684830342258039056296500032145e-16, /* 245, accPolyMid5C9m */ 1.74836661195630966858516330830752849578857421875000e+01, /* 246, accPolyMid5C10h, quickPolyMid5C10h */ 1.43590320985440421817158000882140332196152266840822e-15, /* 247, accPolyMid5C10m */ 3.22483723360128990975681517738848924636840820312500e+01, /* 248, accPolyMid5C11h, quickPolyMid5C11h */ -3.34403568343416729924334128939506733422536740966968e-15, /* 249, accPolyMid5C11m */ 6.02553715792408368656651873607188463211059570312500e+01, /* 250, accPolyMid5C12h, quickPolyMid5C12h */ 3.10919444878682139369989784864394611534570535618660e-15, /* 251, accPolyMid5C12m */ 1.13813051318643047693512926343828439712524414062500e+02, /* 252, accPolyMid5C13h, quickPolyMid5C13h */ -1.71698317353737059559128975443274184793142084909379e-15, /* 253, accPolyMid5C13m */ 2.16961936728312849709254805929958820343017578125000e+02, /* 254, accPolyMid5C14h, quickPolyMid5C14h */ 8.27079867974059458294192504441253562124411295719550e-15, /* 255, accPolyMid5C14m */ 4.16880179488225451223115669563412666320800781250000e+02, /* 256, accPolyMid5C15h */ -2.58735460985196142054738964992050729251298751831811e-14, /* 257, accPolyMid5C15m */ 8.06537874996876666955358814448118209838867187500000e+02, /* 258, accPolyMid5C16h */ 1.56984649251497876321082003414630889892578125000000e+03, /* 259, accPolyMid5C17h */ 3.07188686658870074097649194300174713134765625000000e+03, /* 260, accPolyMid5C18h */ 6.03970064736507720226654782891273498535156250000000e+03, /* 261, accPolyMid5C19h */ 1.19254227020427806564839556813240051269531250000000e+04, /* 262, accPolyMid5C20h */ 2.36373073951149926870130002498626708984375000000000e+04, /* 263, accPolyMid5C21h */ 4.70144622759458434302359819412231445312500000000000e+04, /* 264, accPolyMid5C22h */ 9.38077422737224260345101356506347656250000000000000e+04, /* 265, accPolyMid5C23h */ 1.87716130978103727102279663085937500000000000000000e+05, /* 266, accPolyMid5C24h */ 3.76631599838992522563785314559936523437500000000000e+05, /* 267, accPolyMid5C25h */ 7.57518066926909843459725379943847656250000000000000e+05, /* 268, accPolyMid5C26h */ 1.52703698454281571321189403533935546875000000000000e+06, /* 269, accPolyMid5C27h */ 3.08471154002460883930325508117675781250000000000000e+06, /* 270, accPolyMid5C28h */ 6.24343584097426943480968475341796875000000000000000e+06, /* 271, accPolyMid5C29h */ 1.26595813738393746316432952880859375000000000000000e+07, /* 272, accPolyMid5C30h */ 2.57133891378295645117759704589843750000000000000000e+07, /* 273, accPolyMid5C31h */ 5.23093272367429584264755249023437500000000000000000e+07, /* 274, accPolyMid5C32h */ 1.06415184183835312724113464355468750000000000000000e+08, /* 275, accPolyMid5C33h */ 2.17067016530691206455230712890625000000000000000000e+08, /* 276, accPolyMid5C34h */ 4.69394759797544836997985839843750000000000000000000e+08, /* 277, accPolyMid5C35h */ 1.01546394178491537056416717033435295842436071964172e+00, /* 278, RN rounding constant quick poly middle 5*/ 8.45008379631082379626014328492746516799371469048044e-19, /* 279, RD rounding constant quick poly middle 5*/ 6.04673624038476131836716831458033993840217590332031e-01, /* 280, midpoint in interval 6*/ 6.49356027282211423212743284238968044519424438476562e-01, /* 281, accPolyMid6C0h, quickPolyMid6C0h */ -1.25840412187919035681267493345871686399113240956856e-20, /* 282, accPolyMid6C0m, quickPolyMid6C0l */ 1.25553477869155938329015498311491683125495910644531e+00, /* 283, accPolyMid6C1h, quickPolyMid6C1h */ 5.00523898265236280615595780032763663310079252366513e-17, /* 284, accPolyMid6C1m, quickPolyMid6C1l */ 2.70452092654099855316456962656407597917508288905533e-33, /* 285, accPolyMid6C1l */ 5.98380278107774499218862729321699589490890502929688e-01, /* 286, accPolyMid6C2h, quickPolyMid6C2h */ 3.73915919375620074681511372815883902051293891666555e-18, /* 287, accPolyMid6C2m, quickPolyMid6C2l */ 1.02836809807342008154037540277599096854529496615931e-34, /* 288, accPolyMid6C2l */ 9.00232892880871604646131345361936837434768676757812e-01, /* 289, accPolyMid6C3h, quickPolyMid6C3h */ -1.70995008965645412422671790545314082452432030961170e-17, /* 290, accPolyMid6C3m, quickPolyMid6C3l */ 1.26596066229657064182610642365044212709535948254084e-33, /* 291, accPolyMid6C3l */ 1.38703629702026587366958665370475500822067260742188e+00, /* 292, accPolyMid6C4h, quickPolyMid6C4h */ 3.98819447215487913236315415179165676291502931117595e-17, /* 293, accPolyMid6C4m, quickPolyMid6C4l */ -6.55797179513908183565792353381331895988112885430413e-34, /* 294, accPolyMid6C4l */ 2.48954277308397298185127510805614292621612548828125e+00, /* 295, accPolyMid6C5h, quickPolyMid6C5h */ 9.74092851599686234698415065747156883706428073441651e-17, /* 296, accPolyMid6C5m, quickPolyMid6C5l */ 1.56743989943601791748641837689163542493404742470630e-33, /* 297, accPolyMid6C5l */ 4.72562522409656082800211152061820030212402343750000e+00, /* 298, accPolyMid6C6h, quickPolyMid6C6h */ 6.88679830761278595465306080986277758416307765996557e-18, /* 299, accPolyMid6C6m, quickPolyMid6C6l */ -9.47395090301458455484031652124848364407920780715874e-35, /* 300, accPolyMid6C6l */ 9.41432957016690785678747488418594002723693847656250e+00, /* 301, accPolyMid6C7h, quickPolyMid6C7h */ 8.62157085484702984705473460305131094967840256568931e-16, /* 302, accPolyMid6C7m, quickPolyMid6C7l */ 1.93709907584273430813937011407688260078430175781250e+01, /* 303, accPolyMid6C8h, quickPolyMid6C8h */ -1.40839418808440953673043657798045432960211596437085e-16, /* 304, accPolyMid6C8m */ 4.08734031574560177091370860580354928970336914062500e+01, /* 305, accPolyMid6C9h, quickPolyMid6C9h */ -2.98667469102598629922297846034715799734023919430673e-16, /* 306, accPolyMid6C9m */ 8.79464044588732321017232607118785381317138671875000e+01, /* 307, accPolyMid6C10h, quickPolyMid6C10h */ 3.61512961738881992095483091045503569454095245351219e-16, /* 308, accPolyMid6C10m */ 1.92241339189846911494896630756556987762451171875000e+02, /* 309, accPolyMid6C11h, quickPolyMid6C11h */ 6.61037281166591217605498682969545683054486597679533e-15, /* 310, accPolyMid6C11m */ 4.25700873706194784062972757965326309204101562500000e+02, /* 311, accPolyMid6C12h, quickPolyMid6C12h */ -6.48144847243744916328196408044704617877580310816854e-15, /* 312, accPolyMid6C12m */ 9.52958531675870517574367113411426544189453125000000e+02, /* 313, accPolyMid6C13h, quickPolyMid6C13h */ -3.41559781098088121115265032630996540232080319228480e-15, /* 314, accPolyMid6C13m */ 2.15300037043921429358306340873241424560546875000000e+03, /* 315, accPolyMid6C14h, quickPolyMid6C14h */ -4.69254271757335955512545725611899433103182087412275e-14, /* 316, accPolyMid6C14m */ 4.90290875724837587767979130148887634277343750000000e+03, /* 317, accPolyMid6C15h */ -4.54544125910656089453646656943432828883091406657613e-13, /* 318, accPolyMid6C15m */ 1.12422266608999743766617029905319213867187500000000e+04, /* 319, accPolyMid6C16h */ 2.59341556033402121101971715688705444335937500000000e+04, /* 320, accPolyMid6C17h */ 6.01463753209276546840555965900421142578125000000000e+04, /* 321, accPolyMid6C18h */ 1.40155647347781836288049817085266113281250000000000e+05, /* 322, accPolyMid6C19h */ 3.27990517748617625329643487930297851562500000000000e+05, /* 323, accPolyMid6C20h */ 7.70511269948243047110736370086669921875000000000000e+05, /* 324, accPolyMid6C21h */ 1.81638100581354671157896518707275390625000000000000e+06, /* 325, accPolyMid6C22h */ 4.29545835214607417583465576171875000000000000000000e+06, /* 326, accPolyMid6C23h */ 1.01875211922164466232061386108398437500000000000000e+07, /* 327, accPolyMid6C24h */ 2.42259292905952110886573791503906250000000000000000e+07, /* 328, accPolyMid6C25h */ 5.77502706188629567623138427734375000000000000000000e+07, /* 329, accPolyMid6C26h */ 1.37977551882563471794128417968750000000000000000000e+08, /* 330, accPolyMid6C27h */ 3.30348046445899784564971923828125000000000000000000e+08, /* 331, accPolyMid6C28h */ 7.92463843911740779876708984375000000000000000000000e+08, /* 332, accPolyMid6C29h */ 1.90447027047677397727966308593750000000000000000000e+09, /* 333, accPolyMid6C30h */ 4.58479383261657714843750000000000000000000000000000e+09, /* 334, accPolyMid6C31h */ 1.10545369624155406951904296875000000000000000000000e+10, /* 335, accPolyMid6C32h */ 2.66385731955786666870117187500000000000000000000000e+10, /* 336, accPolyMid6C33h */ 6.43976383194783477783203125000000000000000000000000e+10, /* 337, accPolyMid6C34h */ 1.66775070729799957275390625000000000000000000000000e+11, /* 338, accPolyMid6C35h */ 1.02865713098129091896393402230525290748739350993607e+00, /* 339, RN rounding constant quick poly middle 6*/ 1.54107813388901044122294580378974284123051351850249e-18, /* 340, RD rounding constant quick poly middle 6*/ 6.67959213256959061233430929860332980751991271972656e-01, /* 341, midpoint in interval 7*/ 7.31463137281961883751080222282325848937034606933594e-01, /* 342, accPolyMid7C0h, quickPolyMid7C0h */ 8.54719742452471207894475172794621662948903828511743e-18, /* 343, accPolyMid7C0m, quickPolyMid7C0l */ 1.34372862717732943771409281907835975289344787597656e+00, /* 344, accPolyMid7C1h, quickPolyMid7C1h */ -9.37080278359462608557638680730489336344772507156678e-17, /* 345, accPolyMid7C1m, quickPolyMid7C1l */ -3.73014429525577422762683976038701673929582903516469e-33, /* 346, accPolyMid7C1l */ 8.10316454021746457314634426438715308904647827148438e-01, /* 347, accPolyMid7C2h, quickPolyMid7C2h */ 2.83724520944754281479328686665519600224801269794297e-17, /* 348, accPolyMid7C2m, quickPolyMid7C2l */ 5.82045706927347254178829289360700371297572159541923e-34, /* 349, accPolyMid7C2l */ 1.38167386397960734178980146680260077118873596191406e+00, /* 350, accPolyMid7C3h, quickPolyMid7C3h */ 2.02013329353188582679931981349209152232167295906717e-17, /* 351, accPolyMid7C3m, quickPolyMid7C3l */ 6.40114855650846168897999343294667085370954557070054e-34, /* 352, accPolyMid7C3l */ 2.57070122683855739609271040535531938076019287109375e+00, /* 353, accPolyMid7C4h, quickPolyMid7C4h */ -1.97101208773651620042078427599655545421327570922328e-16, /* 354, accPolyMid7C4m, quickPolyMid7C4l */ -5.16498810795509657208158829628186048443297866770160e-33, /* 355, accPolyMid7C4l */ 5.46327133150128840810566543950699269771575927734375e+00, /* 356, accPolyMid7C5h, quickPolyMid7C5h */ 4.46002282634806142830756936399426613343260291679165e-17, /* 357, accPolyMid7C5m, quickPolyMid7C5l */ 1.00630542800586945033209683978834296850153546719007e-33, /* 358, accPolyMid7C5l */ 1.23592045140328163910226066946052014827728271484375e+01, /* 359, accPolyMid7C6h, quickPolyMid7C6h */ -6.31168277706663387163074158423931222709606927382536e-16, /* 360, accPolyMid7C6m, quickPolyMid7C6l */ -2.86577343636081880556771704346742846876298657614067e-32, /* 361, accPolyMid7C6l */ 2.92955857889283457495821494376286864280700683593750e+01, /* 362, accPolyMid7C7h, quickPolyMid7C7h */ 1.68044477586948138119056363287999050823887212287311e-15, /* 363, accPolyMid7C7m, quickPolyMid7C7l */ 7.17613428086569200559097225777804851531982421875000e+01, /* 364, accPolyMid7C8h, quickPolyMid7C8h */ 6.23119826880857970524569208326049427014155061843592e-15, /* 365, accPolyMid7C8m */ 1.80247733513940403327069361694157123565673828125000e+02, /* 366, accPolyMid7C9h, quickPolyMid7C9h */ 5.02375884230076452151557056132473497202104361844532e-15, /* 367, accPolyMid7C9m */ 4.61706463186508131002483423799276351928710937500000e+02, /* 368, accPolyMid7C10h, quickPolyMid7C10h */ 1.87384815286128587607402694756722954854896712184598e-14, /* 369, accPolyMid7C10m */ 1.20148795335111071835854090750217437744140625000000e+03, /* 370, accPolyMid7C11h, quickPolyMid7C11h */ 2.60459063066423653270039910766913797650205005668189e-14, /* 371, accPolyMid7C11m */ 3.16745162323707290852325968444347381591796875000000e+03, /* 372, accPolyMid7C12h, quickPolyMid7C12h */ -2.76092355337723539107271551080313829589234133482512e-14, /* 373, accPolyMid7C12m */ 8.44145526317249823478050529956817626953125000000000e+03, /* 374, accPolyMid7C13h, quickPolyMid7C13h */ -2.33235416338613018856460888065680920494017469568604e-13, /* 375, accPolyMid7C13m */ 2.27054147369064739905297756195068359375000000000000e+04, /* 376, accPolyMid7C14h, quickPolyMid7C14h */ -3.76196185348520617410321355221587231933578349130087e-13, /* 377, accPolyMid7C14m */ 6.15579784849813586333766579627990722656250000000000e+04, /* 378, accPolyMid7C15h */ -5.34885488214934542022410271185570626302323293810304e-13, /* 379, accPolyMid7C15m */ 1.68046954551722796168178319931030273437500000000000e+05, /* 380, accPolyMid7C16h */ 4.61530358172978565562516450881958007812500000000000e+05, /* 381, accPolyMid7C17h */ 1.27435135728149255737662315368652343750000000000000e+06, /* 382, accPolyMid7C18h */ 3.53543876571432314813137054443359375000000000000000e+06, /* 383, accPolyMid7C19h */ 9.85027146846828423440456390380859375000000000000000e+06, /* 384, accPolyMid7C20h */ 2.75499693650120757520198822021484375000000000000000e+07, /* 385, accPolyMid7C21h */ 7.73223713417402952909469604492187500000000000000000e+07, /* 386, accPolyMid7C22h */ 2.17703077316092193126678466796875000000000000000000e+08, /* 387, accPolyMid7C23h */ 6.14725288059689402580261230468750000000000000000000e+08, /* 388, accPolyMid7C24h */ 1.74040800223112154006958007812500000000000000000000e+09, /* 389, accPolyMid7C25h */ 4.93950269498267459869384765625000000000000000000000e+09, /* 390, accPolyMid7C26h */ 1.40506579253189964294433593750000000000000000000000e+10, /* 391, accPolyMid7C27h */ 4.00515555251962203979492187500000000000000000000000e+10, /* 392, accPolyMid7C28h */ 1.14389701296316925048828125000000000000000000000000e+11, /* 393, accPolyMid7C29h */ 3.27296809500310974121093750000000000000000000000000e+11, /* 394, accPolyMid7C30h */ 9.38089913584087280273437500000000000000000000000000e+11, /* 395, accPolyMid7C31h */ 2.69293079636161279296875000000000000000000000000000e+12, /* 396, accPolyMid7C32h */ 7.72833097677600292968750000000000000000000000000000e+12, /* 397, accPolyMid7C33h */ 2.22444558194129648437500000000000000000000000000000e+13, /* 398, accPolyMid7C34h */ 6.82401753565838359375000000000000000000000000000000e+13, /* 399, accPolyMid7C35h */ 1.01768360014066378266267100775040494087129736780625e+00, /* 400, RN rounding constant quick poly middle 7*/ 9.50960845417677113226513686606015976666256457529322e-19, /* 401, RD rounding constant quick poly middle 7*/ 7.19008445739778290217714129539672285318374633789062e-01, /* 402, midpoint in interval 8*/ 8.02374569969830475635319544380763545632362365722656e-01, /* 403, accPolyMid8C0h, quickPolyMid8C0h */ -5.57232596267891548198947769768214754835408022265973e-18, /* 404, accPolyMid8C0m, quickPolyMid8C0l */ 1.43884615807450622071428369963541626930236816406250e+00, /* 405, accPolyMid8C1h, quickPolyMid8C1h */ 3.59501817700961691698905527113737832717163932379732e-17, /* 406, accPolyMid8C1m, quickPolyMid8C1l */ 1.42139791223330171535988185118707169939451756100115e-33, /* 407, accPolyMid8C1l */ 1.07089546798848767039658014255110174417495727539062e+00, /* 408, accPolyMid8C2h, quickPolyMid8C2h */ 7.12234409493595206110752393915421282220770659974638e-18, /* 409, accPolyMid8C2m, quickPolyMid8C2l */ 4.88803415361541961399074298884647415525574790319603e-34, /* 410, accPolyMid8C2l */ 2.09054748952818103546746897336561232805252075195312e+00, /* 411, accPolyMid8C3h, quickPolyMid8C3h */ -4.76201670474478458619338404030121517580491201111076e-17, /* 412, accPolyMid8C3m, quickPolyMid8C3l */ 9.85965711757934088944524691800382507878970211803297e-34, /* 413, accPolyMid8C3l */ 4.62886640680389760404978005681186914443969726562500e+00, /* 414, accPolyMid8C4h, quickPolyMid8C4h */ -6.26076461255283992652654162871089011104493903198467e-17, /* 415, accPolyMid8C4m, quickPolyMid8C4l */ -3.79525038577018957662309046851941714013728344004132e-33, /* 416, accPolyMid8C4l */ 1.15940096700862280698629547259770333766937255859375e+01, /* 417, accPolyMid8C5h, quickPolyMid8C5h */ 5.00344758332442110044971487490682364429618307708619e-16, /* 418, accPolyMid8C5m, quickPolyMid8C5l */ 5.05400641998677592107699970650218041381398322944134e-33, /* 419, accPolyMid8C5l */ 3.09983076631741454320945194922387599945068359375000e+01, /* 420, accPolyMid8C6h, quickPolyMid8C6h */ -1.68695534318490565671111852385917462817518447859219e-16, /* 421, accPolyMid8C6m, quickPolyMid8C6l */ 6.85050661529605157727571454320758800953682098824324e-34, /* 422, accPolyMid8C6l */ 8.67969690247392975379625568166375160217285156250000e+01, /* 423, accPolyMid8C7h, quickPolyMid8C7h */ -5.77909319686569076564604963233208513019264259552576e-15, /* 424, accPolyMid8C7m, quickPolyMid8C7l */ 2.51207737556061232453430420719087123870849609375000e+02, /* 425, accPolyMid8C8h, quickPolyMid8C8h */ -2.34229223147066395573123458231502220325151528840246e-15, /* 426, accPolyMid8C8m */ 7.45516108151238086065859533846378326416015625000000e+02, /* 427, accPolyMid8C9h, quickPolyMid8C9h */ 5.42429462463291658149197032428663192617240449908134e-15, /* 428, accPolyMid8C9m */ 2.25637900900536169501719996333122253417968750000000e+03, /* 429, accPolyMid8C10h, quickPolyMid8C10h */ 1.04118075698860813774916020354956791986217497225642e-13, /* 430, accPolyMid8C10m */ 6.93796098101582811068510636687278747558593750000000e+03, /* 431, accPolyMid8C11h, quickPolyMid8C11h */ 8.59862281333229161222916847764065622815798321104674e-15, /* 432, accPolyMid8C11m */ 2.16119867410615115659311413764953613281250000000000e+04, /* 433, accPolyMid8C12h, quickPolyMid8C12h */ 1.06661614083783310365636876324959361083581990681246e-13, /* 434, accPolyMid8C12m */ 6.80579130650992592563852667808532714843750000000000e+04, /* 435, accPolyMid8C13h, quickPolyMid8C13h */ 6.62014084472278982961475227363418833651659278771717e-12, /* 436, accPolyMid8C13m */ 2.16307061102022911654785275459289550781250000000000e+05, /* 437, accPolyMid8C14h, quickPolyMid8C14h */ -2.44881501957370731470213892899278376432195547529602e-12, /* 438, accPolyMid8C14m */ 6.92960027312710066325962543487548828125000000000000e+05, /* 439, accPolyMid8C15h */ -5.66500973206806599245652257405055779448943553688878e-11, /* 440, accPolyMid8C15m */ 2.23531716476973146200180053710937500000000000000000e+06, /* 441, accPolyMid8C16h */ 7.25429400587130710482597351074218750000000000000000e+06, /* 442, accPolyMid8C17h */ 2.36685600768156014382839202880859375000000000000000e+07, /* 443, accPolyMid8C18h */ 7.75916356685774326324462890625000000000000000000000e+07, /* 444, accPolyMid8C19h */ 2.55452232123835593461990356445312500000000000000000e+08, /* 445, accPolyMid8C20h */ 8.44254469674954175949096679687500000000000000000000e+08, /* 446, accPolyMid8C21h */ 2.79994093996573638916015625000000000000000000000000e+09, /* 447, accPolyMid8C22h */ 9.31537507532041358947753906250000000000000000000000e+09, /* 448, accPolyMid8C23h */ 3.10820362568210334777832031250000000000000000000000e+10, /* 449, accPolyMid8C24h */ 1.03985438377022964477539062500000000000000000000000e+11, /* 450, accPolyMid8C25h */ 3.48737110205060913085937500000000000000000000000000e+11, /* 451, accPolyMid8C26h */ 1.17221005601944750976562500000000000000000000000000e+12, /* 452, accPolyMid8C27h */ 3.94841085036352832031250000000000000000000000000000e+12, /* 453, accPolyMid8C28h */ 1.33255264873973789062500000000000000000000000000000e+13, /* 454, accPolyMid8C29h */ 4.50540615593679062500000000000000000000000000000000e+13, /* 455, accPolyMid8C30h */ 1.52590744626434593750000000000000000000000000000000e+14, /* 456, accPolyMid8C31h */ 5.17610884067860062500000000000000000000000000000000e+14, /* 457, accPolyMid8C32h */ 1.75591888512180650000000000000000000000000000000000e+15, /* 458, accPolyMid8C33h */ 5.97247050283681300000000000000000000000000000000000e+15, /* 459, accPolyMid8C34h */ 2.15157732956128240000000000000000000000000000000000e+16, /* 460, accPolyMid8C35h */ 1.01164858801777814945850739843488049838102483351729e+00, /* 461, RN rounding constant quick poly middle 8*/ 6.36522991537283605877265237263241827159525525595558e-19, /* 462, RD rounding constant quick poly middle 8*/ 7.60880231857352207214262307388707995414733886718750e-01, /* 463, midpoint in interval 9*/ 8.64668552766275078091950945236021652817726135253906e-01, /* 464, accPolyMid9C0h, quickPolyMid9C0h */ 2.22107768610709483983000348580034922276618040094248e-19, /* 465, accPolyMid9C0m, quickPolyMid9C0l */ 1.54108768708640897493467036838410422205924987792969e+00, /* 466, accPolyMid9C1h, quickPolyMid9C1h */ 3.32820103504311843280112118328828427349507594590859e-17, /* 467, accPolyMid9C1m, quickPolyMid9C1l */ 1.00469319336666835386896691703426687648516206509999e-33, /* 468, accPolyMid9C1l */ 1.39241392226891269601196654548402875661849975585938e+00, /* 469, accPolyMid9C2h, quickPolyMid9C2h */ -7.78438411380474954824767774215038405507043967534661e-17, /* 470, accPolyMid9C2m, quickPolyMid9C2l */ -2.75498989204243544757760916231818015864525586405625e-34, /* 471, accPolyMid9C2l */ 3.12616775988369477445871780219022184610366821289062e+00, /* 472, accPolyMid9C3h, quickPolyMid9C3h */ -1.83136634474213254639590598215495010130375003296228e-16, /* 473, accPolyMid9C3m, quickPolyMid9C3l */ -1.37039877493057234685308732075670776376976824689825e-33, /* 474, accPolyMid9C3l */ 8.16374541867330982825023966142907738685607910156250e+00, /* 475, accPolyMid9C4h, quickPolyMid9C4h */ 6.61331422381139448266729896007647878117248843327786e-16, /* 476, accPolyMid9C4m, quickPolyMid9C4l */ -2.34411228408683938039171677313602417735464237635307e-32, /* 477, accPolyMid9C4l */ 2.39942774487262227012251969426870346069335937500000e+01, /* 478, accPolyMid9C5h, quickPolyMid9C5h */ 3.56709659583669727593018389598696746405922754956722e-16, /* 479, accPolyMid9C5m, quickPolyMid9C5l */ 1.92887188784617492937549821774446261489627075560113e-32, /* 480, accPolyMid9C5l */ 7.53789452793380974071624223142862319946289062500000e+01, /* 481, accPolyMid9C6h, quickPolyMid9C6h */ -4.89236491033052363530754653203901634957086880239885e-15, /* 482, accPolyMid9C6m, quickPolyMid9C6l */ 1.86966182047363315238712995890702987106854589421809e-31, /* 483, accPolyMid9C6l */ 2.47970017761763045882617007009685039520263671875000e+02, /* 484, accPolyMid9C7h, quickPolyMid9C7h */ -5.49773113276874172897358146458574130047619382341550e-15, /* 485, accPolyMid9C7m, quickPolyMid9C7l */ 8.43239639560233626980334520339965820312500000000000e+02, /* 486, accPolyMid9C8h, quickPolyMid9C8h */ 4.61444619149467756136937751706191309842186761003280e-14, /* 487, accPolyMid9C8m */ 2.94042238989191673681489191949367523193359375000000e+03, /* 488, accPolyMid9C9h, quickPolyMid9C9h */ -6.26529947434876144165574723786618699307871677151027e-14, /* 489, accPolyMid9C9m */ 1.04570596262470262445276603102684020996093750000000e+04, /* 490, accPolyMid9C10h, quickPolyMid9C10h */ 4.33811913399171164864172764349193352065910816994787e-13, /* 491, accPolyMid9C10m */ 3.77816423278584625222720205783843994140625000000000e+04, /* 492, accPolyMid9C11h, quickPolyMid9C11h */ -4.21825155017599752908316500880066660420734253600372e-14, /* 493, accPolyMid9C11m */ 1.38292932619114842964336276054382324218750000000000e+05, /* 494, accPolyMid9C12h, quickPolyMid9C12h */ -2.02223055949190022685968858135129700521678830504868e-12, /* 495, accPolyMid9C12m */ 5.11733514125351735856384038925170898437500000000000e+05, /* 496, accPolyMid9C13h, quickPolyMid9C13h */ -2.25025523408315347550056625257165819446736332309911e-11, /* 497, accPolyMid9C13m */ 1.91116705355792236514389514923095703125000000000000e+06, /* 498, accPolyMid9C14h, quickPolyMid9C14h */ -6.92308947161053801527502899602797403061371639410027e-11, /* 499, accPolyMid9C14m */ 7.19450694938360899686813354492187500000000000000000e+06, /* 500, accPolyMid9C15h */ -3.25836107774239441972945896739397887709177581427866e-10, /* 501, accPolyMid9C15m */ 2.72708481033120900392532348632812500000000000000000e+07, /* 502, accPolyMid9C16h */ 1.03997450389555335044860839843750000000000000000000e+08, /* 503, accPolyMid9C17h */ 3.98720516462098360061645507812500000000000000000000e+08, /* 504, accPolyMid9C18h */ 1.53596677859462237358093261718750000000000000000000e+09, /* 505, accPolyMid9C19h */ 5.94220454070446586608886718750000000000000000000000e+09, /* 506, accPolyMid9C20h */ 2.30771902569618682861328125000000000000000000000000e+10, /* 507, accPolyMid9C21h */ 8.99354036055935974121093750000000000000000000000000e+10, /* 508, accPolyMid9C22h */ 3.51604905808161804199218750000000000000000000000000e+11, /* 509, accPolyMid9C23h */ 1.37859673609756665039062500000000000000000000000000e+12, /* 510, accPolyMid9C24h */ 5.41968316905909179687500000000000000000000000000000e+12, /* 511, accPolyMid9C25h */ 2.13586334787060429687500000000000000000000000000000e+13, /* 512, accPolyMid9C26h */ 8.43635735241271562500000000000000000000000000000000e+13, /* 513, accPolyMid9C27h */ 3.33923015327480937500000000000000000000000000000000e+14, /* 514, accPolyMid9C28h */ 1.32429009755987925000000000000000000000000000000000e+15, /* 515, accPolyMid9C29h */ 5.26147664189654100000000000000000000000000000000000e+15, /* 516, accPolyMid9C30h */ 2.09399836831170720000000000000000000000000000000000e+16, /* 517, accPolyMid9C31h */ 8.34692893106752000000000000000000000000000000000000e+16, /* 518, accPolyMid9C32h */ 3.32762568376608000000000000000000000000000000000000e+17, /* 519, accPolyMid9C33h */ 1.33003631888338841600000000000000000000000000000000e+18, /* 520, accPolyMid9C34h */ 5.62235923730283212800000000000000000000000000000000e+18, /* 521, accPolyMid9C35h */ 1.01058279621692383521501837291497341253743085794782e+00, /* 522, RN rounding constant quick poly middle 9*/ 5.78284088727747938003347592934948079832502681677348e-19, /* 523, RD rounding constant quick poly middle 9*/ -8.33333333333333287074040640618477482348680496215820e-02, /* 524, accPolyHighC1h, quickPolyHighC1h */ -4.62592926927148532830780603208030422795294098867636e-18, /* 525, accPolyHighC1m, quickPolyHighC1l */ -2.56790659251636222413745757067544746896901530409675e-34, /* 526, accPolyHighC1l */ -1.87499999999999993061106096092771622352302074432373e-02, /* 527, accPolyHighC2h, quickPolyHighC2h */ -6.93889390390722876283368680301479756432058851698546e-19, /* 528, accPolyHighC2m, quickPolyHighC2l */ 3.85185989241340205035888971870941307651344283492079e-35, /* 529, accPolyHighC2l */ -5.58035714285714298105167685548622102942317724227905e-03, /* 530, accPolyHighC3h, quickPolyHighC3h */ 1.23908819712629071293959090145008148963025205053831e-19, /* 531, accPolyHighC3m, quickPolyHighC3l */ 6.87827508933260239532125196237951282993345739214379e-36, /* 532, accPolyHighC3l */ -1.89887152777777775368439616698879035538993775844574e-03, /* 533, accPolyHighC4h, quickPolyHighC4h */ -2.40933816107889860849364897504182511872549009826894e-20, /* 534, accPolyHighC4m, quickPolyHighC4l */ -1.31413379554614650822698366533512762375439292005686e-36, /* 535, accPolyHighC4l */ -6.99129971590909120478241067786484563839621841907501e-04, /* 536, accPolyHighC5h, quickPolyHighC5h */ 2.95691501586955672658426997372092637662516651210484e-20, /* 537, accPolyHighC5m, quickPolyHighC5l */ 1.93248831638054158509225332576516713663708940033800e-36, /* 538, accPolyHighC5l */ -2.71136944110576935586948144063512700085993856191635e-04, /* 539, accPolyHighC6h, quickPolyHighC6h */ 1.25100250671414776773311485375106982275955017737813e-20, /* 540, accPolyHighC6m, quickPolyHighC6l */ -2.41797324682937785630481140742729367728409168219340e-37, /* 541, accPolyHighC6l */ -1.09100341796875005421010862427522170037264004349709e-04, /* 542, accPolyHighC7h, quickPolyHighC7h */ 5.42101086231091719294416952538483743258993211884145e-21, /* 543, accPolyHighC7m, quickPolyHighC7l */ 9.55338141209871258458343868890229946241110412925982e-38, /* 544, accPolyHighC7l */ -4.51242222505457229141112573955751940957270562648773e-05, /* 545, accPolyHighC8h, quickPolyHighC8h */ -3.18882990973711044045301474516264873522265001897356e-21, /* 546, accPolyHighC8m, quickPolyHighC8l */ 1.26912673390128847048400261536391292203355395300755e-37, /* 547, accPolyHighC8l */ -1.90656436117071843741425929419364138084347359836102e-05, /* 548, accPolyHighC9h, quickPolyHighC9h */ -1.06993691223935686411543055030763865855410413408366e-21, /* 549, accPolyHighC9m, quickPolyHighC9l */ -8.19368731407892096011823940271412425317976158112288e-06, /* 550, accPolyHighC10h, quickPolyHighC10h */ -4.03323388732262270981356256138402986149007425086112e-22, /* 551, accPolyHighC10m */ -3.57056927421818625395413641931963155684570665471256e-06, /* 552, accPolyHighC11h, quickPolyHighC11h */ 1.64796270839759047485693620137778762426170587507193e-22, /* 553, accPolyHighC11m */ -1.57402595505118377679448869038703051614902506116778e-06, /* 554, accPolyHighC12h, quickPolyHighC12h */ 1.03140748281100284102117735554826521589797225638379e-22, /* 555, accPolyHighC12m */ -7.00688192241446386609332076800260580284884781576693e-07, /* 556, accPolyHighC13h, quickPolyHighC13h */ 1.64297063257073230214010320767916245637133227760945e-23, /* 557, accPolyHighC13m */ -3.14533061665020903893046425037205438002274604514241e-07, /* 558, accPolyHighC14h, quickPolyHighC14h */ -1.57714454767442613704253788250439912924415496806915e-23, /* 559, accPolyHighC14m */ -1.42216292935838748302118661470672122959513217210770e-07, /* 560, accPolyHighC15h, quickPolyHighC15h */ 3.70163506723718792079998292841186813204562291235770e-24, /* 561, accPolyHighC15m */ -6.47111067734723877623606537110023673164960200665519e-08, /* 562, accPolyHighC16h, quickPolyHighC16h */ 1.96959302136511249382763415085950224265202199251341e-24, /* 563, accPolyHighC16m */ -2.96094098107419582578099602043070204260288846853655e-08, /* 564, accPolyHighC17h, quickPolyHighC17h */ -1.33210241793138800698071276025711826265682121011801e-25, /* 565, accPolyHighC17m */ -1.36154377785683810553931313304908135020099280154682e-08, /* 566, accPolyHighC18h, quickPolyHighC18h */ -6.28864412480332248702787563995712794007175716615166e-09, /* 567, accPolyHighC19h */ -2.91615151940413698643198065114674061293342788303562e-09, /* 568, accPolyHighC20h */ -1.35724329813454494662594037565671659106847357634251e-09, /* 569, accPolyHighC21h */ -6.33321170158103043923636695899503229467697451582353e-10, /* 570, accPolyHighC22h */ -2.98137047522453658533318439889463723202478462326326e-10, /* 571, accPolyHighC23h */ -1.35174910337425390381481209427921852395115820399951e-10, /* 572, accPolyHighC24h */ -7.57694791124210735879864558660150546803846438592700e-11, /* 573, accPolyHighC25h */ -1.19244777215077355372683280351504137017926154840097e-11, /* 574, accPolyHighC26h */ -4.08879979855917754145740023360966995669141255120849e-11, /* 575, accPolyHighC27h */ 1.75342081019476863949528641668112755730435381451571e-11, /* 576, accPolyHighC28h */ -1.60530246587119583502980643958298338953849526689055e-11, /* 577, accPolyHighC29h */ 1.00010073610227913567190400341090722191910177379040e+00, /* 578, RN rounding constant quick poly high*/ 5.59129439367752644847269214347219849204178767344215e-21, /* 579, RD rounding constant quick poly high*/ }; interval-3.2.0/src/crlibm/asin-td.c0000644000000000000000000012737213316017127015245 0ustar 00000000000000/* * Correctly rounded arcsine * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Christoph Lauter (ENS Lyon) * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "asin-td.h" #define AVOID_FMA 1 void asin_accurate_lower(double *asinh, double *asinm, double *asinl, double x, double xSqh, double xSql, double sign) { double highPoly; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l; double tt1h, tt1l; double t8h, t8m, t8l, t9h, t9m, t9l, t10h, t10m, t10l, t11h, t11m, t11l, t12h, t12m, t12l; double tt8h, tt8m, tt8l, tt9h, tt9m, tt9l, tt10h, tt10m, tt10l, tt11h, tt11m, tt11l, tt12h, tt12m, tt12l; double xCubeh, xCubem, xCubel, tt13h, tt13m, tt13l, t13h, t13m, t13l, polyh, polym, polyl; double tt11hover, tt11mover, tt11lover; #if EVAL_PERF crlibm_second_step_taken++; #endif /* Evaluate the polynomial of degree 37 Its coefficients start at tbl[0] p(x) = x + x * x^2 * (c3 + x^2 * (c5 + ... We receive x^2 as xSqh + xSql = x * x (exactly) in argument |x| <= 0.185 = 2^(-2.43) Compute monomials 27 to 37 in double precision monomials 13 to 25 in double-double and 1 to 11 in triple-double precision in a modified Horner form */ /* Double computations */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(tbl[33],xSqh,tbl[32]),xSqh,tbl[31]),xSqh,tbl[30]),xSqh,tbl[29]),xSqh,tbl[28]); #else highPoly = tbl[28] + xSqh * (tbl[29] + xSqh * (tbl[30] + xSqh * (tbl[31] + xSqh * (tbl[32] + xSqh * tbl[33])))); #endif /* Double-double computations */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[27],0,tt1h,tt1l); MulAdd22(&t2h,&t2l,tbl[25],tbl[26],xSqh,xSql,t1h,t1l); MulAdd22(&t3h,&t3l,tbl[23],tbl[24],xSqh,xSql,t2h,t2l); MulAdd22(&t4h,&t4l,tbl[21],tbl[22],xSqh,xSql,t3h,t3l); MulAdd22(&t5h,&t5l,tbl[19],tbl[20],xSqh,xSql,t4h,t4l); MulAdd22(&t6h,&t6l,tbl[17],tbl[18],xSqh,xSql,t5h,t5l); MulAdd22(&t7h,&t7l,tbl[15],tbl[16],xSqh,xSql,t6h,t6l); /* Triple-double computations */ Mul23(&tt8h,&tt8m,&tt8l,xSqh,xSql,t7h,t7l); /* 149 - 48/53 */ Add33(&t8h,&t8m,&t8l,tbl[12],tbl[13],tbl[14],tt8h,tt8m,tt8l); /* 145 - 43/53 */ Mul233(&tt9h,&tt9m,&tt9l,xSqh,xSql,t8h,t8m,t8l); /* 139 - 39/53 */ Add33(&t9h,&t9m,&t9l,tbl[9],tbl[10],tbl[11],tt9h,tt9m,tt9l); /* 136 - 34/53 */ Mul233(&tt10h,&tt10m,&tt10l,xSqh,xSql,t9h,t9m,t9l); /* 130 - 30/53 */ Add33(&t10h,&t10m,&t10l,tbl[6],tbl[7],tbl[8],tt10h,tt10m,tt10l); /* 127 - 25/53 */ Mul233(&tt11hover,&tt11mover,&tt11lover,xSqh,xSql,t10h,t10m,t10l); /* 121 - 21/53 */ Renormalize3(&tt11h,&tt11m,&tt11l,tt11hover,tt11mover,tt11lover); /* infty - 52/53 */ Add33(&t11h,&t11m,&t11l,tbl[3],tbl[4],tbl[5],tt11h,tt11m,tt11l); /* 149 - 47/53 */ Mul233(&tt12h,&tt12m,&tt12l,xSqh,xSql,t11h,t11m,t11l); /* 143 - 43/53 */ Add33(&t12h,&t12m,&t12l,tbl[0],tbl[1],tbl[2],tt12h,tt12m,tt12l); /* 140 - 38/53 */ Mul123(&xCubeh,&xCubem,&xCubel,x,xSqh,xSql); /* 154 - 47/53 */ Mul33(&tt13h,&tt13m,&tt13l,xCubeh,xCubem,xCubel,t12h,t12m,t12l); /* 136 - 34/53 */ Add133(&t13h,&t13m,&t13l,x,tt13h,tt13m,tt13l); /* 138 - 32/53 */ Renormalize3(&polyh,&polym,&polyl,t13h,t13m,t13l); /* infty - 52/53 */ *asinh = sign * polyh; *asinm = sign * polym; *asinl = sign * polyl; } void asin_accurate_middle(double *asinh, double *asinm, double *asinl, double z, int i, double sign) { double highPoly; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l, t8h, t8l, t9h, t9l; double t10h, t10m, t10l, t11h, t11m, t11l, t12h, t12m, t12l, t13h, t13m, t13l, t14h, t14m, t14l; double t15h, t15m, t15l, t16h, t16m, t16l; double tt1h, tt1l; double tt10h, tt10m, tt10l, tt11h, tt11m, tt11l, tt12h, tt12m, tt12l; double tt13h, tt13m, tt13l, tt14h, tt14m, tt14l, tt15h, tt15m, tt15l, tt16h, tt16m, tt16l; double polyh, polym, polyl, tt13hover, tt13mover, tt13lover; #if EVAL_PERF crlibm_second_step_taken++; #endif /* Evaluate the polynomial of degree 35 Its coefficients start at tbl[i+1] Evaluate degrees 35 to 20 in double precision, degrees 20 to 7 in double-double precision and finally degrees 6 to 1 in triple-double. The constant coefficient is a double-double, the computations are nevertheless in triple-double */ /* Double computations */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[i+58] ,z,tbl[i+57]),z,tbl[i+56]),z,tbl[i+55]),z,tbl[i+54]),z, tbl[i+53]),z,tbl[i+52]),z,tbl[i+51]),z,tbl[i+50]),z,tbl[i+49]),z, tbl[i+48]),z,tbl[i+47]),z,tbl[i+46]),z,tbl[i+45]),z,tbl[i+44]),z, tbl[i+43]),z,tbl[i+42]),z,tbl[i+41]),z,tbl[i+40]),z,tbl[i+39]); #else highPoly = tbl[i+39] + z * (tbl[i+40] + z * (tbl[i+41] + z * (tbl[i+42] + z * ( tbl[i+43] + z * (tbl[i+44] + z * (tbl[i+45] + z * (tbl[i+46] + z * ( tbl[i+47] + z * (tbl[i+48] + z * (tbl[i+49] + z * (tbl[i+50] + z * ( tbl[i+51] + z * (tbl[i+52] + z * (tbl[i+53] + z * (tbl[i+54] + z * ( tbl[i+55] + z * (tbl[i+56] + z * (tbl[i+57] + z * tbl[i+58])))))))))))))))))); #endif /* Double-double computations */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+37],tbl[i+38],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+35],tbl[i+36],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+33],tbl[i+34],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+31],tbl[i+32],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+29],tbl[i+30],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+27],tbl[i+28],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[i+25],tbl[i+26],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[i+23],tbl[i+24],z,t7h,t7l); MulAdd212(&t9h,&t9l,tbl[i+21],tbl[i+22],z,t8h,t8l); /* Triple-double computations */ Mul123(&tt10h,&tt10m,&tt10l,z,t9h,t9l); /* 154 - 47/53 */ Add33(&t10h,&t10m,&t10l,tbl[i+18],tbl[i+19],tbl[i+20],tt10h,tt10m,tt10l); /* 144 - 42/53 */ Mul133(&tt11h,&tt11m,&tt11l,z,t10h,t10m,t10l); /* 142 - 38/53 */ Add33(&t11h,&t11m,&t11l,tbl[i+15],tbl[i+16],tbl[i+17],tt11h,tt11m,tt11l); /* 136 - 33/53 */ Mul133(&tt12h,&tt12m,&tt12l,z,t11h,t11m,t11l); /* 133 - 28/53 */ Add33(&t12h,&t12m,&t12l,tbl[i+12],tbl[i+13],tbl[i+14],tt12h,tt12m,tt12l); /* 125 - 23/53 */ Mul133(&tt13hover,&tt13mover,&tt13lover,z,t12h,t12m,t12l); /* 123 - 18/53 */ Renormalize3(&tt13h,&tt13m,&tt13l,tt13hover,tt13mover,tt13lover); /* infty - 52/53 */ Add33(&t13h,&t13m,&t13l,tbl[i+9],tbl[i+10],tbl[i+11],tt13h,tt13m,tt13l); /* 149 - 47/53 */ Mul133(&tt14h,&tt14m,&tt14l,z,t13h,t13m,t13l); /* 147 - 42/53 */ Add33(&t14h,&t14m,&t14l,tbl[i+6],tbl[i+7],tbl[i+8],tt14h,tt14m,tt14l); /* 139 - 37/53 */ Mul133(&tt15h,&tt15m,&tt15l,z,t14h,t14m,t14l); /* 137 - 32/53 */ Add33(&t15h,&t15m,&t15l,tbl[i+3],tbl[i+4],tbl[i+5],tt15h,tt15m,tt15l); /* 129 - 28/53 */ Mul133(&tt16h,&tt16m,&tt16l,z,t15h,t15m,t15l); /* 128 - 23/53 */ Add233(&t16h,&t16m,&t16l,tbl[i+1],tbl[i+2],tt16h,tt16m,tt16l); /* 126 - 19/53 */ Renormalize3(&polyh,&polym,&polyl,t16h,t16m,t16l); /* infty - 52/53 */ *asinh = sign * polyh; *asinm = sign * polym; *asinl = sign * polyl; } void asin_accurate_higher(double *asinh, double *asinm, double *asinl, double z, double sign) { double highPoly; double tt1h, tt1l; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l, t8h, t8l; double tt10h, tt10m, tt10l, tt11h, tt11m, tt11l, tt12h, tt12m, tt12l, tt13h, tt13m, tt13l; double tt14h, tt14m, tt14l, tt15h, tt15m, tt15l, tt16h, tt16m, tt16l, tt17h, tt17m, tt17l; double t9h, t9l, t10h, t10m, t10l, t11h, t11m, t11l, t12h, t12m, t12l, t13h, t13m, t13l; double t14h, t14m, t14l, t15h, t15m, t15l, t16h, t16m, t16l, t17h, t17m, t17l; double tt18h, tt18m, tt18l, polyh, polym, polyl; double sqrtzh, sqrtzm, sqrtzl, twoZ, pTimesSh, pTimesSm, pTimesSl; double allhover, allmover, alllover, allh, allm, alll; double tt13hover, tt13mover, tt13lover, tt16hover, tt16mover, tt16lover; #if EVAL_PERF crlibm_second_step_taken++; #endif /* We evaluate asin(x) as asin(x) = f(z) * sqrt(2*z) + Pi/2 with z = 1 - x and f(z) = (asin(z) - Pi/2) / sqrt(2*z) f(z) is approximated by p(z) The polynomial p(z) is of degree 29 Its coefficients start at tbl[TBLIDX10] Coefficients for degrees 29 to 18 are in double precision, for degrees 17 to 9 in double-double precision and finally for degrees 8 to 1 in triple-double. The constant coefficient (-1) is not stored in the table, the computations are nevertheless in triple-double We evaluate the monomials in the precision in which the correspondant coefficients are stored The coefficients' values decrease very quickly so even with |z| < 2^-2.18 we can compute degree 18 already in double precision Compute than sqrt(2*z) as a triple-double multiply in triple-double and add Pi/2 We will cancel no bit in the addition since f(z) < 0.5 * Pi/2 */ /* Double computations */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[TBLIDX10+53] ,z,tbl[TBLIDX10+52]),z,tbl[TBLIDX10+51]),z, tbl[TBLIDX10+50]),z,tbl[TBLIDX10+49]),z,tbl[TBLIDX10+48]),z, tbl[TBLIDX10+47]),z,tbl[TBLIDX10+46]),z,tbl[TBLIDX10+45]),z, tbl[TBLIDX10+44]),z,tbl[TBLIDX10+43]),z,tbl[TBLIDX10+42]); #else highPoly = tbl[TBLIDX10+42] + z * (tbl[TBLIDX10+43] + z * (tbl[TBLIDX10+44] + z * ( tbl[TBLIDX10+45] + z * (tbl[TBLIDX10+46] + z * (tbl[TBLIDX10+47] + z * ( tbl[TBLIDX10+48] + z * (tbl[TBLIDX10+49] + z * (tbl[TBLIDX10+50] + z * ( tbl[TBLIDX10+51] + z * (tbl[TBLIDX10+52] + z * tbl[TBLIDX10+53])))))))))); #endif /* Double-double computations */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+40],tbl[TBLIDX10+41],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+38],tbl[TBLIDX10+39],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+36],tbl[TBLIDX10+37],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+34],tbl[TBLIDX10+35],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+32],tbl[TBLIDX10+33],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+30],tbl[TBLIDX10+31],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+28],tbl[TBLIDX10+29],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+26],tbl[TBLIDX10+27],z,t7h,t7l); MulAdd212(&t9h,&t9l,tbl[TBLIDX10+24],tbl[TBLIDX10+25],z,t8h,t8l); /* Triple-double computations */ Mul123(&tt10h,&tt10m,&tt10l,z,t9h,t9l); /* 154 - 47/53 */ Add33(&t10h,&t10m,&t10l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tbl[TBLIDX10+23],tt10h,tt10m,tt10l); /* 144 - 42/53 */ Mul133(&tt11h,&tt11m,&tt11l,z,t10h,t10m,t10l); /* 142 - 37/53 */ Add33(&t11h,&t11m,&t11l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],tbl[TBLIDX10+20],tt11h,tt11m,tt11l); /* 134 - 32/53 */ Mul133(&tt12h,&tt12m,&tt12l,z,t11h,t11m,t11l); /* 132 - 27/53 */ Add33(&t12h,&t12m,&t12l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],tbl[TBLIDX10+17],tt12h,tt12m,tt12l); /* 124 - 22/53 */ Mul133(&tt13hover,&tt13mover,&tt13lover,z,t12h,t12m,t12l); /* 122 - 17/53 */ Renormalize3(&tt13h,&tt13m,&tt13l,tt13hover,tt13mover,tt13lover); /* infty - 52/53 */ Add33(&t13h,&t13m,&t13l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],tbl[TBLIDX10+14],tt13h,tt13m,tt13l); /* 149 - 47/53 */ Mul133(&tt14h,&tt14m,&tt14l,z,t13h,t13m,t13l); /* 147 - 42/53 */ Add33(&t14h,&t14m,&t14l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],tbl[TBLIDX10+11],tt14h,tt14m,tt14l); /* 139 - 37/53 */ Mul133(&tt15h,&tt15m,&tt15l,z,t14h,t14m,t14l); /* 137 - 32/53 */ Add33(&t15h,&t15m,&t15l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],tbl[TBLIDX10+8],tt15h,tt15m,tt15l); /* 129 - 27/53 */ Mul133(&tt16hover,&tt16mover,&tt16lover,z,t15h,t15m,t15l); /* 127 - 22/53 */ Renormalize3(&tt16h,&tt16m,&tt16l,tt16hover,tt16mover,tt16lover); /* infty - 52/53 */ Add33(&t16h,&t16m,&t16l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],tbl[TBLIDX10+5],tt16h,tt16m,tt16l); /* 149 - 47/53 */ Mul133(&tt17h,&tt17m,&tt17l,z,t16h,t16m,t16l); /* 147 - 42/53 */ Add33(&t17h,&t17m,&t17l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],tbl[TBLIDX10+2],tt17h,tt17m,tt17l); /* 139 - 37/53 */ Mul133(&tt18h,&tt18m,&tt18l,z,t17h,t17m,t17l); /* 137 - 32/53 */ Add133(&polyh,&polym,&polyl,-1,tt18h,tt18m,tt18l); /* 136 - 30/53 */ /* Compute sqrt(2*z) as a triple-double */ twoZ = 2 * z; Sqrt13(&sqrtzh,&sqrtzm,&sqrtzl,twoZ); /* 146 - 52/53 */ /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul33(&pTimesSh,&pTimesSm,&pTimesSl,polyh,polym,polyl,sqrtzh,sqrtzm,sqrtzl); /* 128 - 26/53 */ Add33(&allhover,&allmover,&alllover,PIHALFH,PIHALFM,PIHALFL,pTimesSh,pTimesSm,pTimesSl); /* 126 - 21/53 */ /* Renormalize and multiply by sign */ Renormalize3(&allh,&allm,&alll,allhover,allmover,alllover); /* infty - 52/53 */ *asinh = sign * allh; *asinm = sign * allm; *asinl = sign * alll; } double asin_rn(double x) { db_number xdb; double sign, z, asinh, asinm, asinl; int i; double xSqh, xSql; double tt1h, tt1l; double tt6h, tt6l; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l; double t7h, t7l, t8h, t8l, polyh, polyl, twoZ, sqrtzh, sqrtzl; double pTimesSh, pTimesSl, allh, alll, highPoly, xCubeh, xCubel; double tmp1, tmp2, tmp3, tmp4, tmp5; /* Transform the argument into integer */ xdb.d = x; /* Special case handling */ /* Strip off the sign of argument x */ if (xdb.i[HI] & 0x80000000) sign = -1; else sign = 1; xdb.i[HI] &= 0x7fffffff; /* asin is defined on -1 <= x <= 1, elsewhere it is NaN */ if ((xdb.i[HI] > 0x3ff00000) || ((xdb.i[HI] == 0x3ff00000) && (xdb.i[LO] != 0x00000000))) { return (x-x)/0.0; /* return NaN */ } /* If |x| < 2^(-28) we have arcsin(x) = x * ( 1 + xi ) with 0 <= xi < 2^(-55) So we can decide the rounding without any computation */ if (xdb.i[HI] < 0x3e300000) { return x; } /* Recast x */ x = xdb.d; /* Find correspondant interval and compute index to the table We start by filtering the two special cases around 0 and 1 */ if (xdb.i[HI] < BOUND1) { /* Special interval 0..BOUND1 The polynomial has no even monomials We must prove extra accuracy in the interval 0..sin(2^(-18)) */ /* Quick phase starts */ /* Compute square of x for both quick and accurate phases */ Mul12(&xSqh,&xSql,x,x); tmp4 = tbl[3]; tmp5 = tbl[4]; t4h = tmp4; t4l = tmp5; if (xdb.i[HI] > EXTRABOUND) { /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(tbl[23],xSqh,tbl[21]),xSqh,tbl[19]),xSqh,tbl[17]),xSqh,tbl[15]); #else highPoly = tbl[15] + xSqh * (tbl[17] + xSqh * (tbl[19] + xSqh * (tbl[21] + xSqh * tbl[23]))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[12],tbl[13],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[9],tbl[10],xSqh,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[6],tbl[7],xSqh,t2h,t2l); MulAdd22(&t4h,&t4l,tmp4,tmp5,xSqh,xSql,t3h,t3l); } MulAdd22(&t5h,&t5l,tbl[0],tbl[1],xSqh,xSql,t4h,t4l); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt6h,&tt6l,xCubeh,xCubel,t5h,t5l); Add12(tmp1,tmp2,x,tt6h); tmp3 = tmp2 + tt6l; Add12(polyh,polyl,tmp1,tmp3); /* Multiply by sign */ asinh = sign * polyh; asinm = sign * polyl; /* Rounding test (on polyh+polyl, equivalently to asinh+asinm) The RN rounding constant is at tbl[34] */ if(polyh == (polyh + (polyl * tbl[34]))) return asinh; /* Launch accurate phase */ asin_accurate_lower(&asinh,&asinm,&asinl,x,xSqh,xSql,sign); ReturnRoundToNearest3(asinh,asinm,asinl); } if (xdb.i[HI] >= BOUND9) { /* Special interval BOUND9..1 We use an asymptotic development of arcsin in sqrt(1 - x) */ /* Argument reduction for quick and accurate phase z = 1 - x The operation is exact as per Sterbenz' lemma */ z = 1 - x; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[TBLIDX10+42] ,z,tbl[TBLIDX10+40]),z,tbl[TBLIDX10+38]),z, tbl[TBLIDX10+36]),z,tbl[TBLIDX10+34]),z,tbl[TBLIDX10+32]),z, tbl[TBLIDX10+30]),z,tbl[TBLIDX10+28]),z,tbl[TBLIDX10+26]),z, tbl[TBLIDX10+24]); #else highPoly = tbl[TBLIDX10+24] + z * (tbl[TBLIDX10+26] + z * (tbl[TBLIDX10+28] + z * ( tbl[TBLIDX10+30] + z * (tbl[TBLIDX10+32] + z * (tbl[TBLIDX10+34] + z * ( tbl[TBLIDX10+36] + z * (tbl[TBLIDX10+38] + z * (tbl[TBLIDX10+40] + z * tbl[TBLIDX10+42])))))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],z,t7h,t7l); MulAdd212(&polyh,&polyl,-1,0,z,t8h,t8l); /* Compute sqrt(2*z) as a double-double */ twoZ = 2 * z; sqrt12(&sqrtzh,&sqrtzl,twoZ); /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul22(&pTimesSh,&pTimesSl,polyh,polyl,sqrtzh,sqrtzl); Add22(&allh,&alll,PIHALFH,PIHALFM,pTimesSh,pTimesSl); /* Multiply by sign */ asinh = sign * allh; asinm = sign * alll; /* Rounding test The RN rounding constant is at tbl[TBLIDX10+54] */ if(allh == (allh + (alll * tbl[TBLIDX10+54]))) return asinh; /* Launch accurate phase */ asin_accurate_higher(&asinh,&asinm,&asinl,z,sign); ReturnRoundToNearest3(asinh,asinm,asinl); } /* General 8 main intervals We can already suppose that BOUND1 <= x <= BOUND9 */ if (xdb.i[HI] < BOUND5) { if (xdb.i[HI] < BOUND3) { if (xdb.i[HI] < BOUND2) i = TBLIDX2; else i = TBLIDX3; } else { if (xdb.i[HI] < BOUND4) i = TBLIDX4; else i = TBLIDX5; } } else { if (xdb.i[HI] < BOUND7) { if (xdb.i[HI] < BOUND6) i = TBLIDX6; else i = TBLIDX7; } else { if (xdb.i[HI] < BOUND8) i = TBLIDX8; else i = TBLIDX9; } } /* Argument reduction i points to the interval midpoint value in the table */ z = x - tbl[i]; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[i+35] ,z,tbl[i+33]),z,tbl[i+31]),z,tbl[i+29]),z, tbl[i+27]),z,tbl[i+25]),z,tbl[i+23]),z,tbl[i+21]); #else highPoly = tbl[i+21] + z * (tbl[i+23] + z * (tbl[i+25] + z * ( tbl[i+27] + z * (tbl[i+29] + z * (tbl[i+31] + z * ( tbl[i+33] + z * tbl[i+35])))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+18],tbl[i+19],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+15],tbl[i+16],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+12],tbl[i+13],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+9],tbl[i+10],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+6],tbl[i+7],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+3],tbl[i+4],z,t5h,t5l); MulAdd212(&polyh,&polyl,tbl[i+1],tbl[i+2],z,t6h,t6l); /* Multiply by sign */ asinh = sign * polyh; asinm = sign * polyl; /* Rounding test The RN rounding constant is at tbl[i+59] */ if(polyh == (polyh + (polyl * tbl[i+59]))) return asinh; /* Launch accurate phase */ asin_accurate_middle(&asinh,&asinm,&asinl,z,i,sign); ReturnRoundToNearest3(asinh,asinm,asinl); } double asin_ru(double x) { db_number xdb; double sign, z, asinh, asinm, asinl; int i; double xSqh, xSql; double tt1h, tt1l; double tt6h, tt6l; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l; double t7h, t7l, t8h, t8l, polyh, polyl, twoZ, sqrtzh, sqrtzl; double pTimesSh, pTimesSl, allh, alll, highPoly, xCubeh, xCubel; double tmp1, tmp2, tmp3, tmp4, tmp5; /* Transform the argument into integer */ xdb.d = x; /* Special case handling */ /* Strip off the sign of argument x */ if (xdb.i[HI] & 0x80000000) sign = -1; else sign = 1; xdb.i[HI] &= 0x7fffffff; /* asin is defined on -1 <= x <= 1, elsewhere it is NaN */ if ((xdb.i[HI] > 0x3ff00000) || ((xdb.i[HI] == 0x3ff00000) && (xdb.i[LO] != 0x00000000))) { return (x-x)/0.0; /* return NaN */ } /* If |x| < 2^(-28) we have arcsin(x) = x * ( 1 + xi ) with 0 <= xi < 2^(-55) So we can decide the rounding without any computation */ if (xdb.i[HI] < 0x3e300000) { /* If x == 0 then we got the algebraic result arcsin(0) = 0 If x < 0 then the truncation rest is negative but less than 1 ulp; we round upwards by returning x */ if (x <= 0) return x; /* Otherwise the rest is positive, less than 1 ulp and the image is not algebraic We return x + 1ulp */ xdb.l++; return xdb.d; } /* Recast x */ x = xdb.d; /* Find correspondant interval and compute index to the table We start by filtering the two special cases around 0 and 1 */ if (xdb.i[HI] < BOUND1) { /* Special interval 0..BOUND1 The polynomial has no even monomials We must prove extra accuracy in the interval 0..sin(2^(-18)) */ /* Quick phase starts */ /* Compute square of x for both quick and accurate phases */ Mul12(&xSqh,&xSql,x,x); tmp4 = tbl[3]; tmp5 = tbl[4]; t4h = tmp4; t4l = tmp5; if (xdb.i[HI] > EXTRABOUND) { /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(tbl[23],xSqh,tbl[21]),xSqh,tbl[19]),xSqh,tbl[17]),xSqh,tbl[15]); #else highPoly = tbl[15] + xSqh * (tbl[17] + xSqh * (tbl[19] + xSqh * (tbl[21] + xSqh * tbl[23]))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[12],tbl[13],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[9],tbl[10],xSqh,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[6],tbl[7],xSqh,t2h,t2l); MulAdd22(&t4h,&t4l,tmp4,tmp5,xSqh,xSql,t3h,t3l); } MulAdd22(&t5h,&t5l,tbl[0],tbl[1],xSqh,xSql,t4h,t4l); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt6h,&tt6l,xCubeh,xCubel,t5h,t5l); Add12(tmp1,tmp2,x,tt6h); tmp3 = tmp2 + tt6l; Add12(polyh,polyl,tmp1,tmp3); /* Multiply by sign */ asinh = sign * polyh; asinm = sign * polyl; /* Rounding test The RU rounding constant is at tbl[35] */ TEST_AND_RETURN_RU(asinh, asinm, tbl[35]); /* Launch accurate phase */ asin_accurate_lower(&asinh,&asinm,&asinl,x,xSqh,xSql,sign); ReturnRoundUpwards3(asinh,asinm,asinl); } if (xdb.i[HI] > BOUND9) { /* Special interval BOUND9..1 We use an asymptotic development of arcsin in sqrt(1 - x) */ /* Argument reduction for quick and accurate phase z = 1 - x The operation is exact as per Sterbenz' lemma */ z = 1 - x; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[TBLIDX10+42] ,z,tbl[TBLIDX10+40]),z,tbl[TBLIDX10+38]),z, tbl[TBLIDX10+36]),z,tbl[TBLIDX10+34]),z,tbl[TBLIDX10+32]),z, tbl[TBLIDX10+30]),z,tbl[TBLIDX10+28]),z,tbl[TBLIDX10+26]),z, tbl[TBLIDX10+24]); #else highPoly = tbl[TBLIDX10+24] + z * (tbl[TBLIDX10+26] + z * (tbl[TBLIDX10+28] + z * ( tbl[TBLIDX10+30] + z * (tbl[TBLIDX10+32] + z * (tbl[TBLIDX10+34] + z * ( tbl[TBLIDX10+36] + z * (tbl[TBLIDX10+38] + z * (tbl[TBLIDX10+40] + z * tbl[TBLIDX10+42])))))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],z,t7h,t7l); MulAdd212(&polyh,&polyl,-1,0,z,t8h,t8l); /* Compute sqrt(2*z) as a double-double */ twoZ = 2 * z; sqrt12(&sqrtzh,&sqrtzl,twoZ); /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul22(&pTimesSh,&pTimesSl,polyh,polyl,sqrtzh,sqrtzl); Add22(&allh,&alll,PIHALFH,PIHALFM,pTimesSh,pTimesSl); /* Multiply by sign */ asinh = sign * allh; asinm = sign * alll; /* Rounding test The RU rounding constant is at tbl[TBLIDX10+55] */ TEST_AND_RETURN_RU(asinh, asinm, tbl[TBLIDX10+55]); /* Launch accurate phase */ asin_accurate_higher(&asinh,&asinm,&asinl,z,sign); ReturnRoundUpwards3(asinh,asinm,asinl); } /* General 8 main intervals We can already suppose that BOUND1 <= x <= BOUND9 */ if (xdb.i[HI] < BOUND5) { if (xdb.i[HI] < BOUND3) { if (xdb.i[HI] < BOUND2) i = TBLIDX2; else i = TBLIDX3; } else { if (xdb.i[HI] < BOUND4) i = TBLIDX4; else i = TBLIDX5; } } else { if (xdb.i[HI] < BOUND7) { if (xdb.i[HI] < BOUND6) i = TBLIDX6; else i = TBLIDX7; } else { if (xdb.i[HI] < BOUND8) i = TBLIDX8; else i = TBLIDX9; } } /* Argument reduction i points to the interval midpoint value in the table */ z = x - tbl[i]; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[i+35] ,z,tbl[i+33]),z,tbl[i+31]),z,tbl[i+29]),z, tbl[i+27]),z,tbl[i+25]),z,tbl[i+23]),z,tbl[i+21]); #else highPoly = tbl[i+21] + z * (tbl[i+23] + z * (tbl[i+25] + z * ( tbl[i+27] + z * (tbl[i+29] + z * (tbl[i+31] + z * ( tbl[i+33] + z * tbl[i+35])))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+18],tbl[i+19],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+15],tbl[i+16],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+12],tbl[i+13],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+9],tbl[i+10],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+6],tbl[i+7],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+3],tbl[i+4],z,t5h,t5l); MulAdd212(&polyh,&polyl,tbl[i+1],tbl[i+2],z,t6h,t6l); /* Multiply by sign */ asinh = sign * polyh; asinm = sign * polyl; /* Rounding test The RU rounding constant is at tbl[i+60] */ TEST_AND_RETURN_RU(asinh, asinm, tbl[i+60]); /* Launch accurate phase */ asin_accurate_middle(&asinh,&asinm,&asinl,z,i,sign); ReturnRoundUpwards3(asinh,asinm,asinl); } double asin_rd(double x) { db_number xdb; double sign, z, asinh, asinm, asinl; int i; double xSqh, xSql; double tt1h, tt1l; double tt6h, tt6l; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l; double t7h, t7l, t8h, t8l, polyh, polyl, twoZ, sqrtzh, sqrtzl; double pTimesSh, pTimesSl, allh, alll, highPoly, xCubeh, xCubel; double tmp1, tmp2, tmp3, tmp4, tmp5; /* Transform the argument into integer */ xdb.d = x; /* Special case handling */ /* Strip off the sign of argument x */ if (xdb.i[HI] & 0x80000000) sign = -1; else sign = 1; xdb.i[HI] &= 0x7fffffff; /* asin is defined on -1 <= x <= 1, elsewhere it is NaN */ if ((xdb.i[HI] > 0x3ff00000) || ((xdb.i[HI] == 0x3ff00000) && (xdb.i[LO] != 0x00000000))) { return (x-x)/0.0; /* return NaN */ } /* If |x| < 2^(-28) we have arcsin(x) = x * ( 1 + xi ) with 0 <= xi < 2^(-55) So we can decide the rounding without any computation */ if (xdb.i[HI] < 0x3e300000) { /* If x == 0 then we got the algebraic result arcsin(0) = 0 If x > 0 then the truncation rest is positive but less than 1 ulp; we round downwards by returning x */ if (x >= 0) return x; /* Otherwise the rest is negative, less than 1 ulp and the image is not algebraic We return x - 1ulp We stripped off the sign, so we add 1 ulp to -x (in xdb.d) and multiply by -1 */ xdb.l++; return -1 * xdb.d; } /* Recast x */ x = xdb.d; /* Find correspondant interval and compute index to the table We start by filtering the two special cases around 0 and 1 */ if (xdb.i[HI] < BOUND1) { /* Special interval 0..BOUND1 The polynomial has no even monomials We must prove extra accuracy in the interval 0..sin(2^(-18)) */ /* Quick phase starts */ /* Compute square of x for both quick and accurate phases */ Mul12(&xSqh,&xSql,x,x); tmp4 = tbl[3]; tmp5 = tbl[4]; t4h = tmp4; t4l = tmp5; if (xdb.i[HI] > EXTRABOUND) { /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(tbl[23],xSqh,tbl[21]),xSqh,tbl[19]),xSqh,tbl[17]),xSqh,tbl[15]); #else highPoly = tbl[15] + xSqh * (tbl[17] + xSqh * (tbl[19] + xSqh * (tbl[21] + xSqh * tbl[23]))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[12],tbl[13],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[9],tbl[10],xSqh,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[6],tbl[7],xSqh,t2h,t2l); MulAdd22(&t4h,&t4l,tmp4,tmp5,xSqh,xSql,t3h,t3l); } MulAdd22(&t5h,&t5l,tbl[0],tbl[1],xSqh,xSql,t4h,t4l); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt6h,&tt6l,xCubeh,xCubel,t5h,t5l); Add12(tmp1,tmp2,x,tt6h); tmp3 = tmp2 + tt6l; Add12(polyh,polyl,tmp1,tmp3); /* Multiply by sign */ asinh = sign * polyh; asinm = sign * polyl; /* Rounding test The RD rounding constant is at tbl[35] */ TEST_AND_RETURN_RD(asinh, asinm, tbl[35]); /* Launch accurate phase */ asin_accurate_lower(&asinh,&asinm,&asinl,x,xSqh,xSql,sign); ReturnRoundDownwards3(asinh,asinm,asinl); } if (xdb.i[HI] > BOUND9) { /* Special interval BOUND9..1 We use an asymptotic development of arcsin in sqrt(1 - x) */ /* Argument reduction for quick and accurate phase z = 1 - x The operation is exact as per Sterbenz' lemma */ z = 1 - x; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[TBLIDX10+42] ,z,tbl[TBLIDX10+40]),z,tbl[TBLIDX10+38]),z, tbl[TBLIDX10+36]),z,tbl[TBLIDX10+34]),z,tbl[TBLIDX10+32]),z, tbl[TBLIDX10+30]),z,tbl[TBLIDX10+28]),z,tbl[TBLIDX10+26]),z, tbl[TBLIDX10+24]); #else highPoly = tbl[TBLIDX10+24] + z * (tbl[TBLIDX10+26] + z * (tbl[TBLIDX10+28] + z * ( tbl[TBLIDX10+30] + z * (tbl[TBLIDX10+32] + z * (tbl[TBLIDX10+34] + z * ( tbl[TBLIDX10+36] + z * (tbl[TBLIDX10+38] + z * (tbl[TBLIDX10+40] + z * tbl[TBLIDX10+42])))))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],z,t7h,t7l); MulAdd212(&polyh,&polyl,-1,0,z,t8h,t8l); /* Compute sqrt(2*z) as a double-double */ twoZ = 2 * z; sqrt12(&sqrtzh,&sqrtzl,twoZ); /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul22(&pTimesSh,&pTimesSl,polyh,polyl,sqrtzh,sqrtzl); Add22(&allh,&alll,PIHALFH,PIHALFM,pTimesSh,pTimesSl); /* Multiply by sign */ asinh = sign * allh; asinm = sign * alll; /* Rounding test The RD rounding constant is at tbl[TBLIDX10+55] */ TEST_AND_RETURN_RD(asinh, asinm, tbl[TBLIDX10+55]); /* Launch accurate phase */ asin_accurate_higher(&asinh,&asinm,&asinl,z,sign); ReturnRoundDownwards3(asinh,asinm,asinl); } /* General 8 main intervals We can already suppose that BOUND1 <= x <= BOUND9 */ if (xdb.i[HI] < BOUND5) { if (xdb.i[HI] < BOUND3) { if (xdb.i[HI] < BOUND2) i = TBLIDX2; else i = TBLIDX3; } else { if (xdb.i[HI] < BOUND4) i = TBLIDX4; else i = TBLIDX5; } } else { if (xdb.i[HI] < BOUND7) { if (xdb.i[HI] < BOUND6) i = TBLIDX6; else i = TBLIDX7; } else { if (xdb.i[HI] < BOUND8) i = TBLIDX8; else i = TBLIDX9; } } /* Argument reduction i points to the interval midpoint value in the table */ z = x - tbl[i]; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[i+35] ,z,tbl[i+33]),z,tbl[i+31]),z,tbl[i+29]),z, tbl[i+27]),z,tbl[i+25]),z,tbl[i+23]),z,tbl[i+21]); #else highPoly = tbl[i+21] + z * (tbl[i+23] + z * (tbl[i+25] + z * ( tbl[i+27] + z * (tbl[i+29] + z * (tbl[i+31] + z * ( tbl[i+33] + z * tbl[i+35])))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+18],tbl[i+19],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+15],tbl[i+16],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+12],tbl[i+13],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+9],tbl[i+10],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+6],tbl[i+7],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+3],tbl[i+4],z,t5h,t5l); MulAdd212(&polyh,&polyl,tbl[i+1],tbl[i+2],z,t6h,t6l); /* Multiply by sign */ asinh = sign * polyh; asinm = sign * polyl; /* Rounding test The RD rounding constant is at tbl[i+60] */ TEST_AND_RETURN_RD(asinh, asinm, tbl[i+60]); /* Launch accurate phase */ asin_accurate_middle(&asinh,&asinm,&asinl,z,i,sign); ReturnRoundDownwards3(asinh,asinm,asinl); } double asin_rz(double x) { db_number xdb; double sign, z, asinh, asinm, asinl; int i; double xSqh, xSql; double tt1h, tt1l; double tt6h, tt6l; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l; double t7h, t7l, t8h, t8l, polyh, polyl, twoZ, sqrtzh, sqrtzl; double pTimesSh, pTimesSl, allh, alll, highPoly, xCubeh, xCubel; double tmp1, tmp2, tmp3, tmp4, tmp5; /* Transform the argument into integer */ xdb.d = x; /* Special case handling */ /* Strip off the sign of argument x */ if (xdb.i[HI] & 0x80000000) sign = -1; else sign = 1; xdb.i[HI] &= 0x7fffffff; /* asin is defined on -1 <= x <= 1, elsewhere it is NaN */ if ((xdb.i[HI] > 0x3ff00000) || ((xdb.i[HI] == 0x3ff00000) && (xdb.i[LO] != 0x00000000))) { return (x-x)/0.0; /* return NaN */ } /* If |x| < 2^(-28) we have arcsin(x) = x * ( 1 + xi ) with 0 <= xi < 2^(-55) So we can decide the rounding without any computation */ if (xdb.i[HI] < 0x3e300000) { /* If x == 0 the result is algebraic and equal to 0 If x < 0 the truncation rest is negative and less than 1 ulp, we return x If x > 0 the truncation rest is positive and less than 1 ulp, we return x */ return x; } /* Recast x */ x = xdb.d; /* Find correspondant interval and compute index to the table We start by filtering the two special cases around 0 and 1 */ if (xdb.i[HI] < BOUND1) { /* Special interval 0..BOUND1 The polynomial has no even monomials We must prove extra accuracy in the interval 0..sin(2^(-18)) */ /* Quick phase starts */ /* Compute square of x for both quick and accurate phases */ Mul12(&xSqh,&xSql,x,x); tmp4 = tbl[3]; tmp5 = tbl[4]; t4h = tmp4; t4l = tmp5; if (xdb.i[HI] > EXTRABOUND) { /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(tbl[23],xSqh,tbl[21]),xSqh,tbl[19]),xSqh,tbl[17]),xSqh,tbl[15]); #else highPoly = tbl[15] + xSqh * (tbl[17] + xSqh * (tbl[19] + xSqh * (tbl[21] + xSqh * tbl[23]))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[12],tbl[13],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[9],tbl[10],xSqh,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[6],tbl[7],xSqh,t2h,t2l); MulAdd22(&t4h,&t4l,tmp4,tmp5,xSqh,xSql,t3h,t3l); } MulAdd22(&t5h,&t5l,tbl[0],tbl[1],xSqh,xSql,t4h,t4l); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt6h,&tt6l,xCubeh,xCubel,t5h,t5l); Add12(tmp1,tmp2,x,tt6h); tmp3 = tmp2 + tt6l; Add12(polyh,polyl,tmp1,tmp3); /* Multiply by sign */ asinh = sign * polyh; asinm = sign * polyl; /* Rounding test The RZ rounding constant is at tbl[35] */ TEST_AND_RETURN_RZ(asinh, asinm, tbl[35]); /* Launch accurate phase */ asin_accurate_lower(&asinh,&asinm,&asinl,x,xSqh,xSql,sign); ReturnRoundTowardsZero3(asinh,asinm,asinl); } if (xdb.i[HI] > BOUND9) { /* Special interval BOUND9..1 We use an asymptotic development of arcsin in sqrt(1 - x) */ /* Argument reduction for quick and accurate phase z = 1 - x The operation is exact as per Sterbenz' lemma */ z = 1 - x; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[TBLIDX10+42] ,z,tbl[TBLIDX10+40]),z,tbl[TBLIDX10+38]),z, tbl[TBLIDX10+36]),z,tbl[TBLIDX10+34]),z,tbl[TBLIDX10+32]),z, tbl[TBLIDX10+30]),z,tbl[TBLIDX10+28]),z,tbl[TBLIDX10+26]),z, tbl[TBLIDX10+24]); #else highPoly = tbl[TBLIDX10+24] + z * (tbl[TBLIDX10+26] + z * (tbl[TBLIDX10+28] + z * ( tbl[TBLIDX10+30] + z * (tbl[TBLIDX10+32] + z * (tbl[TBLIDX10+34] + z * ( tbl[TBLIDX10+36] + z * (tbl[TBLIDX10+38] + z * (tbl[TBLIDX10+40] + z * tbl[TBLIDX10+42])))))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],z,t7h,t7l); MulAdd212(&polyh,&polyl,-1,0,z,t8h,t8l); /* Compute sqrt(2*z) as a double-double */ twoZ = 2 * z; sqrt12(&sqrtzh,&sqrtzl,twoZ); /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul22(&pTimesSh,&pTimesSl,polyh,polyl,sqrtzh,sqrtzl); Add22(&allh,&alll,PIHALFH,PIHALFM,pTimesSh,pTimesSl); /* Multiply by sign */ asinh = sign * allh; asinm = sign * alll; /* Rounding test The RZ rounding constant is at tbl[TBLIDX10+55] */ TEST_AND_RETURN_RZ(asinh, asinm, tbl[TBLIDX10+55]); /* Launch accurate phase */ asin_accurate_higher(&asinh,&asinm,&asinl,z,sign); ReturnRoundTowardsZero3(asinh,asinm,asinl); } /* General 8 main intervals We can already suppose that BOUND1 <= x <= BOUND9 */ if (xdb.i[HI] < BOUND5) { if (xdb.i[HI] < BOUND3) { if (xdb.i[HI] < BOUND2) i = TBLIDX2; else i = TBLIDX3; } else { if (xdb.i[HI] < BOUND4) i = TBLIDX4; else i = TBLIDX5; } } else { if (xdb.i[HI] < BOUND7) { if (xdb.i[HI] < BOUND6) i = TBLIDX6; else i = TBLIDX7; } else { if (xdb.i[HI] < BOUND8) i = TBLIDX8; else i = TBLIDX9; } } /* Argument reduction i points to the interval midpoint value in the table */ z = x - tbl[i]; /* Quick phase starts */ /* Double precision evaluation */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(FMA(FMA(FMA( tbl[i+35] ,z,tbl[i+33]),z,tbl[i+31]),z,tbl[i+29]),z, tbl[i+27]),z,tbl[i+25]),z,tbl[i+23]),z,tbl[i+21]); #else highPoly = tbl[i+21] + z * (tbl[i+23] + z * (tbl[i+25] + z * ( tbl[i+27] + z * (tbl[i+29] + z * (tbl[i+31] + z * ( tbl[i+33] + z * tbl[i+35])))))); #endif /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+18],tbl[i+19],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+15],tbl[i+16],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+12],tbl[i+13],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+9],tbl[i+10],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+6],tbl[i+7],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+3],tbl[i+4],z,t5h,t5l); MulAdd212(&polyh,&polyl,tbl[i+1],tbl[i+2],z,t6h,t6l); /* Multiply by sign */ asinh = sign * polyh; asinm = sign * polyl; /* Rounding test The RZ rounding constant is at tbl[i+60] */ TEST_AND_RETURN_RZ(asinh, asinm, tbl[i+60]); /* Launch accurate phase */ asin_accurate_middle(&asinh,&asinm,&asinl,z,i,sign); ReturnRoundTowardsZero3(asinh,asinm,asinl); } interval-3.2.0/src/crlibm/asin-td.h0000644000000000000000000015603713316017127015252 0ustar 00000000000000/* * Correctly rounded arcsine * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" /* File generated by maple/asin-td.mpl */ /* High order words of interval bounds (low order word is 0) */ #define BOUND1 0x3FC7AE14 #define BOUND2 0x3FD32E91 #define BOUND3 0x3FD9CA24 #define BOUND4 0x3FDF90B3 #define BOUND5 0x3FE23ADC #define BOUND6 0x3FE4781D #define BOUND7 0x3FE647BB #define BOUND8 0x3FE7BC81 #define BOUND9 0x3FE8F5C2 #define EXTRABOUND 0x3F500000 /* Pi/2 as a triple-double*/ #define PIHALFH 1.57079632679489655799898173427209258079528808593750e+00 #define PIHALFM 6.12323399573676603586882014729198302312846062338790e-17 #define PIHALFL -1.49738490485916983294350817710599200835275047616952e-33 /* Indices to the following table */ #define TBLIDX2 36 #define TBLIDX3 97 #define TBLIDX4 158 #define TBLIDX5 219 #define TBLIDX6 280 #define TBLIDX7 341 #define TBLIDX8 402 #define TBLIDX9 463 #define TBLIDX10 524 /* Table with midpoints and polynomial coefficients */ static const double tbl[580] = { 1.66666666666666657414808128123695496469736099243164e-01, /* 0, accPolyLowC3h, quickPolyLowC3h */ 9.25185853854297065661561206416060845590588197735272e-18, /* 1, accPolyLowC3m, quickPolyLowC3l */ 5.13580782192052290146917464639635163327575367072527e-34, /* 2, accPolyLowC3l */ 7.49999999999999972244424384371086489409208297729492e-02, /* 3, accPolyLowC5h, quickPolyLowC5h */ 2.77555756156289150513347472120591902572823540679419e-18, /* 4, accPolyLowC5m, quickPolyLowC5l */ -1.43929408167863119589461549455410834291155585333144e-34, /* 5, accPolyLowC5l */ 4.46428571428571438484134148438897682353854179382324e-02, /* 6, accPolyLowC7h, quickPolyLowC7h */ -9.91270557701064540788749549275225920938048550224136e-19, /* 7, accPolyLowC7m, quickPolyLowC7l */ 3.33748090721822991762574824757600091731436462508019e-35, /* 8, accPolyLowC7l */ 3.03819444444444440589503386718206456862390041351318e-02, /* 9, accPolyLowC9h, quickPolyLowC9h */ 3.85494105812324030564107341625454073114449944250081e-19, /* 10, accPolyLowC9m, quickPolyLowC9l */ -1.43865090242821346711405668429425189868490718470116e-36, /* 11, accPolyLowC9l */ 2.23721590909090918553037141691675060428678989410400e-02, /* 12, accPolyLowC11h, quickPolyLowC11h */ -9.46212831143868745925658651601400487408631908148174e-19, /* 13, accPolyLowC11m, quickPolyLowC11l */ 2.71756033709005426155900473576766627205226477546134e-36, /* 14, accPolyLowC11l */ 1.73527644230769238775646812200648128055036067962646e-02, /* 15, accPolyLowC13h, quickPolyLowC13h */ -8.00631194349979385750725428497500824341216859291999e-19, /* 16, accPolyLowC13m */ 1.39648437500000006938893903907228377647697925567627e-02, /* 17, accPolyLowC15h, quickPolyLowC15h */ -6.96640576418186252434826298980545123112053091491650e-19, /* 18, accPolyLowC15m */ 1.15518008961397068007359578700743441004306077957153e-02, /* 19, accPolyLowC17h, quickPolyLowC17h */ -4.10583074045422929898575008733550170923265860856307e-19, /* 20, accPolyLowC17m */ 9.76160952919401074534544449079476180486381053924561e-03, /* 21, accPolyLowC19h, quickPolyLowC19h */ 3.58257464358998522024321439568214748872569190564464e-19, /* 22, accPolyLowC19m */ 8.39033580962353364718353532225592061877250671386719e-03, /* 23, accPolyLowC21h, quickPolyLowC21h */ 7.09494992486164270601178799400238696830257336508353e-20, /* 24, accPolyLowC21m */ 7.31252587309846099200560942676929698791354894638062e-03, /* 25, accPolyLowC23h */ 3.10147942381298802750887889395221073583507364742961e-19, /* 26, accPolyLowC23m */ 6.44721034012319445943850482194648066069930791854858e-03, /* 27, accPolyLowC25h */ 5.74003646399263555560876781669321644585579633712769e-03, /* 28, accPolyLowC27h */ 5.15334845775329911110596015078044729307293891906738e-03, /* 29, accPolyLowC29h */ 4.65922376559379288613049752143524528946727514266968e-03, /* 30, accPolyLowC31h */ 4.25648267385331235956869022629689425230026245117188e-03, /* 31, accPolyLowC33h */ 3.70384206863821549560178425508638611063361167907715e-03, /* 32, accPolyLowC35h */ 4.76149788232017000255691385746104060672223567962646e-03, /* 33, accPolyLowC37h */ 1.01829039548491739886060258868383243680000305175781e+00, /* 34, RN rounding constant quick poly low*/ 9.99456520626465193846360776661410034560333454445527e-19, /* 35, RD rounding constant quick poly low*/ 2.42358565330489938993707710324088111519813537597656e-01, /* 36, midpoint in interval 2*/ 2.44796158322043572175275016888917889446020126342773e-01, /* 37, accPolyMid2C0h, quickPolyMid2C0h */ -7.80764437719474476036120943295127199090063761923808e-18, /* 38, accPolyMid2C0m, quickPolyMid2C0l */ 1.03072939530366736171629327145637944340705871582031e+00, /* 39, accPolyMid2C1h, quickPolyMid2C1h */ -8.85738929015520959086405013050480695702241994387953e-17, /* 40, accPolyMid2C1m, quickPolyMid2C1l */ -3.43332793693232296155057781643135490790330671255580e-33, /* 41, accPolyMid2C1l */ 1.32697384480218755209435244069027248769998550415039e-01, /* 42, accPolyMid2C2h, quickPolyMid2C2h */ -3.05519908299053827321743308736081906443885446585898e-18, /* 43, accPolyMid2C2m, quickPolyMid2C2l */ 1.84968471282800310046349200266639560111473343387153e-34, /* 44, accPolyMid2C2l */ 2.16675601140875473404889817174989730119705200195312e-01, /* 45, accPolyMid2C3h, quickPolyMid2C3h */ -1.09855192148394476119822843562855651270724326884774e-18, /* 46, accPolyMid2C3m, quickPolyMid2C3l */ 1.30965185306611444030805369954695892224998714815939e-35, /* 47, accPolyMid2C3l */ 1.16730419643667523987851097899692831560969352722168e-01, /* 48, accPolyMid2C4h, quickPolyMid2C4h */ 4.87619704882669077472238320833491156897798846867617e-18, /* 49, accPolyMid2C4m, quickPolyMid2C4l */ 2.44421677078199513698242322477237313066476585423275e-34, /* 50, accPolyMid2C4l */ 1.45667026718228842518954024853883311152458190917969e-01, /* 51, accPolyMid2C5h, quickPolyMid2C5h */ 5.36594969153474426628449995112694156468179831261122e-19, /* 52, accPolyMid2C5m, quickPolyMid2C5l */ 8.48516201835513020738766305454795330663195678132569e-36, /* 53, accPolyMid2C5l */ 1.22401266966440255834491779296513414010405540466309e-01, /* 54, accPolyMid2C6h, quickPolyMid2C6h */ -2.20822551943355103564859204431825679093840107651564e-19, /* 55, accPolyMid2C6m, quickPolyMid2C6l */ -8.07441439403117291580512089023909180599052269668925e-36, /* 56, accPolyMid2C6l */ 1.41642750696223979067767118067422416061162948608398e-01, /* 57, accPolyMid2C7h, quickPolyMid2C7h */ 8.52401858052517523392878261510621535534995050169401e-18, /* 58, accPolyMid2C7m, quickPolyMid2C7l */ 1.42861418735328621343327881731966044753789901733398e-01, /* 59, accPolyMid2C8h, quickPolyMid2C8h */ -1.33006668328318919665132697553096363383321713310227e-17, /* 60, accPolyMid2C8m */ 1.63718343060216098283632391030550934374332427978516e-01, /* 61, accPolyMid2C9h, quickPolyMid2C9h */ 6.13394557799256408251130704849071363459255390907063e-18, /* 62, accPolyMid2C9m */ 1.79592723769284340340490757625957485288381576538086e-01, /* 63, accPolyMid2C10h, quickPolyMid2C10h */ -1.30198260064097970981442998070110461849845662150849e-17, /* 64, accPolyMid2C10m */ 2.07951828711086583734157784419949166476726531982422e-01, /* 65, accPolyMid2C11h, quickPolyMid2C11h */ -1.26159975996932877835486818675875580593424383227469e-17, /* 66, accPolyMid2C11m */ 2.38247271379822073145149374795437324792146682739258e-01, /* 67, accPolyMid2C12h, quickPolyMid2C12h */ 6.62361216505959744828122635016705548667940611263800e-18, /* 68, accPolyMid2C12m */ 2.79893913215572998076652311283396556973457336425781e-01, /* 69, accPolyMid2C13h, quickPolyMid2C13h */ -2.24149827195062967543013296493616902343167004009288e-17, /* 70, accPolyMid2C13m */ 3.28958991769599307097848850389709696173667907714844e-01, /* 71, accPolyMid2C14h, quickPolyMid2C14h */ -1.05211249452308945191032281708802957418482198191124e-17, /* 72, accPolyMid2C14m */ 3.91766249806127564436764032507198862731456756591797e-01, /* 73, accPolyMid2C15h */ -2.02194096713130520849748106020797136930683180643846e-17, /* 74, accPolyMid2C15m */ 4.68246642053942785377529389734263531863689422607422e-01, /* 75, accPolyMid2C16h */ 5.64148787932559847568825261987512931227684020996094e-01, /* 76, accPolyMid2C17h */ 6.82488400757435664800709673727396875619888305664062e-01, /* 77, accPolyMid2C18h */ 8.30182127559316640486031246837228536605834960937500e-01, /* 78, accPolyMid2C19h */ 1.01367533043020308092252435017144307494163513183594e+00, /* 79, accPolyMid2C20h */ 1.24281078928695176699648072826676070690155029296875e+00, /* 80, accPolyMid2C21h */ 1.52877587404435177909078902303008362650871276855469e+00, /* 81, accPolyMid2C22h */ 1.88667637664635656769007709954166784882545471191406e+00, /* 82, accPolyMid2C23h */ 2.33494551765288571587575461308006197214126586914062e+00, /* 83, accPolyMid2C24h */ 2.89749244536000327698843648249749094247817993164062e+00, /* 84, accPolyMid2C25h */ 3.60426450740106130155027130967937409877777099609375e+00, /* 85, accPolyMid2C26h */ 4.49361107526955017021919047692790627479553222656250e+00, /* 86, accPolyMid2C27h */ 5.61406255377128715622347954194992780685424804687500e+00, /* 87, accPolyMid2C28h */ 7.02754870503224271516273802262730896472930908203125e+00, /* 88, accPolyMid2C29h */ 8.81280667340759649164283473510295152664184570312500e+00, /* 89, accPolyMid2C30h */ 1.10704407960507111852166417520493268966674804687500e+01, /* 90, accPolyMid2C31h */ 1.39282518419665830577969245496205985546112060546875e+01, /* 91, accPolyMid2C32h */ 1.75308292529565719064521545078605413436889648437500e+01, /* 92, accPolyMid2C33h */ 2.21169075633838900785121950320899486541748046875000e+01, /* 93, accPolyMid2C34h */ 2.93386309556562245859367976663634181022644042968750e+01, /* 94, accPolyMid2C35h */ 1.01656637119000103908206256164703518152236938476562e+00, /* 95, RN rounding constant quick poly middle 2*/ 9.05249299973766985475925981961240072045593429326050e-19, /* 96, RD rounding constant quick poly middle 2*/ 3.51339936256424290039745983449392952024936676025391e-01, /* 97, midpoint in interval 3*/ 3.59001896704258527392994437832385301589965820312500e-01, /* 98, accPolyMid3C0h, quickPolyMid3C0h */ 7.25234535377983806008993135801969933842904099082037e-20, /* 99, accPolyMid3C0m, quickPolyMid3C0l */ 1.06809311097735548656828541425056755542755126953125e+00, /* 100, accPolyMid3C1h, quickPolyMid3C1h */ 8.06569140638077604165107730077659782400969546746483e-17, /* 101, accPolyMid3C1m, quickPolyMid3C1l */ -5.04406564603486171676187418521136112402329884904383e-33, /* 102, accPolyMid3C1l */ 2.14054747447713134000935042422497645020484924316406e-01, /* 103, accPolyMid3C2h, quickPolyMid3C2h */ 9.76056255097027764696827253384241478483311533093656e-18, /* 104, accPolyMid3C2m, quickPolyMid3C2l */ -7.76857615284538540734861101748988881714638362963881e-35, /* 105, accPolyMid3C2l */ 2.88880884175958529969108212753781117498874664306641e-01, /* 106, accPolyMid3C3h, quickPolyMid3C3h */ 2.22181200821645624650165429361546283225838059740631e-17, /* 107, accPolyMid3C3m, quickPolyMid3C3l */ -1.14368045348414878337189405350442917783836545775590e-33, /* 108, accPolyMid3C3l */ 2.26134851489718013972662902233423665165901184082031e-01, /* 109, accPolyMid3C4h, quickPolyMid3C4h */ -8.04753534970505104224953947907869405284151781535028e-18, /* 110, accPolyMid3C4m, quickPolyMid3C4l */ 4.22557384286705919324956002465313457843707737945963e-34, /* 111, accPolyMid3C4l */ 2.75196923580072527748541233449941501021385192871094e-01, /* 112, accPolyMid3C5h, quickPolyMid3C5h */ -1.17338666986909136966078634618924264888220762222419e-18, /* 113, accPolyMid3C5m, quickPolyMid3C5l */ -4.68757737099062213529607300203132104484914350463871e-35, /* 114, accPolyMid3C5l */ 3.03044495521890500100425924756564199924468994140625e-01, /* 115, accPolyMid3C6h, quickPolyMid3C6h */ -2.27411416594910816511289518687103845115091724313899e-17, /* 116, accPolyMid3C6m, quickPolyMid3C6l */ 2.34762544350785348445971766662785127027332739123595e-34, /* 117, accPolyMid3C6l */ 3.77749573081396394780284708758699707686901092529297e-01, /* 118, accPolyMid3C7h, quickPolyMid3C7h */ 7.89247891096042648893247867692397394548591651092283e-18, /* 119, accPolyMid3C7m, quickPolyMid3C7l */ 4.68287147615184806692667507377336733043193817138672e-01, /* 120, accPolyMid3C8h, quickPolyMid3C8h */ 1.75668374099909928545987828472120658936175220036884e-17, /* 121, accPolyMid3C8m */ 6.06111063535901939403061078337486833333969116210938e-01, /* 122, accPolyMid3C9h, quickPolyMid3C9h */ 1.72730090011832304135009947489517024111046794620020e-17, /* 123, accPolyMid3C9m */ 7.92895790821915635859795656870119273662567138671875e-01, /* 124, accPolyMid3C10h, quickPolyMid3C10h */ 4.98295614974968378037947765656866085023078681863398e-17, /* 125, accPolyMid3C10m */ 1.05810730062141522545005045685684308409690856933594e+00, /* 126, accPolyMid3C11h, quickPolyMid3C11h */ 8.05577049603995800072512132781137905047707942749781e-17, /* 127, accPolyMid3C11m */ 1.42745521004660447239587028889218345284461975097656e+00, /* 128, accPolyMid3C12h, quickPolyMid3C12h */ -4.55985728468522936328504707804310204497673421624067e-17, /* 129, accPolyMid3C12m */ 1.94854789175488596342233904579188674688339233398438e+00, /* 130, accPolyMid3C13h, quickPolyMid3C13h */ 3.84783704422594121999348237839996274693704597202448e-17, /* 131, accPolyMid3C13m */ 2.68312408725385909136207374103832989931106567382812e+00, /* 132, accPolyMid3C14h, quickPolyMid3C14h */ -3.56068007836116005017028996147996121343986693197868e-17, /* 133, accPolyMid3C14m */ 3.72473732217660824517224682494997978210449218750000e+00, /* 134, accPolyMid3C15h */ -5.87298986037438700709055565377465605786708153319628e-17, /* 135, accPolyMid3C15m */ 5.20573944915823361156981263775378465652465820312500e+00, /* 136, accPolyMid3C16h */ 7.31989734855592644180433126166462898254394531250000e+00, /* 137, accPolyMid3C17h */ 1.03473141302088169624084912356920540332794189453125e+01, /* 138, accPolyMid3C18h */ 1.46964937699531184023271634941920638084411621093750e+01, /* 139, accPolyMid3C19h */ 2.09624579630017748854697856586426496505737304687500e+01, /* 140, accPolyMid3C20h */ 3.00147629377676423700904706493020057678222656250000e+01, /* 141, accPolyMid3C21h */ 4.31254748908798717366153141483664512634277343750000e+01, /* 142, accPolyMid3C22h */ 6.21591110441626426563743734732270240783691406250000e+01, /* 143, accPolyMid3C23h */ 8.98523523311889533715657307766377925872802734375000e+01, /* 144, accPolyMid3C24h */ 1.30228138287161243624723283573985099792480468750000e+02, /* 145, accPolyMid3C25h */ 1.89208159704443204418566892854869365692138671875000e+02, /* 146, accPolyMid3C26h */ 2.75520543663640125942038139328360557556152343750000e+02, /* 147, accPolyMid3C27h */ 4.02045721388318213485035812482237815856933593750000e+02, /* 148, accPolyMid3C28h */ 5.87814144421144646912580356001853942871093750000000e+02, /* 149, accPolyMid3C29h */ 8.60974558223577218996069859713315963745117187500000e+02, /* 150, accPolyMid3C30h */ 1.26323081508058703548158518970012664794921875000000e+03, /* 151, accPolyMid3C31h */ 1.85633061099108476810215506702661514282226562500000e+03, /* 152, accPolyMid3C32h */ 2.72831792235129523760406300425529479980468750000000e+03, /* 153, accPolyMid3C33h */ 4.02017366871190233723609708249568939208984375000000e+03, /* 154, accPolyMid3C34h */ 6.26169941241203287063399329781532287597656250000000e+03, /* 155, accPolyMid3C35h */ 1.01822826558956558429258620890323072671890258789062e+00, /* 156, RN rounding constant quick poly middle 3*/ 9.96061507703610851328544443284249848383807032724405e-19, /* 157, RD rounding constant quick poly middle 3*/ 4.48084712028450460330475380033021792769432067871094e-01, /* 158, midpoint in interval 4*/ 4.64621784296265272207193675058078952133655548095703e-01, /* 159, accPolyMid4C0h, quickPolyMid4C0h */ 5.46463478154141631687941857567549378870836612391668e-19, /* 160, accPolyMid4C0m, quickPolyMid4C0l */ 1.11857936563137916330390453367726877331733703613281e+00, /* 161, accPolyMid4C1h, quickPolyMid4C1h */ -7.52084787570938032181667127523977366268049041253541e-17, /* 162, accPolyMid4C1m, quickPolyMid4C1l */ -2.09600667283052949148765250630641631769479132030207e-33, /* 163, accPolyMid4C1l */ 3.13567137932624417917537584798992611467838287353516e-01, /* 164, accPolyMid4C2h, quickPolyMid4C2h */ -4.41710443385272069717070263863657699262849649693148e-18, /* 165, accPolyMid4C2m, quickPolyMid4C2l */ -1.66857777421172326251970639278136259133415308172276e-34, /* 166, accPolyMid4C2l */ 4.09066962553200574870260197712923400104045867919922e-01, /* 167, accPolyMid4C3h, quickPolyMid4C3h */ -1.77243968292023797220078441566237340174840093946990e-17, /* 168, accPolyMid4C3m, quickPolyMid4C3l */ 1.04993340346633219191766382762445818927028795922212e-33, /* 169, accPolyMid4C3l */ 4.17460970109683637829789404349867254495620727539062e-01, /* 170, accPolyMid4C4h, quickPolyMid4C4h */ 1.39418041407988360348752433713233257018150500547568e-17, /* 171, accPolyMid4C4m, quickPolyMid4C4l */ 1.44515287253394191526867297316859284672731580248765e-33, /* 172, accPolyMid4C4l */ 5.57995436127318722441259524202905595302581787109375e-01, /* 173, accPolyMid4C5h, quickPolyMid4C5h */ 4.36037702989507667583407786816694605825360677277616e-17, /* 174, accPolyMid4C5m, quickPolyMid4C5l */ -1.19172250052693786129959971158569652849573416545361e-33, /* 175, accPolyMid4C5l */ 7.47841169204912281642805282899644225835800170898438e-01, /* 176, accPolyMid4C6h, quickPolyMid4C6h */ -6.76313448015089834151929838334258544557222273487418e-18, /* 177, accPolyMid4C6m, quickPolyMid4C6l */ -3.47721914174083040302762713955940912153154957518196e-34, /* 178, accPolyMid4C6l */ 1.07444730844797153856973181973444297909736633300781e+00, /* 179, accPolyMid4C7h, quickPolyMid4C7h */ 7.55340134261966180374112563614849022138812950329448e-17, /* 180, accPolyMid4C7m, quickPolyMid4C7l */ 1.58041645549890685806815326941432431340217590332031e+00, /* 181, accPolyMid4C8h, quickPolyMid4C8h */ 4.80894355381610072868748091065730787867334028863435e-17, /* 182, accPolyMid4C8m */ 2.39169226022640657447482226416468620300292968750000e+00, /* 183, accPolyMid4C9h, quickPolyMid4C9h */ 1.26753183127964275508490032426937968441812593935712e-16, /* 184, accPolyMid4C9m */ 3.68572936227336489523054297023918479681015014648438e+00, /* 185, accPolyMid4C10h, quickPolyMid4C10h */ -1.41660589025860946857878120315437315934718409357086e-16, /* 186, accPolyMid4C10m */ 5.77285150262833735013145997072570025920867919921875e+00, /* 187, accPolyMid4C11h, quickPolyMid4C11h */ -2.16740363176565772841534018366824459554498708631527e-16, /* 188, accPolyMid4C11m */ 9.15766592727227646264509530737996101379394531250000e+00, /* 189, accPolyMid4C12h, quickPolyMid4C12h */ 4.37180613264180824186691777532090455983551321485214e-16, /* 190, accPolyMid4C12m */ 1.46862422532599090629901184001937508583068847656250e+01, /* 191, accPolyMid4C13h, quickPolyMid4C13h */ 7.89614550363306335166404831558856161121412865593061e-16, /* 192, accPolyMid4C13m */ 2.37692237950290667924946319544687867164611816406250e+01, /* 193, accPolyMid4C14h, quickPolyMid4C14h */ -3.50255834101571646092598176937562449597971181913456e-16, /* 194, accPolyMid4C14m */ 3.87753699929054533868111320771276950836181640625000e+01, /* 195, accPolyMid4C15h */ 5.67060321723933067329766411373458413340348986762113e-16, /* 196, accPolyMid4C15m */ 6.36909499334141528947839105967432260513305664062500e+01, /* 197, accPolyMid4C16h */ 1.05248620915111246176820714026689529418945312500000e+02, /* 198, accPolyMid4C17h */ 1.74851057791898000459696049802005290985107421875000e+02, /* 199, accPolyMid4C18h */ 2.91864013611726591079786885529756546020507812500000e+02, /* 200, accPolyMid4C19h */ 4.89259682748188197365379892289638519287109375000000e+02, /* 201, accPolyMid4C20h */ 8.23309003242859603233227971941232681274414062500000e+02, /* 202, accPolyMid4C21h */ 1.39025484827954846878128591924905776977539062500000e+03, /* 203, accPolyMid4C22h */ 2.35504246227568182803224772214889526367187500000000e+03, /* 204, accPolyMid4C23h */ 4.00090205201026492431992664933204650878906250000000e+03, /* 205, accPolyMid4C24h */ 6.81504309301592911651823669672012329101562500000000e+03, /* 206, accPolyMid4C25h */ 1.16369648030766729789320379495620727539062500000000e+04, /* 207, accPolyMid4C26h */ 1.99154708390699779556598514318466186523437500000000e+04, /* 208, accPolyMid4C27h */ 3.41546126991757555515505373477935791015625000000000e+04, /* 209, accPolyMid4C28h */ 5.86883344113872444722801446914672851562500000000000e+04, /* 210, accPolyMid4C29h */ 1.01027682393336552195250988006591796875000000000000e+05, /* 211, accPolyMid4C30h */ 1.74209975080082920612767338752746582031250000000000e+05, /* 212, accPolyMid4C31h */ 3.00874278784890950191766023635864257812500000000000e+05, /* 213, accPolyMid4C32h */ 5.19633023773909430019557476043701171875000000000000e+05, /* 214, accPolyMid4C33h */ 8.99866392232198733836412429809570312500000000000000e+05, /* 215, accPolyMid4C34h */ 1.65235977806337876245379447937011718750000000000000e+06, /* 216, accPolyMid4C35h */ 1.01836010491198658556299960764590650796890258789062e+00, /* 217, RN rounding constant quick poly middle 4*/ 1.00326570788492020170486150590740535840759810902416e-18, /* 218, RD rounding constant quick poly middle 4*/ 5.31445860862679642089290155126946046948432922363281e-01, /* 219, midpoint in interval 5*/ 5.60306504963744567149319664167705923318862915039062e-01, /* 220, accPolyMid5C0h, quickPolyMid5C0h */ -1.08630439217163180480513733763948654678554607776160e-20, /* 221, accPolyMid5C0m, quickPolyMid5C0l */ 1.18050895658762322604218297783518210053443908691406e+00, /* 222, accPolyMid5C1h, quickPolyMid5C1h */ -3.44936676454714048889716658635127499762917269870727e-17, /* 223, accPolyMid5C1m, quickPolyMid5C1l */ -2.49069456197248953275668118371299181194287558355700e-33, /* 224, accPolyMid5C1l */ 4.37156452058995781406736114149680361151695251464844e-01, /* 225, accPolyMid5C2h, quickPolyMid5C2h */ 4.12350542001181384975859432610288269290340424486530e-18, /* 226, accPolyMid5C2m, quickPolyMid5C2l */ 2.73553164822567581206451159459555826955342358406517e-34, /* 227, accPolyMid5C2l */ 5.97961581435785594074161508615361526608467102050781e-01, /* 228, accPolyMid5C3h, quickPolyMid5C3h */ 1.15786235462823532242451850040378867919657187923266e-17, /* 229, accPolyMid5C3m, quickPolyMid5C3l */ 6.70476163820618923333949946465040969013104876616743e-34, /* 230, accPolyMid5C3l */ 7.56654591443305823972309553937520831823348999023438e-01, /* 231, accPolyMid5C4h, quickPolyMid5C4h */ 5.63361768523770903650379304980880430544181403662856e-18, /* 232, accPolyMid5C4m, quickPolyMid5C4l */ 3.52518369310847108975654467573884198459173315811765e-35, /* 233, accPolyMid5C4l */ 1.15954888868330963092034835426602512598037719726562e+00, /* 234, accPolyMid5C5h, quickPolyMid5C5h */ -2.13088606479945404910718732635657047999226786224539e-17, /* 235, accPolyMid5C5m, quickPolyMid5C5l */ 1.01155988751211667735165829625236622533486662424891e-33, /* 236, accPolyMid5C5l */ 1.85057068266552660062984614341985434293746948242188e+00, /* 237, accPolyMid5C6h, quickPolyMid5C6h */ -4.13756595773451122099466439202037064387337671566669e-18, /* 238, accPolyMid5C6m, quickPolyMid5C6l */ 3.02843501360506226132120912500822054694900989592884e-34, /* 239, accPolyMid5C6l */ 3.11563743870884257702869035711046308279037475585938e+00, /* 240, accPolyMid5C7h, quickPolyMid5C7h */ -5.06302300821373603583774676357699499992045551579126e-17, /* 241, accPolyMid5C7m, quickPolyMid5C7l */ 5.40761322601296168244289219728671014308929443359375e+00, /* 242, accPolyMid5C8h, quickPolyMid5C8h */ 2.97487923575735998744301300115136435889001285861472e-16, /* 243, accPolyMid5C8m */ 9.62995354897343425193412258522585034370422363281250e+00, /* 244, accPolyMid5C9h, quickPolyMid5C9h */ 4.55607422255092503960684830342258039056296500032145e-16, /* 245, accPolyMid5C9m */ 1.74836661195630966858516330830752849578857421875000e+01, /* 246, accPolyMid5C10h, quickPolyMid5C10h */ 1.43590320985440421817158000882140332196152266840822e-15, /* 247, accPolyMid5C10m */ 3.22483723360128990975681517738848924636840820312500e+01, /* 248, accPolyMid5C11h, quickPolyMid5C11h */ -3.34403568343416729924334128939506733422536740966968e-15, /* 249, accPolyMid5C11m */ 6.02553715792408368656651873607188463211059570312500e+01, /* 250, accPolyMid5C12h, quickPolyMid5C12h */ 3.10919444878682139369989784864394611534570535618660e-15, /* 251, accPolyMid5C12m */ 1.13813051318643047693512926343828439712524414062500e+02, /* 252, accPolyMid5C13h, quickPolyMid5C13h */ -1.71698317353737059559128975443274184793142084909379e-15, /* 253, accPolyMid5C13m */ 2.16961936728312849709254805929958820343017578125000e+02, /* 254, accPolyMid5C14h, quickPolyMid5C14h */ 8.27079867974059458294192504441253562124411295719550e-15, /* 255, accPolyMid5C14m */ 4.16880179488225451223115669563412666320800781250000e+02, /* 256, accPolyMid5C15h */ -2.58735460985196142054738964992050729251298751831811e-14, /* 257, accPolyMid5C15m */ 8.06537874996876666955358814448118209838867187500000e+02, /* 258, accPolyMid5C16h */ 1.56984649251497876321082003414630889892578125000000e+03, /* 259, accPolyMid5C17h */ 3.07188686658870074097649194300174713134765625000000e+03, /* 260, accPolyMid5C18h */ 6.03970064736507720226654782891273498535156250000000e+03, /* 261, accPolyMid5C19h */ 1.19254227020427806564839556813240051269531250000000e+04, /* 262, accPolyMid5C20h */ 2.36373073951149926870130002498626708984375000000000e+04, /* 263, accPolyMid5C21h */ 4.70144622759458434302359819412231445312500000000000e+04, /* 264, accPolyMid5C22h */ 9.38077422737224260345101356506347656250000000000000e+04, /* 265, accPolyMid5C23h */ 1.87716130978103727102279663085937500000000000000000e+05, /* 266, accPolyMid5C24h */ 3.76631599838992522563785314559936523437500000000000e+05, /* 267, accPolyMid5C25h */ 7.57518066926909843459725379943847656250000000000000e+05, /* 268, accPolyMid5C26h */ 1.52703698454281571321189403533935546875000000000000e+06, /* 269, accPolyMid5C27h */ 3.08471154002460883930325508117675781250000000000000e+06, /* 270, accPolyMid5C28h */ 6.24343584097426943480968475341796875000000000000000e+06, /* 271, accPolyMid5C29h */ 1.26595813738393746316432952880859375000000000000000e+07, /* 272, accPolyMid5C30h */ 2.57133891378295645117759704589843750000000000000000e+07, /* 273, accPolyMid5C31h */ 5.23093272367429584264755249023437500000000000000000e+07, /* 274, accPolyMid5C32h */ 1.06415184183835312724113464355468750000000000000000e+08, /* 275, accPolyMid5C33h */ 2.17067016530691206455230712890625000000000000000000e+08, /* 276, accPolyMid5C34h */ 4.69394759797544836997985839843750000000000000000000e+08, /* 277, accPolyMid5C35h */ 1.01534217846377439187222080363426357507705688476562e+00, /* 278, RN rounding constant quick poly middle 5*/ 8.45008379631082379626014328492746516799371469048044e-19, /* 279, RD rounding constant quick poly middle 5*/ 6.04673624038476131836716831458033993840217590332031e-01, /* 280, midpoint in interval 6*/ 6.49356027282211423212743284238968044519424438476562e-01, /* 281, accPolyMid6C0h, quickPolyMid6C0h */ -1.25840412187919035681267493345871686399113240956856e-20, /* 282, accPolyMid6C0m, quickPolyMid6C0l */ 1.25553477869155938329015498311491683125495910644531e+00, /* 283, accPolyMid6C1h, quickPolyMid6C1h */ 5.00523898265236280615595780032763663310079252366513e-17, /* 284, accPolyMid6C1m, quickPolyMid6C1l */ 2.70452092654099855316456962656407597917508288905533e-33, /* 285, accPolyMid6C1l */ 5.98380278107774499218862729321699589490890502929688e-01, /* 286, accPolyMid6C2h, quickPolyMid6C2h */ 3.73915919375620074681511372815883902051293891666555e-18, /* 287, accPolyMid6C2m, quickPolyMid6C2l */ 1.02836809807342008154037540277599096854529496615931e-34, /* 288, accPolyMid6C2l */ 9.00232892880871604646131345361936837434768676757812e-01, /* 289, accPolyMid6C3h, quickPolyMid6C3h */ -1.70995008965645412422671790545314082452432030961170e-17, /* 290, accPolyMid6C3m, quickPolyMid6C3l */ 1.26596066229657064182610642365044212709535948254084e-33, /* 291, accPolyMid6C3l */ 1.38703629702026587366958665370475500822067260742188e+00, /* 292, accPolyMid6C4h, quickPolyMid6C4h */ 3.98819447215487913236315415179165676291502931117595e-17, /* 293, accPolyMid6C4m, quickPolyMid6C4l */ -6.55797179513908183565792353381331895988112885430413e-34, /* 294, accPolyMid6C4l */ 2.48954277308397298185127510805614292621612548828125e+00, /* 295, accPolyMid6C5h, quickPolyMid6C5h */ 9.74092851599686234698415065747156883706428073441651e-17, /* 296, accPolyMid6C5m, quickPolyMid6C5l */ 1.56743989943601791748641837689163542493404742470630e-33, /* 297, accPolyMid6C5l */ 4.72562522409656082800211152061820030212402343750000e+00, /* 298, accPolyMid6C6h, quickPolyMid6C6h */ 6.88679830761278595465306080986277758416307765996557e-18, /* 299, accPolyMid6C6m, quickPolyMid6C6l */ -9.47395090301458455484031652124848364407920780715874e-35, /* 300, accPolyMid6C6l */ 9.41432957016690785678747488418594002723693847656250e+00, /* 301, accPolyMid6C7h, quickPolyMid6C7h */ 8.62157085484702984705473460305131094967840256568931e-16, /* 302, accPolyMid6C7m, quickPolyMid6C7l */ 1.93709907584273430813937011407688260078430175781250e+01, /* 303, accPolyMid6C8h, quickPolyMid6C8h */ -1.40839418808440953673043657798045432960211596437085e-16, /* 304, accPolyMid6C8m */ 4.08734031574560177091370860580354928970336914062500e+01, /* 305, accPolyMid6C9h, quickPolyMid6C9h */ -2.98667469102598629922297846034715799734023919430673e-16, /* 306, accPolyMid6C9m */ 8.79464044588732321017232607118785381317138671875000e+01, /* 307, accPolyMid6C10h, quickPolyMid6C10h */ 3.61512961738881992095483091045503569454095245351219e-16, /* 308, accPolyMid6C10m */ 1.92241339189846911494896630756556987762451171875000e+02, /* 309, accPolyMid6C11h, quickPolyMid6C11h */ 6.61037281166591217605498682969545683054486597679533e-15, /* 310, accPolyMid6C11m */ 4.25700873706194784062972757965326309204101562500000e+02, /* 311, accPolyMid6C12h, quickPolyMid6C12h */ -6.48144847243744916328196408044704617877580310816854e-15, /* 312, accPolyMid6C12m */ 9.52958531675870517574367113411426544189453125000000e+02, /* 313, accPolyMid6C13h, quickPolyMid6C13h */ -3.41559781098088121115265032630996540232080319228480e-15, /* 314, accPolyMid6C13m */ 2.15300037043921429358306340873241424560546875000000e+03, /* 315, accPolyMid6C14h, quickPolyMid6C14h */ -4.69254271757335955512545725611899433103182087412275e-14, /* 316, accPolyMid6C14m */ 4.90290875724837587767979130148887634277343750000000e+03, /* 317, accPolyMid6C15h */ -4.54544125910656089453646656943432828883091406657613e-13, /* 318, accPolyMid6C15m */ 1.12422266608999743766617029905319213867187500000000e+04, /* 319, accPolyMid6C16h */ 2.59341556033402121101971715688705444335937500000000e+04, /* 320, accPolyMid6C17h */ 6.01463753209276546840555965900421142578125000000000e+04, /* 321, accPolyMid6C18h */ 1.40155647347781836288049817085266113281250000000000e+05, /* 322, accPolyMid6C19h */ 3.27990517748617625329643487930297851562500000000000e+05, /* 323, accPolyMid6C20h */ 7.70511269948243047110736370086669921875000000000000e+05, /* 324, accPolyMid6C21h */ 1.81638100581354671157896518707275390625000000000000e+06, /* 325, accPolyMid6C22h */ 4.29545835214607417583465576171875000000000000000000e+06, /* 326, accPolyMid6C23h */ 1.01875211922164466232061386108398437500000000000000e+07, /* 327, accPolyMid6C24h */ 2.42259292905952110886573791503906250000000000000000e+07, /* 328, accPolyMid6C25h */ 5.77502706188629567623138427734375000000000000000000e+07, /* 329, accPolyMid6C26h */ 1.37977551882563471794128417968750000000000000000000e+08, /* 330, accPolyMid6C27h */ 3.30348046445899784564971923828125000000000000000000e+08, /* 331, accPolyMid6C28h */ 7.92463843911740779876708984375000000000000000000000e+08, /* 332, accPolyMid6C29h */ 1.90447027047677397727966308593750000000000000000000e+09, /* 333, accPolyMid6C30h */ 4.58479383261657714843750000000000000000000000000000e+09, /* 334, accPolyMid6C31h */ 1.10545369624155406951904296875000000000000000000000e+10, /* 335, accPolyMid6C32h */ 2.66385731955786666870117187500000000000000000000000e+10, /* 336, accPolyMid6C33h */ 6.43976383194783477783203125000000000000000000000000e+10, /* 337, accPolyMid6C34h */ 1.66775070729799957275390625000000000000000000000000e+11, /* 338, accPolyMid6C35h */ 1.02820225588634994728920446505071595311164855957031e+00, /* 339, RN rounding constant quick poly middle 6*/ 1.54107813388901044122294580378974284123051351850249e-18, /* 340, RD rounding constant quick poly middle 6*/ 6.67959213256959061233430929860332980751991271972656e-01, /* 341, midpoint in interval 7*/ 7.31463137281961883751080222282325848937034606933594e-01, /* 342, accPolyMid7C0h, quickPolyMid7C0h */ 8.54719742452471207894475172794621662948903828511743e-18, /* 343, accPolyMid7C0m, quickPolyMid7C0l */ 1.34372862717732943771409281907835975289344787597656e+00, /* 344, accPolyMid7C1h, quickPolyMid7C1h */ -9.37080278359462608557638680730489336344772507156678e-17, /* 345, accPolyMid7C1m, quickPolyMid7C1l */ -3.73014429525577422762683976038701673929582903516469e-33, /* 346, accPolyMid7C1l */ 8.10316454021746457314634426438715308904647827148438e-01, /* 347, accPolyMid7C2h, quickPolyMid7C2h */ 2.83724520944754281479328686665519600224801269794297e-17, /* 348, accPolyMid7C2m, quickPolyMid7C2l */ 5.82045706927347254178829289360700371297572159541923e-34, /* 349, accPolyMid7C2l */ 1.38167386397960734178980146680260077118873596191406e+00, /* 350, accPolyMid7C3h, quickPolyMid7C3h */ 2.02013329353188582679931981349209152232167295906717e-17, /* 351, accPolyMid7C3m, quickPolyMid7C3l */ 6.40114855650846168897999343294667085370954557070054e-34, /* 352, accPolyMid7C3l */ 2.57070122683855739609271040535531938076019287109375e+00, /* 353, accPolyMid7C4h, quickPolyMid7C4h */ -1.97101208773651620042078427599655545421327570922328e-16, /* 354, accPolyMid7C4m, quickPolyMid7C4l */ -5.16498810795509657208158829628186048443297866770160e-33, /* 355, accPolyMid7C4l */ 5.46327133150128840810566543950699269771575927734375e+00, /* 356, accPolyMid7C5h, quickPolyMid7C5h */ 4.46002282634806142830756936399426613343260291679165e-17, /* 357, accPolyMid7C5m, quickPolyMid7C5l */ 1.00630542800586945033209683978834296850153546719007e-33, /* 358, accPolyMid7C5l */ 1.23592045140328163910226066946052014827728271484375e+01, /* 359, accPolyMid7C6h, quickPolyMid7C6h */ -6.31168277706663387163074158423931222709606927382536e-16, /* 360, accPolyMid7C6m, quickPolyMid7C6l */ -2.86577343636081880556771704346742846876298657614067e-32, /* 361, accPolyMid7C6l */ 2.92955857889283457495821494376286864280700683593750e+01, /* 362, accPolyMid7C7h, quickPolyMid7C7h */ 1.68044477586948138119056363287999050823887212287311e-15, /* 363, accPolyMid7C7m, quickPolyMid7C7l */ 7.17613428086569200559097225777804851531982421875000e+01, /* 364, accPolyMid7C8h, quickPolyMid7C8h */ 6.23119826880857970524569208326049427014155061843592e-15, /* 365, accPolyMid7C8m */ 1.80247733513940403327069361694157123565673828125000e+02, /* 366, accPolyMid7C9h, quickPolyMid7C9h */ 5.02375884230076452151557056132473497202104361844532e-15, /* 367, accPolyMid7C9m */ 4.61706463186508131002483423799276351928710937500000e+02, /* 368, accPolyMid7C10h, quickPolyMid7C10h */ 1.87384815286128587607402694756722954854896712184598e-14, /* 369, accPolyMid7C10m */ 1.20148795335111071835854090750217437744140625000000e+03, /* 370, accPolyMid7C11h, quickPolyMid7C11h */ 2.60459063066423653270039910766913797650205005668189e-14, /* 371, accPolyMid7C11m */ 3.16745162323707290852325968444347381591796875000000e+03, /* 372, accPolyMid7C12h, quickPolyMid7C12h */ -2.76092355337723539107271551080313829589234133482512e-14, /* 373, accPolyMid7C12m */ 8.44145526317249823478050529956817626953125000000000e+03, /* 374, accPolyMid7C13h, quickPolyMid7C13h */ -2.33235416338613018856460888065680920494017469568604e-13, /* 375, accPolyMid7C13m */ 2.27054147369064739905297756195068359375000000000000e+04, /* 376, accPolyMid7C14h, quickPolyMid7C14h */ -3.76196185348520617410321355221587231933578349130087e-13, /* 377, accPolyMid7C14m */ 6.15579784849813586333766579627990722656250000000000e+04, /* 378, accPolyMid7C15h */ -5.34885488214934542022410271185570626302323293810304e-13, /* 379, accPolyMid7C15m */ 1.68046954551722796168178319931030273437500000000000e+05, /* 380, accPolyMid7C16h */ 4.61530358172978565562516450881958007812500000000000e+05, /* 381, accPolyMid7C17h */ 1.27435135728149255737662315368652343750000000000000e+06, /* 382, accPolyMid7C18h */ 3.53543876571432314813137054443359375000000000000000e+06, /* 383, accPolyMid7C19h */ 9.85027146846828423440456390380859375000000000000000e+06, /* 384, accPolyMid7C20h */ 2.75499693650120757520198822021484375000000000000000e+07, /* 385, accPolyMid7C21h */ 7.73223713417402952909469604492187500000000000000000e+07, /* 386, accPolyMid7C22h */ 2.17703077316092193126678466796875000000000000000000e+08, /* 387, accPolyMid7C23h */ 6.14725288059689402580261230468750000000000000000000e+08, /* 388, accPolyMid7C24h */ 1.74040800223112154006958007812500000000000000000000e+09, /* 389, accPolyMid7C25h */ 4.93950269498267459869384765625000000000000000000000e+09, /* 390, accPolyMid7C26h */ 1.40506579253189964294433593750000000000000000000000e+10, /* 391, accPolyMid7C27h */ 4.00515555251962203979492187500000000000000000000000e+10, /* 392, accPolyMid7C28h */ 1.14389701296316925048828125000000000000000000000000e+11, /* 393, accPolyMid7C29h */ 3.27296809500310974121093750000000000000000000000000e+11, /* 394, accPolyMid7C30h */ 9.38089913584087280273437500000000000000000000000000e+11, /* 395, accPolyMid7C31h */ 2.69293079636161279296875000000000000000000000000000e+12, /* 396, accPolyMid7C32h */ 7.72833097677600292968750000000000000000000000000000e+12, /* 397, accPolyMid7C33h */ 2.22444558194129648437500000000000000000000000000000e+13, /* 398, accPolyMid7C34h */ 6.82401753565838359375000000000000000000000000000000e+13, /* 399, accPolyMid7C35h */ 1.01740290807493916069859096751315519213676452636719e+00, /* 400, RN rounding constant quick poly middle 7*/ 9.50960845417677113226513686606015976666256457529322e-19, /* 401, RD rounding constant quick poly middle 7*/ 7.19008445739778290217714129539672285318374633789062e-01, /* 402, midpoint in interval 8*/ 8.02374569969830475635319544380763545632362365722656e-01, /* 403, accPolyMid8C0h, quickPolyMid8C0h */ -5.57232596267891548198947769768214754835408022265973e-18, /* 404, accPolyMid8C0m, quickPolyMid8C0l */ 1.43884615807450622071428369963541626930236816406250e+00, /* 405, accPolyMid8C1h, quickPolyMid8C1h */ 3.59501817700961691698905527113737832717163932379732e-17, /* 406, accPolyMid8C1m, quickPolyMid8C1l */ 1.42139791223330171535988185118707169939451756100115e-33, /* 407, accPolyMid8C1l */ 1.07089546798848767039658014255110174417495727539062e+00, /* 408, accPolyMid8C2h, quickPolyMid8C2h */ 7.12234409493595206110752393915421282220770659974638e-18, /* 409, accPolyMid8C2m, quickPolyMid8C2l */ 4.88803415361541961399074298884647415525574790319603e-34, /* 410, accPolyMid8C2l */ 2.09054748952818103546746897336561232805252075195312e+00, /* 411, accPolyMid8C3h, quickPolyMid8C3h */ -4.76201670474478458619338404030121517580491201111076e-17, /* 412, accPolyMid8C3m, quickPolyMid8C3l */ 9.85965711757934088944524691800382507878970211803297e-34, /* 413, accPolyMid8C3l */ 4.62886640680389760404978005681186914443969726562500e+00, /* 414, accPolyMid8C4h, quickPolyMid8C4h */ -6.26076461255283992652654162871089011104493903198467e-17, /* 415, accPolyMid8C4m, quickPolyMid8C4l */ -3.79525038577018957662309046851941714013728344004132e-33, /* 416, accPolyMid8C4l */ 1.15940096700862280698629547259770333766937255859375e+01, /* 417, accPolyMid8C5h, quickPolyMid8C5h */ 5.00344758332442110044971487490682364429618307708619e-16, /* 418, accPolyMid8C5m, quickPolyMid8C5l */ 5.05400641998677592107699970650218041381398322944134e-33, /* 419, accPolyMid8C5l */ 3.09983076631741454320945194922387599945068359375000e+01, /* 420, accPolyMid8C6h, quickPolyMid8C6h */ -1.68695534318490565671111852385917462817518447859219e-16, /* 421, accPolyMid8C6m, quickPolyMid8C6l */ 6.85050661529605157727571454320758800953682098824324e-34, /* 422, accPolyMid8C6l */ 8.67969690247392975379625568166375160217285156250000e+01, /* 423, accPolyMid8C7h, quickPolyMid8C7h */ -5.77909319686569076564604963233208513019264259552576e-15, /* 424, accPolyMid8C7m, quickPolyMid8C7l */ 2.51207737556061232453430420719087123870849609375000e+02, /* 425, accPolyMid8C8h, quickPolyMid8C8h */ -2.34229223147066395573123458231502220325151528840246e-15, /* 426, accPolyMid8C8m */ 7.45516108151238086065859533846378326416015625000000e+02, /* 427, accPolyMid8C9h, quickPolyMid8C9h */ 5.42429462463291658149197032428663192617240449908134e-15, /* 428, accPolyMid8C9m */ 2.25637900900536169501719996333122253417968750000000e+03, /* 429, accPolyMid8C10h, quickPolyMid8C10h */ 1.04118075698860813774916020354956791986217497225642e-13, /* 430, accPolyMid8C10m */ 6.93796098101582811068510636687278747558593750000000e+03, /* 431, accPolyMid8C11h, quickPolyMid8C11h */ 8.59862281333229161222916847764065622815798321104674e-15, /* 432, accPolyMid8C11m */ 2.16119867410615115659311413764953613281250000000000e+04, /* 433, accPolyMid8C12h, quickPolyMid8C12h */ 1.06661614083783310365636876324959361083581990681246e-13, /* 434, accPolyMid8C12m */ 6.80579130650992592563852667808532714843750000000000e+04, /* 435, accPolyMid8C13h, quickPolyMid8C13h */ 6.62014084472278982961475227363418833651659278771717e-12, /* 436, accPolyMid8C13m */ 2.16307061102022911654785275459289550781250000000000e+05, /* 437, accPolyMid8C14h, quickPolyMid8C14h */ -2.44881501957370731470213892899278376432195547529602e-12, /* 438, accPolyMid8C14m */ 6.92960027312710066325962543487548828125000000000000e+05, /* 439, accPolyMid8C15h */ -5.66500973206806599245652257405055779448943553688878e-11, /* 440, accPolyMid8C15m */ 2.23531716476973146200180053710937500000000000000000e+06, /* 441, accPolyMid8C16h */ 7.25429400587130710482597351074218750000000000000000e+06, /* 442, accPolyMid8C17h */ 2.36685600768156014382839202880859375000000000000000e+07, /* 443, accPolyMid8C18h */ 7.75916356685774326324462890625000000000000000000000e+07, /* 444, accPolyMid8C19h */ 2.55452232123835593461990356445312500000000000000000e+08, /* 445, accPolyMid8C20h */ 8.44254469674954175949096679687500000000000000000000e+08, /* 446, accPolyMid8C21h */ 2.79994093996573638916015625000000000000000000000000e+09, /* 447, accPolyMid8C22h */ 9.31537507532041358947753906250000000000000000000000e+09, /* 448, accPolyMid8C23h */ 3.10820362568210334777832031250000000000000000000000e+10, /* 449, accPolyMid8C24h */ 1.03985438377022964477539062500000000000000000000000e+11, /* 450, accPolyMid8C25h */ 3.48737110205060913085937500000000000000000000000000e+11, /* 451, accPolyMid8C26h */ 1.17221005601944750976562500000000000000000000000000e+12, /* 452, accPolyMid8C27h */ 3.94841085036352832031250000000000000000000000000000e+12, /* 453, accPolyMid8C28h */ 1.33255264873973789062500000000000000000000000000000e+13, /* 454, accPolyMid8C29h */ 4.50540615593679062500000000000000000000000000000000e+13, /* 455, accPolyMid8C30h */ 1.52590744626434593750000000000000000000000000000000e+14, /* 456, accPolyMid8C31h */ 5.17610884067860062500000000000000000000000000000000e+14, /* 457, accPolyMid8C32h */ 1.75591888512180650000000000000000000000000000000000e+15, /* 458, accPolyMid8C33h */ 5.97247050283681300000000000000000000000000000000000e+15, /* 459, accPolyMid8C34h */ 2.15157732956128240000000000000000000000000000000000e+16, /* 460, accPolyMid8C35h */ 1.01155686685228385357504521380178630352020263671875e+00, /* 461, RN rounding constant quick poly middle 8*/ 6.36522991537283605877265237263241827159525525595558e-19, /* 462, RD rounding constant quick poly middle 8*/ 7.60880231857352207214262307388707995414733886718750e-01, /* 463, midpoint in interval 9*/ 8.64668552766275078091950945236021652817726135253906e-01, /* 464, accPolyMid9C0h, quickPolyMid9C0h */ 2.22107768610709483983000348580034922276618040094248e-19, /* 465, accPolyMid9C0m, quickPolyMid9C0l */ 1.54108768708640897493467036838410422205924987792969e+00, /* 466, accPolyMid9C1h, quickPolyMid9C1h */ 3.32820103504311843280112118328828427349507594590859e-17, /* 467, accPolyMid9C1m, quickPolyMid9C1l */ 1.00469319336666835386896691703426687648516206509999e-33, /* 468, accPolyMid9C1l */ 1.39241392226891269601196654548402875661849975585938e+00, /* 469, accPolyMid9C2h, quickPolyMid9C2h */ -7.78438411380474954824767774215038405507043967534661e-17, /* 470, accPolyMid9C2m, quickPolyMid9C2l */ -2.75498989204243544757760916231818015864525586405625e-34, /* 471, accPolyMid9C2l */ 3.12616775988369477445871780219022184610366821289062e+00, /* 472, accPolyMid9C3h, quickPolyMid9C3h */ -1.83136634474213254639590598215495010130375003296228e-16, /* 473, accPolyMid9C3m, quickPolyMid9C3l */ -1.37039877493057234685308732075670776376976824689825e-33, /* 474, accPolyMid9C3l */ 8.16374541867330982825023966142907738685607910156250e+00, /* 475, accPolyMid9C4h, quickPolyMid9C4h */ 6.61331422381139448266729896007647878117248843327786e-16, /* 476, accPolyMid9C4m, quickPolyMid9C4l */ -2.34411228408683938039171677313602417735464237635307e-32, /* 477, accPolyMid9C4l */ 2.39942774487262227012251969426870346069335937500000e+01, /* 478, accPolyMid9C5h, quickPolyMid9C5h */ 3.56709659583669727593018389598696746405922754956722e-16, /* 479, accPolyMid9C5m, quickPolyMid9C5l */ 1.92887188784617492937549821774446261489627075560113e-32, /* 480, accPolyMid9C5l */ 7.53789452793380974071624223142862319946289062500000e+01, /* 481, accPolyMid9C6h, quickPolyMid9C6h */ -4.89236491033052363530754653203901634957086880239885e-15, /* 482, accPolyMid9C6m, quickPolyMid9C6l */ 1.86966182047363315238712995890702987106854589421809e-31, /* 483, accPolyMid9C6l */ 2.47970017761763045882617007009685039520263671875000e+02, /* 484, accPolyMid9C7h, quickPolyMid9C7h */ -5.49773113276874172897358146458574130047619382341550e-15, /* 485, accPolyMid9C7m, quickPolyMid9C7l */ 8.43239639560233626980334520339965820312500000000000e+02, /* 486, accPolyMid9C8h, quickPolyMid9C8h */ 4.61444619149467756136937751706191309842186761003280e-14, /* 487, accPolyMid9C8m */ 2.94042238989191673681489191949367523193359375000000e+03, /* 488, accPolyMid9C9h, quickPolyMid9C9h */ -6.26529947434876144165574723786618699307871677151027e-14, /* 489, accPolyMid9C9m */ 1.04570596262470262445276603102684020996093750000000e+04, /* 490, accPolyMid9C10h, quickPolyMid9C10h */ 4.33811913399171164864172764349193352065910816994787e-13, /* 491, accPolyMid9C10m */ 3.77816423278584625222720205783843994140625000000000e+04, /* 492, accPolyMid9C11h, quickPolyMid9C11h */ -4.21825155017599752908316500880066660420734253600372e-14, /* 493, accPolyMid9C11m */ 1.38292932619114842964336276054382324218750000000000e+05, /* 494, accPolyMid9C12h, quickPolyMid9C12h */ -2.02223055949190022685968858135129700521678830504868e-12, /* 495, accPolyMid9C12m */ 5.11733514125351735856384038925170898437500000000000e+05, /* 496, accPolyMid9C13h, quickPolyMid9C13h */ -2.25025523408315347550056625257165819446736332309911e-11, /* 497, accPolyMid9C13m */ 1.91116705355792236514389514923095703125000000000000e+06, /* 498, accPolyMid9C14h, quickPolyMid9C14h */ -6.92308947161053801527502899602797403061371639410027e-11, /* 499, accPolyMid9C14m */ 7.19450694938360899686813354492187500000000000000000e+06, /* 500, accPolyMid9C15h */ -3.25836107774239441972945896739397887709177581427866e-10, /* 501, accPolyMid9C15m */ 2.72708481033120900392532348632812500000000000000000e+07, /* 502, accPolyMid9C16h */ 1.03997450389555335044860839843750000000000000000000e+08, /* 503, accPolyMid9C17h */ 3.98720516462098360061645507812500000000000000000000e+08, /* 504, accPolyMid9C18h */ 1.53596677859462237358093261718750000000000000000000e+09, /* 505, accPolyMid9C19h */ 5.94220454070446586608886718750000000000000000000000e+09, /* 506, accPolyMid9C20h */ 2.30771902569618682861328125000000000000000000000000e+10, /* 507, accPolyMid9C21h */ 8.99354036055935974121093750000000000000000000000000e+10, /* 508, accPolyMid9C22h */ 3.51604905808161804199218750000000000000000000000000e+11, /* 509, accPolyMid9C23h */ 1.37859673609756665039062500000000000000000000000000e+12, /* 510, accPolyMid9C24h */ 5.41968316905909179687500000000000000000000000000000e+12, /* 511, accPolyMid9C25h */ 2.13586334787060429687500000000000000000000000000000e+13, /* 512, accPolyMid9C26h */ 8.43635735241271562500000000000000000000000000000000e+13, /* 513, accPolyMid9C27h */ 3.33923015327480937500000000000000000000000000000000e+14, /* 514, accPolyMid9C28h */ 1.32429009755987925000000000000000000000000000000000e+15, /* 515, accPolyMid9C29h */ 5.26147664189654100000000000000000000000000000000000e+15, /* 516, accPolyMid9C30h */ 2.09399836831170720000000000000000000000000000000000e+16, /* 517, accPolyMid9C31h */ 8.34692893106752000000000000000000000000000000000000e+16, /* 518, accPolyMid9C32h */ 3.32762568376608000000000000000000000000000000000000e+17, /* 519, accPolyMid9C33h */ 1.33003631888338841600000000000000000000000000000000e+18, /* 520, accPolyMid9C34h */ 5.62235923730283212800000000000000000000000000000000e+18, /* 521, accPolyMid9C35h */ 1.01049946711285376643729705392615869641304016113281e+00, /* 522, RN rounding constant quick poly middle 9*/ 5.78284088727747938003347592934948079832502681677348e-19, /* 523, RD rounding constant quick poly middle 9*/ -8.33333333333333287074040640618477482348680496215820e-02, /* 524, accPolyHighC1h, quickPolyHighC1h */ -4.62592926927148532830780603208030422795294098867636e-18, /* 525, accPolyHighC1m, quickPolyHighC1l */ -2.56790659251636222413745757067544746896901530409675e-34, /* 526, accPolyHighC1l */ -1.87499999999999993061106096092771622352302074432373e-02, /* 527, accPolyHighC2h, quickPolyHighC2h */ -6.93889390390722876283368680301479756432058851698546e-19, /* 528, accPolyHighC2m, quickPolyHighC2l */ 3.85185989241340205035888971870941307651344283492079e-35, /* 529, accPolyHighC2l */ -5.58035714285714298105167685548622102942317724227905e-03, /* 530, accPolyHighC3h, quickPolyHighC3h */ 1.23908819712629071293959090145008148963025205053831e-19, /* 531, accPolyHighC3m, quickPolyHighC3l */ 6.87827508933260239532125196237951282993345739214379e-36, /* 532, accPolyHighC3l */ -1.89887152777777775368439616698879035538993775844574e-03, /* 533, accPolyHighC4h, quickPolyHighC4h */ -2.40933816107889860849364897504182511872549009826894e-20, /* 534, accPolyHighC4m, quickPolyHighC4l */ -1.31413379554614650822698366533512762375439292005686e-36, /* 535, accPolyHighC4l */ -6.99129971590909120478241067786484563839621841907501e-04, /* 536, accPolyHighC5h, quickPolyHighC5h */ 2.95691501586955672658426997372092637662516651210484e-20, /* 537, accPolyHighC5m, quickPolyHighC5l */ 1.93248831638054158509225332576516713663708940033800e-36, /* 538, accPolyHighC5l */ -2.71136944110576935586948144063512700085993856191635e-04, /* 539, accPolyHighC6h, quickPolyHighC6h */ 1.25100250671414776773311485375106982275955017737813e-20, /* 540, accPolyHighC6m, quickPolyHighC6l */ -2.41797324682937785630481140742729367728409168219340e-37, /* 541, accPolyHighC6l */ -1.09100341796875005421010862427522170037264004349709e-04, /* 542, accPolyHighC7h, quickPolyHighC7h */ 5.42101086231091719294416952538483743258993211884145e-21, /* 543, accPolyHighC7m, quickPolyHighC7l */ 9.55338141209871258458343868890229946241110412925982e-38, /* 544, accPolyHighC7l */ -4.51242222505457229141112573955751940957270562648773e-05, /* 545, accPolyHighC8h, quickPolyHighC8h */ -3.18882990973711044045301474516264873522265001897356e-21, /* 546, accPolyHighC8m, quickPolyHighC8l */ 1.26912673390128847048400261536391292203355395300755e-37, /* 547, accPolyHighC8l */ -1.90656436117071843741425929419364138084347359836102e-05, /* 548, accPolyHighC9h, quickPolyHighC9h */ -1.06993691223935686411543055030763865855410413408366e-21, /* 549, accPolyHighC9m, quickPolyHighC9l */ -8.19368731407892096011823940271412425317976158112288e-06, /* 550, accPolyHighC10h, quickPolyHighC10h */ -4.03323388732262270981356256138402986149007425086112e-22, /* 551, accPolyHighC10m */ -3.57056927421818625395413641931963155684570665471256e-06, /* 552, accPolyHighC11h, quickPolyHighC11h */ 1.64796270839759047485693620137778762426170587507193e-22, /* 553, accPolyHighC11m */ -1.57402595505118377679448869038703051614902506116778e-06, /* 554, accPolyHighC12h, quickPolyHighC12h */ 1.03140748281100284102117735554826521589797225638379e-22, /* 555, accPolyHighC12m */ -7.00688192241446386609332076800260580284884781576693e-07, /* 556, accPolyHighC13h, quickPolyHighC13h */ 1.64297063257073230214010320767916245637133227760945e-23, /* 557, accPolyHighC13m */ -3.14533061665020903893046425037205438002274604514241e-07, /* 558, accPolyHighC14h, quickPolyHighC14h */ -1.57714454767442613704253788250439912924415496806915e-23, /* 559, accPolyHighC14m */ -1.42216292935838748302118661470672122959513217210770e-07, /* 560, accPolyHighC15h, quickPolyHighC15h */ 3.70163506723718792079998292841186813204562291235770e-24, /* 561, accPolyHighC15m */ -6.47111067734723877623606537110023673164960200665519e-08, /* 562, accPolyHighC16h, quickPolyHighC16h */ 1.96959302136511249382763415085950224265202199251341e-24, /* 563, accPolyHighC16m */ -2.96094098107419582578099602043070204260288846853655e-08, /* 564, accPolyHighC17h, quickPolyHighC17h */ -1.33210241793138800698071276025711826265682121011801e-25, /* 565, accPolyHighC17m */ -1.36154377785683810553931313304908135020099280154682e-08, /* 566, accPolyHighC18h, quickPolyHighC18h */ -6.28864412480332248702787563995712794007175716615166e-09, /* 567, accPolyHighC19h */ -2.91615151940413698643198065114674061293342788303562e-09, /* 568, accPolyHighC20h */ -1.35724329813454494662594037565671659106847357634251e-09, /* 569, accPolyHighC21h */ -6.33321170158103043923636695899503229467697451582353e-10, /* 570, accPolyHighC22h */ -2.98137047522453658533318439889463723202478462326326e-10, /* 571, accPolyHighC23h */ -1.35174910337425390381481209427921852395115820399951e-10, /* 572, accPolyHighC24h */ -7.57694791124210735879864558660150546803846438592700e-11, /* 573, accPolyHighC25h */ -1.19244777215077355372683280351504137017926154840097e-11, /* 574, accPolyHighC26h */ -4.08879979855917754145740023360966995669141255120849e-11, /* 575, accPolyHighC27h */ 1.75342081019476863949528641668112755730435381451571e-11, /* 576, accPolyHighC28h */ -1.60530246587119583502980643958298338953849526689055e-11, /* 577, accPolyHighC29h */ 1.00010072995346011026640553609468042850494384765625e+00, /* 578, RN rounding constant quick poly high*/ 5.59129439367752644847269214347219849204178767344215e-21, /* 579, RD rounding constant quick poly high*/ }; interval-3.2.0/src/crlibm/asincos.c0000644000000000000000000030444713316017127015345 0ustar 00000000000000/* * Correctly rounded arcsine and arccosine * * Copyright (c) 2007 Christoph Lauter (ENS Lyon), * with Sylvain Chevillard (ENS Lyon) for the polynomials * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "asincos.h" static inline void p0_quick(double *p_resh, double *p_resm, double x, int32_t xhi) { double p_x_0_pow2h, p_x_0_pow2m; double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h; double p_t_6_0h; double p_t_7_0h; double p_t_8_0h; double p_t_9_0h; double p_t_10_0h; double p_t_11_0h; double p_t_12_0h; double p_t_13_0h; double p_t_14_0h; double p_t_15_0h; double p_t_16_0h; double p_t_17_0h, p_t_17_0m; double p_t_18_0h, p_t_18_0m; double p_t_19_0h, p_t_19_0m; double p_t_20_0h, p_t_20_0m; if (xhi < EXTRABOUND2) { double t1, t2, t3; t2 = p0_quick_coeff_3h * x; t1 = x * x; t3 = t1 * t2; Add12(*p_resh,*p_resm,x,t3); return; } Mul12(&p_x_0_pow2h,&p_x_0_pow2m,x,x); p_t_15_0h = p0_quick_coeff_5h; if (xhi > EXTRABOUND) { p_t_1_0h = p0_quick_coeff_19h; p_t_2_0h = p_t_1_0h * p_x_0_pow2h; p_t_3_0h = p0_quick_coeff_17h + p_t_2_0h; p_t_4_0h = p_t_3_0h * p_x_0_pow2h; p_t_5_0h = p0_quick_coeff_15h + p_t_4_0h; p_t_6_0h = p_t_5_0h * p_x_0_pow2h; p_t_7_0h = p0_quick_coeff_13h + p_t_6_0h; p_t_8_0h = p_t_7_0h * p_x_0_pow2h; p_t_9_0h = p0_quick_coeff_11h + p_t_8_0h; p_t_10_0h = p_t_9_0h * p_x_0_pow2h; p_t_11_0h = p0_quick_coeff_9h + p_t_10_0h; p_t_12_0h = p_t_11_0h * p_x_0_pow2h; p_t_13_0h = p0_quick_coeff_7h + p_t_12_0h; p_t_14_0h = p_t_13_0h * p_x_0_pow2h; p_t_15_0h = p_t_15_0h + p_t_14_0h; } p_t_16_0h = p_t_15_0h * p_x_0_pow2h; Add12(p_t_17_0h,p_t_17_0m,p0_quick_coeff_3h,p_t_16_0h); Mul122(&p_t_18_0h,&p_t_18_0m,x,p_x_0_pow2h,p_x_0_pow2m); Mul22(&p_t_19_0h,&p_t_19_0m,p_t_17_0h,p_t_17_0m,p_t_18_0h,p_t_18_0m); Add122(&p_t_20_0h,&p_t_20_0m,x,p_t_19_0h,p_t_19_0m); *p_resh = p_t_20_0h; *p_resm = p_t_20_0m; } static inline void p_quick(double *p_resh, double *p_resm, double x, int index) { double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h; double p_t_6_0h; double p_t_7_0h; double p_t_8_0h; double p_t_9_0h; double p_t_10_0h; double p_t_11_0h; double p_t_12_0h; double p_t_13_0h; double p_t_14_0h; double p_t_15_0h; double p_t_16_0h; double p_t_17_0h; double p_t_18_0h; double p_t_19_0h; double p_t_20_0h; double p_t_21_0h, p_t_21_0m; double p_t_22_0h, p_t_22_0m; double p_t_23_0h, p_t_23_0m; p_t_1_0h = p_quick_coeff_12h; p_t_2_0h = p_t_1_0h * x; p_t_3_0h = p_quick_coeff_11h + p_t_2_0h; p_t_4_0h = p_t_3_0h * x; p_t_5_0h = p_quick_coeff_10h + p_t_4_0h; p_t_6_0h = p_t_5_0h * x; p_t_7_0h = p_quick_coeff_9h + p_t_6_0h; p_t_8_0h = p_t_7_0h * x; p_t_9_0h = p_quick_coeff_8h + p_t_8_0h; p_t_10_0h = p_t_9_0h * x; p_t_11_0h = p_quick_coeff_7h + p_t_10_0h; p_t_12_0h = p_t_11_0h * x; p_t_13_0h = p_quick_coeff_6h + p_t_12_0h; p_t_14_0h = p_t_13_0h * x; p_t_15_0h = p_quick_coeff_5h + p_t_14_0h; p_t_16_0h = p_t_15_0h * x; p_t_17_0h = p_quick_coeff_4h + p_t_16_0h; p_t_18_0h = p_t_17_0h * x; p_t_19_0h = p_quick_coeff_3h + p_t_18_0h; p_t_20_0h = p_t_19_0h * x; Add12(p_t_21_0h,p_t_21_0m,p_quick_coeff_2h,p_t_20_0h); MulAdd212(&p_t_22_0h,&p_t_22_0m,p_quick_coeff_1h,p_quick_coeff_1m,x,p_t_21_0h,p_t_21_0m); MulAdd212(&p_t_23_0h,&p_t_23_0m,p_quick_coeff_0h,p_quick_coeff_0m,x,p_t_22_0h,p_t_22_0m); *p_resh = p_t_23_0h; *p_resm = p_t_23_0m; } static inline void p9_quick(double *p_resh, double *p_resm, double x) { double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h; double p_t_6_0h; double p_t_7_0h; double p_t_8_0h; double p_t_9_0h; double p_t_10_0h; double p_t_11_0h; double p_t_12_0h; double p_t_13_0h; double p_t_14_0h; double p_t_15_0h; double p_t_16_0h; double p_t_17_0h; double p_t_18_0h; double p_t_19_0h; double p_t_20_0h; double p_t_21_0h, p_t_21_0m; double p_t_22_0h, p_t_22_0m; double p_t_23_0h, p_t_23_0m; p_t_1_0h = p9_quick_coeff_11h; p_t_2_0h = p_t_1_0h * x; p_t_3_0h = p9_quick_coeff_10h + p_t_2_0h; p_t_4_0h = p_t_3_0h * x; p_t_5_0h = p9_quick_coeff_9h + p_t_4_0h; p_t_6_0h = p_t_5_0h * x; p_t_7_0h = p9_quick_coeff_8h + p_t_6_0h; p_t_8_0h = p_t_7_0h * x; p_t_9_0h = p9_quick_coeff_7h + p_t_8_0h; p_t_10_0h = p_t_9_0h * x; p_t_11_0h = p9_quick_coeff_6h + p_t_10_0h; p_t_12_0h = p_t_11_0h * x; p_t_13_0h = p9_quick_coeff_5h + p_t_12_0h; p_t_14_0h = p_t_13_0h * x; p_t_15_0h = p9_quick_coeff_4h + p_t_14_0h; p_t_16_0h = p_t_15_0h * x; p_t_17_0h = p9_quick_coeff_3h + p_t_16_0h; p_t_18_0h = p_t_17_0h * x; p_t_19_0h = p9_quick_coeff_2h + p_t_18_0h; p_t_20_0h = p_t_19_0h * x; Add12(p_t_21_0h,p_t_21_0m,p9_quick_coeff_1h,p_t_20_0h); Mul122(&p_t_22_0h,&p_t_22_0m,x,p_t_21_0h,p_t_21_0m); Add122(&p_t_23_0h,&p_t_23_0m,p9_quick_coeff_0h,p_t_22_0h,p_t_22_0m); *p_resh = p_t_23_0h; *p_resm = p_t_23_0m; } static void p0_accu(double *p_resh, double *p_resm, double *p_resl, double x) { double p_x_0_pow2h, p_x_0_pow2m; Mul12(&p_x_0_pow2h,&p_x_0_pow2m,x,x); double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h; double p_t_6_0h; double p_t_7_0h, p_t_7_0m; double p_t_8_0h, p_t_8_0m; double p_t_9_0h, p_t_9_0m; double p_t_10_0h, p_t_10_0m; double p_t_11_0h, p_t_11_0m; double p_t_12_0h, p_t_12_0m; double p_t_13_0h, p_t_13_0m; double p_t_14_0h, p_t_14_0m; double p_t_15_0h, p_t_15_0m; double p_t_16_0h, p_t_16_0m; double p_t_17_0h, p_t_17_0m; double p_t_18_0h, p_t_18_0m; double p_t_19_0h, p_t_19_0m; double p_t_20_0h, p_t_20_0m; double p_t_21_0h, p_t_21_0m; double p_t_22_0h, p_t_22_0m; double p_t_23_0h, p_t_23_0m; double p_t_24_0h, p_t_24_0m; double p_t_25_0h, p_t_25_0m; double p_t_26_0h, p_t_26_0m; double p_t_27_0h, p_t_27_0m; double p_t_28_0h, p_t_28_0m, p_t_28_0l; double p_t_29_0h, p_t_29_0m, p_t_29_0l; double p_t_30_0h, p_t_30_0m, p_t_30_0l; double p_t_31_0h, p_t_31_0m, p_t_31_0l; double p_t_32_0h, p_t_32_0m, p_t_32_0l; double p_t_33_0h, p_t_33_0m, p_t_33_0l; double p_t_34_0h, p_t_34_0m, p_t_34_0l; double p_t_35_0h, p_t_35_0m, p_t_35_0l; p_t_1_0h = p0_accu_coeff_37h; p_t_2_0h = p_t_1_0h * p_x_0_pow2h; p_t_3_0h = p0_accu_coeff_35h + p_t_2_0h; p_t_4_0h = p_t_3_0h * p_x_0_pow2h; p_t_5_0h = p0_accu_coeff_33h + p_t_4_0h; p_t_6_0h = p_t_5_0h * p_x_0_pow2h; Add12(p_t_7_0h,p_t_7_0m,p0_accu_coeff_31h,p_t_6_0h); Mul22(&p_t_8_0h,&p_t_8_0m,p_t_7_0h,p_t_7_0m,p_x_0_pow2h,p_x_0_pow2m); Add122(&p_t_9_0h,&p_t_9_0m,p0_accu_coeff_29h,p_t_8_0h,p_t_8_0m); Mul22(&p_t_10_0h,&p_t_10_0m,p_t_9_0h,p_t_9_0m,p_x_0_pow2h,p_x_0_pow2m); Add122(&p_t_11_0h,&p_t_11_0m,p0_accu_coeff_27h,p_t_10_0h,p_t_10_0m); Mul22(&p_t_12_0h,&p_t_12_0m,p_t_11_0h,p_t_11_0m,p_x_0_pow2h,p_x_0_pow2m); Add122(&p_t_13_0h,&p_t_13_0m,p0_accu_coeff_25h,p_t_12_0h,p_t_12_0m); Mul22(&p_t_14_0h,&p_t_14_0m,p_t_13_0h,p_t_13_0m,p_x_0_pow2h,p_x_0_pow2m); Add122(&p_t_15_0h,&p_t_15_0m,p0_accu_coeff_23h,p_t_14_0h,p_t_14_0m); Mul22(&p_t_16_0h,&p_t_16_0m,p_t_15_0h,p_t_15_0m,p_x_0_pow2h,p_x_0_pow2m); Add122(&p_t_17_0h,&p_t_17_0m,p0_accu_coeff_21h,p_t_16_0h,p_t_16_0m); Mul22(&p_t_18_0h,&p_t_18_0m,p_t_17_0h,p_t_17_0m,p_x_0_pow2h,p_x_0_pow2m); Add122(&p_t_19_0h,&p_t_19_0m,p0_accu_coeff_19h,p_t_18_0h,p_t_18_0m); Mul22(&p_t_20_0h,&p_t_20_0m,p_t_19_0h,p_t_19_0m,p_x_0_pow2h,p_x_0_pow2m); Add122(&p_t_21_0h,&p_t_21_0m,p0_accu_coeff_17h,p_t_20_0h,p_t_20_0m); Mul22(&p_t_22_0h,&p_t_22_0m,p_t_21_0h,p_t_21_0m,p_x_0_pow2h,p_x_0_pow2m); Add122(&p_t_23_0h,&p_t_23_0m,p0_accu_coeff_15h,p_t_22_0h,p_t_22_0m); MulAdd22(&p_t_24_0h,&p_t_24_0m,p0_accu_coeff_13h,p0_accu_coeff_13m,p_x_0_pow2h,p_x_0_pow2m,p_t_23_0h,p_t_23_0m); MulAdd22(&p_t_25_0h,&p_t_25_0m,p0_accu_coeff_11h,p0_accu_coeff_11m,p_x_0_pow2h,p_x_0_pow2m,p_t_24_0h,p_t_24_0m); MulAdd22(&p_t_26_0h,&p_t_26_0m,p0_accu_coeff_9h,p0_accu_coeff_9m,p_x_0_pow2h,p_x_0_pow2m,p_t_25_0h,p_t_25_0m); Mul22(&p_t_27_0h,&p_t_27_0m,p_t_26_0h,p_t_26_0m,p_x_0_pow2h,p_x_0_pow2m); Add23(&p_t_28_0h,&p_t_28_0m,&p_t_28_0l,p0_accu_coeff_7h,p0_accu_coeff_7m,p_t_27_0h,p_t_27_0m); Mul233(&p_t_29_0h,&p_t_29_0m,&p_t_29_0l,p_x_0_pow2h,p_x_0_pow2m,p_t_28_0h,p_t_28_0m,p_t_28_0l); Add233(&p_t_30_0h,&p_t_30_0m,&p_t_30_0l,p0_accu_coeff_5h,p0_accu_coeff_5m,p_t_29_0h,p_t_29_0m,p_t_29_0l); Mul233(&p_t_31_0h,&p_t_31_0m,&p_t_31_0l,p_x_0_pow2h,p_x_0_pow2m,p_t_30_0h,p_t_30_0m,p_t_30_0l); Add233(&p_t_32_0h,&p_t_32_0m,&p_t_32_0l,p0_accu_coeff_3h,p0_accu_coeff_3m,p_t_31_0h,p_t_31_0m,p_t_31_0l); Mul233(&p_t_33_0h,&p_t_33_0m,&p_t_33_0l,p_x_0_pow2h,p_x_0_pow2m,p_t_32_0h,p_t_32_0m,p_t_32_0l); Add133(&p_t_34_0h,&p_t_34_0m,&p_t_34_0l,p0_accu_coeff_1h,p_t_33_0h,p_t_33_0m,p_t_33_0l); Mul133(&p_t_35_0h,&p_t_35_0m,&p_t_35_0l,x,p_t_34_0h,p_t_34_0m,p_t_34_0l); Renormalize3(p_resh,p_resm,p_resl,p_t_35_0h,p_t_35_0m,p_t_35_0l); } static void p_accu(double *p_resh, double *p_resm, double *p_resl, double x, int index) { double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h; double p_t_6_0h; double p_t_7_0h; double p_t_8_0h; double p_t_9_0h; double p_t_10_0h; double p_t_11_0h; double p_t_12_0h; double p_t_13_0h; double p_t_14_0h; double p_t_15_0h; double p_t_16_0h; double p_t_17_0h, p_t_17_0m; double p_t_18_0h, p_t_18_0m; double p_t_19_0h, p_t_19_0m; double p_t_20_0h, p_t_20_0m; double p_t_21_0h, p_t_21_0m; double p_t_22_0h, p_t_22_0m; double p_t_23_0h, p_t_23_0m; double p_t_24_0h, p_t_24_0m; double p_t_25_0h, p_t_25_0m; double p_t_26_0h, p_t_26_0m; double p_t_27_0h, p_t_27_0m; double p_t_28_0h, p_t_28_0m; double p_t_29_0h, p_t_29_0m; double p_t_30_0h, p_t_30_0m; double p_t_31_0h, p_t_31_0m; double p_t_32_0h, p_t_32_0m; double p_t_33_0h, p_t_33_0m; double p_t_34_0h, p_t_34_0m; double p_t_35_0h, p_t_35_0m, p_t_35_0l; double p_t_36_0h, p_t_36_0m, p_t_36_0l; double p_t_37_0h, p_t_37_0m, p_t_37_0l; double p_t_38_0h, p_t_38_0m, p_t_38_0l; double p_t_39_0h, p_t_39_0m, p_t_39_0l; p_t_1_0h = p_accu_coeff_22h; p_t_2_0h = p_t_1_0h * x; p_t_3_0h = p_accu_coeff_21h + p_t_2_0h; p_t_4_0h = p_t_3_0h * x; p_t_5_0h = p_accu_coeff_20h + p_t_4_0h; p_t_6_0h = p_t_5_0h * x; p_t_7_0h = p_accu_coeff_19h + p_t_6_0h; p_t_8_0h = p_t_7_0h * x; p_t_9_0h = p_accu_coeff_18h + p_t_8_0h; p_t_10_0h = p_t_9_0h * x; p_t_11_0h = p_accu_coeff_17h + p_t_10_0h; p_t_12_0h = p_t_11_0h * x; p_t_13_0h = p_accu_coeff_16h + p_t_12_0h; p_t_14_0h = p_t_13_0h * x; p_t_15_0h = p_accu_coeff_15h + p_t_14_0h; p_t_16_0h = p_t_15_0h * x; Add12(p_t_17_0h,p_t_17_0m,p_accu_coeff_14h,p_t_16_0h); Mul122(&p_t_18_0h,&p_t_18_0m,x,p_t_17_0h,p_t_17_0m); Add122(&p_t_19_0h,&p_t_19_0m,p_accu_coeff_13h,p_t_18_0h,p_t_18_0m); Mul122(&p_t_20_0h,&p_t_20_0m,x,p_t_19_0h,p_t_19_0m); Add122(&p_t_21_0h,&p_t_21_0m,p_accu_coeff_12h,p_t_20_0h,p_t_20_0m); Mul122(&p_t_22_0h,&p_t_22_0m,x,p_t_21_0h,p_t_21_0m); Add122(&p_t_23_0h,&p_t_23_0m,p_accu_coeff_11h,p_t_22_0h,p_t_22_0m); Mul122(&p_t_24_0h,&p_t_24_0m,x,p_t_23_0h,p_t_23_0m); Add122(&p_t_25_0h,&p_t_25_0m,p_accu_coeff_10h,p_t_24_0h,p_t_24_0m); Mul122(&p_t_26_0h,&p_t_26_0m,x,p_t_25_0h,p_t_25_0m); Add122(&p_t_27_0h,&p_t_27_0m,p_accu_coeff_9h,p_t_26_0h,p_t_26_0m); MulAdd212(&p_t_28_0h,&p_t_28_0m,p_accu_coeff_8h,p_accu_coeff_8m,x,p_t_27_0h,p_t_27_0m); MulAdd212(&p_t_29_0h,&p_t_29_0m,p_accu_coeff_7h,p_accu_coeff_7m,x,p_t_28_0h,p_t_28_0m); MulAdd212(&p_t_30_0h,&p_t_30_0m,p_accu_coeff_6h,p_accu_coeff_6m,x,p_t_29_0h,p_t_29_0m); MulAdd212(&p_t_31_0h,&p_t_31_0m,p_accu_coeff_5h,p_accu_coeff_5m,x,p_t_30_0h,p_t_30_0m); MulAdd212(&p_t_32_0h,&p_t_32_0m,p_accu_coeff_4h,p_accu_coeff_4m,x,p_t_31_0h,p_t_31_0m); MulAdd212(&p_t_33_0h,&p_t_33_0m,p_accu_coeff_3h,p_accu_coeff_3m,x,p_t_32_0h,p_t_32_0m); Mul122(&p_t_34_0h,&p_t_34_0m,x,p_t_33_0h,p_t_33_0m); Add23(&p_t_35_0h,&p_t_35_0m,&p_t_35_0l,p_accu_coeff_2h,p_accu_coeff_2m,p_t_34_0h,p_t_34_0m); Mul133(&p_t_36_0h,&p_t_36_0m,&p_t_36_0l,x,p_t_35_0h,p_t_35_0m,p_t_35_0l); Add233(&p_t_37_0h,&p_t_37_0m,&p_t_37_0l,p_accu_coeff_1h,p_accu_coeff_1m,p_t_36_0h,p_t_36_0m,p_t_36_0l); Mul133(&p_t_38_0h,&p_t_38_0m,&p_t_38_0l,x,p_t_37_0h,p_t_37_0m,p_t_37_0l); Add233(&p_t_39_0h,&p_t_39_0m,&p_t_39_0l,p_accu_coeff_0h,p_accu_coeff_0m,p_t_38_0h,p_t_38_0m,p_t_38_0l); Renormalize3(p_resh,p_resm,p_resl,p_t_39_0h,p_t_39_0m,p_t_39_0l); } static void p9_accu(double *p_resh, double *p_resm, double *p_resl, double x) { double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h; double p_t_6_0h; double p_t_7_0h; double p_t_8_0h; double p_t_9_0h; double p_t_10_0h; double p_t_11_0h; double p_t_12_0h; double p_t_13_0h; double p_t_14_0h; double p_t_15_0h; double p_t_16_0h; double p_t_17_0h, p_t_17_0m; double p_t_18_0h, p_t_18_0m; double p_t_19_0h, p_t_19_0m; double p_t_20_0h, p_t_20_0m; double p_t_21_0h, p_t_21_0m; double p_t_22_0h, p_t_22_0m; double p_t_23_0h, p_t_23_0m; double p_t_24_0h, p_t_24_0m; double p_t_25_0h, p_t_25_0m; double p_t_26_0h, p_t_26_0m; double p_t_27_0h, p_t_27_0m; double p_t_28_0h, p_t_28_0m; double p_t_29_0h, p_t_29_0m; double p_t_30_0h, p_t_30_0m; double p_t_31_0h, p_t_31_0m; double p_t_32_0h, p_t_32_0m; double p_t_33_0h, p_t_33_0m, p_t_33_0l; double p_t_34_0h, p_t_34_0m, p_t_34_0l; double p_t_35_0h, p_t_35_0m, p_t_35_0l; p_t_1_0h = p9_accu_coeff_20h; p_t_2_0h = p_t_1_0h * x; p_t_3_0h = p9_accu_coeff_19h + p_t_2_0h; p_t_4_0h = p_t_3_0h * x; p_t_5_0h = p9_accu_coeff_18h + p_t_4_0h; p_t_6_0h = p_t_5_0h * x; p_t_7_0h = p9_accu_coeff_17h + p_t_6_0h; p_t_8_0h = p_t_7_0h * x; p_t_9_0h = p9_accu_coeff_16h + p_t_8_0h; p_t_10_0h = p_t_9_0h * x; p_t_11_0h = p9_accu_coeff_15h + p_t_10_0h; p_t_12_0h = p_t_11_0h * x; p_t_13_0h = p9_accu_coeff_14h + p_t_12_0h; p_t_14_0h = p_t_13_0h * x; p_t_15_0h = p9_accu_coeff_13h + p_t_14_0h; p_t_16_0h = p_t_15_0h * x; Add12(p_t_17_0h,p_t_17_0m,p9_accu_coeff_12h,p_t_16_0h); Mul122(&p_t_18_0h,&p_t_18_0m,x,p_t_17_0h,p_t_17_0m); Add122(&p_t_19_0h,&p_t_19_0m,p9_accu_coeff_11h,p_t_18_0h,p_t_18_0m); Mul122(&p_t_20_0h,&p_t_20_0m,x,p_t_19_0h,p_t_19_0m); Add122(&p_t_21_0h,&p_t_21_0m,p9_accu_coeff_10h,p_t_20_0h,p_t_20_0m); Mul122(&p_t_22_0h,&p_t_22_0m,x,p_t_21_0h,p_t_21_0m); Add122(&p_t_23_0h,&p_t_23_0m,p9_accu_coeff_9h,p_t_22_0h,p_t_22_0m); Mul122(&p_t_24_0h,&p_t_24_0m,x,p_t_23_0h,p_t_23_0m); Add122(&p_t_25_0h,&p_t_25_0m,p9_accu_coeff_8h,p_t_24_0h,p_t_24_0m); MulAdd212(&p_t_26_0h,&p_t_26_0m,p9_accu_coeff_7h,p9_accu_coeff_7m,x,p_t_25_0h,p_t_25_0m); MulAdd212(&p_t_27_0h,&p_t_27_0m,p9_accu_coeff_6h,p9_accu_coeff_6m,x,p_t_26_0h,p_t_26_0m); MulAdd212(&p_t_28_0h,&p_t_28_0m,p9_accu_coeff_5h,p9_accu_coeff_5m,x,p_t_27_0h,p_t_27_0m); MulAdd212(&p_t_29_0h,&p_t_29_0m,p9_accu_coeff_4h,p9_accu_coeff_4m,x,p_t_28_0h,p_t_28_0m); MulAdd212(&p_t_30_0h,&p_t_30_0m,p9_accu_coeff_3h,p9_accu_coeff_3m,x,p_t_29_0h,p_t_29_0m); MulAdd212(&p_t_31_0h,&p_t_31_0m,p9_accu_coeff_2h,p9_accu_coeff_2m,x,p_t_30_0h,p_t_30_0m); Mul122(&p_t_32_0h,&p_t_32_0m,x,p_t_31_0h,p_t_31_0m); Add23(&p_t_33_0h,&p_t_33_0m,&p_t_33_0l,p9_accu_coeff_1h,p9_accu_coeff_1m,p_t_32_0h,p_t_32_0m); Mul133(&p_t_34_0h,&p_t_34_0m,&p_t_34_0l,x,p_t_33_0h,p_t_33_0m,p_t_33_0l); Add233(&p_t_35_0h,&p_t_35_0m,&p_t_35_0l,p9_accu_coeff_0h,p9_accu_coeff_0m,p_t_34_0h,p_t_34_0m,p_t_34_0l); Renormalize3(p_resh,p_resm,p_resl,p_t_35_0h,p_t_35_0m,p_t_35_0l); } double asin_rn(double x) { db_number xdb, zdb; double sign, z, zp; int index; double asinh, asinm, asinl; double asinhover, asinmover, asinlover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double asin; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-28) we have arcsin(x) = x * ( 1 + xi ) with 0 <= xi < 2^(-55) So we can decide the rounding without any computation */ if (xdb.i[HI] < ASINSIMPLEBOUND) { return x; } /* asin is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return PIHALFH; } if (x == -1.0) { return - PIHALFH; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Rounding test */ if(asinh == (asinh + (asinm * RNROUNDCST))) return asinh; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Final rounding */ RoundToNearest3(&asin,asinh,asinm,asinl); return asin; } /* Strip off the sign of argument x */ sign = 1.0; if (x < 0.0) sign = -sign; index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); p9h = -p9h; p9m = -p9m; sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Add22(&asinh,&asinm,PIHALFH,PIHALFM,t1h,t1m); /* Rounding test */ if(asinh == (asinh + (asinm * RNROUNDCST))) return sign * asinh; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); p9h = -p9h; p9m = -p9m; p9l = -p9l; Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Add33(&asinhover,&asinmover,&asinlover,PIHALFH,PIHALFM,PIHALFL,t1h,t1m,t1l); Renormalize3(&asinh,&asinm,&asinl,asinhover,asinmover,asinlover); /* Final rounding */ RoundToNearest3(&asin,asinh,asinm,asinl); return sign * asin; } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Rounding test */ if(asinh == (asinh + (asinm * RNROUNDCST))) return sign * asinh; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); /* Final rounding */ RoundToNearest3(&asin,asinh,asinm,asinl); return sign * asin; } double asin_ru(double x) { db_number xdb, zdb; double sign, z, zp; int index; double asinh, asinm, asinl; double asinhover, asinmover, asinlover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-28) we have arcsin(x) = x * ( 1 + xi ) with 0 <= xi < 2^(-55) So we can decide the rounding without any computation */ if (xdb.i[HI] < ASINSIMPLEBOUND) { /* If x == 0 then we got the algebraic result arcsin(0) = 0 If x < 0 then the truncation rest is negative but less than 1 ulp; we round upwards by returning x */ if (x <= 0.0) return x; /* Otherwise the rest is positive, less than 1 ulp and the image is not algebraic We return x + 1ulp */ xdb.l++; return xdb.d; } /* asin is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return PIHALFRU; } if (x == -1.0) { return - PIHALFH; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Rounding test */ TEST_AND_RETURN_RU(asinh, asinm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Final rounding */ ReturnRoundUpwards3(asinh,asinm,asinl); } /* Strip off the sign of argument x */ sign = 1.0; if (x < 0.0) sign = -sign; index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); p9h = -p9h; p9m = -p9m; sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Add22(&asinh,&asinm,PIHALFH,PIHALFM,t1h,t1m); /* Rounding test */ asinh *= sign; asinm *= sign; TEST_AND_RETURN_RU(asinh, asinm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); p9h = -p9h; p9m = -p9m; p9l = -p9l; Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Add33(&asinhover,&asinmover,&asinlover,PIHALFH,PIHALFM,PIHALFL,t1h,t1m,t1l); Renormalize3(&asinh,&asinm,&asinl,asinhover,asinmover,asinlover); /* Final rounding */ asinh *= sign; asinm *= sign; asinl *= sign; ReturnRoundUpwards3(asinh,asinm,asinl); } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Rounding test */ asinh *= sign; asinm *= sign; TEST_AND_RETURN_RU(asinh, asinm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif if (x == ASINBADCASEX) return ASINBADCASEYRU; p_accu(&asinh, &asinm, &asinl, z, index); /* Final rounding */ asinh *= sign; asinm *= sign; asinl *= sign; ReturnRoundUpwards3(asinh,asinm,asinl); } double asin_rd(double x) { db_number xdb, zdb; double sign, z, zp; int index; double asinh, asinm, asinl; double asinhover, asinmover, asinlover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-28) we have arcsin(x) = x * ( 1 + xi ) with 0 <= xi < 2^(-55) So we can decide the rounding without any computation */ if (xdb.i[HI] < ASINSIMPLEBOUND) { /* If x == 0 then we got the algebraic result arcsin(0) = 0 If x > 0 then the truncation rest is positive but less than 1 ulp; we round downwards by returning x */ if (x >= 0) return x; /* Otherwise the rest is negative, less than 1 ulp and the image is not algebraic We return x - 1ulp We stripped off the sign, so we add 1 ulp to -x (in xdb.d) and multiply by -1 */ xdb.l++; return -1 * xdb.d; } /* asin is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return PIHALFH; } if (x == -1.0) { return - PIHALFRU; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Rounding test */ TEST_AND_RETURN_RD(asinh, asinm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Final rounding */ ReturnRoundDownwards3(asinh,asinm,asinl); } /* Strip off the sign of argument x */ sign = 1.0; if (x < 0.0) sign = -sign; index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); p9h = -p9h; p9m = -p9m; sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Add22(&asinh,&asinm,PIHALFH,PIHALFM,t1h,t1m); /* Rounding test */ asinh *= sign; asinm *= sign; TEST_AND_RETURN_RD(asinh, asinm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); p9h = -p9h; p9m = -p9m; p9l = -p9l; Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Add33(&asinhover,&asinmover,&asinlover,PIHALFH,PIHALFM,PIHALFL,t1h,t1m,t1l); Renormalize3(&asinh,&asinm,&asinl,asinhover,asinmover,asinlover); /* Final rounding */ asinh *= sign; asinm *= sign; asinl *= sign; ReturnRoundDownwards3(asinh,asinm,asinl); } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Rounding test */ asinh *= sign; asinm *= sign; TEST_AND_RETURN_RD(asinh, asinm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif if (x == ASINBADCASEX) return ASINBADCASEYRD; p_accu(&asinh, &asinm, &asinl, z, index); /* Final rounding */ asinh *= sign; asinm *= sign; asinl *= sign; ReturnRoundDownwards3(asinh,asinm,asinl); } double asin_rz(double x) { db_number xdb, zdb; double sign, z, zp; int index; double asinh, asinm, asinl; double asinhover, asinmover, asinlover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-28) we have arcsin(x) = x * ( 1 + xi ) with 0 <= xi < 2^(-55) So we can decide the rounding without any computation */ if (xdb.i[HI] < ASINSIMPLEBOUND) { /* If x == 0 the result is algebraic and equal to 0 If x < 0 the truncation rest is negative and less than 1 ulp, we return x If x > 0 the truncation rest is positive and less than 1 ulp, we return x */ return x; } /* asin is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return PIHALFH; } if (x == -1.0) { return - PIHALFH; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Rounding test */ TEST_AND_RETURN_RZ(asinh, asinm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Final rounding */ ReturnRoundTowardsZero3(asinh,asinm,asinl); } /* Strip off the sign of argument x */ sign = 1.0; if (x < 0.0) sign = -sign; index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); p9h = -p9h; p9m = -p9m; sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Add22(&asinh,&asinm,PIHALFH,PIHALFM,t1h,t1m); /* Rounding test */ asinh *= sign; asinm *= sign; TEST_AND_RETURN_RZ(asinh, asinm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); p9h = -p9h; p9m = -p9m; p9l = -p9l; Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Add33(&asinhover,&asinmover,&asinlover,PIHALFH,PIHALFM,PIHALFL,t1h,t1m,t1l); Renormalize3(&asinh,&asinm,&asinl,asinhover,asinmover,asinlover); /* Final rounding */ asinh *= sign; asinm *= sign; asinl *= sign; ReturnRoundTowardsZero3(asinh,asinm,asinl); } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Rounding test */ asinh *= sign; asinm *= sign; TEST_AND_RETURN_RZ(asinh, asinm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif if (x == ASINBADCASEX) return ASINBADCASEYRD; p_accu(&asinh, &asinm, &asinl, z, index); /* Final rounding */ asinh *= sign; asinm *= sign; asinl *= sign; ReturnRoundTowardsZero3(asinh,asinm,asinl); } double acos_rn(double x) { db_number xdb, zdb; double z, zp; int index; double asinh, asinm, asinl; double acosh, acosm, acosl; double acoshover, acosmover, acoslover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-28) we have arccos(x) = (double-double(pi/2) - x) * ( 1 + xi ) with 0 <= xi < 2^(-87) From 2^(-27) we have no bad rounding case longer than 5 bits more than the ulp of x, thus the approximation suffices. */ if (xdb.i[HI] < ACOSSIMPLEBOUND) { Add212(&acosh,&acosm,PIHALFH,PIHALFM,-x); return acosh; } /* acos is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.0; } if (x == -1.0) { return PIH; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Recompose acos No cancellation possible because |asin(x)| <= 0.264 for |x| <= 0.26 */ asinh = - asinh; asinm = - asinm; Add22(&acosh,&acosm,PIHALFH,PIHALFM,asinh,asinm); /* Rounding test */ if(acosh == (acosh + (acosm * RNROUNDCST))) return acosh; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Recompose acos */ asinh = -asinh; asinm = -asinm; asinl = -asinl; Add33(&acoshover,&acosmover,&acoslover,PIHALFH,PIHALFM,PIHALFL,asinh,asinm,asinl); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundToNearest3(acosh,acosm,acosl); } index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); if (x > 0.0) { acosh = t1h; acosm = t1m; } else { /* arccos(-x) = Pi - arccos(x) */ t1h = - t1h; t1m = - t1m; Add22(&acosh,&acosm,PIH,PIM,t1h,t1m); } /* Rounding test */ if(acosh == (acosh + (acosm * RNROUNDCST))) return acosh; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); if (x > 0.0) { Renormalize3(&acosh,&acosm,&acosl,t1h,t1m,t1l); } else { /* arccos(-x) = Pi - arccos(x) */ t1h = - t1h; t1m = - t1m; t1l = - t1l; Add33(&acoshover,&acosmover,&acoslover,PIH,PIM,PIL,t1h,t1m,t1l); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); } /* Final rounding */ ReturnRoundToNearest3(acosh,acosm,acosl); } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Recompose acos(x) out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; } Add22Cond(&acosh,&acosm,PIHALFH,PIHALFM,asinh,asinm); /* Rounding test */ if(acosh == (acosh + (acosm * RNROUNDCST))) return acosh; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); /* Recompose acos(x) out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; asinl = - asinl; } Add33Cond(&acoshover,&acosmover,&acoslover,PIHALFH,PIHALFM,PIHALFL,asinh,asinm,asinl); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundToNearest3(acosh,acosm,acosl); } double acos_ru(double x) { db_number xdb, zdb, acoshdb; double z, zp; int index; double asinh, asinm, asinl; double acosh, acosm, acosl; double acoshover, acosmover, acoslover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-28) we have arccos(x) = (double-double(pi/2) - x) * ( 1 + xi ) with 0 <= xi < 2^(-87) From 2^(-27) we have no bad rounding case longer than 5 bits more than the ulp of x, thus the approximation suffices. */ if (xdb.i[HI] < ACOSSIMPLEBOUND) { Add212(&acosh,&acosm,PIHALFH,PIHALFM,-x); /* acosh is the round-to-nearest of acos(x) in this domain acosm is a at least 20 bit exact correction of the rounding error of this round-to-nearest rounding. If acosh is the rounded up result of acos(x), the correction is negative and vice-versa. */ if (acosm < 0.0) return acosh; /* Here the correction acosm is positive, acosh is therefore the rounded down result of acos(x). We add thus one ulp. */ acoshdb.d = acosh; acoshdb.l++; return acoshdb.d; } /* acos is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.0; } if (x == -1.0) { return PIRU; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Recompose acos No cancellation possible because |asin(x)| <= 0.264 for |x| <= 0.26 */ asinh = - asinh; asinm = - asinm; Add22(&acosh,&acosm,PIHALFH,PIHALFM,asinh,asinm); /* Rounding test */ TEST_AND_RETURN_RU(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Recompose acos */ asinh = -asinh; asinm = -asinm; asinl = -asinl; Add33(&acoshover,&acosmover,&acoslover,PIHALFH,PIHALFM,PIHALFL,asinh,asinm,asinl); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundUpwards3(acosh,acosm,acosl); } index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); if (x > 0.0) { acosh = t1h; acosm = t1m; } else { /* arccos(-x) = Pi - arccos(x) */ t1h = - t1h; t1m = - t1m; Add22(&acosh,&acosm,PIH,PIM,t1h,t1m); } /* Rounding test */ TEST_AND_RETURN_RU(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); if (x > 0.0) { Renormalize3(&acosh,&acosm,&acosl,t1h,t1m,t1l); } else { /* arccos(-x) = Pi - arccos(x) */ t1h = - t1h; t1m = - t1m; t1l = - t1l; Add33(&acoshover,&acosmover,&acoslover,PIH,PIM,PIL,t1h,t1m,t1l); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); } /* Final rounding */ ReturnRoundUpwards3(acosh,acosm,acosl); } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Recompose acos(x) out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; } Add22Cond(&acosh,&acosm,PIHALFH,PIHALFM,asinh,asinm); /* Rounding test */ TEST_AND_RETURN_RU(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); /* Recompose acos(x) out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; asinl = - asinl; } Add33Cond(&acoshover,&acosmover,&acoslover,PIHALFH,PIHALFM,PIHALFL,asinh,asinm,asinl); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundUpwards3(acosh,acosm,acosl); } double acos_rd(double x) { db_number xdb, zdb, acoshdb; double z, zp; int index; double asinh, asinm, asinl; double acosh, acosm, acosl; double acoshover, acosmover, acoslover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-28) we have arccos(x) = (double-double(pi/2) - x) * ( 1 + xi ) with 0 <= xi < 2^(-87) From 2^(-27) we have no bad rounding case longer than 5 bits more than the ulp of x, thus the approximation suffices. */ if (xdb.i[HI] < ACOSSIMPLEBOUND) { Add212(&acosh,&acosm,PIHALFH,PIHALFM,-x); /* acosh is the round-to-nearest of acos(x) in this domain acosm is a at least 20 bit exact correction of the rounding error of this round-to-nearest rounding. If acosh is the rounded up result of acos(x), the correction is negative and vice-versa. */ if (acosm > 0.0) return acosh; /* Here the correction acosm is negative, acosh is therefore the rounded up result of acos(x). We subtract thus one ulp. */ acoshdb.d = acosh; acoshdb.l--; return acoshdb.d; } /* acos is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.0; } if (x == -1.0) { return PIH; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Recompose acos No cancellation possible because |asin(x)| <= 0.264 for |x| <= 0.26 */ asinh = - asinh; asinm = - asinm; Add22(&acosh,&acosm,PIHALFH,PIHALFM,asinh,asinm); /* Rounding test */ TEST_AND_RETURN_RD(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Recompose acos */ asinh = -asinh; asinm = -asinm; asinl = -asinl; Add33(&acoshover,&acosmover,&acoslover,PIHALFH,PIHALFM,PIHALFL,asinh,asinm,asinl); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundDownwards3(acosh,acosm,acosl); } index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); if (x > 0.0) { acosh = t1h; acosm = t1m; } else { /* arccos(-x) = Pi - arccos(x) */ t1h = - t1h; t1m = - t1m; Add22(&acosh,&acosm,PIH,PIM,t1h,t1m); } /* Rounding test */ TEST_AND_RETURN_RD(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); if (x > 0.0) { Renormalize3(&acosh,&acosm,&acosl,t1h,t1m,t1l); } else { /* arccos(-x) = Pi - arccos(x) */ t1h = - t1h; t1m = - t1m; t1l = - t1l; Add33(&acoshover,&acosmover,&acoslover,PIH,PIM,PIL,t1h,t1m,t1l); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); } /* Final rounding */ ReturnRoundDownwards3(acosh,acosm,acosl); } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Recompose acos(x) out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; } Add22Cond(&acosh,&acosm,PIHALFH,PIHALFM,asinh,asinm); /* Rounding test */ TEST_AND_RETURN_RD(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); /* Recompose acos(x) out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; asinl = - asinl; } Add33Cond(&acoshover,&acosmover,&acoslover,PIHALFH,PIHALFM,PIHALFL,asinh,asinm,asinl); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundDownwards3(acosh,acosm,acosl); } double acospi_rn(double x) { db_number xdb, zdb; double z, zp; int index; double asinh, asinm, asinl; double asinpih, asinpim, asinpil; double acosh, acosm, acosl; double acoshover, acosmover, acoslover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double t2h, t2m, t2l; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-54) we have arccos(x)/pi = 1/2 * (1 + xi) with 0 <= xi < 2^(-54) So arcospi(x) = 0.5 in this case. */ if (xdb.i[HI] < ACOSPISIMPLEBOUND) { return 0.5; } /* acospi is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.0; } if (x == -1.0) { return 1.0; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Recompose acos/pi We have arccos(x)/pi = 1/2 + (-1/pi) * arcsin(x) No cancellation possible because |asin(x)/pi| <= 0.0837 for |x| <= 0.26 */ Mul22(&asinpih,&asinpim,MRECPRPIH,MRECPRPIM,asinh,asinm); Add122(&acosh,&acosm,0.5,asinpih,asinpim); /* Rounding test */ if(acosh == (acosh + (acosm * RNROUNDCST))) return acosh; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Recompose acos/pi */ Mul33(&asinpih,&asinpim,&asinpil,MRECPRPIH,MRECPRPIM,MRECPRPIL,asinh,asinm,asinl); Add133(&acoshover,&acosmover,&acoslover,0.5,asinpih,asinpim,asinpil); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundToNearest3(acosh,acosm,acosl); } index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Mul22(&t2h,&t2m,RECPRPIH,RECPRPIM,t1h,t1m); if (x > 0.0) { acosh = t2h; acosm = t2m; } else { /* arccos(-x)/pi = 1 - arccos(x)/pi */ t2h = - t2h; t2m = - t2m; Add122(&acosh,&acosm,1.0,t2h,t2m); } /* Rounding test */ if(acosh == (acosh + (acosm * RNROUNDCST))) return acosh; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Mul33(&t2h,&t2m,&t2l,RECPRPIH,RECPRPIM,RECPRPIL,t1h,t1m,t1l); if (x > 0.0) { Renormalize3(&acosh,&acosm,&acosl,t2h,t2m,t2l); } else { /* arccos(-x)/pi = 1 - arccos(x)/pi */ t2h = - t2h; t2m = - t2m; t2l = - t2l; Add133(&acoshover,&acosmover,&acoslover,1.0,t2h,t2m,t2l); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); } /* Final rounding */ ReturnRoundToNearest3(acosh,acosm,acosl); } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Recompose acos(x)/pi out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; } Mul22(&asinpih,&asinpim,RECPRPIH,RECPRPIM,asinh,asinm); Add122Cond(&acosh,&acosm,0.5,asinpih,asinpim); /* Rounding test */ if(acosh == (acosh + (acosm * RNROUNDCST))) return acosh; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); /* Recompose acos(x) out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; asinl = - asinl; } Mul33(&asinpih,&asinpim,&asinpil,RECPRPIH,RECPRPIM,RECPRPIL,asinh,asinm,asinl); Add133Cond(&acoshover,&acosmover,&acoslover,0.5,asinpih,asinpim,asinpil); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundToNearest3(acosh,acosm,acosl); } double acospi_rd(double x) { db_number xdb, zdb; double z, zp; int index; double asinh, asinm, asinl; double asinpih, asinpim, asinpil; double acosh, acosm, acosl; double acoshover, acosmover, acoslover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double t2h, t2m, t2l; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-54) we have arccos(x)/pi = 1/2 * (1 + xi) with 0 <= xi < 2^(-54) Thus we have acospi(x) = (i) 0.5 if x <= 0 (ii) 0.5 - 1/2 ulp(0.5) if x > 0 */ if (xdb.i[HI] < ACOSPISIMPLEBOUND) { if (x <= 0.0) return 0.5; return HALFMINUSHALFULP; } /* acospi is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.0; } if (x == -1.0) { return 1.0; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Recompose acos/pi We have arccos(x)/pi = 1/2 + (-1/pi) * arcsin(x) No cancellation possible because |asin(x)/pi| <= 0.0837 for |x| <= 0.26 */ Mul22(&asinpih,&asinpim,MRECPRPIH,MRECPRPIM,asinh,asinm); Add122(&acosh,&acosm,0.5,asinpih,asinpim); /* Rounding test */ TEST_AND_RETURN_RD(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Recompose acos/pi */ Mul33(&asinpih,&asinpim,&asinpil,MRECPRPIH,MRECPRPIM,MRECPRPIL,asinh,asinm,asinl); Add133(&acoshover,&acosmover,&acoslover,0.5,asinpih,asinpim,asinpil); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundDownwards3(acosh,acosm,acosl); } index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Mul22(&t2h,&t2m,RECPRPIH,RECPRPIM,t1h,t1m); if (x > 0.0) { acosh = t2h; acosm = t2m; } else { /* arccos(-x)/pi = 1 - arccos(x)/pi */ t2h = - t2h; t2m = - t2m; Add122(&acosh,&acosm,1.0,t2h,t2m); } /* Rounding test */ TEST_AND_RETURN_RD(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Mul33(&t2h,&t2m,&t2l,RECPRPIH,RECPRPIM,RECPRPIL,t1h,t1m,t1l); if (x > 0.0) { Renormalize3(&acosh,&acosm,&acosl,t2h,t2m,t2l); } else { /* arccos(-x)/pi = 1 - arccos(x)/pi */ t2h = - t2h; t2m = - t2m; t2l = - t2l; Add133(&acoshover,&acosmover,&acoslover,1.0,t2h,t2m,t2l); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); } /* Final rounding */ ReturnRoundDownwards3(acosh,acosm,acosl); } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Recompose acos(x)/pi out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; } Mul22(&asinpih,&asinpim,RECPRPIH,RECPRPIM,asinh,asinm); Add122Cond(&acosh,&acosm,0.5,asinpih,asinpim); /* Rounding test */ TEST_AND_RETURN_RD(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); /* Recompose acos(x) out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; asinl = - asinl; } Mul33(&asinpih,&asinpim,&asinpil,RECPRPIH,RECPRPIM,RECPRPIL,asinh,asinm,asinl); Add133Cond(&acoshover,&acosmover,&acoslover,0.5,asinpih,asinpim,asinpil); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundDownwards3(acosh,acosm,acosl); } double acospi_ru(double x) { db_number xdb, zdb; double z, zp; int index; double asinh, asinm, asinl; double asinpih, asinpim, asinpil; double acosh, acosm, acosl; double acoshover, acosmover, acoslover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double t2h, t2m, t2l; double xabs; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-54) we have arccos(x)/pi = 1/2 * (1 + xi) with 0 <= xi < 2^(-54) Thus we have acospi(x) = (i) 0.5 if x >= 0 (ii) 0.5 + 1 ulp(0.5) if x < 0 */ if (xdb.i[HI] < ACOSPISIMPLEBOUND) { if (x >= 0.0) return 0.5; return 0.50000000000000011102230246251565404236316680908203125; } /* acospi is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.0; } if (x == -1.0) { return 1.0; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); /* Recompose acos/pi We have arccos(x)/pi = 1/2 + (-1/pi) * arcsin(x) No cancellation possible because |asin(x)/pi| <= 0.0837 for |x| <= 0.26 */ Mul22(&asinpih,&asinpim,MRECPRPIH,MRECPRPIM,asinh,asinm); Add122(&acosh,&acosm,0.5,asinpih,asinpim); /* Rounding test */ TEST_AND_RETURN_RU(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); /* Recompose acos/pi */ Mul33(&asinpih,&asinpim,&asinpil,MRECPRPIH,MRECPRPIM,MRECPRPIL,asinh,asinm,asinl); Add133(&acoshover,&acosmover,&acoslover,0.5,asinpih,asinpim,asinpil); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundUpwards3(acosh,acosm,acosl); } index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Mul22(&t2h,&t2m,RECPRPIH,RECPRPIM,t1h,t1m); if (x > 0.0) { acosh = t2h; acosm = t2m; } else { /* arccos(-x)/pi = 1 - arccos(x)/pi */ t2h = - t2h; t2m = - t2m; Add122(&acosh,&acosm,1.0,t2h,t2m); } /* Rounding test */ TEST_AND_RETURN_RU(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Mul33(&t2h,&t2m,&t2l,RECPRPIH,RECPRPIM,RECPRPIL,t1h,t1m,t1l); if (x > 0.0) { Renormalize3(&acosh,&acosm,&acosl,t2h,t2m,t2l); } else { /* arccos(-x)/pi = 1 - arccos(x)/pi */ t2h = - t2h; t2m = - t2m; t2l = - t2l; Add133(&acoshover,&acosmover,&acoslover,1.0,t2h,t2m,t2l); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); } /* Final rounding */ ReturnRoundUpwards3(acosh,acosm,acosl); } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); /* Recompose acos(x)/pi out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; } Mul22(&asinpih,&asinpim,RECPRPIH,RECPRPIM,asinh,asinm); Add122Cond(&acosh,&acosm,0.5,asinpih,asinpim); /* Rounding test */ TEST_AND_RETURN_RU(acosh, acosm, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); /* Recompose acos(x) out of asin(abs(x)) In the case of a substraction, we will cancel not more than 1 bit. */ if (x > 0.0) { asinh = - asinh; asinm = - asinm; asinl = - asinl; } Mul33(&asinpih,&asinpim,&asinpil,RECPRPIH,RECPRPIM,RECPRPIL,asinh,asinm,asinl); Add133Cond(&acoshover,&acosmover,&acoslover,0.5,asinpih,asinpim,asinpil); Renormalize3(&acosh,&acosm,&acosl,acoshover,acosmover,acoslover); /* Final rounding */ ReturnRoundUpwards3(acosh,acosm,acosl); } double asinpi_rn(double x) { db_number xdb, zdb, asinhdb, tempdb; double sign, z, zp; int index; double asinh, asinm, asinl; double asinpih, asinpim, asinpil; double asinpihover, asinpimover, asinpilover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double t2h, t2m, t2l; double asinpi; double xabs; double xScaled; double xPih, xPim, xPil; double xPihover, xPimover, xPilover; double deltatemp, deltah, deltal; double temp1, temp2h, temp2l, temp3; double miulp; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-60) we have arcsin(x)/pi = x * triple-double(1/pi) * ( 1 + xi ) with 0 <= xi < 2^(-122) We have no bad case worser than 112 bits for asinpi(x) for |x| > 2^(-58) and the order 3 term of asinpi is still more far away. */ if (xdb.i[HI] < ASINPISIMPLEBOUND) { /* For a faster path for the exact case, we check first if x = 0 */ if (x == 0.0) return x; /* We want a relatively fast path for values where neither the input nor the output is subnormal because subnormal rounding is expensive. Since abs(double(asin(x)/pi)) <= 2^(-860) for abs(x) <= 2^(-858), we filter for this (normal) value. */ if (xdb.i[HI] >= ASINPINOSUBNORMALBOUND) { /* Here abs(x) >= 2^(-858). The result is therefore clearly normal and the double precision numbers in the triple-double representation of TD(1/pi) * x are all normal, too. For speed, we use a two-step approach. We know that || x*DD(1/pi)/(asin(x)/pi) - 1 ||_[-2^(-60);2^(-60)]^\infty <= 2^(-107.8) <= 2^(-80) */ Mul122(&xPih,&xPim,x,RECPRPIH,RECPRPIM); if(xPih == (xPih + (xPim * RNROUNDCSTASINPI))) return xPih; Mul133(&xPihover,&xPimover,&xPilover,x,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&xPih,&xPim,&xPil,xPihover,xPimover,xPilover); ReturnRoundToNearest3(xPih,xPim,xPil); } /* Here abs(x) < 2^(-858) Because of subnormals and especially because of the fact that 1/pi < 1, we must scale x appropriately. We compute hence: asinpi(x) = round( ((x * 2^(1000)) * triple-double(1/pi)) * 2^(-1000)) where the rounding procedure works temporarily on the scaled intermediate. */ xScaled = x * TWO1000; Mul133(&xPihover,&xPimover,&xPilover,xScaled,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&xPih,&xPim,&xPil,xPihover,xPimover,xPilover); /* Produce a (possibly) subnormal intermediate rounding */ asinhdb.d = xPih * TWOM1000; #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) tempdb.i[HI] = asinhdb.i[HI]; tempdb.i[LO] = asinhdb.i[LO]; asinhdb.i[LO] = tempdb.i[LO]; asinhdb.i[HI] = tempdb.i[HI]; #else tempdb.d = asinhdb.d; #endif /* Rescale the result */ temp1 = asinhdb.d * TWO1000; /* Compute the scaled error, the operation is exact by Sterbenz' lemma */ deltatemp = xPih - temp1; /* Sum up the errors, representing them on a double-double This is exact for the normal rounding case and the error is neglectable in the subnormal rounding case. */ Add12Cond(temp2h,temp2l,deltatemp,xPim); temp3 = temp2l + xPil; Add12(deltah,deltal,temp2h,temp3); /* Compute now a scaled 1/2 ulp of the intermediate result in the direction of delta */ if ((x >= 0.0) ^ (deltah >= 0.0)) tempdb.l--; else tempdb.l++; miulp = TWO999 * (tempdb.d - asinhdb.d); /* We must correct the intermediate rounding if the error on deltah + deltal is greater in absolute value than miulp = 1/2 ulp in the right direction. */ if (ABS(deltah) < ABS(miulp)) { /* deltah is less than miulp, deltal is less than 1/2 the ulp of deltah. Thus deltah + deltal is less than miulp. We do not need to correct the intermediate rounding. */ return asinhdb.d; } if (ABS(deltah) > ABS(miulp)) { /* deltah is greater than miulp and deltal cannot correct it. We must correct the rounding. tempdb.d (= asinhdb.d +/- 1 ulp) is the correct rounding. */ return tempdb.d; } /* Here deltah and miulp are equal in absolute value We must correct the intermediate rounding iff the sign of deltal and deltah are the same. */ if ((deltah >= 0.0) ^ (deltal >= 0.0)) { /* Here the sign is different, we return the intermediate rounding asinhdb.d */ return asinhdb.d; } /* Return the corrected result tempdb.d */ return tempdb.d; } /* asinpi is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.5; } if (x == -1.0) { return - 0.5; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); Mul22(&asinpih,&asinpim,asinh,asinm,RECPRPIH,RECPRPIM); /* Rounding test */ if(asinpih == (asinpih + (asinpim * RNROUNDCST))) return asinpih; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); Mul33(&asinpihover,&asinpimover,&asinpilover,asinh,asinm,asinl,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ ReturnRoundToNearest3(asinpih,asinpim,asinpil); } /* Strip off the sign of argument x */ sign = 1.0; if (x < 0.0) sign = -sign; index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); p9h = -p9h; p9m = -p9m; sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Mul22(&t2h,&t2m,t1h,t1m,RECPRPIH,RECPRPIM); Add122(&asinpih,&asinpim,0.5,t2h,t2m); /* Rounding test */ if(asinpih == (asinpih + (asinpim * RNROUNDCST))) return sign * asinpih; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); p9h = -p9h; p9m = -p9m; p9l = -p9l; Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Mul33(&t2h,&t2m,&t2l,t1h,t1m,t1l,RECPRPIH,RECPRPIM,RECPRPIL); Add133(&asinpihover,&asinpimover,&asinpilover,0.5,t2h,t2m,t2l); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ RoundToNearest3(&asinpi,asinpih,asinpim,asinpil); return sign * asinpi; } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); Mul22(&asinpih,&asinpim,asinh,asinm,RECPRPIH,RECPRPIM); /* Rounding test */ if(asinpih == (asinpih + (asinpim * RNROUNDCST))) return sign * asinpih; /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); Mul33(&asinpihover,&asinpimover,&asinpilover,asinh,asinm,asinl,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ RoundToNearest3(&asinpi,asinpih,asinpim,asinpil); return sign * asinpi; } double asinpi_rd(double x) { db_number xdb, zdb, asinhdb; double sign, z, zp; int index; double asinh, asinm, asinl; double asinpih, asinpim, asinpil; double asinpihover, asinpimover, asinpilover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double t2h, t2m, t2l; double asinpi; double xabs; double xScaled; double xPih, xPim, xPil; double xPihover, xPimover, xPilover; #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) db_number tempdb; #endif double deltatemp, deltah, deltal; double temp1, temp2h, temp2l, temp3; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-60) we have arcsin(x)/pi = x * triple-double(1/pi) * ( 1 + xi ) with 0 <= xi < 2^(-122) We have no bad case worser than 112 bits for asinpi(x) for |x| > 2^(-58) and the order 3 term of asinpi is still more far away. */ if (xdb.i[HI] < ASINPISIMPLEBOUND) { /* For a faster path for the exact case, we check first if x = 0 */ if (x == 0.0) return x; /* We want a relatively fast path for values where neither the input nor the output is subnormal because subnormal rounding is expensive. Since abs(double(asin(x)/pi)) <= 2^(-860) for abs(x) <= 2^(-858), we filter for this (normal) value. */ if (xdb.i[HI] >= ASINPINOSUBNORMALBOUND) { /* Here abs(x) >= 2^(-858). The result is therefore clearly normal and the double precision numbers in the triple-double representation of TD(1/pi) * x are all normal, too. For speed, we use a two-step approach. We know that || x*DD(1/pi)/(asin(x)/pi) - 1 ||_[-2^(-60);2^(-60)]^\infty <= 2^(-107.8) <= 2^(-80) */ Mul122(&xPih,&xPim,x,RECPRPIH,RECPRPIM); TEST_AND_RETURN_RD(xPih, xPim, RDROUNDCSTASINPI); Mul133(&xPihover,&xPimover,&xPilover,x,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&xPih,&xPim,&xPil,xPihover,xPimover,xPilover); ReturnRoundDownwards3(xPih,xPim,xPil); } /* Here abs(x) < 2^(-858) Because of subnormals and especially because of the fact that 1/pi < 1, we must scale x appropriately. We compute hence: asinpi(x) = round( ((x * 2^(1000)) * triple-double(1/pi)) * 2^(-1000)) where the rounding procedure works temporarily on the scaled intermediate. */ xScaled = x * TWO1000; Mul133(&xPihover,&xPimover,&xPilover,xScaled,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&xPih,&xPim,&xPil,xPihover,xPimover,xPilover); /* Produce a (possibly) subnormal intermediate rounding */ asinhdb.d = xPih * TWOM1000; #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) tempdb.i[HI] = asinhdb.i[HI]; tempdb.i[LO] = asinhdb.i[LO]; asinhdb.i[LO] = tempdb.i[LO]; asinhdb.i[HI] = tempdb.i[HI]; #endif /* Rescale the result */ temp1 = asinhdb.d * TWO1000; /* Compute the scaled error, the operation is exact by Sterbenz' lemma */ deltatemp = xPih - temp1; /* Sum up the errors, representing them on a double-double This is exact for the normal rounding case and the error is neglectable in the subnormal rounding case. */ Add12Cond(temp2h,temp2l,deltatemp,xPim); temp3 = temp2l + xPil; Add12(deltah,deltal,temp2h,temp3); /* We are doing directed rounding. Thus we must correct the rounding if the sign of the error is not correct RD -> sign must be positive for correct rounding RU -> sign must be negative for correct rounding RZ -> sign must be positive for positive x and negative for negative x */ if (deltah >= 0.0) { /* The sign is correct, return the intermediate rounding */ return asinhdb.d; } /* The sign is not correct RD -> subtract 1 ulp RU -> add 1 ulp RZ -> subtract 1 ulp if x positive, add 1 ulp if x negative */ if (x < 0.0) asinhdb.l++; else asinhdb.l--; return asinhdb.d; } /* asinpi is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.5; } if (x == -1.0) { return - 0.5; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); Mul22(&asinpih,&asinpim,asinh,asinm,RECPRPIH,RECPRPIM); /* Rounding test */ TEST_AND_RETURN_RD(asinpih, asinpim, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); Mul33(&asinpihover,&asinpimover,&asinpilover,asinh,asinm,asinl,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ ReturnRoundDownwards3(asinpih,asinpim,asinpil); } /* Strip off the sign of argument x */ sign = 1.0; if (x < 0.0) sign = -sign; index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); p9h = -p9h; p9m = -p9m; sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Mul22(&t2h,&t2m,t1h,t1m,RECPRPIH,RECPRPIM); Add122(&asinpih,&asinpim,0.5,t2h,t2m); /* Rounding test */ asinpih *= sign; asinpim *= sign; TEST_AND_RETURN_RD(asinpih, asinpim, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); p9h = -p9h; p9m = -p9m; p9l = -p9l; Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Mul33(&t2h,&t2m,&t2l,t1h,t1m,t1l,RECPRPIH,RECPRPIM,RECPRPIL); Add133(&asinpihover,&asinpimover,&asinpilover,0.5,t2h,t2m,t2l); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ RoundDownwards3(&asinpi,asinpih,asinpim,asinpil); return sign * asinpi; } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); Mul22(&asinpih,&asinpim,asinh,asinm,RECPRPIH,RECPRPIM); /* Rounding test */ asinpih *= sign; asinpim *= sign; TEST_AND_RETURN_RD(asinpih, asinpim, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); Mul33(&asinpihover,&asinpimover,&asinpilover,asinh,asinm,asinl,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ RoundDownwards3(&asinpi,asinpih,asinpim,asinpil); return sign * asinpi; } double asinpi_ru(double x) { db_number xdb, zdb, asinhdb; double sign, z, zp; int index; double asinh, asinm, asinl; double asinpih, asinpim, asinpil; double asinpihover, asinpimover, asinpilover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double t2h, t2m, t2l; double asinpi; double xabs; double xScaled; double xPih, xPim, xPil; double xPihover, xPimover, xPilover; #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) db_number tempdb; #endif double deltatemp, deltah, deltal; double temp1, temp2h, temp2l, temp3; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-60) we have arcsin(x)/pi = x * triple-double(1/pi) * ( 1 + xi ) with 0 <= xi < 2^(-122) We have no bad case worser than 112 bits for asinpi(x) for |x| > 2^(-58) and the order 3 term of asinpi is still more far away. */ if (xdb.i[HI] < ASINPISIMPLEBOUND) { /* For a faster path for the exact case, we check first if x = 0 */ if (x == 0.0) return x; /* We want a relatively fast path for values where neither the input nor the output is subnormal because subnormal rounding is expensive. Since abs(double(asin(x)/pi)) <= 2^(-860) for abs(x) <= 2^(-858), we filter for this (normal) value. */ if (xdb.i[HI] >= ASINPINOSUBNORMALBOUND) { /* Here abs(x) >= 2^(-858). The result is therefore clearly normal and the double precision numbers in the triple-double representation of TD(1/pi) * x are all normal, too. For speed, we use a two-step approach. We know that || x*DD(1/pi)/(asin(x)/pi) - 1 ||_[-2^(-60);2^(-60)]^\infty <= 2^(-107.8) <= 2^(-80) */ Mul122(&xPih,&xPim,x,RECPRPIH,RECPRPIM); TEST_AND_RETURN_RU(xPih, xPim, RDROUNDCSTASINPI); Mul133(&xPihover,&xPimover,&xPilover,x,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&xPih,&xPim,&xPil,xPihover,xPimover,xPilover); ReturnRoundUpwards3(xPih,xPim,xPil); } /* Here abs(x) < 2^(-858) Because of subnormals and especially because of the fact that 1/pi < 1, we must scale x appropriately. We compute hence: asinpi(x) = round( ((x * 2^(1000)) * triple-double(1/pi)) * 2^(-1000)) where the rounding procedure works temporarily on the scaled intermediate. */ xScaled = x * TWO1000; Mul133(&xPihover,&xPimover,&xPilover,xScaled,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&xPih,&xPim,&xPil,xPihover,xPimover,xPilover); /* Produce a (possibly) subnormal intermediate rounding */ asinhdb.d = xPih * TWOM1000; #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) tempdb.i[HI] = asinhdb.i[HI]; tempdb.i[LO] = asinhdb.i[LO]; asinhdb.i[LO] = tempdb.i[LO]; asinhdb.i[HI] = tempdb.i[HI]; #endif /* Rescale the result */ temp1 = asinhdb.d * TWO1000; /* Compute the scaled error, the operation is exact by Sterbenz' lemma */ deltatemp = xPih - temp1; /* Sum up the errors, representing them on a double-double This is exact for the normal rounding case and the error is neglectable in the subnormal rounding case. */ Add12Cond(temp2h,temp2l,deltatemp,xPim); temp3 = temp2l + xPil; Add12(deltah,deltal,temp2h,temp3); /* We are doing directed rounding. Thus we must correct the rounding if the sign of the error is not correct RD -> sign must be positive for correct rounding RU -> sign must be negative for correct rounding RZ -> sign must be positive for positive x and negative for negative x */ if (deltah <= 0.0) { /* The sign is correct, return the intermediate rounding */ return asinhdb.d; } /* The sign is not correct RD -> subtract 1 ulp RU -> add 1 ulp RZ -> subtract 1 ulp if x positive, add 1 ulp if x negative */ if (x < 0.0) asinhdb.l--; else asinhdb.l++; return asinhdb.d; } /* asinpi is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.5; } if (x == -1.0) { return - 0.5; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); Mul22(&asinpih,&asinpim,asinh,asinm,RECPRPIH,RECPRPIM); /* Rounding test */ TEST_AND_RETURN_RU(asinpih, asinpim, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); Mul33(&asinpihover,&asinpimover,&asinpilover,asinh,asinm,asinl,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ ReturnRoundUpwards3(asinpih,asinpim,asinpil); } /* Strip off the sign of argument x */ sign = 1.0; if (x < 0.0) sign = -sign; index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); p9h = -p9h; p9m = -p9m; sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Mul22(&t2h,&t2m,t1h,t1m,RECPRPIH,RECPRPIM); Add122(&asinpih,&asinpim,0.5,t2h,t2m); /* Rounding test */ asinpih *= sign; asinpim *= sign; TEST_AND_RETURN_RU(asinpih, asinpim, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); p9h = -p9h; p9m = -p9m; p9l = -p9l; Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Mul33(&t2h,&t2m,&t2l,t1h,t1m,t1l,RECPRPIH,RECPRPIM,RECPRPIL); Add133(&asinpihover,&asinpimover,&asinpilover,0.5,t2h,t2m,t2l); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ RoundUpwards3(&asinpi,asinpih,asinpim,asinpil); return sign * asinpi; } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); Mul22(&asinpih,&asinpim,asinh,asinm,RECPRPIH,RECPRPIM); /* Rounding test */ asinpih *= sign; asinpim *= sign; TEST_AND_RETURN_RU(asinpih, asinpim, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); Mul33(&asinpihover,&asinpimover,&asinpilover,asinh,asinm,asinl,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ RoundUpwards3(&asinpi,asinpih,asinpim,asinpil); return sign * asinpi; } double asinpi_rz(double x) { db_number xdb, zdb, asinhdb; double sign, z, zp; int index; double asinh, asinm, asinl; double asinpih, asinpim, asinpil; double asinpihover, asinpimover, asinpilover; double p9h, p9m, p9l, sqrh, sqrm, sqrl; double t1h, t1m, t1l; double t2h, t2m, t2l; double asinpi; double xabs; double xScaled; double xPih, xPim, xPil; double xPihover, xPimover, xPilover; #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) db_number tempdb; #endif double deltatemp, deltah, deltal; double temp1, temp2h, temp2l, temp3; /* Start already computations for argument reduction */ zdb.d = 1.0 + x * x; xdb.d = x; /* Special case handling */ /* Remove sign of x in floating-point */ xabs = ABS(x); xdb.i[HI] &= 0x7fffffff; /* If |x| < 2^(-60) we have arcsin(x)/pi = x * triple-double(1/pi) * ( 1 + xi ) with 0 <= xi < 2^(-122) We have no bad case worser than 112 bits for asinpi(x) for |x| > 2^(-58) and the order 3 term of asinpi is still more far away. */ if (xdb.i[HI] < ASINPISIMPLEBOUND) { /* For a faster path for the exact case, we check first if x = 0 */ if (x == 0.0) return x; /* We want a relatively fast path for values where neither the input nor the output is subnormal because subnormal rounding is expensive. Since abs(double(asin(x)/pi)) <= 2^(-860) for abs(x) <= 2^(-858), we filter for this (normal) value. */ if (xdb.i[HI] >= ASINPINOSUBNORMALBOUND) { /* Here abs(x) >= 2^(-858). The result is therefore clearly normal and the double precision numbers in the triple-double representation of TD(1/pi) * x are all normal, too. For speed, we use a two-step approach. We know that || x*DD(1/pi)/(asin(x)/pi) - 1 ||_[-2^(-60);2^(-60)]^\infty <= 2^(-107.8) <= 2^(-80) */ Mul122(&xPih,&xPim,x,RECPRPIH,RECPRPIM); TEST_AND_RETURN_RZ(xPih, xPim, RDROUNDCSTASINPI); Mul133(&xPihover,&xPimover,&xPilover,x,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&xPih,&xPim,&xPil,xPihover,xPimover,xPilover); ReturnRoundTowardsZero3(xPih,xPim,xPil); } /* Here abs(x) < 2^(-858) Because of subnormals and especially because of the fact that 1/pi < 1, we must scale x appropriately. We compute hence: asinpi(x) = round( ((x * 2^(1000)) * triple-double(1/pi)) * 2^(-1000)) where the rounding procedure works temporarily on the scaled intermediate. */ xScaled = x * TWO1000; Mul133(&xPihover,&xPimover,&xPilover,xScaled,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&xPih,&xPim,&xPil,xPihover,xPimover,xPilover); /* Produce a (possibly) subnormal intermediate rounding */ asinhdb.d = xPih * TWOM1000; #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) tempdb.i[HI] = asinhdb.i[HI]; tempdb.i[LO] = asinhdb.i[LO]; asinhdb.i[LO] = tempdb.i[LO]; asinhdb.i[HI] = tempdb.i[HI]; #endif /* Rescale the result */ temp1 = asinhdb.d * TWO1000; /* Compute the scaled error, the operation is exact by Sterbenz' lemma */ deltatemp = xPih - temp1; /* Sum up the errors, representing them on a double-double This is exact for the normal rounding case and the error is neglectable in the subnormal rounding case. */ Add12Cond(temp2h,temp2l,deltatemp,xPim); temp3 = temp2l + xPil; Add12(deltah,deltal,temp2h,temp3); /* We are doing directed rounding. Thus we must correct the rounding if the sign of the error is not correct RD -> sign must be positive for correct rounding RU -> sign must be negative for correct rounding RZ -> sign must be positive for positive x and negative for negative x */ if ((x > 0.0) ^ (deltah < 0.0)) { /* The sign is correct, return the intermediate rounding */ return asinhdb.d; } /* The sign is not correct RD -> subtract 1 ulp RU -> add 1 ulp RZ -> subtract 1 ulp if x positive, add 1 ulp if x negative */ asinhdb.l--; return asinhdb.d; } /* asinpi is defined on -1 <= x <= 1, elsewhere it is NaN */ if (xdb.i[HI] >= 0x3ff00000) { if (x == 1.0) { return 0.5; } if (x == -1.0) { return - 0.5; } return (x-x)/0.0; /* return NaN */ } /* Argument reduction: We have 10 intervals and 3 paths: - interval 0 => path 1 using p0 - interval 1-8 => path 2 using p - interval 9 => path 3 using p9 */ index = (0x000f0000 & zdb.i[HI]) >> 16; /* 0 <= index <= 15 index approximates roughly x^2 Map indexes to intervals as follows: 0 -> 0 1 -> 1 ... 8 -> 8 9 -> 9 ... 15 -> 9 For this mapping, filter first the case 0 -> 0 In consequence, 1 <= index <= 15, i.e. 0 <= index - 1 <= 14 with the mapping index - 1 -> interval as 0 -> 1 ... 7 -> 8 8 -> 9 ... 15 -> 9 Thus it suffices to check the 3rd bit of index - 1 after the first filter. */ if (index == 0) { /* Path 1 using p0 */ p0_quick(&asinh, &asinm, x, xdb.i[HI]); Mul22(&asinpih,&asinpim,asinh,asinm,RECPRPIH,RECPRPIM); /* Rounding test */ TEST_AND_RETURN_RZ(asinpih, asinpim, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p0_accu(&asinh, &asinm, &asinl, x); Mul33(&asinpihover,&asinpimover,&asinpilover,asinh,asinm,asinl,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ ReturnRoundTowardsZero3(asinpih,asinpim,asinpil); } /* Strip off the sign of argument x */ sign = 1.0; if (x < 0.0) sign = -sign; index--; if ((index & 0x8) != 0) { /* Path 3 using p9 */ /* Do argument reduction using a MI_9 as a midpoint value for the polynomial and compute exactly zp = 2 * (1 - x) for the asymptotical approximation using a square root. */ z = xabs - MI_9; zp = 2.0 * (1.0 - xabs); /* Polynomial approximation and square root extraction */ p9_quick(&p9h, &p9m, z); p9h = -p9h; p9m = -p9m; sqrt12_64_unfiltered(&sqrh,&sqrm,zp); /* Reconstruction */ Mul22(&t1h,&t1m,sqrh,sqrm,p9h,p9m); Mul22(&t2h,&t2m,t1h,t1m,RECPRPIH,RECPRPIM); Add122(&asinpih,&asinpim,0.5,t2h,t2m); /* Rounding test */ asinpih *= sign; asinpim *= sign; TEST_AND_RETURN_RZ(asinpih, asinpim, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p9_accu(&p9h, &p9m, &p9l, z); p9h = -p9h; p9m = -p9m; p9l = -p9l; Sqrt13(&sqrh,&sqrm,&sqrl,zp); /* Reconstruction */ Mul33(&t1h,&t1m,&t1l,sqrh,sqrm,sqrl,p9h,p9m,p9l); Mul33(&t2h,&t2m,&t2l,t1h,t1m,t1l,RECPRPIH,RECPRPIM,RECPRPIL); Add133(&asinpihover,&asinpimover,&asinpilover,0.5,t2h,t2m,t2l); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ RoundTowardsZero3(&asinpi,asinpih,asinpim,asinpil); return sign * asinpi; } /* Path 2 using p */ /* Do argument reduction using a table value for the midpoint value */ z = xabs - mi_i; p_quick(&asinh, &asinm, z, index); Mul22(&asinpih,&asinpim,asinh,asinm,RECPRPIH,RECPRPIM); /* Rounding test */ asinpih *= sign; asinpim *= sign; TEST_AND_RETURN_RZ(asinpih, asinpim, RDROUNDCST); /* Rounding test failed, launch accurate phase */ #if EVAL_PERF crlibm_second_step_taken++; #endif p_accu(&asinh, &asinm, &asinl, z, index); Mul33(&asinpihover,&asinpimover,&asinpilover,asinh,asinm,asinl,RECPRPIH,RECPRPIM,RECPRPIL); Renormalize3(&asinpih,&asinpim,&asinpil,asinpihover,asinpimover,asinpilover); /* Final rounding */ RoundTowardsZero3(&asinpi,asinpih,asinpim,asinpil); return sign * asinpi; } interval-3.2.0/src/crlibm/asincos.h0000644000000000000000000015712413316017127015350 0ustar 00000000000000/* * Correctly rounded arcsine and arccosine * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" #define RNROUNDCST 1.00277296776935912123020172797003775857085744686284e+00 #define RDROUNDCST 1.53329341668337408143884997262066747209318683475599e-19 #define RNROUNDCSTASINPI 1.00000001500000000000000000000000000000000000000000e+00 #define RDROUNDCSTASINPI 0.827180612553027674871408692069962853565812110900878906e-24 #define ASINSIMPLEBOUND 0x3e300000 #define ACOSSIMPLEBOUND 0x3e400000 #define ASINPISIMPLEBOUND 0x3c300000 #define ACOSPISIMPLEBOUND 0x3c900000 #define ASINPINOSUBNORMALBOUND 0xa5000000 #define EXTRABOUND 0x3f500000 #define EXTRABOUND2 0x3f020000 #define PIHALFH 1.57079632679489655799898173427209258079528808593750e+00 #define PIHALFM 6.12323399573676603586882014729198302312846062338790e-17 #define PIHALFL -1.49738490485916983294350817710599200835275047616952e-33 #define PIHALFRU 0.15707963267948967800435866593034006655216217041015625e1 #define PIRU 0.3141592653589793560087173318606801331043243408203125e1 #define PIH 0.3141592653589793115997963468544185161590576171875e1 #define PIM 0.12246467991473532071737640294583966046256921246775800638e-15 #define PIL -0.29947698097183396658870163542119840167055009523390379678e-32 #define RECPRPIH 0.318309886183790691216444201927515678107738494873046875 #define RECPRPIM -0.19678676675182485881895190914091814184147410411859432932679681016452e-16 #define RECPRPIL -0.10721436282893004003289965208411408821619722030338845557662168511367e-32 #define MRECPRPIH -0.318309886183790691216444201927515678107738494873046875 #define MRECPRPIM 0.19678676675182485881895190914091814184147410411859432932679681016452e-16 #define MRECPRPIL 0.10721436282893004003289965208411408821619722030338845557662168511367e-32 #define HALFPLUSULP 0.50000000000000011102230246251565404236316680908203125 #define HALFMINUSHALFULP 0.499999999999999944488848768742172978818416595458984375 #define TWO1000 0.107150860718626732094842504906000181056140481170553360744e302 #define TWOM1000 0.933263618503218878990089544723817169617091446371708024622e-301 #define TWO999 0.535754303593133660474212524530000905280702405852766803722e301 #define ASINBADCASEX 0.47810755953933303796787868122919462621212005615234375 #define ASINBADCASEYRU 0.49849878588087548347829169870237819850444793701171875 #define ASINBADCASEYRD 0.498498785880875427967140467444551177322864532470703125 #define p0_quick_coeff_19h 1.28394578033992016324882357025671808514744043350219726562500000000000000000000000e-02 #define p0_quick_coeff_17h 1.11230171262417399519195626567125145811587572097778320312500000000000000000000000e-02 #define p0_quick_coeff_15h 1.39970189350021451124561622236797120422124862670898437500000000000000000000000000e-02 #define p0_quick_coeff_13h 1.73513233791185925158906400156411109492182731628417968750000000000000000000000000e-02 #define p0_quick_coeff_11h 2.23721986984502102524530187110940460115671157836914062500000000000000000000000000e-02 #define p0_quick_coeff_9h 3.03819437875142428495678359468001872301101684570312500000000000000000000000000000e-02 #define p0_quick_coeff_7h 4.46428571490314687886247213555179769173264503479003906250000000000000000000000000e-02 #define p0_quick_coeff_5h 7.49999999999713951037705328417359851300716400146484375000000000000000000000000000e-02 #define p0_quick_coeff_3h 1.66666666666666712925959359381522517651319503784179687500000000000000000000000000e-01 #define p0_quick_coeff_1h 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00 #define mi_i asinPolyQuickMiddleTbl[16 * index + 0] #define p_quick_coeff_0h asinPolyQuickMiddleTbl[16 * index + 1] #define p_quick_coeff_0m asinPolyQuickMiddleTbl[16 * index + 2] #define p_quick_coeff_1h asinPolyQuickMiddleTbl[16 * index + 3] #define p_quick_coeff_1m asinPolyQuickMiddleTbl[16 * index + 4] #define p_quick_coeff_2h asinPolyQuickMiddleTbl[16 * index + 5] #define p_quick_coeff_3h asinPolyQuickMiddleTbl[16 * index + 6] #define p_quick_coeff_4h asinPolyQuickMiddleTbl[16 * index + 7] #define p_quick_coeff_5h asinPolyQuickMiddleTbl[16 * index + 8] #define p_quick_coeff_6h asinPolyQuickMiddleTbl[16 * index + 9] #define p_quick_coeff_7h asinPolyQuickMiddleTbl[16 * index + 10] #define p_quick_coeff_8h asinPolyQuickMiddleTbl[16 * index + 11] #define p_quick_coeff_9h asinPolyQuickMiddleTbl[16 * index + 12] #define p_quick_coeff_10h asinPolyQuickMiddleTbl[16 * index + 13] #define p_quick_coeff_11h asinPolyQuickMiddleTbl[16 * index + 14] #define p_quick_coeff_12h asinPolyQuickMiddleTbl[16 * index + 15] #define MI_9 0.87500000000078237416545334781403653323650360107421875 #define p9_quick_coeff_0h 1.01072102056824553173441927356179803609848022460937500000000000000000000000000000e+00 #define p9_quick_coeff_1h -8.82981536812866424357437722392205614596605300903320312500000000000000000000000000e-02 #define p9_quick_coeff_2h 2.10353760393442237863759203264635289087891578674316406250000000000000000000000000e-02 #define p9_quick_coeff_3h -6.65063923819934552095212154654291225597262382507324218750000000000000000000000000e-03 #define p9_quick_coeff_4h 2.40768516599235756631136595729003602173179388046264648437500000000000000000000000e-03 #define p9_quick_coeff_5h -9.43873142704901193882072174545783127541653811931610107421875000000000000000000000e-04 #define p9_quick_coeff_6h 3.89946181164527888064752492169873221428133547306060791015625000000000000000000000e-04 #define p9_quick_coeff_7h -1.67200190558221219085804909454395783541258424520492553710937500000000000000000000e-04 #define p9_quick_coeff_8h 7.37040535228812338126858083597880977322347462177276611328125000000000000000000000e-05 #define p9_quick_coeff_9h -3.32003992244226181431050737291599261880037374794483184814453125000000000000000000e-05 #define p9_quick_coeff_10h 1.53656152855036036170705004977321550541091710329055786132812500000000000000000000e-05 #define p9_quick_coeff_11h -7.04415207421768136802344914548790200115035986527800559997558593750000000000000000e-06 #define p0_accu_coeff_1h 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00 #define p0_accu_coeff_3h 1.66666666666666657414808128123695496469736099243164062500000000000000000000000000e-01 #define p0_accu_coeff_3m 9.25185853854296757512770104458324356634117384146900539554358999794203555211424828e-18 #define p0_accu_coeff_5h 7.49999999999999972244424384371086489409208297729492187500000000000000000000000000e-02 #define p0_accu_coeff_5m 2.77555756157123848551244900139306363413139848179272961559149734966922551393508911e-18 #define p0_accu_coeff_7h 4.46428571428571438484134148438897682353854179382324218750000000000000000000000000e-02 #define p0_accu_coeff_7m -9.91270564650888671257031422999640405542600950171395167431764861021292745135724545e-19 #define p0_accu_coeff_9h 3.03819444444444440589503386718206456862390041351318359375000000000000000000000000e-02 #define p0_accu_coeff_9m 3.85497067132392282371332994114988395042540962791093560324551248186253360472619534e-19 #define p0_accu_coeff_11h 2.23721590909090918553037141691675060428678989410400390625000000000000000000000000e-02 #define p0_accu_coeff_11m -9.46970190235819944882493359250540536388374860744029243297958942093828227370977402e-19 #define p0_accu_coeff_13h 1.73527644230769238775646812200648128055036067962646484375000000000000000000000000e-02 #define p0_accu_coeff_13m -6.73286913315360860061003796178520710524664576113391175476996508564297982957214117e-19 #define p0_accu_coeff_15h 1.39648437499999850813781065994589880574494600296020507812500000000000000000000000e-02 #define p0_accu_coeff_17h 1.15518008961409714141499449624461703933775424957275390625000000000000000000000000e-02 #define p0_accu_coeff_19h 9.76160952911427071132521859908592887222766876220703125000000000000000000000000000e-03 #define p0_accu_coeff_21h 8.39033581342360154642356917520373826846480369567871093750000000000000000000000000e-03 #define p0_accu_coeff_23h 7.31252573485535913022648202286291052587330341339111328125000000000000000000000000e-03 #define p0_accu_coeff_25h 6.44721419032266533644115469314783695153892040252685546875000000000000000000000000e-03 #define p0_accu_coeff_27h 5.73995473599474108350459999883241835050284862518310546875000000000000000000000000e-03 #define p0_accu_coeff_29h 5.15465255859299739671364193327462999150156974792480468750000000000000000000000000e-03 #define p0_accu_coeff_31h 4.64401037031901206542094939777598483487963676452636718750000000000000000000000000e-03 #define p0_accu_coeff_33h 4.37957744519422778606276835944299818947911262512207031250000000000000000000000000e-03 #define p0_accu_coeff_35h 3.08318270558301894476715965254243201343342661857604980468750000000000000000000000e-03 #define p0_accu_coeff_37h 6.23791382502981474333925149267088272608816623687744140625000000000000000000000000e-03 #define p_accu_coeff_0h asinPolyAccuMiddleTbl[32 * index + 0] #define p_accu_coeff_0m asinPolyAccuMiddleTbl[32 * index + 1] #define p_accu_coeff_1h asinPolyAccuMiddleTbl[32 * index + 2] #define p_accu_coeff_1m asinPolyAccuMiddleTbl[32 * index + 3] #define p_accu_coeff_2h asinPolyAccuMiddleTbl[32 * index + 4] #define p_accu_coeff_2m asinPolyAccuMiddleTbl[32 * index + 5] #define p_accu_coeff_3h asinPolyAccuMiddleTbl[32 * index + 6] #define p_accu_coeff_3m asinPolyAccuMiddleTbl[32 * index + 7] #define p_accu_coeff_4h asinPolyAccuMiddleTbl[32 * index + 8] #define p_accu_coeff_4m asinPolyAccuMiddleTbl[32 * index + 9] #define p_accu_coeff_5h asinPolyAccuMiddleTbl[32 * index + 10] #define p_accu_coeff_5m asinPolyAccuMiddleTbl[32 * index + 11] #define p_accu_coeff_6h asinPolyAccuMiddleTbl[32 * index + 12] #define p_accu_coeff_6m asinPolyAccuMiddleTbl[32 * index + 13] #define p_accu_coeff_7h asinPolyAccuMiddleTbl[32 * index + 14] #define p_accu_coeff_7m asinPolyAccuMiddleTbl[32 * index + 15] #define p_accu_coeff_8h asinPolyAccuMiddleTbl[32 * index + 16] #define p_accu_coeff_8m asinPolyAccuMiddleTbl[32 * index + 17] #define p_accu_coeff_9h asinPolyAccuMiddleTbl[32 * index + 18] #define p_accu_coeff_10h asinPolyAccuMiddleTbl[32 * index + 19] #define p_accu_coeff_11h asinPolyAccuMiddleTbl[32 * index + 20] #define p_accu_coeff_12h asinPolyAccuMiddleTbl[32 * index + 21] #define p_accu_coeff_13h asinPolyAccuMiddleTbl[32 * index + 22] #define p_accu_coeff_14h asinPolyAccuMiddleTbl[32 * index + 23] #define p_accu_coeff_15h asinPolyAccuMiddleTbl[32 * index + 24] #define p_accu_coeff_16h asinPolyAccuMiddleTbl[32 * index + 25] #define p_accu_coeff_17h asinPolyAccuMiddleTbl[32 * index + 26] #define p_accu_coeff_18h asinPolyAccuMiddleTbl[32 * index + 27] #define p_accu_coeff_19h asinPolyAccuMiddleTbl[32 * index + 28] #define p_accu_coeff_20h asinPolyAccuMiddleTbl[32 * index + 29] #define p_accu_coeff_21h asinPolyAccuMiddleTbl[32 * index + 30] #define p_accu_coeff_22h asinPolyAccuMiddleTbl[32 * index + 31] #define p9_accu_coeff_0h 1.01072102056824553173441927356179803609848022460937500000000000000000000000000000e+00 #define p9_accu_coeff_0m 1.39129934510313097947345056199237890632902839379463674068793110905062349047511816e-20 #define p9_accu_coeff_1h -8.82981536812866424357437722392205614596605300903320312500000000000000000000000000e-02 #define p9_accu_coeff_1m 2.41792724167186006978828150786347532734726726246399404474107797113902051933109760e-18 #define p9_accu_coeff_2h 2.10353760393441266418612656252662418410181999206542968750000000000000000000000000e-02 #define p9_accu_coeff_2m 1.08336737333055412851633739558643005025128690376628494418387305131545872427523136e-18 #define p9_accu_coeff_3h -6.65063923820143239329372164547748980112373828887939453125000000000000000000000000e-03 #define p9_accu_coeff_3m -3.26520170221686406454105223534078119197675928213141878161951403569673857418820262e-19 #define p9_accu_coeff_4h 2.40768516606927433787443959545271354727447032928466796875000000000000000000000000e-03 #define p9_accu_coeff_4m -1.97265146971483602383336920707508202998297784121844945705998020102356349525507540e-19 #define p9_accu_coeff_5h -9.43873142126153748948658162021274620201438665390014648437500000000000000000000000e-04 #define p9_accu_coeff_5m -1.00627526920533400945274389592272919368733418903938436114037235924456581415142864e-20 #define p9_accu_coeff_6h 3.89946159535203471478703729502512942417524755001068115234375000000000000000000000e-04 #define p9_accu_coeff_6m -1.68716106145871574328060887792714981312318371720271803146373734705321112414821982e-21 #define p9_accu_coeff_7h -1.67200258171404256496775375673280450428137555718421936035156250000000000000000000e-04 #define p9_accu_coeff_7m 1.19784970040097203700724589956273625590162416200800595011445592863452702658833005e-20 #define p9_accu_coeff_8h 7.37067653300902520495385683574340873747132718563079833984375000000000000000000000e-05 #define p9_accu_coeff_9h -3.31971960015731878111157338029357788400375284254550933837890625000000000000000000e-05 #define p9_accu_coeff_10h 1.52100265651915579552836896293221968790021492168307304382324218750000000000000000e-05 #define p9_accu_coeff_11h -7.06684216556374468498364499469133193088055122643709182739257812500000000000000000e-06 #define p9_accu_coeff_12h 3.32174016771150049044582924784307920162973459810018539428710937500000000000000000e-06 #define p9_accu_coeff_13h -1.57676504579047108034364592377141178758392925374209880828857421875000000000000000e-06 #define p9_accu_coeff_14h 7.54770805302124936124669781628560016883966454770416021347045898437500000000000000e-07 #define p9_accu_coeff_15h -3.63931772276869473623270951831432107326236291555687785148620605468750000000000000e-07 #define p9_accu_coeff_16h 1.76596931693785619791949872102454488498324280953966081142425537109375000000000000e-07 #define p9_accu_coeff_17h -8.61593313016896376739609539688324879591618810081854462623596191406250000000000000e-08 #define p9_accu_coeff_18h 4.22538400682347749169000988064132107169257324130740016698837280273437500000000000e-08 #define p9_accu_coeff_19h -2.12414533709850257115170054159070112120843987213447690010070800781250000000000000e-08 #define p9_accu_coeff_20h 1.04941939883081181921218176284101020190320241454173810780048370361328125000000000e-08 static const double asinPolyQuickMiddleTbl[128] = { 0.30177669529663886383019644199521280825138092041015625, // mi_1 3.06555683602418194144689778113388456404209136962890625000000000000000000000000000e-01, // p_coeff_0h 1.37864228855288786229514205458277346294726855883500333047053665325165638932958245e-19, // p_coeff_0m 1.04890120337530645677759366662940010428428649902343750000000000000000000000000000e+00, // p_coeff_1h -1.03997489957388085277493589447823941146606896923035995294881672634801361709833145e-16, // p_coeff_1m 1.74124328129031780143520791170885786414146423339843750000000000000000000000000000e-01, // p_coeff_2h 2.50143932843980842939402009506011381745338439941406250000000000000000000000000000e-01, // p_coeff_3h 1.67670575222466200493443011509953066706657409667968750000000000000000000000000000e-01, // p_coeff_4h 2.01779349315375722273557812513899989426136016845703125000000000000000000000000000e-01, // p_coeff_5h 1.98874061108935212827120153633586596697568893432617187500000000000000000000000000e-01, // p_coeff_6h 2.35900184842710441968094414733059238642454147338867187500000000000000000000000000e-01, // p_coeff_7h 2.67930172148400869147621961019467562437057495117187500000000000000000000000000000e-01, // p_coeff_8h 3.24866122351198272077965611970284953713417053222656250000000000000000000000000000e-01, // p_coeff_9h 3.92983759990528369598905555903911590576171875000000000000000000000000000000000000e-01, // p_coeff_10h 4.95395034513885057503301823089714162051677703857421875000000000000000000000000000e-01, // p_coeff_11h 6.17581482281306048953695153613807633519172668457031250000000000000000000000000000e-01, // p_coeff_12h 0.393283046242751843646345832894439809024333953857421875, // mi_2 4.04199666960039116769820566332782618701457977294921875000000000000000000000000000e-01, // p_coeff_0h -7.29414577305862355348006038497258990002592122212580672446953500287492033749003895e-21, // p_coeff_0m 1.08764522696446319649510314775398001074790954589843750000000000000000000000000000e+00, // p_coeff_1h 7.18002807945845121967809924279486007735232949667977808694274699519155547022819519e-17, // p_coeff_1m 2.53009602569167157959384439891437068581581115722656250000000000000000000000000000e-01, // p_coeff_2h 3.32153251441154206968775497443857602775096893310546875000000000000000000000000000e-01, // p_coeff_3h 2.92932692232720115477206945797661319375038146972656250000000000000000000000000000e-01, // p_coeff_4h 3.67616411036137902268450261544785462319850921630859375000000000000000000000000000e-01, // p_coeff_5h 4.41363028117747802081538566199014894664287567138671875000000000000000000000000000e-01, // p_coeff_6h 5.81535898184487698436839764326578006148338317871093750000000000000000000000000000e-01, // p_coeff_7h 7.75300865782017067928677533927839249372482299804687500000000000000000000000000000e-01, // p_coeff_8h 1.06930850499925678143142704357160255312919616699218750000000000000000000000000000e+00, // p_coeff_9h 1.49812947255186612594002326659392565488815307617187500000000000000000000000000000e+00, // p_coeff_10h 2.15844993342769164712535712169483304023742675781250000000000000000000000000000000e+00, // p_coeff_11h 3.06928679300128992579743680835235863924026489257812500000000000000000000000000000e+00, // p_coeff_12h 0.466506350946100212251366201599012129008769989013671875, // mi_3 4.85336867180323261461438733022077940404415130615234375000000000000000000000000000e-01, // p_coeff_0h 2.48687685471405101032185714779683260767432502103446885499682394993214984424412251e-18, // p_coeff_0m 1.13055943592368102201817237073555588722229003906250000000000000000000000000000000e+00, // p_coeff_1h 8.31884808460703843039094509953103826114589262451931572783792034897487610578536987e-17, // p_coeff_1m 3.37060423475326498277127029723487794399261474609375000000000000000000000000000000e-01, // p_coeff_2h 4.41819848339723264540879199557821266353130340576171875000000000000000000000000000e-01, // p_coeff_3h 4.72912200341658373048403518623672425746917724609375000000000000000000000000000000e-01, // p_coeff_4h 6.48901300732837138518505071260733529925346374511718750000000000000000000000000000e-01, // p_coeff_5h 9.02760918994661598624418274994241073727607727050781250000000000000000000000000000e-01, // p_coeff_6h 1.33957799576799718721531462506391108036041259765625000000000000000000000000000000e+00, // p_coeff_7h 2.03975089767692541187216193065978586673736572265625000000000000000000000000000000e+00, // p_coeff_8h 3.19221018967622649498139253410045057535171508789062500000000000000000000000000000e+00, // p_coeff_9h 5.09007693218536960699793780804611742496490478515625000000000000000000000000000000e+00, // p_coeff_10h 8.32900562875201266876956651685759425163269042968750000000000000000000000000000000e+00, // p_coeff_11h 1.35684931403507018643495030119083821773529052734375000000000000000000000000000000e+01, // p_coeff_12h 0.52950849718750470085382175966515205800533294677734375, // mi_4 5.58021066268902909968119274708442389965057373046875000000000000000000000000000000e-01, // p_coeff_0h 9.12034392087434999453497016043152989309974709890359127750780743326686206273734570e-20, // p_coeff_0m 1.17882180572684136521388609253335744142532348632812500000000000000000000000000000e+00, // p_coeff_1h 2.42941652280796864299660766500640409154688815034626482580737416583360754884779453e-18, // p_coeff_1m 4.33698001053000381510571514809271320700645446777343750000000000000000000000000000e-01, // p_coeff_2h 5.92141175601994751431789154594298452138900756835937500000000000000000000000000000e-01, // p_coeff_3h 7.45525652675174788086565058620180934667587280273437500000000000000000000000000000e-01, // p_coeff_4h 1.13828091051635160724231354834046214818954467773437500000000000000000000000000000e+00, // p_coeff_5h 1.80888030356391027453355491161346435546875000000000000000000000000000000000000000e+00, // p_coeff_6h 3.03311161272506835118178969423752278089523315429687500000000000000000000000000000e+00, // p_coeff_7h 5.24261669742490976631188459577970206737518310546875000000000000000000000000000000e+00, // p_coeff_8h 9.29745896553562900521683332044631242752075195312500000000000000000000000000000000e+00, // p_coeff_9h 1.68115356121078072249019896844401955604553222656250000000000000000000000000000000e+01, // p_coeff_10h 3.11875660002322234731764183379709720611572265625000000000000000000000000000000000e+01, // p_coeff_11h 5.76621480399203818478781613521277904510498046875000000000000000000000000000000000e+01, // p_coeff_12h 0.58569471503532011258386091867578215897083282470703125, // mi_5 6.25736902820868912122875826753443107008934020996093750000000000000000000000000000e-01, // p_coeff_0h 1.09771341515678393197247834713042073087550408801910172083143857335585380496922880e-20, // p_coeff_0m 1.23375797792237640315704538807040080428123474121093750000000000000000000000000000e+00, // p_coeff_1h -1.59140559577392273960428308971385735880640476257478696520131222769123269245028496e-17, // p_coeff_1m 5.49960162399266483390647408668883144855499267578125000000000000000000000000000000e-01, // p_coeff_2h 8.03296584298027416259913024987326934933662414550781250000000000000000000000000000e-01, // p_coeff_3h 1.17423627321739276752055047836620360612869262695312500000000000000000000000000000e+00, // p_coeff_4h 2.01583293591475243289323771023191511631011962890625000000000000000000000000000000e+00, // p_coeff_5h 3.64900021733109003463368935626931488513946533203125000000000000000000000000000000e+00, // p_coeff_6h 6.93854486506604661855135418591089546680450439453125000000000000000000000000000000e+00, // p_coeff_7h 1.36226794507666699729497850057668983936309814453125000000000000000000000000000000e+01, // p_coeff_8h 2.74281125080204652988413727143779397010803222656250000000000000000000000000000000e+01, // p_coeff_9h 5.63049247624184658889134880155324935913085937500000000000000000000000000000000000e+01, // p_coeff_10h 1.18700353964991606403600599151104688644409179687500000000000000000000000000000000e+02, // p_coeff_11h 2.55076107485252919104823376983404159545898437500000000000000000000000000000000000e+02, // p_coeff_12h 0.636905131730956863833625902771018445491790771484375, // mi_6 6.90477178468776764397318856936180964112281799316406250000000000000000000000000000e-01, // p_coeff_0h 3.39469506786599975391257859730058491397981612722623695477253136232320684939622879e-18, // p_coeff_0m 1.29711412734153253012436834978871047496795654296875000000000000000000000000000000e+00, // p_coeff_1h -4.95712225725049321877947559927504147795821978121980078135777603165479376912117004e-17, // p_coeff_1m 6.94991224248453054457286270917393267154693603515625000000000000000000000000000000e-01, // p_coeff_2h 1.10848340356457941702217340207425877451896667480468750000000000000000000000000000e+00, // p_coeff_3h 1.87458354117332537391860114439623430371284484863281250000000000000000000000000000e+00, // p_coeff_4h 3.65157801390048675216348783578723669052124023437500000000000000000000000000000000e+00, // p_coeff_5h 7.55165652847091450894367881119251251220703125000000000000000000000000000000000000e+00, // p_coeff_6h 1.63735362549250531571942701702937483787536621093750000000000000000000000000000000e+01, // p_coeff_7h 3.66799061204043113093575811944901943206787109375000000000000000000000000000000000e+01, // p_coeff_8h 8.42542910813925374213795294053852558135986328125000000000000000000000000000000000e+01, // p_coeff_9h 1.97368592013039233279414474964141845703125000000000000000000000000000000000000000e+02, // p_coeff_10h 4.75165552896886765665840357542037963867187500000000000000000000000000000000000000e+02, // p_coeff_11h 1.14668095983602756859909277409315109252929687500000000000000000000000000000000000e+03, // p_coeff_12h 0.68427230447631171017519591259770095348358154296875, // mi_7 7.53605330605588874526290510402759537100791931152343750000000000000000000000000000e-01, // p_coeff_0h -6.81399026788433814240085924387948818667013384621768622671778015131849315366707742e-20, // p_coeff_0m 1.37131588394733516800272354885237291455268859863281250000000000000000000000000000e+00, // p_coeff_1h 5.75522635997281408409017033924079017806689197384387157718776961701223626732826233e-17, // p_coeff_1m 8.82290262843787198576706032326910644769668579101562500000000000000000000000000000e-01, // p_coeff_2h 1.56510752146510800919543271447764709591865539550781250000000000000000000000000000e+00, // p_coeff_3h 3.07048550645086359978108703217003494501113891601562500000000000000000000000000000e+00, // p_coeff_4h 6.85588913497096008597964100772514939308166503906250000000000000000000000000000000e+00, // p_coeff_5h 1.63125257116160859993669873801991343498229980468750000000000000000000000000000000e+01, // p_coeff_6h 4.06593958002900990322814323008060455322265625000000000000000000000000000000000000e+01, // p_coeff_7h 1.04739642911711854367240448482334613800048828125000000000000000000000000000000000e+02, // p_coeff_8h 2.76645653402371124229830456897616386413574218750000000000000000000000000000000000e+02, // p_coeff_9h 7.45184231247284060373203828930854797363281250000000000000000000000000000000000000e+02, // p_coeff_10h 2.06663648786018939063069410622119903564453125000000000000000000000000000000000000e+03, // p_coeff_11h 5.75344088930418638483388349413871765136718750000000000000000000000000000000000000e+03, // p_coeff_12h 0.7285533905932444209696541292942129075527191162109375, // mi_8 8.16207699480864135033186812506755813956260681152343750000000000000000000000000000e-01, // p_coeff_0h 1.13998759014226814082709277093003596330685011160153518976201336698750310461036861e-20, // p_coeff_0m 1.45987741598546749699494284868706017732620239257812500000000000000000000000000000e+00, // p_coeff_1h 1.00585284375539824516783136958955684505754068277117579954804682529356796294450760e-16, // p_coeff_1m 1.13339308477403566399743795045651495456695556640625000000000000000000000000000000e+00, // p_coeff_2h 2.27840492593358323603069948148913681507110595703125000000000000000000000000000000e+00, // p_coeff_3h 5.22734481752265178755578745040111243724822998046875000000000000000000000000000000e+00, // p_coeff_4h 1.35483951828855158083797505241818726062774658203125000000000000000000000000000000e+01, // p_coeff_5h 3.74970966332361186346133763436228036880493164062500000000000000000000000000000000e+01, // p_coeff_6h 1.08680173096203162685924326069653034210205078125000000000000000000000000000000000e+02, // p_coeff_7h 3.25593435218005822662235004827380180358886718750000000000000000000000000000000000e+02, // p_coeff_8h 1.00013553235534163832198828458786010742187500000000000000000000000000000000000000e+03, // p_coeff_9h 3.13330209627358499346883036196231842041015625000000000000000000000000000000000000e+03, // p_coeff_10h 1.01324957719780304614687338471412658691406250000000000000000000000000000000000000e+04, // p_coeff_11h 3.27393534650766232516616582870483398437500000000000000000000000000000000000000000e+04 // p_coeff_12h }; static const double asinPolyAccuMiddleTbl[258] = { 3.06555683602418194144689778113388456404209136962890625000000000000000000000000000e-01, // p_coeff_0h 1.38398751617026410180086928097698669616246328887899420551771401122209681489039212e-19, // p_coeff_0m 1.04890120337530645677759366662940010428428649902343750000000000000000000000000000e+00, // p_coeff_1h -1.03082627287649058162739898016810705246384011505786371110104937542928382754325867e-16, // p_coeff_1m 1.74124328129031780143520791170885786414146423339843750000000000000000000000000000e-01, // p_coeff_2h -1.22415542219236523063144722572481689558635471916500300770813680628634756430983543e-17, // p_coeff_2m 2.50143932843971239510239001901936717331409454345703125000000000000000000000000000e-01, // p_coeff_3h -4.13151149720064821141736364751386140320745355927365902171111144980386598035693169e-18, // p_coeff_3m 1.67670575222510526147701170884829480201005935668945312500000000000000000000000000e-01, // p_coeff_4h 9.08471320692536034881317437634606200189439625594786317797080243963137036189436913e-18, // p_coeff_4m 2.01779349344123004605933147104224190115928649902343750000000000000000000000000000e-01, // p_coeff_5h -2.81327768912778086871203966934740276353563377312707108335310124402894871309399605e-18, // p_coeff_5m 1.98874061057130652185875874238263349980115890502929687500000000000000000000000000e-01, // p_coeff_6h 4.84208641776008377910230190635861197948724910162295737015014651660749223083257675e-18, // p_coeff_6m 2.35900148032034129297329627661383710801601409912109375000000000000000000000000000e-01, // p_coeff_7h -7.70265627820459694705350308676046582995139915634938421185040624550310894846916199e-18, // p_coeff_7m 2.67930188076546671460675952403107658028602600097656250000000000000000000000000000e-01, // p_coeff_8h -1.74203278137786025999080009256505191287370077696727496685547009747097035869956017e-17, // p_coeff_8m 3.24889007694808218396076426870422437787055969238281250000000000000000000000000000e-01, // p_coeff_9h 3.92992300726306809099952488395501859486103057861328125000000000000000000000000000e-01, // p_coeff_10h 4.88578374389609604300233058893354609608650207519531250000000000000000000000000000e-01, // p_coeff_11h 6.11426267619878727188620359811466187238693237304687500000000000000000000000000000e-01, // p_coeff_12h 7.76087253732093085289989176089875400066375732421875000000000000000000000000000000e-01, // p_coeff_13h 9.92362795771243533238248346606269478797912597656250000000000000000000000000000000e-01, // p_coeff_14h 1.28020190849177639691447438963223248720169067382812500000000000000000000000000000e+00, // p_coeff_15h 1.66202082783864191206646410137182101607322692871093750000000000000000000000000000e+00, // p_coeff_16h 2.17134697355479078240136914246249943971633911132812500000000000000000000000000000e+00, // p_coeff_17h 2.85144941725608758176235824066679924726486206054687500000000000000000000000000000e+00, // p_coeff_18h 3.76113082197504100534501958463806658983230590820312500000000000000000000000000000e+00, // p_coeff_19h 4.98320258065187005058760405518114566802978515625000000000000000000000000000000000e+00, // p_coeff_20h 6.83567147351494863727339179604314267635345458984375000000000000000000000000000000e+00, // p_coeff_21h 9.17671174961649249723905086284503340721130371093750000000000000000000000000000000e+00, // p_coeff_22h 4.04199666960039116769820566332782618701457977294921875000000000000000000000000000e-01, // p_coeff_0h -6.46825370068901234687011200856515476665908008275043725957432344531028434175823350e-21, // p_coeff_0m 1.08764522696446319649510314775398001074790954589843750000000000000000000000000000e+00, // p_coeff_1h 7.20122509204450857334003577729908463703780203035882678808121681868215091526508331e-17, // p_coeff_1m 2.53009602569167157959384439891437068581581115722656250000000000000000000000000000e-01, // p_coeff_2h -2.62855515233500204494953653812414612827096270443634484781370019845780916512012482e-17, // p_coeff_2m 3.32153251441150376699340540653793141245841979980468750000000000000000000000000000e-01, // p_coeff_3h -2.17141385535786665092496720426544052591009587195721927677105611564911669120192528e-17, // p_coeff_3m 2.92932692232876656923679092869861051440238952636718750000000000000000000000000000e-01, // p_coeff_4h -2.54506532782342113657805222827712812531223364242776927013345300565561046823859215e-17, // p_coeff_4m 3.67616411055874059421455513074761256575584411621093750000000000000000000000000000e-01, // p_coeff_5h -6.76970835849273256879417289105284614692988316998734608931354017613557516597211361e-18, // p_coeff_5m 4.41363027759851866971274603201891295611858367919921875000000000000000000000000000e-01, // p_coeff_6h -2.90651996480231385490406350336172813253854649135862232844917940610685036517679691e-18, // p_coeff_6m 5.81535855061384165942683921457501128315925598144531250000000000000000000000000000e-01, // p_coeff_7h 2.15506151894707480118506866417280461854749969158187919426872269923478597775101662e-17, // p_coeff_7m 7.75301235143548206352193119528237730264663696289062500000000000000000000000000000e-01, // p_coeff_8h -5.09980429509694427469186543286592667631136122693286116813737862685229629278182983e-17, // p_coeff_8m 1.06935418322891551135001009242841973900794982910156250000000000000000000000000000e+00, // p_coeff_9h 1.49796852292175275422891900234390050172805786132812500000000000000000000000000000e+00, // p_coeff_10h 2.13528146071462776589555687678512185811996459960937500000000000000000000000000000e+00, // p_coeff_11h 3.08095882478763538614430217421613633632659912109375000000000000000000000000000000e+00, // p_coeff_12h 4.49525762116327154416239864076487720012664794921875000000000000000000000000000000e+00, // p_coeff_13h 6.61832853156151212914437564904801547527313232421875000000000000000000000000000000e+00, // p_coeff_14h 9.82196882969892293147040618350729346275329589843750000000000000000000000000000000e+00, // p_coeff_15h 1.46763291696545170594845330924727022647857666015625000000000000000000000000000000e+01, // p_coeff_16h 2.20625545956168913619421800831332802772521972656250000000000000000000000000000000e+01, // p_coeff_17h 3.33428595472074320582578366156667470932006835937500000000000000000000000000000000e+01, // p_coeff_18h 5.06298287402715487814930384047329425811767578125000000000000000000000000000000000e+01, // p_coeff_19h 7.72361044088683854624832747504115104675292968750000000000000000000000000000000000e+01, // p_coeff_20h 1.19605340680796203400859667453914880752563476562500000000000000000000000000000000e+02, // p_coeff_21h 1.80182167313889749493682757019996643066406250000000000000000000000000000000000000e+02, // p_coeff_22h 4.85336867180323261461438733022077940404415130615234375000000000000000000000000000e-01, // p_coeff_0h 2.48711731548431450339898686061161136444646421020973452165048200868113781325519085e-18, // p_coeff_0m 1.13055943592368102201817237073555588722229003906250000000000000000000000000000000e+00, // p_coeff_1h 8.33253077521152707672020411779329031688034814541986283753516318029141984879970551e-17, // p_coeff_1m 3.37060423475326498277127029723487794399261474609375000000000000000000000000000000e-01, // p_coeff_2h -1.06567668725757610844479862637418971752325776427227331522029629695680341683328152e-17, // p_coeff_2m 4.41819848339719767338351630314718931913375854492187500000000000000000000000000000e-01, // p_coeff_3h 1.00442163349492148002936541754087371062381994416120786772772532913222676143050194e-17, // p_coeff_3m 4.72912200341745858622743980959057807922363281250000000000000000000000000000000000e-01, // p_coeff_4h 4.32579192702017095690398912101462577298397752038590716172627992364141391590237617e-18, // p_coeff_4m 6.48901300757961929654982213833136484026908874511718750000000000000000000000000000e-01, // p_coeff_5h 5.53173550473638312502352924376368778723557407693469517573348070982319768518209457e-17, // p_coeff_5m 9.02760918723618410730580308154458180069923400878906250000000000000000000000000000e-01, // p_coeff_6h 1.83127184204758972652773042458306136013081307308989972848500826785311801359057426e-17, // p_coeff_6m 1.33957791852745100591448590421350672841072082519531250000000000000000000000000000e+00, // p_coeff_7h -8.08660441258249393782142982707336982340679568071958871477988850529072806239128113e-17, // p_coeff_7m 2.03975126091931757699171612330246716737747192382812500000000000000000000000000000e+00, // p_coeff_8h 1.39326386720348649025304457272644525059897659732127683795965822355356067419052124e-16, // p_coeff_8m 3.19232532691492343346340021525975316762924194335937500000000000000000000000000000e+00, // p_coeff_9h 5.08990447700057480062696413369849324226379394531250000000000000000000000000000000e+00, // p_coeff_10h 8.24681325581985547046315332408994436264038085937500000000000000000000000000000000e+00, // p_coeff_11h 1.35339383861901847438957702252082526683807373046875000000000000000000000000000000e+01, // p_coeff_12h 2.24533939052931295066173333907499909400939941406250000000000000000000000000000000e+01, // p_coeff_13h 3.75945346965856899146274372469633817672729492187500000000000000000000000000000000e+01, // p_coeff_14h 6.34457878603441614018265681806951761245727539062500000000000000000000000000000000e+01, // p_coeff_15h 1.07811054823829493898301734589040279388427734375000000000000000000000000000000000e+02, // p_coeff_16h 1.84306463662936579339657328091561794281005859375000000000000000000000000000000000e+02, // p_coeff_17h 3.16759786376428792209480889141559600830078125000000000000000000000000000000000000e+02, // p_coeff_18h 5.47025706678748861122585367411375045776367187500000000000000000000000000000000000e+02, // p_coeff_19h 9.49215135261129944410640746355056762695312500000000000000000000000000000000000000e+02, // p_coeff_20h 1.66325303120893772756971884518861770629882812500000000000000000000000000000000000e+03, // p_coeff_21h 2.81005886721817250872845761477947235107421875000000000000000000000000000000000000e+03, // p_coeff_22h 5.58021066268902909968119274708442389965057373046875000000000000000000000000000000e-01, // p_coeff_0h 9.14056635248981946291334736807400951779846267656755277007663007537985322414897382e-20, // p_coeff_0m 1.17882180572684136521388609253335744142532348632812500000000000000000000000000000e+00, // p_coeff_1h 2.57506761959083747975269601591872190204330911429892510960959484123122820165008307e-18, // p_coeff_1m 4.33698001053000381510571514809271320700645446777343750000000000000000000000000000e-01, // p_coeff_2h -1.13987489167043526825762332057111190978471845558278249810335580605169525370001793e-17, // p_coeff_2m 5.92141175601989977472783266421174630522727966308593750000000000000000000000000000e-01, // p_coeff_3h 1.51434599074934130528344780896022003291074232766760462864930047999223461374640465e-17, // p_coeff_3m 7.45525652675293803994804875401314347982406616210937500000000000000000000000000000e-01, // p_coeff_4h -4.95666529120828261720386639182573717908098482969568576717023233868530951440334320e-17, // p_coeff_4m 1.13828091056041680317889586149249225854873657226562500000000000000000000000000000e+00, // p_coeff_5h 6.30476130024642952826684347359752494928069360322596403900519135277136228978633881e-17, // p_coeff_5m 1.80888030309746783430568939365912228822708129882812500000000000000000000000000000e+00, // p_coeff_6h 6.53471855925770582546264336577217040248932212759963578108113324560690671205520630e-17, // p_coeff_6m 3.03311143845375674743536364985629916191101074218750000000000000000000000000000000e+00, // p_coeff_7h -2.14585117370534459252749227343052173552538040022033549725222201232099905610084534e-16, // p_coeff_7m 5.24261747644370590393236852833069860935211181640625000000000000000000000000000000e+00, // p_coeff_8h -5.46512862978737750269761176067830595023185492192796530730447557289153337478637695e-17, // p_coeff_8m 9.29779331096978367554584110621362924575805664062500000000000000000000000000000000e+00, // p_coeff_9h 1.68111140106672962701850337907671928405761718750000000000000000000000000000000000e+01, // p_coeff_10h 3.08802874723923395094971056096255779266357421875000000000000000000000000000000000e+01, // p_coeff_11h 5.74616531317601229034153220709413290023803710937500000000000000000000000000000000e+01, // p_coeff_12h 1.08089434897446437844337197020649909973144531250000000000000000000000000000000000e+02, // p_coeff_13h 2.05202846011656902192044071853160858154296875000000000000000000000000000000000000e+02, // p_coeff_14h 3.92662709897826516680652275681495666503906250000000000000000000000000000000000000e+02, // p_coeff_15h 7.56557048606022931380721274763345718383789062500000000000000000000000000000000000e+02, // p_coeff_16h 1.46649727257876816111092921346426010131835937500000000000000000000000000000000000e+03, // p_coeff_17h 2.85782276299161503629875369369983673095703125000000000000000000000000000000000000e+03, // p_coeff_18h 5.59751274793538505036849528551101684570312500000000000000000000000000000000000000e+03, // p_coeff_19h 1.10145801644146959006320685148239135742187500000000000000000000000000000000000000e+04, // p_coeff_20h 2.15676400725272833369672298431396484375000000000000000000000000000000000000000000e+04, // p_coeff_21h 4.10662669419021476642228662967681884765625000000000000000000000000000000000000000e+04, // p_coeff_22h 6.25736902820868912122875826753443107008934020996093750000000000000000000000000000e-01, // p_coeff_0h 1.03044861946200352361105560063972534424839340803290894401332555840866689322865568e-20, // p_coeff_0m 1.23375797792237640315704538807040080428123474121093750000000000000000000000000000e+00, // p_coeff_1h -1.56943153280384722085732805658465945105123195556662968330741136924189049750566483e-17, // p_coeff_1m 5.49960162399266483390647408668883144855499267578125000000000000000000000000000000e-01, // p_coeff_2h 4.77724544586887245869366226653936105958167895554379589473370515406713820993900299e-17, // p_coeff_2m 8.03296584298018756520320948766311630606651306152343750000000000000000000000000000e-01, // p_coeff_3h 8.24298592592304193429233278946371287822415169276122487440616737330856267362833023e-18, // p_coeff_3m 1.17423627321674173273891028657089918851852416992187500000000000000000000000000000e+00, // p_coeff_4h 6.51885136427795249608596859127055587343811181939758764292136561380175407975912094e-18, // p_coeff_4m 2.01583293601212298895575258939061313867568969726562500000000000000000000000000000e+00, // p_coeff_5h -1.74898605368430358273924263609101302050140983100449953990818130478146485984325409e-16, // p_coeff_5m 3.64900022085783248826373892370611429214477539062500000000000000000000000000000000e+00, // p_coeff_6h 1.43304714197470670030886399120078425706334125872346008101487768726656213402748108e-16, // p_coeff_6m 6.93854439566079062018388867727480828762054443359375000000000000000000000000000000e+00, // p_coeff_7h -3.60750117305009285790273957823616258349535174413877380850124154676450416445732117e-16, // p_coeff_7m 1.36226702672788579917551032849587500095367431640625000000000000000000000000000000e+01, // p_coeff_8h 5.62980642478103599614115253967152086402971956392848884576096679666079580783843994e-16, // p_coeff_8m 2.74292117002245703361040796153247356414794921875000000000000000000000000000000000e+01, // p_coeff_9h 5.63167951919359666135278530418872833251953125000000000000000000000000000000000000e+01, // p_coeff_10h 1.17466533739617389642262423876672983169555664062500000000000000000000000000000000e+02, // p_coeff_11h 2.48208400271530678082854137755930423736572265625000000000000000000000000000000000e+02, // p_coeff_12h 5.30187120971580611694662366062402725219726562500000000000000000000000000000000000e+02, // p_coeff_13h 1.14298685390676246242946945130825042724609375000000000000000000000000000000000000e+03, // p_coeff_14h 2.48365898527212812041398137807846069335937500000000000000000000000000000000000000e+03, // p_coeff_15h 5.43413912381613681645831093192100524902343750000000000000000000000000000000000000e+03, // p_coeff_16h 1.19616511180501001945231109857559204101562500000000000000000000000000000000000000e+04, // p_coeff_17h 2.64708277570606114750262349843978881835937500000000000000000000000000000000000000e+04, // p_coeff_18h 5.88376889385143513209186494350433349609375000000000000000000000000000000000000000e+04, // p_coeff_19h 1.31386216977166535798460245132446289062500000000000000000000000000000000000000000e+05, // p_coeff_20h 3.03303368112601048778742551803588867187500000000000000000000000000000000000000000e+05, // p_coeff_21h 6.82215743360355845652520656585693359375000000000000000000000000000000000000000000e+05, // p_coeff_22h 6.90477178468776764397318856936180964112281799316406250000000000000000000000000000e-01, // p_coeff_0h 3.39466231816613032388245073452427079551490712938188829689289960356290976051241159e-18, // p_coeff_0m 1.29711412734153253012436834978871047496795654296875000000000000000000000000000000e+00, // p_coeff_1h -4.91536443957924304285159601199758593586250555616465329755726543226046487689018250e-17, // p_coeff_1m 6.94991224248453054457286270917393267154693603515625000000000000000000000000000000e-01, // p_coeff_2h 4.14055567174545404801311585696815622965502227300336503257316422832445823587477207e-18, // p_coeff_2m 1.10848340356455987709693999931914731860160827636718750000000000000000000000000000e+00, // p_coeff_3h 4.16266958244922006708243033738862584564114206709881105261672473716316744685173035e-17, // p_coeff_3m 1.87458354117322345544494055502582341432571411132812500000000000000000000000000000e+00, // p_coeff_4h 1.01371418047977543599188915056692109774560397669751488081146817421540617942810059e-16, // p_coeff_4m 3.65157801416010441286630339163821190595626831054687500000000000000000000000000000e+00, // p_coeff_5h 1.26536476346012852031977695308463633490816727090143289924384362166165374219417572e-16, // p_coeff_5m 7.55165652946598697781155351549386978149414062500000000000000000000000000000000000e+00, // p_coeff_6h -2.14190464475496048348382959343551268818198527301224776131505223020212724804878235e-16, // p_coeff_6m 1.63735347750204702776954945875331759452819824218750000000000000000000000000000000e+01, // p_coeff_7h 1.51055732062479748503833695277300766424363764363347772956558401347137987613677979e-15, // p_coeff_7m 3.66799013891310394797073968220502138137817382812500000000000000000000000000000000e+01, // p_coeff_8h -1.96467879903428952233615671924270070336884016354295212636316136922687292098999023e-15, // p_coeff_8m 8.42583880764557306974893435835838317871093750000000000000000000000000000000000000e+01, // p_coeff_9h 1.97380229224487067085647140629589557647705078125000000000000000000000000000000000e+02, // p_coeff_10h 4.69729422521515630251087713986635208129882812500000000000000000000000000000000000e+02, // p_coeff_11h 1.13246616901346669692429713904857635498046875000000000000000000000000000000000000e+03, // p_coeff_12h 2.76004978747814584494335576891899108886718750000000000000000000000000000000000000e+03, // p_coeff_13h 6.78908667818280082428827881813049316406250000000000000000000000000000000000000000e+03, // p_coeff_14h 1.68324374222143451333977282047271728515625000000000000000000000000000000000000000e+04, // p_coeff_15h 4.20216193300401428132317960262298583984375000000000000000000000000000000000000000e+04, // p_coeff_16h 1.05540980227414402179419994354248046875000000000000000000000000000000000000000000e+05, // p_coeff_17h 2.66494483142128563486039638519287109375000000000000000000000000000000000000000000e+05, // p_coeff_18h 6.76009364551451755687594413757324218750000000000000000000000000000000000000000000e+05, // p_coeff_19h 1.72216034198046685196459293365478515625000000000000000000000000000000000000000000e+06, // p_coeff_20h 4.49188704440361727029085159301757812500000000000000000000000000000000000000000000e+06, // p_coeff_21h 1.15993861480669919401407241821289062500000000000000000000000000000000000000000000e+07, // p_coeff_22h 7.53605330605588874526290510402759537100791931152343750000000000000000000000000000e-01, // p_coeff_0h -6.86303578932659590324882262388685086010663787564085999357010869914574868744239211e-20, // p_coeff_0m 1.37131588394733516800272354885237291455268859863281250000000000000000000000000000e+00, // p_coeff_1h 5.85729819349925155946752593741546617096794483808830378279708384070545434951782227e-17, // p_coeff_1m 8.82290262843787198576706032326910644769668579101562500000000000000000000000000000e-01, // p_coeff_2h 5.16377114572074856584788281695076928068533622922381409736658497422467917203903198e-17, // p_coeff_2m 1.56510752146505316417801623174455016851425170898437500000000000000000000000000000e+00, // p_coeff_3h -4.39163602371923391288987498767894166026634554891340533888666186612681485712528229e-17, // p_coeff_3m 3.07048550644979600932060748164076358079910278320312500000000000000000000000000000e+00, // p_coeff_4h -1.10182145686314872930592860300828689006905830376995686359364867712429258972406387e-16, // p_coeff_4m 6.85588913581356962367863161489367485046386718750000000000000000000000000000000000e+00, // p_coeff_5h 4.35622325486244782178679451752414705321823684735019210911843856592895463109016418e-16, // p_coeff_5m 1.63125257206586802283254655776545405387878417968750000000000000000000000000000000e+01, // p_coeff_6h -1.42810985056358952027816317128163090933704222357941704402151117392349988222122192e-16, // p_coeff_6m 4.06593902603693564401510229799896478652954101562500000000000000000000000000000000e+01, // p_coeff_7h 1.26451118649566617072575681437226509832616233499485991487176761438604444265365601e-15, // p_coeff_7m 1.04739604506448415577324340119957923889160156250000000000000000000000000000000000e+02, // p_coeff_8h -4.21355762035756719251654947961735015460869348269401513107368373312056064605712891e-16, // p_coeff_8m 2.76663345345012544385099317878484725952148437500000000000000000000000000000000000e+02, // p_coeff_9h 7.45270800399650397594086825847625732421875000000000000000000000000000000000000000e+02, // p_coeff_10h 2.03955855522386173106497153639793395996093750000000000000000000000000000000000000e+03, // p_coeff_11h 5.65453975726426688197534531354904174804687500000000000000000000000000000000000000e+03, // p_coeff_12h 1.58480736247709683084394782781600952148437500000000000000000000000000000000000000e+04, // p_coeff_13h 4.48292577388124118442647159099578857421875000000000000000000000000000000000000000e+04, // p_coeff_14h 1.27817476628451069700531661510467529296875000000000000000000000000000000000000000e+05, // p_coeff_15h 3.66953462486772332340478897094726562500000000000000000000000000000000000000000000e+05, // p_coeff_16h 1.05988028936582896858453750610351562500000000000000000000000000000000000000000000e+06, // p_coeff_17h 3.07766344983369577676057815551757812500000000000000000000000000000000000000000000e+06, // p_coeff_18h 8.97598008321647346019744873046875000000000000000000000000000000000000000000000000e+06, // p_coeff_19h 2.63006417766936272382736206054687500000000000000000000000000000000000000000000000e+07, // p_coeff_20h 7.97293238009131550788879394531250000000000000000000000000000000000000000000000000e+07, // p_coeff_21h 2.35266135040413618087768554687500000000000000000000000000000000000000000000000000e+08, // p_coeff_22h 8.16207699480864135033186812506755813956260681152343750000000000000000000000000000e-01, // p_coeff_0h 1.10010191397663675140086054218782967355131241568134164879148861881930088202352636e-20, // p_coeff_0m 1.45987741598546749699494284868706017732620239257812500000000000000000000000000000e+00, // p_coeff_1h 1.03784174873658842691949705484313598874177727812186111666648002938018180429935455e-16, // p_coeff_1m 1.13339308477403566399743795045651495456695556640625000000000000000000000000000000e+00, // p_coeff_2h 6.19984751477578508212901866489819694255822369395765580879498202193644829094409943e-17, // p_coeff_2m 2.27840492593338828086757530400063842535018920898437500000000000000000000000000000e+00, // p_coeff_3h 1.29623917002581965214107410636027293901696556366158474826733026930014602839946747e-16, // p_coeff_3m 5.22734481752082214001120519242249429225921630859375000000000000000000000000000000e+00, // p_coeff_4h -3.48196612292005370465186545711763157537164151090688934964134659821866080164909363e-16, // p_coeff_4m 1.35483951862735629845246876357123255729675292968750000000000000000000000000000000e+01, // p_coeff_5h -4.53291289318611746967298644014774748053833951222640202827207644986629020422697067e-17, // p_coeff_5m 3.74970966548151878328098973724991083145141601562500000000000000000000000000000000e+01, // p_coeff_6h 3.16809448186690022670167104047109366061463187579094746837427010177634656429290771e-15, // p_coeff_6m 1.08680147858936038574029225856065750122070312500000000000000000000000000000000000e+02, // p_coeff_7h -6.36137089188991992639408248982314785589906210028221522634339635260403156280517578e-15, // p_coeff_7m 3.25593310030335430838022148236632347106933593750000000000000000000000000000000000e+02, // p_coeff_8h 1.91287227671501587672951512619431386699611966073497626439348096027970314025878906e-14, // p_coeff_8m 1.00022684509519501716567901894450187683105468750000000000000000000000000000000000e+03, // p_coeff_9h 3.13368188220144656952470541000366210937500000000000000000000000000000000000000000e+03, // p_coeff_10h 9.97418849150001005909871309995651245117187500000000000000000000000000000000000000e+03, // p_coeff_11h 3.21620985996262825210578739643096923828125000000000000000000000000000000000000000e+04, // p_coeff_12h 1.04841470601619919762015342712402343750000000000000000000000000000000000000000000e+05, // p_coeff_13h 3.44929702756780723575502634048461914062500000000000000000000000000000000000000000e+05, // p_coeff_14h 1.14386293806761899031698703765869140625000000000000000000000000000000000000000000e+06, // p_coeff_15h 3.81954181095832167193293571472167968750000000000000000000000000000000000000000000e+06, // p_coeff_16h 1.28314429144318234175443649291992187500000000000000000000000000000000000000000000e+07, // p_coeff_17h 4.33370274414261654019355773925781250000000000000000000000000000000000000000000000e+07, // p_coeff_18h 1.46996088810462892055511474609375000000000000000000000000000000000000000000000000e+08, // p_coeff_19h 5.00961200009291708469390869140625000000000000000000000000000000000000000000000000e+08, // p_coeff_20h 1.77139381348167872428894042968750000000000000000000000000000000000000000000000000e+09, // p_coeff_21h 6.08314919055301284790039062500000000000000000000000000000000000000000000000000000e+09 // p_coeff_22h }; interval-3.2.0/src/crlibm/atan_accurate.c0000644000000000000000000001647213316017127016476 0ustar 00000000000000/* * Correctly rounded arctangent * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Nicolas Gast (Ecole Normale Superieure), Florent de Dinechin * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm_private.h" #include "atan_accurate.h" #include "atan_fast.h" /* * WHAT WE CAN DO : * * 1) Range reduction * * x > 0 because atan(-x) = - atan(x) * * we have built 50 intervals I(i), associated to a b(i) so that : * * For every x : * * we find the interval I(i) , as atan(x) = atan(b(i)) + atan( (x - b(i)) / (1 + x * b(i)) ) * * so that X = (x - b(i)) / (1 + x * b(i)) be in interval [ -2^(-6) , 2^(-6) ] * There is no cancellation because : * for every x in [ -2^(-6) , 2^(-6) ], * * atan(x) <= 0.01562372862 in binary 0.000001111111111 * AND for the smallest b(i) atan(b(i)) = 0.04687118592 in binary 0.00001011111111 * * * 2) Polynomial evaluation of atan(X), atan(b(i)) is tabulated. * * (-???) * Approximation error: |err| < 2^ * * * 3) Reconstruction: * * atan(x) = atan(b(i)) + atan(X) * * * 4) Rounding: * * when |x| is too big, the result is always sign(x) * Pi/2, * because Pi/2 is appromated by the biggest value smallest than Pi/2, * in order not to have an atan > Pi/2. */ static void scs_atan(scs_ptr res_scs, scs_ptr x){ scs_t X_scs, denom1_scs, denom2_scs, poly_scs, X2; scs_t atanbhihi,atanbhilo, atanblo, atanbhi, atanb; scs_t bsc_ptr; db_number db; double test; int k, i=31; scs_get_d(&db.d, x); #if EVAL_PERF crlibm_second_step_taken++; #endif /* test if x as to be reduced */ if (db.d > MIN_REDUCTION_NEEDED) { /* Compute i so that x E [a[i],a[i+1]] */ if (db.d < arctan_table[i][A].d) i-= 16; else i+=16; if (db.d < arctan_table[i][A].d) i-= 8; else i+= 8; if (db.d < arctan_table[i][A].d) i-= 4; else i+= 4; if (db.d < arctan_table[i][A].d) i-= 2; else i+= 2; if (db.d < arctan_table[i][A].d) i-= 1; else if (i<61) i+= 1; if (db.d < arctan_table[i][A].d) i-= 1; /* evaluate X = (x - b(i)) / (1 + x*b(i)) */ scs_set_d(bsc_ptr, arctan_table[i][B].d); scs_mul(denom1_scs,bsc_ptr,x); scs_add(denom2_scs,denom1_scs,SCS_ONE); scs_sub(X_scs,x,bsc_ptr); scs_div(X_scs,X_scs,denom2_scs); scs_get_d(&test,X_scs); /* Polynomial evaluation of atan(X) , X = (x-b(i)) / (1+ x*b(i)) */ scs_square(X2, X_scs); scs_set(res_scs, constant_poly_ptr[0]); for(k=1; k < 10; k++) { /* we use Horner expression */ scs_mul(res_scs, res_scs, X2); scs_add(res_scs, constant_poly_ptr[k], res_scs); } scs_mul(poly_scs, res_scs, X_scs); /* reconstruction : */ /* 1st we load atan ( b[i] ) in a scs*/ scs_set_d( atanbhihi , arctan_table[i][ATAN_BHI].d); scs_set_d( atanbhilo , arctan_table[i][ATAN_BLO].d); scs_set_d( atanblo , atan_blolo[i].d); scs_add(atanbhi,atanbhihi,atanbhilo); scs_add(atanb,atanbhi,atanblo); scs_add(res_scs,atanb, poly_scs); return; } else { /* no reduction needed */ /* Polynomial evaluation of atan(x) */ scs_square(X2, x); scs_set(res_scs, constant_poly_ptr[0]); for(k=1; k < 10; k++) { /* we use Horner expression */ scs_mul(res_scs, res_scs, X2); scs_add(res_scs, constant_poly_ptr[k], res_scs); } scs_mul(res_scs, res_scs, x); return; } } static void scs_atanpi(scs_ptr res, scs_ptr x){ scs_t at; scs_atan(at, x); scs_mul(res, at, InvPiSCS_ptr); } double scs_atan_rn(double x){ /* This function does NOT compute atan(x) correctly if it isn't * called in atan_rn() */ scs_t sc1; scs_t res_scs; db_number res; int sign =1; res.d = x; if (x < 0){ sign = -1; x *= -1; } scs_set_d(sc1, x); scs_atan(res_scs, sc1); scs_get_d(&res.d, res_scs); res.d *= sign; return res.d; } double scs_atan_rd(double x){ scs_t sc1; scs_t res_scs; db_number res; int sign = 1; res.d = x; /* Filter cases */ if (x < 0){ sign = -1; x *= -1; } scs_set_d(sc1, x); scs_atan(res_scs, sc1); if (sign == -1){ scs_get_d_pinf(&res.d, res_scs); res.d *= -1; return res.d; } else{ scs_get_d_minf(&res.d, res_scs); return res.d; } } double scs_atan_ru(double x){ scs_t sc1; scs_t res_scs; db_number res; int sign = 1; res.d = x; /* Filter cases */ if (x < 0){ sign = -1; x *= -1; } scs_set_d(sc1, x); scs_atan(res_scs, sc1); if (sign == -1){ scs_get_d_minf(&res.d, res_scs); res.d *= -1; return res.d; } else{ scs_get_d_pinf(&res.d, res_scs); return res.d; } } /************************************************************/ /******** AtanPi *******************************************/ double scs_atanpi_rn(double x){ /* This function does NOT compute atanpi(x) correctly if it isn't * called in atanpi_rn() */ scs_t sc1; scs_t res_scs; db_number res; int sign =1; res.d = x; if (x < 0){ sign = -1; x *= -1; } scs_set_d(sc1, x); scs_atanpi(res_scs, sc1); scs_get_d(&res.d, res_scs); res.d *= sign; return res.d; } double scs_atanpi_rd(double x){ scs_t sc1; scs_t res_scs; db_number res; int sign = 1; res.d = x; /* Filter cases */ if (x < 0){ sign = -1; x *= -1; } scs_set_d(sc1, x); scs_atanpi(res_scs, sc1); if (sign == -1){ scs_get_d_pinf(&res.d, res_scs); res.d *= -1; return res.d; } else{ scs_get_d_minf(&res.d, res_scs); return res.d; } } /************************************************************* ************************************************************* * ROUNDED TOWARD +INFINITY ************************************************************* *************************************************************/ double scs_atanpi_ru(double x){ scs_t sc1; scs_t res_scs; db_number res; int sign = 1; res.d = x; /* Filter cases */ if (x < 0){ sign = -1; x *= -1; } scs_set_d(sc1, x); scs_atanpi(res_scs, sc1); if (sign == -1){ scs_get_d_minf(&res.d, res_scs); res.d *= -1; return res.d; } else{ scs_get_d_pinf(&res.d, res_scs); return res.d; } } interval-3.2.0/src/crlibm/atan_accurate.h0000644000000000000000000002572513316017127016504 0ustar 00000000000000/* * Correctly rounded arctangent * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" #include "atan_fast.h" /*File generated by maple/atan.mpl */ static const scs constant_poly [10]= /* ~-5.26315789473684210526315789473684210526315789473684e-02 */ {{{0x035e50d7, 0x250d7943, 0x179435e5, 0x035e50d7, 0x250d7943, 0x179435e5, 0x035e50d7, 0x250d7943}, DB_ONE, -1, -1 } , /* ~5.88235294117647058823529411764705882352941176470588e-02 */ {{0x03c3c3c3, 0x30f0f0f0, 0x3c3c3c3c, 0x0f0f0f0f, 0x03c3c3c3, 0x30f0f0f0, 0x3c3c3c3c, 0x0f0f0f0f}, DB_ONE, -1, 1 } , /* ~-6.66666666666666666666666666666666666666666666666667e-02 */ {{0x04444444, 0x11111111, 0x04444444, 0x11111111, 0x04444444, 0x11111111, 0x04444444, 0x11111111}, DB_ONE, -1, -1 } , /* ~7.69230769230769230769230769230769230769230769230769e-02 */ {{0x04ec4ec4, 0x3b13b13b, 0x04ec4ec4, 0x3b13b13b, 0x04ec4ec4, 0x3b13b13b, 0x04ec4ec4, 0x3b13b13b}, DB_ONE, -1, 1 } , /* ~-9.09090909090909090909090909090909090909090909090909e-02 */ {{0x05d1745d, 0x05d1745d, 0x05d1745d, 0x05d1745d, 0x05d1745d, 0x05d1745d, 0x05d1745d, 0x05d1745d}, DB_ONE, -1, -1 } , /* ~1.11111111111111111111111111111111111111111111111111e-01 */ {{0x071c71c7, 0x071c71c7, 0x071c71c7, 0x071c71c7, 0x071c71c7, 0x071c71c7, 0x071c71c7, 0x071c71c7}, DB_ONE, -1, 1 } , /* ~-1.42857142857142857142857142857142857142857142857143e-01 */ {{0x09249249, 0x09249249, 0x09249249, 0x09249249, 0x09249249, 0x09249249, 0x09249249, 0x09249249}, DB_ONE, -1, -1 } , /* ~2.00000000000000000000000000000000000000000000000000e-01 */ {{0x0ccccccc, 0x33333333, 0x0ccccccc, 0x33333333, 0x0ccccccc, 0x33333333, 0x0ccccccc, 0x33333333}, DB_ONE, -1, 1 } , /* ~-3.33333333333333333333333333333333333333333333333333e-01 */ {{0x15555555, 0x15555555, 0x15555555, 0x15555555, 0x15555555, 0x15555555, 0x15555555, 0x15555555}, DB_ONE, -1, -1 } , /* ~1.00000000000000000000000000000000000000000000000000e+00 */ {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, DB_ONE, 0, 1 } }; #define constant_poly_ptr (scs_ptr)&constant_poly static const scs InvPiSCS= {{0x145f306d, 0x327220a9, 0x13f84eaf, 0x28fa9a6e, 0x381b6c52, 0x2cc9e21c, 0x2083fca2, 0x31d5ef5d}, DB_ONE, -1, 1 } ; #define InvPiSCS_ptr (scs_ptr)(& InvPiSCS) #ifdef WORDS_BIGENDIAN static const db_number atan_blolo[62] = { /* 0 */ {{0xB8D1C5F3,0xA947CCE9}} /* -5.3484426395e-35 */, /* 1 */ {{0xB8B05943,0x3C749846}} /* -1.2299381479e-35 */, /* 2 */ {{0x38FC2F2A,0x267751FB}} /* +3.3925541143e-34 */, /* 3 */ {{0x38D44E61,0xDDA4249D}} /* +6.1106690132e-35 */, /* 4 */ {{0xB906FBFA,0xA5B245C8}} /* -5.5332673453e-34 */, /* 5 */ {{0xB8DE1E98,0x67CABE65}} /* -9.0637612563e-35 */, /* 6 */ {{0x38BD7B8F,0x45D13048}} /* +2.2180284354e-35 */, /* 7 */ {{0xB9049436,0x23AD369B}} /* -4.9542022687e-34 */, /* 8 */ {{0xB8F98586,0xF6BB1DB7}} /* -3.0720497269e-34 */, /* 9 */ {{0xB89BC985,0xCB4D6219}} /* -5.2261910438e-36 */, /* 10 */ {{0xB8C4002C,0x9C3884F4}} /* -3.0093679582e-35 */, /* 11 */ {{0x3910CBC4,0x893058D9}} /* +8.0869642604e-34 */, /* 12 */ {{0xB8F5408B,0xFF010BB5}} /* -2.5581328396e-34 */, /* 13 */ {{0xB908570F,0xB5813578}} /* -5.8596619457e-34 */, /* 14 */ {{0x39155B89,0x7E967248}} /* +1.0283294335e-33 */, /* 15 */ {{0xB8CD159A,0x2031F115}} /* -4.3761315763e-35 */, /* 16 */ {{0xB8E8D9C6,0x0FC3C81C}} /* -1.4956458040e-34 */, /* 17 */ {{0x38C0AC30,0x8219F20D}} /* +2.5086163140e-35 */, /* 18 */ {{0x38B36506,0x32EDCB95}} /* +1.4590894790e-35 */, /* 19 */ {{0xB8FD57B0,0x5932E7C2}} /* -3.5319791285e-34 */, /* 20 */ {{0x38C73827,0x91A2D916}} /* +3.4936600564e-35 */, /* 21 */ {{0xB92FE60D,0x9EC5116C}} /* -3.0717278111e-33 */, /* 22 */ {{0x3903AADF,0x6A3B8AE2}} /* +4.7347715466e-34 */, /* 23 */ {{0xB88D6A01,0x71B87C3C}} /* -2.7660872166e-36 */, /* 24 */ {{0xB8E17427,0xEA5AC8E8}} /* -1.0504584084e-34 */, /* 25 */ {{0x38F4ED52,0xF776B005}} /* +2.5190016806e-34 */, /* 26 */ {{0xB9265B23,0x75D2B05C}} /* -2.1528054385e-33 */, /* 27 */ {{0xB8DA45DA,0xAFEAB282}} /* -7.9062036715e-35 */, /* 28 */ {{0x3912EF75,0xBD16D3D4}} /* +9.1170587963e-34 */, /* 29 */ {{0x390AB3D7,0xE904B022}} /* +6.4283962392e-34 */, /* 30 */ {{0xB8EE688B,0x3F9F468B}} /* -1.8301374849e-34 */, /* 31 */ {{0xB9225DF6,0x71A98823}} /* -1.7686817787e-33 */, /* 32 */ {{0xB8CC82B0,0x522BE0F8}} /* -4.2897836993e-35 */, /* 33 */ {{0xB912AFE0,0x88BB6A0B}} /* -8.9974727841e-34 */, /* 34 */ {{0x38D4DC99,0x8640FAE5}} /* +6.2778447830e-35 */, /* 35 */ {{0xB9016FC6,0x406A343B}} /* -4.1977132916e-34 */, /* 36 */ {{0x3909804C,0x126FC74C}} /* +6.1391811422e-34 */, /* 37 */ {{0x39051033,0xE5B0956F}} /* +5.0708030720e-34 */, /* 38 */ {{0xB910CADC,0x203B114C}} /* -8.0852567814e-34 */, /* 39 */ {{0x38EFCAC7,0xF97ED36B}} /* +1.9134182531e-34 */, /* 40 */ {{0xB92464C0,0xB51D77B4}} /* -1.9638289218e-33 */, /* 41 */ {{0x391157F3,0x2D4A03DE}} /* +8.3506176591e-34 */, /* 42 */ {{0xB92BD929,0x136A8DDE}} /* -2.6816921082e-33 */, /* 43 */ {{0x390F1514,0x035DF6B3}} /* +7.4828003563e-34 */, /* 44 */ {{0xB92606EC,0x19DB7E3B}} /* -2.1211268072e-33 */, /* 45 */ {{0x393B104B,0xCDA1B51D}} /* +5.2122706777e-33 */, /* 46 */ {{0x3935FB01,0xF88A520C}} /* +4.2332900876e-33 */, /* 47 */ {{0xB9189ED1,0x1940944D}} /* -1.1854280852e-33 */, /* 48 */ {{0xB914E8F2,0x38D4794B}} /* -1.0067772791e-33 */, /* 49 */ {{0xB93DF07A,0x73581CF5}} /* -5.7661126209e-33 */, /* 50 */ {{0xB939C22F,0x727CE10C}} /* -4.9609136744e-33 */, /* 51 */ {{0xB8EF37D2,0x26E1A810}} /* -1.8788680655e-34 */, /* 52 */ {{0x391A4251,0x45155DAA}} /* +1.2643273919e-33 */, /* 53 */ {{0xB9126D2F,0xA42D0A9A}} /* -8.8720409776e-34 */, /* 54 */ {{0xB93CAF8B,0x3DFAFFA5}} /* -5.5246684074e-33 */, /* 55 */ {{0x3919C170,0xA9A35831}} /* +1.2400882522e-33 */, /* 56 */ {{0xB924C2B3,0xAE51E4B3}} /* -1.9991686511e-33 */, /* 57 */ {{0xB8DEFB7D,0x0DE98917}} /* -9.3234199178e-35 */, /* 58 */ {{0xB916EC39,0x1ABE373B}} /* -1.1036900898e-33 */, /* 59 */ {{0x391C5BA4,0x4135ADBE}} /* +1.3653868341e-33 */, /* 60 */ {{0xB9112692,0xD7179E60}} /* -8.2577511316e-34 */, /* 61 */ {{0x392F96B5,0xBCC93753}} /* +3.0418821818e-33 */, }; #else static const db_number atan_blolo[62] = { /* 0 */ {{0xA947CCE9,0xB8D1C5F3}} /* -5.3484426395e-35 */, /* 1 */ {{0x3C749846,0xB8B05943}} /* -1.2299381479e-35 */, /* 2 */ {{0x267751FB,0x38FC2F2A}} /* +3.3925541143e-34 */, /* 3 */ {{0xDDA4249D,0x38D44E61}} /* +6.1106690132e-35 */, /* 4 */ {{0xA5B245C8,0xB906FBFA}} /* -5.5332673453e-34 */, /* 5 */ {{0x67CABE65,0xB8DE1E98}} /* -9.0637612563e-35 */, /* 6 */ {{0x45D13048,0x38BD7B8F}} /* +2.2180284354e-35 */, /* 7 */ {{0x23AD369B,0xB9049436}} /* -4.9542022687e-34 */, /* 8 */ {{0xF6BB1DB7,0xB8F98586}} /* -3.0720497269e-34 */, /* 9 */ {{0xCB4D6219,0xB89BC985}} /* -5.2261910438e-36 */, /* 10 */ {{0x9C3884F4,0xB8C4002C}} /* -3.0093679582e-35 */, /* 11 */ {{0x893058D9,0x3910CBC4}} /* +8.0869642604e-34 */, /* 12 */ {{0xFF010BB5,0xB8F5408B}} /* -2.5581328396e-34 */, /* 13 */ {{0xB5813578,0xB908570F}} /* -5.8596619457e-34 */, /* 14 */ {{0x7E967248,0x39155B89}} /* +1.0283294335e-33 */, /* 15 */ {{0x2031F115,0xB8CD159A}} /* -4.3761315763e-35 */, /* 16 */ {{0x0FC3C81C,0xB8E8D9C6}} /* -1.4956458040e-34 */, /* 17 */ {{0x8219F20D,0x38C0AC30}} /* +2.5086163140e-35 */, /* 18 */ {{0x32EDCB95,0x38B36506}} /* +1.4590894790e-35 */, /* 19 */ {{0x5932E7C2,0xB8FD57B0}} /* -3.5319791285e-34 */, /* 20 */ {{0x91A2D916,0x38C73827}} /* +3.4936600564e-35 */, /* 21 */ {{0x9EC5116C,0xB92FE60D}} /* -3.0717278111e-33 */, /* 22 */ {{0x6A3B8AE2,0x3903AADF}} /* +4.7347715466e-34 */, /* 23 */ {{0x71B87C3C,0xB88D6A01}} /* -2.7660872166e-36 */, /* 24 */ {{0xEA5AC8E8,0xB8E17427}} /* -1.0504584084e-34 */, /* 25 */ {{0xF776B005,0x38F4ED52}} /* +2.5190016806e-34 */, /* 26 */ {{0x75D2B05C,0xB9265B23}} /* -2.1528054385e-33 */, /* 27 */ {{0xAFEAB282,0xB8DA45DA}} /* -7.9062036715e-35 */, /* 28 */ {{0xBD16D3D4,0x3912EF75}} /* +9.1170587963e-34 */, /* 29 */ {{0xE904B022,0x390AB3D7}} /* +6.4283962392e-34 */, /* 30 */ {{0x3F9F468B,0xB8EE688B}} /* -1.8301374849e-34 */, /* 31 */ {{0x71A98823,0xB9225DF6}} /* -1.7686817787e-33 */, /* 32 */ {{0x522BE0F8,0xB8CC82B0}} /* -4.2897836993e-35 */, /* 33 */ {{0x88BB6A0B,0xB912AFE0}} /* -8.9974727841e-34 */, /* 34 */ {{0x8640FAE5,0x38D4DC99}} /* +6.2778447830e-35 */, /* 35 */ {{0x406A343B,0xB9016FC6}} /* -4.1977132916e-34 */, /* 36 */ {{0x126FC74C,0x3909804C}} /* +6.1391811422e-34 */, /* 37 */ {{0xE5B0956F,0x39051033}} /* +5.0708030720e-34 */, /* 38 */ {{0x203B114C,0xB910CADC}} /* -8.0852567814e-34 */, /* 39 */ {{0xF97ED36B,0x38EFCAC7}} /* +1.9134182531e-34 */, /* 40 */ {{0xB51D77B4,0xB92464C0}} /* -1.9638289218e-33 */, /* 41 */ {{0x2D4A03DE,0x391157F3}} /* +8.3506176591e-34 */, /* 42 */ {{0x136A8DDE,0xB92BD929}} /* -2.6816921082e-33 */, /* 43 */ {{0x035DF6B3,0x390F1514}} /* +7.4828003563e-34 */, /* 44 */ {{0x19DB7E3B,0xB92606EC}} /* -2.1211268072e-33 */, /* 45 */ {{0xCDA1B51D,0x393B104B}} /* +5.2122706777e-33 */, /* 46 */ {{0xF88A520C,0x3935FB01}} /* +4.2332900876e-33 */, /* 47 */ {{0x1940944D,0xB9189ED1}} /* -1.1854280852e-33 */, /* 48 */ {{0x38D4794B,0xB914E8F2}} /* -1.0067772791e-33 */, /* 49 */ {{0x73581CF5,0xB93DF07A}} /* -5.7661126209e-33 */, /* 50 */ {{0x727CE10C,0xB939C22F}} /* -4.9609136744e-33 */, /* 51 */ {{0x26E1A810,0xB8EF37D2}} /* -1.8788680655e-34 */, /* 52 */ {{0x45155DAA,0x391A4251}} /* +1.2643273919e-33 */, /* 53 */ {{0xA42D0A9A,0xB9126D2F}} /* -8.8720409776e-34 */, /* 54 */ {{0x3DFAFFA5,0xB93CAF8B}} /* -5.5246684074e-33 */, /* 55 */ {{0xA9A35831,0x3919C170}} /* +1.2400882522e-33 */, /* 56 */ {{0xAE51E4B3,0xB924C2B3}} /* -1.9991686511e-33 */, /* 57 */ {{0x0DE98917,0xB8DEFB7D}} /* -9.3234199178e-35 */, /* 58 */ {{0x1ABE373B,0xB916EC39}} /* -1.1036900898e-33 */, /* 59 */ {{0x4135ADBE,0x391C5BA4}} /* +1.3653868341e-33 */, /* 60 */ {{0xD7179E60,0xB9112692}} /* -8.2577511316e-34 */, /* 61 */ {{0xBCC93753,0x392F96B5}} /* +3.0418821818e-33 */, }; #endif /* WORDS_BIGENDIAN */ interval-3.2.0/src/crlibm/atan_fast.c0000644000000000000000000002706713316017127015646 0ustar 00000000000000/* * Correctly rounded arctangent * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Nicolas Gast (Ecole Normale Superieure), Florent de Dinechin * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "atan_fast.h" extern double scs_atan_rn(double); extern double scs_atan_rd(double); extern double scs_atan_ru(double); extern double scs_atanpi_rn(double); extern double scs_atanpi_rd(double); extern double scs_atanpi_ru(double); static void atan_quick(double *atanhi,double *atanlo, int *index_of_e, double x) { double tmphi,tmplo, x0hi,x0lo; double q,Xred2,x2; double Xredhi,Xredlo; double xmBihi, xmBilo, tmphi2, tmplo2, atanlolo; int i; if (x > MIN_REDUCTION_NEEDED) /* test if reduction is necessary : */ { /* * 1) Argument reduction : * * tan(x) = tan( b(i) ) + tan ( (x-b(i)) / (1+x*b(i))) * * 6.3 * we choose 62 b(i) so that (x-b(i)) / (1+x*b(i)) < 2^ */ if (x > arctan_table[61][B].d) { i=61; Add12( xmBihi , xmBilo , x , -arctan_table[61][B].d); } else { /* compute i so that a[i] < x < a[i+1] */ i=31; if (x < arctan_table[i][A].d) i-= 16; else i+=16; if (x < arctan_table[i][A].d) i-= 8; else i+= 8; if (x < arctan_table[i][A].d) i-= 4; else i+= 4; if (x < arctan_table[i][A].d) i-= 2; else i+= 2; if (x < arctan_table[i][A].d) i-= 1; else i+= 1; if (x < arctan_table[i][A].d) i-= 1; xmBihi = x-arctan_table[i][B].d; xmBilo = 0.0; } /* we now compute Xred = ( x-b[i] ) / ( 1 + x*b[i] ) * * def : x0 := 1+x*b[i] * * 1st we compute an approximation of y = 1/x0 * then we compute a better approx x' = y*(2-x0*y) * we can proove that : * if y = 1/x0*(1+e) * then x' = 1/x0 * (1-e^2) * */ Mul12(&tmphi,&tmplo, x, arctan_table[i][B].d); if (x > 1) Add22(&x0hi,&x0lo,tmphi,tmplo, 1.0,0.0); else {Add22( &x0hi , &x0lo , 1.0,0.0,tmphi,tmplo);} Div22( &Xredhi, &Xredlo, xmBihi , xmBilo , x0hi,x0lo); /* Polynomial evaluation : * * 1rt compute Q(x^2) = (1 - x^2/3 + ...) * then P(x) = x * Q(x^2) * */ Xred2 = Xredhi*Xredhi; q = Xred2*(coef_poly[3]+Xred2* (coef_poly[2]+Xred2* (coef_poly[1]+Xred2* coef_poly[0]))) ; /* reconstruction : atan(x) = atan(b[i]) + atan(x) */ atanlolo = (Xredlo + arctan_table[i][ATAN_BLO].d); atanlolo += Xredhi*q; Add12( tmphi2, tmplo2, arctan_table[i][ATAN_BHI].d, Xredhi); Add12( *atanhi, *atanlo, tmphi2, (tmplo2+atanlolo)); if (i<10) *index_of_e = 0; else *index_of_e = 1; } else // no reduction needed { /* Polynomial evaluation : * * 1rt compute Q(x^2) = (1 - x^2/3 + ...) * then P(x) = x * Q(x^2) * */ x2 = x*x; q = x2*(coef_poly[3]+x2* (coef_poly[2]+x2* (coef_poly[1]+x2* coef_poly[0]))) ; Add12(*atanhi,*atanlo, x , x*q); *index_of_e = 2; } } extern double atan_rn(double x) { double atanhi,atanlo; int index_of_e; double sign; db_number x_db; int absxhi; x_db.d = x; absxhi = x_db.i[HI] & 0x7fffffff; if(x_db.i[HI] & 0x80000000){ x_db.i[HI] = absxhi; sign =-1; } else sign=1; /* Filter cases */ if ( absxhi >= 0x43500000) /* x >= 2^54 */ { if ((absxhi > 0x7ff00000) || ((absxhi == 0x7ff00000) && (x_db.i[LO] != 0))) return x+x; /* NaN */ else return sign*HALFPI.d; /* atan(+/-infty) = +/- Pi/2 */ } if ( absxhi < 0x3E400000 ) return x; /* x<2^-27 then atan(x) =~ x */ atan_quick(&atanhi, &atanlo,&index_of_e , x_db.d); if (atanhi == (atanhi + (atanlo*rncst[index_of_e]))) return sign*atanhi; else { /* more accuracy is needed , lauch accurate phase */ return sign*scs_atan_rn(x_db.d); } } extern double atan_rd(double x) { double atanhi,atanlo; int index_of_e; double maxepsilon; db_number x_db; int absxhi; int sign; x_db.d = x; absxhi = x_db.i[HI] & 0x7FFFFFFF; if(x_db.i[HI] & 0x80000000){ x_db.i[HI] = absxhi; sign =-1; } else sign=1; /* Filter cases */ if ( absxhi >= 0x43500000) /* x >= 2^54 */ { if ((absxhi > 0x7ff00000) || ((absxhi == 0x7ff00000) && (x_db.i[LO] != 0))) return x+x; /* NaN */ else{ if (sign>0) return HALFPI.d; else return -HALFPI_TO_PLUS_INFINITY.d; /* atan(x) = Pi/2 */ } } else if ( absxhi < 0x3E400000 ) {if (sign>0) {if(x==0) return x; else x_db.l--; return x_db.d; } else return x; } atan_quick(&atanhi, &atanlo,&index_of_e, x_db.d); maxepsilon = epsilon[index_of_e]; atanhi = sign*atanhi; atanlo = sign*atanlo; /* Rounding test to - infinity */ TEST_AND_RETURN_RD(atanhi, atanlo, maxepsilon); /* if the previous block didn't return a value, launch accurate phase */ return scs_atan_rd(sign*x_db.d); } extern double atan_ru(double x) { double atanhi,atanlo; int index_of_e; int sign; double maxepsilon; db_number x_db; int absxhi; x_db.d = x; absxhi = x_db.i[HI] & 0x7FFFFFFF; if (x_db.i[HI] & 0x80000000){ sign = -1; x_db.i[HI] = absxhi; } else sign = 1; /* Filter cases */ if ( absxhi >= 0x43500000) /* x >= 2^54 */ { if ((absxhi > 0x7ff00000) || ((absxhi == 0x7ff00000) && (x_db.i[LO] != 0))) return x+x; /* NaN */ else { if (sign>0) return HALFPI_TO_PLUS_INFINITY.d; else return -HALFPI.d; /* atan(x) = Pi/2 */ } } if ( absxhi < 0x3E400000 ){ if(x==0) return x; if (sign<0) { x_db.l--; return -x_db.d; } else return x; } /* x<2^-27 then atan(x) =~ x */ atan_quick(&atanhi, &atanlo, &index_of_e, x_db.d); maxepsilon = epsilon[index_of_e]; atanhi = sign*atanhi; atanlo = sign*atanlo; TEST_AND_RETURN_RU(atanhi, atanlo, maxepsilon); /* if the previous block didn't return a value, launch accurate phase */ return scs_atan_ru(x); } extern double atan_rz(double x) { if (x>0) return atan_rd(x); else return atan_ru(x); } /************************************************************* ************************************************************* * AtanPi * ************************************************************* *************************************************************/ extern double atanpi_rn(double x) { double atanhi,atanlo,atanpihi,atanpilo; int index_of_e; double sign; db_number x_db; int absxhi; x_db.d = x; absxhi = x_db.i[HI] & 0x7fffffff; if(x_db.i[HI] & 0x80000000){ x_db.i[HI] = absxhi; sign =-1; } else sign=1; /* Filter cases */ if ( absxhi >= 0x43500000) /* x >= 2^54 */ { if ((absxhi > 0x7ff00000) || ((absxhi == 0x7ff00000) && (x_db.i[LO] != 0))) return x+x; /* NaN */ else return sign*0.5; /* atan(+/-infty) = +/- Pi/2 */ } if ( absxhi < 0x3E400000 ) return sign*scs_atanpi_rn(x_db.d); /* TODO optim here */ atan_quick(&atanhi, &atanlo,&index_of_e , x_db.d); Mul22(&atanpihi,&atanpilo, INVPIH, INVPIL, atanhi,atanlo); if (atanpihi == (atanpihi + (atanpilo*rncst[index_of_e]))) return sign*atanpihi; else /* more accuracy is needed , lauch accurate phase */ return sign*scs_atanpi_rn(x_db.d); } extern double atanpi_rd(double x) { double atanhi,atanlo,atanpihi,atanpilo; int index_of_e; double maxepsilon; db_number x_db; int absxhi; int sign; x_db.d = x; absxhi = x_db.i[HI] & 0x7FFFFFFF; if(x_db.i[HI] & 0x80000000){ x_db.i[HI] = absxhi; sign =-1; } else sign=1; /* Filter cases */ if ( absxhi >= 0x43500000) /* x >= 2^54 */ { if ((absxhi > 0x7ff00000) || ((absxhi == 0x7ff00000) && (x_db.i[LO] != 0))) return x+x; /* NaN */ else{ if (sign>0) return 0.5; /* Or should it be 0.4999999999999999444888487687421729788184165954589843750; nextdown(0.5) */ else return -0.5; /* atan(infty) = Pi/2 */ } } else if ( absxhi < 0x3E400000 ) { if(x==0.0) return x; /* signed */ else return scs_atanpi_rd(sign*x_db.d); /* TODO optim here */ } atan_quick(&atanhi, &atanlo,&index_of_e, x_db.d); Mul22(&atanpihi,&atanpilo, INVPIH, INVPIL, atanhi,atanlo); maxepsilon = epsilon[index_of_e]; atanpihi = sign*atanpihi; atanpilo = sign*atanpilo; /* Rounding test to - infinity */ TEST_AND_RETURN_RD(atanpihi, atanpilo, maxepsilon); /* if the previous block didn't return a value, launch accurate phase */ return scs_atanpi_rd(sign*x_db.d); } extern double atanpi_ru(double x) { double atanhi,atanlo,atanpihi,atanpilo; int index_of_e; int sign; double maxepsilon; db_number x_db; int absxhi; x_db.d = x; absxhi = x_db.i[HI] & 0x7FFFFFFF; if (x_db.i[HI] & 0x80000000){ sign = -1; x_db.i[HI] = absxhi; } else sign = 1; /* Filter cases */ if ( absxhi >= 0x43500000) /* x >= 2^54 */ { if ((absxhi > 0x7ff00000) || ((absxhi == 0x7ff00000) && (x_db.i[LO] != 0))) return x+x; /* NaN */ else { if (sign>0) return 0.5; else return - 0.5; } } if ( absxhi < 0x3E400000 ) { if(x==0.0) return x; /* signed */ else return scs_atanpi_ru(x); } atan_quick(&atanhi, &atanlo, &index_of_e, x_db.d); Mul22(&atanpihi,&atanpilo, INVPIH, INVPIL, atanhi,atanlo); maxepsilon = epsilon[index_of_e]; atanpihi = sign*atanpihi; atanpilo = sign*atanpilo; TEST_AND_RETURN_RU(atanpihi, atanpilo, maxepsilon); /* if the previous block didn't return a value, launch accurate phase */ return scs_atanpi_ru(x); } extern double atanpi_rz(double x) { if (x>0) return atanpi_rd(x); else return atanpi_ru(x); } interval-3.2.0/src/crlibm/atan_fast.h0000644000000000000000000010375413316017127015651 0ustar 00000000000000/* * Correctly rounded arctangent * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /*File generated by maple/atan.mpl */ #ifndef _ATAN_FAST_H #define _ATAN_FAST_H #include "crlibm.h" #include "crlibm_private.h" #ifdef WORDS_BIGENDIAN static const db_number HALFPI = {{0x3FF921FB,0x54442D18}};static const db_number HALFPI_TO_PLUS_INFINITY = {{0x3FF921FB,0x54442D19}}; #else static const db_number HALFPI = {{0x54442D18,0x3FF921FB}};static const db_number HALFPI_TO_PLUS_INFINITY = {{0x54442D19,0x3FF921FB}}; #endif #define MIN_REDUCTION_NEEDED 0.01269144369306618004077670910586377580133132772550 #define INVPIH 0.31830988618379069121644420192751567810773849487305 #define INVPIL -0.00000000000000001967867667518248588189519091409181 #define nb_of_ai 62 #define nb_of_bi 62 static const double rncst[4] ={ 1.00108178765940960655050071055243374002677613873338 , /* i<10 */ 1.00005232457100223306383112145248847898875939835839 , /* i>10 */ 1.00177430465884899885886845639867196876576265849646 , /* e > 2^-10 */ 1.00001038174963923723172604569348623337721036178939 , /* e < 2^-10 */ }; static const double epsilon[4] ={ 5.98811545469121308132334292226294391299405661608483e-20 , 2.85148356343799927177205125935801754271662806490715e-21 , 9.82484875894815915914535124879847312836985338769278e-20 , 5.23355329168770007392834621113547073694289911517614e-22 , }; #define DEGREE 4 static double const coef_poly[4] = { /* coef for degree 9 */ 0.11111111111111110494320541874913033097982406616211, /* coef for degree 7 */ -0.14285714285714284921269268124888185411691665649414, /* coef for degree 5 */ 0.20000000000000001110223024625156540423631668090820, /* coef for degree 3 */ -0.33333333333333331482961625624739099293947219848633, }; #define A 0 #define B 1 #define ATAN_BHI 2 #define ATAN_BLO 3 #ifdef WORDS_BIGENDIAN /* limits of the intervals [a[i],b[i]] */ static db_number const arctan_table[62][4] = { { /*a[0] */ {{0x3F89FDF8,0xBCCE533D}} /* +1.2691443693e-02 */ , /*b[0] : */ {{0x3F99FF0B,0x27760007}} /* +2.5386976512e-02 */ , /*atan_b[0]*/ {{0x3F99FD9D,0x4969F96C}} /* +2.5381524664e-02 */,{{0xBC301997,0x750685EA}} /* -8.7278097631e-19 */ , } ,{ /*a[1] */ {{0x3FA3809F,0x90CEBC31}} /* +3.8090692927e-02 */ , /*b[1] : */ {{0x3FAA0355,0xE3547CC2}} /* +5.0806697846e-02 */ , /*atan_b[1]*/ {{0x3FA9FD9D,0x4936262D}} /* +5.0763049304e-02 */,{{0xBC4C1F96,0x3A2D0F59}} /* -3.0491436238e-18 */ , } ,{ /*a[2] */ {{0x3FB04419,0x68FBA526}} /* +6.3539112216e-02 */ , /*b[2] : */ {{0x3FB387E0,0xABF7BFB9}} /* +7.6292078003e-02 */ , /*atan_b[2]*/ {{0x3FB37E35,0xF6C1E06C}} /* +7.6144573921e-02 */,{{0xBC556710,0x8378E024}} /* -4.6409481568e-18 */ , } ,{ /*a[3] */ {{0x3FB6CD46,0xABCDFA25}} /* +8.9069764084e-02 */ , /*b[3] : */ {{0x3FBA1491,0xE265B8AB}} /* +1.0187637117e-01 */ , /*atan_b[3]*/ {{0x3FB9FD9D,0x48CF1996}} /* +1.0152609851e-01 */,{{0xBC4360DC,0xB73BED3C}} /* -2.1010068528e-18 */ , } ,{ /*a[4] */ {{0x3FBD5E09,0x6D2EA546}} /* +1.1471613803e-01 */ , /*b[4] : */ {{0x3FC054FA,0x9124D46B}} /* +1.2759334647e-01 */ , /*atan_b[4]*/ {{0x3FC03E82,0x4D618156}} /* +1.2690762308e-01 */,{{0x3C62604E,0x49A86344}} /* +7.9694040325e-18 */ , } ,{ /*a[5] */ {{0x3FC1FC4E,0xD691E891}} /* +1.4051232793e-01 */ , /*b[5] : */ {{0x3FC3A526,0x51F57043}} /* +1.5347746851e-01 */ , /*atan_b[5]*/ {{0x3FC37E35,0xF64EF83E}} /* +1.5228914763e-01 */,{{0x3C5F2B13,0xB4A55EA6}} /* +6.7585410867e-18 */ , } ,{ /*a[6] */ {{0x3FC54FA6,0x531F610B}} /* +1.6649321612e-01 */ , /*b[6] : */ {{0x3FC6FBF4,0xB99F2601}} /* +1.7956408561e-01 */ , /*atan_b[6]*/ {{0x3FC6BDE9,0x9F302425}} /* +1.7767067216e-01 */,{{0xBC23B62A,0xC4D330CE}} /* -5.3428372026e-19 */ , } ,{ /*a[7] */ {{0x3FC8AA38,0x0550EAF1}} /* +1.9269466648e-01 */ , /*b[7] : */ {{0x3FCA5A97,0x61D9D63D}} /* +2.0588962820e-01 */ , /*atan_b[7]*/ {{0x3FC9FD9D,0x48053FC8}} /* +2.0305219666e-01 */,{{0xBC67A12C,0x98474AF1}} /* -1.0247699700e-17 */ , } ,{ /*a[8] */ {{0x3FCC0D3A,0xB8975BD9}} /* +2.1915372861e-01 */ , /*b[8] : */ {{0x3FCDC24A,0xBCBF6ABC}} /* +2.3249181954e-01 */ , /*atan_b[8]*/ {{0x3FCD3D50,0xF0CE8DD9}} /* +2.2843372114e-01 */,{{0x3C6EF257,0x3A31D353}} /* +1.3420967238e-17 */ , } ,{ /*a[9] */ {{0x3FCF79F0,0xFEE46885}} /* +2.4590885588e-01 */ , /*b[9] : */ {{0x3FD09A2B,0xFCF66B85}} /* +2.5940990165e-01 */ , /*atan_b[9]*/ {{0x3FD03E82,0x4CC62C6B}} /* +2.5381524560e-01 */,{{0x3C5DA594,0x95C6E482}} /* +6.4286246635e-18 */ , } ,{ /*a[10] */ {{0x3FD178D5,0x943274CA}} /* +2.7300013993e-01 */ , /*b[10] : */ {{0x3FD2590B,0x8943E603}} /* +2.8668487935e-01 */ , /*atan_b[10]*/ {{0x3FD1DE5C,0x211F7969}} /* +2.7919677004e-01 */,{{0x3C3C4E87,0x0B01EF44}} /* +1.5345118889e-18 */ , } ,{ /*a[11] */ {{0x3FD33AE4,0xB2CFB5F7}} /* +3.0046956503e-01 */ , /*b[11] : */ {{0x3FD41E78,0x81B0D1DF}} /* +3.1435978570e-01 */ , /*atan_b[11]*/ {{0x3FD37E35,0xF5735AA1}} /* +3.0457829447e-01 */,{{0xBC772D05,0x8D437AE9}} /* -2.0101859382e-17 */ , } ,{ /*a[12] */ {{0x3FD503DF,0x0DD40A5B}} /* +3.2836128569e-01 */ , /*b[12] : */ {{0x3FD5EB31,0x1EB6A659}} /* +3.4247997283e-01 */ , /*atan_b[12]*/ {{0x3FD51E0F,0xC9C20060}} /* +3.2995981887e-01 */,{{0xBC6C0F53,0x20BA7A7B}} /* -1.2169025414e-17 */ , } ,{ /*a[13] */ {{0x3FD6D488,0x3998DD14}} /* +3.5672193169e-01 */ , /*b[13] : */ {{0x3FD7BFFE,0xAAF865B1}} /* +3.7109343239e-01 */ , /*atan_b[13]*/ {{0x3FD6BDE9,0x9E0B9E67}} /* +3.5534134325e-01 */,{{0x3C797792,0x870D5E8E}} /* +2.2089170409e-17 */ , } ,{ /*a[14] */ {{0x3FD8ADAF,0x964ABFA5}} /* +3.8560094525e-01 */ , /*b[14] : */ {{0x3FD99DB7,0x00A6F44E}} /* +4.0025115074e-01 */ , /*atan_b[14]*/ {{0x3FD85DC3,0x72506BCA}} /* +3.8072286762e-01 */,{{0x3C720BD1,0x43A1CBA3}} /* +1.5652550322e-17 */ , } ,{ /*a[15] */ {{0x3FDA9031,0xE241114E}} /* +4.1505095573e-01 */ , /*b[15] : */ {{0x3FDB853E,0x327F0E90}} /* +4.3000750476e-01 */ , /*atan_b[15]*/ {{0x3FD9FD9D,0x4690A2C8}} /* +4.0610439197e-01 */,{{0xBC6A048E,0xEFB73034}} /* -1.1283424731e-17 */ , } ,{ /*a[16] */ {{0x3FDC7CFA,0xFB78B41D}} /* +4.4512819822e-01 */ , /*b[16] : */ {{0x3FDD7788,0x67BE333A}} /* +4.6042070514e-01 */ , /*atan_b[16]*/ {{0x3FDB9D77,0x1ACC80A6}} /* +4.3148591630e-01 */,{{0x3C6A9BD7,0xE8FB154D}} /* +1.1539711581e-17 */ , } ,{ /*a[17] */ {{0x3FDE7507,0xD82B9DC6}} /* +4.7589298354e-01 */ , /*b[17] : */ {{0x3FDF759B,0xF3B4AACC}} /* +4.9155329513e-01 */ , /*atan_b[17]*/ {{0x3FDD3D50,0xEF044589}} /* +4.5686744062e-01 */,{{0x3C575857,0x09E8652E}} /* +5.0621568797e-18 */ , } ,{ /*a[18] */ {{0x3FE03CB4,0x5FF4B2AB}} /* +5.0741022817e-01 */ , /*b[18] : */ {{0x3FE0C049,0xD9952BEF}} /* +5.2347271439e-01 */ , /*atan_b[18]*/ {{0x3FDEDD2A,0xC338344A}} /* +4.8224896492e-01 */,{{0x3C23C787,0x81513292}} /* +5.3612202011e-19 */ , } ,{ /*a[19] */ {{0x3FE145A1,0xE826E4EA}} /* +5.3975005476e-01 */ , /*b[19] : */ {{0x3FE1CCD0,0xDDD96DE0}} /* +5.5625193911e-01 */ , /*atan_b[19]*/ {{0x3FE03E82,0x4BB44923}} /* +5.0763048922e-01 */,{{0x3C8CAF01,0x49DF0A58}} /* +4.9758137561e-17 */ , } ,{ /*a[20] */ {{0x3FE255EB,0xED462BAC}} /* +5.7298847525e-01 */ , /*b[20] : */ {{0x3FE2E109,0x35B0819C}} /* +5.8997021185e-01 */ , /*atan_b[20]*/ {{0x3FE10E6F,0x35CAD39D}} /* +5.3301201350e-01 */,{{0x3C45DB33,0x0D1EB36B}} /* +2.3696591272e-18 */ , } ,{ /*a[21] */ {{0x3FE36E3F,0xD4CDD9AC}} /* +6.0720817149e-01 */ , /*b[21] : */ {{0x3FE3FDA7,0xF51235D9}} /* +6.2471387735e-01 */ , /*atan_b[21]*/ {{0x3FE1DE5C,0x1FDFDE84}} /* +5.5839353776e-01 */,{{0x3C86FBEF,0xD3921CA6}} /* +3.9871106783e-17 */ , } ,{ /*a[22] */ {{0x3FE48F5A,0xE1FB2991}} /* +6.4249939095e-01 */ , /*b[22] : */ {{0x3FE52373,0x18D0CCB0}} /* +6.6057734343e-01 */ , /*atan_b[22]*/ {{0x3FE2AE49,0x09F38FC9}} /* +5.8377506202e-01 */,{{0xBC84BBB5,0x058084C6}} /* -3.5966422408e-17 */ , } ,{ /*a[23] */ {{0x3FE5BA0C,0x5FE86E27}} /* +6.7896097881e-01 */ , /*b[23] : */ {{0x3FE65343,0xDA588D41}} /* +6.9766419073e-01 */ , /*atan_b[23]*/ {{0x3FE37E35,0xF4060E3D}} /* +6.0915658627e-01 */,{{0x3BF6235C,0xAE25B9B7}} /* +7.5006911959e-20 */ , } ,{ /*a[24] */ {{0x3FE6EF38,0x22C19A5D}} /* +7.1670157231e-01 */ , /*b[24] : */ {{0x3FE78E09,0x629002BC}} /* +7.3608845950e-01 */ , /*atan_b[24]*/ {{0x3FE44E22,0xDE17817F}} /* +6.3453811052e-01 */,{{0xBC85F46E,0x1A6D25E3}} /* -3.8085515717e-17 */ , } ,{ /*a[25] */ {{0x3FE82FD9,0x70F967BD}} /* +7.5584098878e-01 */ , /*b[25] : */ {{0x3FE8D4CB,0xEE8B9555}} /* +7.7597614852e-01 */ , /*atan_b[25]*/ {{0x3FE51E0F,0xC82811DC}} /* +6.5991963475e-01 */,{{0xBC81CCF7,0xFCB9720C}} /* -3.0879221028e-17 */ , } ,{ /*a[26] */ {{0x3FE97D06,0x69351A0D}} /* +7.9651184605e-01 */ , /*b[26] : */ {{0x3FEA28B0,0x7D0D616A}} /* +8.1746696877e-01 */ , /*atan_b[26]*/ {{0x3FE5EDFC,0xB237E838}} /* +6.8530115898e-01 */,{{0xBC833EA8,0xF8F29048}} /* -3.3384347049e-17 */ , } ,{ /*a[27] */ {{0x3FEAD7F3,0xFE730FCD}} /* +8.3886146257e-01 */ , /*b[27] : */ {{0x3FEB8AFD,0x21335E3D}} /* +8.6071640477e-01 */ , /*atan_b[27]*/ {{0x3FE6BDE9,0x9C472DF1}} /* +7.1068268321e-01 */,{{0x3C5E8127,0x80DED249}} /* +6.6146109909e-18 */ , } ,{ /*a[28] */ {{0x3FEC41FA,0xAA0A733E}} /* +8.8305409633e-01 */ , /*b[28] : */ {{0x3FECFD1E,0x1D9A7669}} /* +9.0589814932e-01 */ , /*atan_b[28]*/ {{0x3FE78DD6,0x86560CC5}} /* +7.3606420743e-01 */,{{0xBC7E962F,0x9396D511}} /* -2.6529701578e-17 */ , } ,{ /*a[29] */ {{0x3FEDBC9B,0xFAEEEADF}} /* +9.2927359591e-01 */ , /*b[29] : */ {{0x3FEE80AB,0xF41419E7}} /* +9.5320699379e-01 */ , /*atan_b[29]*/ {{0x3FE85DC3,0x7064AEB4}} /* +7.6144573166e-01 */,{{0x3C77C0FC,0x5225ACD1}} /* +2.0603180716e-17 */ , } ,{ /*a[30] */ {{0x3FEF4989,0x33AC790A}} /* +9.7772655575e-01 */ , /*b[30] : */ {{0x3FF00BB9,0x50BB2D02}} /* +1.0028622774e+00 */ , /*atan_b[30]*/ {{0x3FE92DB0,0x5A733DE9}} /* +7.8682725588e-01 */,{{0xBC6598C9,0xA318D041}} /* -9.3661305872e-18 */ , } ,{ /*a[31] */ {{0x3FF07555,0x9AC922B4}} /* +1.0286460921e+00 */ , /*b[31] : */ {{0x3FF0E1BD,0x25F4BC57}} /* +1.0551120265e+00 */ , /*atan_b[31]*/ {{0x3FE9FD9D,0x4481E499}} /* +8.1220878010e-01 */,{{0xBC82E89F,0x9464A40D}} /* -3.2801339756e-17 */ , } ,{ /*a[32] */ {{0x3FF15116,0x0440E8D3}} /* +1.0822963873e+00 */ , /*b[32] : */ {{0x3FF1C388,0xDEC8DA1A}} /* +1.1102379515e+00 */ , /*atan_b[32]*/ {{0x3FEACD8A,0x2E90CCEA}} /* +8.3759030433e-01 */,{{0x3C60B8DB,0xFE4AC33B}} /* +7.2520578222e-18 */ , } ,{ /*a[33] */ {{0x3FF23941,0x329D3DD8}} /* +1.1389781930e+00 */ , /*b[33] : */ {{0x3FF2B26D,0x8F9CF3AD}} /* +1.1685615168e+00 */ , /*atan_b[33]*/ {{0x3FEB9D77,0x18A020D8}} /* +8.6297182855e-01 */,{{0x3C714EA3,0x43DDC7EE}} /* +1.5011584621e-17 */ , } ,{ /*a[34] */ {{0x3FF32F3F,0xE2DB7094}} /* +1.1990355360e+00 */ , /*b[34] : */ {{0x3FF3AFED,0xC485093A}} /* +1.2304513623e+00 */ , /*atan_b[34]*/ {{0x3FEC6D64,0x02B00A17}} /* +8.8835335278e-01 */,{{0x3C5CF722,0xC1E56981}} /* +6.2808643065e-18 */ , } ,{ /*a[35] */ {{0x3FF434B0,0xD38A35D7}} /* +1.2628639472e+00 */ , /*b[35] : */ {{0x3FF4BDC7,0x16D89BC7}} /* +1.2963324444e+00 */ , /*atan_b[35]*/ {{0x3FED3D50,0xECC0B1F8}} /* +9.1373487702e-01 */,{{0x3C8FFD9A,0xC689AE1B}} /* +5.5494919315e-17 */ , } ,{ /*a[36] */ {{0x3FF54B73,0x6F41F96D}} /* +1.3309206339e+00 */ , /*b[36] : */ {{0x3FF5DDFE,0x11C53212}} /* +1.3666973776e+00 */ , /*atan_b[36]*/ {{0x3FEE0D3D,0xD6D24151}} /* +9.3911640126e-01 */,{{0xBC654F0F,0xC830B564}} /* -9.2412338910e-18 */ , } ,{ /*a[37] */ {{0x3FF675B5,0x165CA5E1}} /* +1.4037371515e+00 */ , /*b[37] : */ {{0x3FF712ED,0x13170C5B}} /* +1.4421206232e+00 */ , /*atan_b[37]*/ {{0x3FEEDD2A,0xC0E4E05B}} /* +9.6449792552e-01 */,{{0xBC8FEAC3,0xBF676FFE}} /* -5.5367254830e-17 */ , } ,{ /*a[38] */ {{0x3FF7B601,0xD0DEA3C6}} /* +1.4819353255e+00 */ , /*b[38] : */ {{0x3FF85F57,0x11FBEA40}} /* +1.5232763960e+00 */ , /*atan_b[38]*/ {{0x3FEFAD17,0xAAF8B69E}} /* +9.8987944978e-01 */,{{0x3C8B8DA3,0xE69F3AF7}} /* +4.7797325436e-17 */ , } ,{ /*a[39] */ {{0x3FF90F59,0x79506F51}} /* +1.5662474383e+00 */ , /*b[39] : */ {{0x3FF9C67F,0x8AF460DF}} /* +1.6109614780e+00 */ , /*atan_b[39]*/ {{0x3FF03E82,0x4A86F56B}} /* +1.0152609740e+00 */,{{0x3C8C4641,0xDE1DF40B}} /* +4.9048339280e-17 */ , } ,{ /*a[40] */ {{0x3FFA854A,0xD74CF791}} /* +1.6575420771e+00 */ , /*b[40] : */ {{0x3FFB4C49,0x4A696F14}} /* +1.7061245829e+00 */ , /*atan_b[40]*/ {{0x3FF0A678,0xBF92516C}} /* +1.0406424983e+00 */,{{0xBC9194FF,0x6A0966AF}} /* -6.0999893718e-17 */ , } ,{ /*a[41] */ {{0x3FFC1C16,0xB3972246}} /* +1.7568575874e+00 */ , /*b[41] : */ {{0x3FFCF55E,0x80F0B83E}} /* +1.8099045788e+00 */ , /*atan_b[41]*/ {{0x3FF10E6F,0x349E81BA}} /* +1.0660240226e+00 */,{{0x3C9C7D12,0x3CD05C13}} /* +9.8839546037e-17 */ , } ,{ /*a[42] */ {{0x3FFDD8DD,0xC6DB1831}} /* +1.8654458778e+00 */ , /*b[42] : */ {{0x3FFEC765,0x927D039C}} /* +1.9236808512e+00 */ , /*atan_b[42]*/ {{0x3FF17665,0xA9AB9836}} /* +1.0914055469e+00 */,{{0xBC924DFA,0x7B9C115B}} /* -6.3506850178e-17 */ , } ,{ /*a[43] */ {{0x3FFFC1DD,0xA4F6D032}} /* +1.9848305172e+00 */ , /*b[43] : */ {{0x400064A3,0xCDEC630C}} /* +2.0491405571e+00 */ , /*atan_b[43]*/ {{0x3FF1DE5C,0x1EB9A624}} /* +1.1167870712e+00 */,{{0xBC7002F6,0x595EC15D}} /* -1.3887824475e-17 */ , } ,{ /*a[44] */ {{0x4000EF61,0x56AEFAF2}} /* +2.1168848774e+00 */ , /*b[44] : */ {{0x400181C8,0x02FA3F97}} /* +2.1883697732e+00 */ , /*atan_b[44]*/ {{0x3FF24652,0x93C8BC28}} /* +1.1421685956e+00 */,{{0xBC8FE336,0xC61E8575}} /* -5.5316089441e-17 */ , } ,{ /*a[45] */ {{0x40021C8B,0xFD9A80C1}} /* +2.2639388860e+00 */ , /*b[45] : */ {{0x4002C078,0x188015C0}} /* +2.3439790644e+00 */ , /*atan_b[45]*/ {{0x3FF2AE49,0x08D8EA37}} /* +1.1675501199e+00 */,{{0xBC99C943,0x56281657}} /* -8.9463796524e-17 */ , } ,{ /*a[46] */ {{0x40036E71,0x7D67269C}} /* +2.4289274022e+00 */ , /*b[46] : */ {{0x4004277C,0x17EDBBF3}} /* +2.5192796583e+00 */ , /*atan_b[46]*/ {{0x3FF3163F,0x7DEA3F8C}} /* +1.1929316443e+00 */,{{0x3C9AD329,0x90EB721B}} /* +9.3067404471e-17 */ , } ,{ /*a[47] */ {{0x4004ECBF,0xF069F1E4}} /* +2.6156004698e+00 */ , /*b[47] : */ {{0x4005BF8F,0xA99113B9}} /* +2.7185357330e+00 */ , /*atan_b[47]*/ {{0x3FF37E35,0xF2FCCAA3}} /* +1.2183131687e+00 */,{{0xBC96C4D7,0x8B3674F4}} /* -7.8995539059e-17 */ , } ,{ /*a[48] */ {{0x4006A170,0x780169B7}} /* +2.8288277984e+00 */ , /*b[48] : */ {{0x40079423,0xEECFDE39}} /* +2.9473341615e+00 */ , /*atan_b[48]*/ {{0x3FF3E62C,0x68109926}} /* +1.2436946931e+00 */,{{0x3C9D395E,0x46562D7D}} /* +1.0139144652e-16 */ , } ,{ /*a[49] */ {{0x400899B4,0x319C3F02}} /* +3.0750507236e+00 */ , /*b[49] : */ {{0x4009B483,0x34491C9A}} /* +3.2131408772e+00 */ , /*atan_b[49]*/ {{0x3FF44E22,0xDD25B7F0}} /* +1.2690762175e+00 */,{{0xBC9AC408,0x96299AC9}} /* -9.2862370643e-17 */ , } ,{ /*a[50] */ {{0x400AE75E,0x05B0834A}} /* +3.3629723019e+00 */ , /*b[50] : */ {{0x400C3595,0x6451B6E9}} /* +3.5261638486e+00 */ , /*atan_b[50]*/ {{0x3FF4B619,0x523C32F8}} /* +1.2944577420e+00 */,{{0x3C98372D,0x9A6CF82B}} /* +8.4014530055e-17 */ , } ,{ /*a[51] */ {{0x400DA31D,0x739BD0E3}} /* +3.7046460182e+00 */ , /*b[51] : */ {{0x400F34B7,0x088B2A13}} /* +3.9007397335e+00 */ , /*atan_b[51]*/ {{0x3FF51E0F,0xC7541555}} /* +1.3198392664e+00 */,{{0xBC4DA0E1,0xD97CC177}} /* -3.2123225727e-18 */ , } ,{ /*a[52] */ {{0x40107813,0x1886BC57}} /* +4.1172603447e+00 */ , /*b[52] : */ {{0x40116E3D,0x8D819944}} /* +4.3576566801e+00 */ , /*atan_b[52]*/ {{0x3FF58606,0x3C6D692D}} /* +1.3452207909e+00 */,{{0xBC7DAB9D,0xD9D13C46}} /* -2.5734950076e-17 */ , } ,{ /*a[53] */ {{0x4012813A,0x8BCE2241}} /* +4.6261998982e+00 */ , /*b[53] : */ {{0x4013B685,0x9F0E4EBF}} /* +4.9282440999e+00 */ , /*atan_b[53]*/ {{0x3FF5EDFC,0xB18837B4}} /* +1.3706023154e+00 */,{{0xBC858200,0xBC854F71}} /* -3.7310126753e-17 */ , } ,{ /*a[54] */ {{0x40151516,0x4ACECE78}} /* +5.2705928506e+00 */ , /*b[54] : */ {{0x4016A5E9,0xF3CD0189}} /* +5.6620252699e+00 */ , /*atan_b[54]*/ {{0x3FF655F3,0x26A48924}} /* +1.3959838399e+00 */,{{0xBC95DCD4,0x0EF07703}} /* -7.5851168241e-17 */ , } ,{ /*a[55] */ {{0x401874CE,0x9526FAB9}} /* +6.1140693002e+00 */ , /*b[55] : */ {{0x401A9194,0xBA057809}} /* +6.6421689096e+00 */ , /*atan_b[55]*/ {{0x3FF6BDE9,0x9BC264B7}} /* +1.4213653645e+00 */,{{0x3C839FB7,0x555821B5}} /* +3.4042024747e-17 */ , } ,{ /*a[56] */ {{0x401D11EB,0xE094C913}} /* +7.2675013629e+00 */ , /*b[56] : */ {{0x40200A31,0xA01EFACA}} /* +8.0199098623e+00 */ , /*atan_b[56]*/ {{0x3FF725E0,0x10E1D0A5}} /* +1.4467468891e+00 */,{{0x3C86B63B,0x56DADB03}} /* +3.9398767140e-17 */ , } ,{ /*a[57] */ {{0x4021E2BC,0x220DFA19}} /* +8.9428415911e+00 */ , /*b[57] : */ {{0x40243445,0xFBA72898}} /* +1.0102096428e+01 */ , /*atan_b[57]*/ {{0x3FF78DD6,0x8602D21D}} /* +1.4721284137e+00 */,{{0xBC9FD7D6,0x4D2EA6E0}} /* -1.1047799388e-16 */ , } ,{ /*a[58] */ {{0x40273463,0xD0337C49}} /* +1.1602324015e+01 */ , /*b[58] : */ {{0x402B3DC7,0x4A4A5A1D}} /* +1.3620661089e+01 */ , /*atan_b[58]*/ {{0x3FF7F5CC,0xFB256D40}} /* +1.4975099383e+00 */,{{0x3C954E9E,0xA28CF77C}} /* +7.3923881174e-17 */ , } ,{ /*a[59] */ {{0x40307B8E,0x26350916}} /* +1.6482637775e+01 */ , /*b[59] : */ {{0x4034DBD6,0x24D415BF}} /* +2.0858736326e+01 */ , /*atan_b[59]*/ {{0x3FF85DC3,0x7049A526}} /* +1.5228914629e+00 */,{{0xBC8424E5,0xE9374500}} /* -3.4944500702e-17 */ , } ,{ /*a[60] */ {{0x403C62CF,0x497BF2F2}} /* +2.8385975449e+01 */ , /*b[60] : */ {{0x40463208,0x6C3EC43C}} /* +4.4390882044e+01 */ , /*atan_b[60]*/ {{0x3FF8C5B9,0xE56F7BD2}} /* +1.5482729876e+00 */,{{0xBC81D57A,0x2F7EC153}} /* -3.0936877458e-17 */ , } ,{ /*a[61] */ {{0x40596CC3,0xFA9E0EF4}} /* +1.0169946161e+02 */ , /*b[61] : */ {{0x4054B2C4,0x7BFF8329}} /* +8.2793242454e+01 */ , /*atan_b[61]*/ {{0x3FF8F082,0xF333CBBA}} /* +1.5587186337e+00 */,{{0x3C952577,0x3909BC3A}} /* +7.3366141099e-17 */ , } , }; #else /* limits of the intervals [a[i],b[i]] */ static db_number const arctan_table[62][4] = { { /*a[0] */ {{0xBCCE533D,0x3F89FDF8}} /* +1.2691443693e-02 */ , /*b[0] : */ {{0x27760007,0x3F99FF0B}} /* +2.5386976512e-02 */ , /*atan_b[0]*/ {{0x4969F96C,0x3F99FD9D}} /* +2.5381524664e-02 */,{{0x750685EA,0xBC301997}} /* -8.7278097631e-19 */ , } ,{ /*a[1] */ {{0x90CEBC31,0x3FA3809F}} /* +3.8090692927e-02 */ , /*b[1] : */ {{0xE3547CC2,0x3FAA0355}} /* +5.0806697846e-02 */ , /*atan_b[1]*/ {{0x4936262D,0x3FA9FD9D}} /* +5.0763049304e-02 */,{{0x3A2D0F59,0xBC4C1F96}} /* -3.0491436238e-18 */ , } ,{ /*a[2] */ {{0x68FBA526,0x3FB04419}} /* +6.3539112216e-02 */ , /*b[2] : */ {{0xABF7BFB9,0x3FB387E0}} /* +7.6292078003e-02 */ , /*atan_b[2]*/ {{0xF6C1E06C,0x3FB37E35}} /* +7.6144573921e-02 */,{{0x8378E024,0xBC556710}} /* -4.6409481568e-18 */ , } ,{ /*a[3] */ {{0xABCDFA25,0x3FB6CD46}} /* +8.9069764084e-02 */ , /*b[3] : */ {{0xE265B8AB,0x3FBA1491}} /* +1.0187637117e-01 */ , /*atan_b[3]*/ {{0x48CF1996,0x3FB9FD9D}} /* +1.0152609851e-01 */,{{0xB73BED3C,0xBC4360DC}} /* -2.1010068528e-18 */ , } ,{ /*a[4] */ {{0x6D2EA546,0x3FBD5E09}} /* +1.1471613803e-01 */ , /*b[4] : */ {{0x9124D46B,0x3FC054FA}} /* +1.2759334647e-01 */ , /*atan_b[4]*/ {{0x4D618156,0x3FC03E82}} /* +1.2690762308e-01 */,{{0x49A86344,0x3C62604E}} /* +7.9694040325e-18 */ , } ,{ /*a[5] */ {{0xD691E891,0x3FC1FC4E}} /* +1.4051232793e-01 */ , /*b[5] : */ {{0x51F57043,0x3FC3A526}} /* +1.5347746851e-01 */ , /*atan_b[5]*/ {{0xF64EF83E,0x3FC37E35}} /* +1.5228914763e-01 */,{{0xB4A55EA6,0x3C5F2B13}} /* +6.7585410867e-18 */ , } ,{ /*a[6] */ {{0x531F610B,0x3FC54FA6}} /* +1.6649321612e-01 */ , /*b[6] : */ {{0xB99F2601,0x3FC6FBF4}} /* +1.7956408561e-01 */ , /*atan_b[6]*/ {{0x9F302425,0x3FC6BDE9}} /* +1.7767067216e-01 */,{{0xC4D330CE,0xBC23B62A}} /* -5.3428372026e-19 */ , } ,{ /*a[7] */ {{0x0550EAF1,0x3FC8AA38}} /* +1.9269466648e-01 */ , /*b[7] : */ {{0x61D9D63D,0x3FCA5A97}} /* +2.0588962820e-01 */ , /*atan_b[7]*/ {{0x48053FC8,0x3FC9FD9D}} /* +2.0305219666e-01 */,{{0x98474AF1,0xBC67A12C}} /* -1.0247699700e-17 */ , } ,{ /*a[8] */ {{0xB8975BD9,0x3FCC0D3A}} /* +2.1915372861e-01 */ , /*b[8] : */ {{0xBCBF6ABC,0x3FCDC24A}} /* +2.3249181954e-01 */ , /*atan_b[8]*/ {{0xF0CE8DD9,0x3FCD3D50}} /* +2.2843372114e-01 */,{{0x3A31D353,0x3C6EF257}} /* +1.3420967238e-17 */ , } ,{ /*a[9] */ {{0xFEE46885,0x3FCF79F0}} /* +2.4590885588e-01 */ , /*b[9] : */ {{0xFCF66B85,0x3FD09A2B}} /* +2.5940990165e-01 */ , /*atan_b[9]*/ {{0x4CC62C6B,0x3FD03E82}} /* +2.5381524560e-01 */,{{0x95C6E482,0x3C5DA594}} /* +6.4286246635e-18 */ , } ,{ /*a[10] */ {{0x943274CA,0x3FD178D5}} /* +2.7300013993e-01 */ , /*b[10] : */ {{0x8943E603,0x3FD2590B}} /* +2.8668487935e-01 */ , /*atan_b[10]*/ {{0x211F7969,0x3FD1DE5C}} /* +2.7919677004e-01 */,{{0x0B01EF44,0x3C3C4E87}} /* +1.5345118889e-18 */ , } ,{ /*a[11] */ {{0xB2CFB5F7,0x3FD33AE4}} /* +3.0046956503e-01 */ , /*b[11] : */ {{0x81B0D1DF,0x3FD41E78}} /* +3.1435978570e-01 */ , /*atan_b[11]*/ {{0xF5735AA1,0x3FD37E35}} /* +3.0457829447e-01 */,{{0x8D437AE9,0xBC772D05}} /* -2.0101859382e-17 */ , } ,{ /*a[12] */ {{0x0DD40A5B,0x3FD503DF}} /* +3.2836128569e-01 */ , /*b[12] : */ {{0x1EB6A659,0x3FD5EB31}} /* +3.4247997283e-01 */ , /*atan_b[12]*/ {{0xC9C20060,0x3FD51E0F}} /* +3.2995981887e-01 */,{{0x20BA7A7B,0xBC6C0F53}} /* -1.2169025414e-17 */ , } ,{ /*a[13] */ {{0x3998DD14,0x3FD6D488}} /* +3.5672193169e-01 */ , /*b[13] : */ {{0xAAF865B1,0x3FD7BFFE}} /* +3.7109343239e-01 */ , /*atan_b[13]*/ {{0x9E0B9E67,0x3FD6BDE9}} /* +3.5534134325e-01 */,{{0x870D5E8E,0x3C797792}} /* +2.2089170409e-17 */ , } ,{ /*a[14] */ {{0x964ABFA5,0x3FD8ADAF}} /* +3.8560094525e-01 */ , /*b[14] : */ {{0x00A6F44E,0x3FD99DB7}} /* +4.0025115074e-01 */ , /*atan_b[14]*/ {{0x72506BCA,0x3FD85DC3}} /* +3.8072286762e-01 */,{{0x43A1CBA3,0x3C720BD1}} /* +1.5652550322e-17 */ , } ,{ /*a[15] */ {{0xE241114E,0x3FDA9031}} /* +4.1505095573e-01 */ , /*b[15] : */ {{0x327F0E90,0x3FDB853E}} /* +4.3000750476e-01 */ , /*atan_b[15]*/ {{0x4690A2C8,0x3FD9FD9D}} /* +4.0610439197e-01 */,{{0xEFB73034,0xBC6A048E}} /* -1.1283424731e-17 */ , } ,{ /*a[16] */ {{0xFB78B41D,0x3FDC7CFA}} /* +4.4512819822e-01 */ , /*b[16] : */ {{0x67BE333A,0x3FDD7788}} /* +4.6042070514e-01 */ , /*atan_b[16]*/ {{0x1ACC80A6,0x3FDB9D77}} /* +4.3148591630e-01 */,{{0xE8FB154D,0x3C6A9BD7}} /* +1.1539711581e-17 */ , } ,{ /*a[17] */ {{0xD82B9DC6,0x3FDE7507}} /* +4.7589298354e-01 */ , /*b[17] : */ {{0xF3B4AACC,0x3FDF759B}} /* +4.9155329513e-01 */ , /*atan_b[17]*/ {{0xEF044589,0x3FDD3D50}} /* +4.5686744062e-01 */,{{0x09E8652E,0x3C575857}} /* +5.0621568797e-18 */ , } ,{ /*a[18] */ {{0x5FF4B2AB,0x3FE03CB4}} /* +5.0741022817e-01 */ , /*b[18] : */ {{0xD9952BEF,0x3FE0C049}} /* +5.2347271439e-01 */ , /*atan_b[18]*/ {{0xC338344A,0x3FDEDD2A}} /* +4.8224896492e-01 */,{{0x81513292,0x3C23C787}} /* +5.3612202011e-19 */ , } ,{ /*a[19] */ {{0xE826E4EA,0x3FE145A1}} /* +5.3975005476e-01 */ , /*b[19] : */ {{0xDDD96DE0,0x3FE1CCD0}} /* +5.5625193911e-01 */ , /*atan_b[19]*/ {{0x4BB44923,0x3FE03E82}} /* +5.0763048922e-01 */,{{0x49DF0A58,0x3C8CAF01}} /* +4.9758137561e-17 */ , } ,{ /*a[20] */ {{0xED462BAC,0x3FE255EB}} /* +5.7298847525e-01 */ , /*b[20] : */ {{0x35B0819C,0x3FE2E109}} /* +5.8997021185e-01 */ , /*atan_b[20]*/ {{0x35CAD39D,0x3FE10E6F}} /* +5.3301201350e-01 */,{{0x0D1EB36B,0x3C45DB33}} /* +2.3696591272e-18 */ , } ,{ /*a[21] */ {{0xD4CDD9AC,0x3FE36E3F}} /* +6.0720817149e-01 */ , /*b[21] : */ {{0xF51235D9,0x3FE3FDA7}} /* +6.2471387735e-01 */ , /*atan_b[21]*/ {{0x1FDFDE84,0x3FE1DE5C}} /* +5.5839353776e-01 */,{{0xD3921CA6,0x3C86FBEF}} /* +3.9871106783e-17 */ , } ,{ /*a[22] */ {{0xE1FB2991,0x3FE48F5A}} /* +6.4249939095e-01 */ , /*b[22] : */ {{0x18D0CCB0,0x3FE52373}} /* +6.6057734343e-01 */ , /*atan_b[22]*/ {{0x09F38FC9,0x3FE2AE49}} /* +5.8377506202e-01 */,{{0x058084C6,0xBC84BBB5}} /* -3.5966422408e-17 */ , } ,{ /*a[23] */ {{0x5FE86E27,0x3FE5BA0C}} /* +6.7896097881e-01 */ , /*b[23] : */ {{0xDA588D41,0x3FE65343}} /* +6.9766419073e-01 */ , /*atan_b[23]*/ {{0xF4060E3D,0x3FE37E35}} /* +6.0915658627e-01 */,{{0xAE25B9B7,0x3BF6235C}} /* +7.5006911959e-20 */ , } ,{ /*a[24] */ {{0x22C19A5D,0x3FE6EF38}} /* +7.1670157231e-01 */ , /*b[24] : */ {{0x629002BC,0x3FE78E09}} /* +7.3608845950e-01 */ , /*atan_b[24]*/ {{0xDE17817F,0x3FE44E22}} /* +6.3453811052e-01 */,{{0x1A6D25E3,0xBC85F46E}} /* -3.8085515717e-17 */ , } ,{ /*a[25] */ {{0x70F967BD,0x3FE82FD9}} /* +7.5584098878e-01 */ , /*b[25] : */ {{0xEE8B9555,0x3FE8D4CB}} /* +7.7597614852e-01 */ , /*atan_b[25]*/ {{0xC82811DC,0x3FE51E0F}} /* +6.5991963475e-01 */,{{0xFCB9720C,0xBC81CCF7}} /* -3.0879221028e-17 */ , } ,{ /*a[26] */ {{0x69351A0D,0x3FE97D06}} /* +7.9651184605e-01 */ , /*b[26] : */ {{0x7D0D616A,0x3FEA28B0}} /* +8.1746696877e-01 */ , /*atan_b[26]*/ {{0xB237E838,0x3FE5EDFC}} /* +6.8530115898e-01 */,{{0xF8F29048,0xBC833EA8}} /* -3.3384347049e-17 */ , } ,{ /*a[27] */ {{0xFE730FCD,0x3FEAD7F3}} /* +8.3886146257e-01 */ , /*b[27] : */ {{0x21335E3D,0x3FEB8AFD}} /* +8.6071640477e-01 */ , /*atan_b[27]*/ {{0x9C472DF1,0x3FE6BDE9}} /* +7.1068268321e-01 */,{{0x80DED249,0x3C5E8127}} /* +6.6146109909e-18 */ , } ,{ /*a[28] */ {{0xAA0A733E,0x3FEC41FA}} /* +8.8305409633e-01 */ , /*b[28] : */ {{0x1D9A7669,0x3FECFD1E}} /* +9.0589814932e-01 */ , /*atan_b[28]*/ {{0x86560CC5,0x3FE78DD6}} /* +7.3606420743e-01 */,{{0x9396D511,0xBC7E962F}} /* -2.6529701578e-17 */ , } ,{ /*a[29] */ {{0xFAEEEADF,0x3FEDBC9B}} /* +9.2927359591e-01 */ , /*b[29] : */ {{0xF41419E7,0x3FEE80AB}} /* +9.5320699379e-01 */ , /*atan_b[29]*/ {{0x7064AEB4,0x3FE85DC3}} /* +7.6144573166e-01 */,{{0x5225ACD1,0x3C77C0FC}} /* +2.0603180716e-17 */ , } ,{ /*a[30] */ {{0x33AC790A,0x3FEF4989}} /* +9.7772655575e-01 */ , /*b[30] : */ {{0x50BB2D02,0x3FF00BB9}} /* +1.0028622774e+00 */ , /*atan_b[30]*/ {{0x5A733DE9,0x3FE92DB0}} /* +7.8682725588e-01 */,{{0xA318D041,0xBC6598C9}} /* -9.3661305872e-18 */ , } ,{ /*a[31] */ {{0x9AC922B4,0x3FF07555}} /* +1.0286460921e+00 */ , /*b[31] : */ {{0x25F4BC57,0x3FF0E1BD}} /* +1.0551120265e+00 */ , /*atan_b[31]*/ {{0x4481E499,0x3FE9FD9D}} /* +8.1220878010e-01 */,{{0x9464A40D,0xBC82E89F}} /* -3.2801339756e-17 */ , } ,{ /*a[32] */ {{0x0440E8D3,0x3FF15116}} /* +1.0822963873e+00 */ , /*b[32] : */ {{0xDEC8DA1A,0x3FF1C388}} /* +1.1102379515e+00 */ , /*atan_b[32]*/ {{0x2E90CCEA,0x3FEACD8A}} /* +8.3759030433e-01 */,{{0xFE4AC33B,0x3C60B8DB}} /* +7.2520578222e-18 */ , } ,{ /*a[33] */ {{0x329D3DD8,0x3FF23941}} /* +1.1389781930e+00 */ , /*b[33] : */ {{0x8F9CF3AD,0x3FF2B26D}} /* +1.1685615168e+00 */ , /*atan_b[33]*/ {{0x18A020D8,0x3FEB9D77}} /* +8.6297182855e-01 */,{{0x43DDC7EE,0x3C714EA3}} /* +1.5011584621e-17 */ , } ,{ /*a[34] */ {{0xE2DB7094,0x3FF32F3F}} /* +1.1990355360e+00 */ , /*b[34] : */ {{0xC485093A,0x3FF3AFED}} /* +1.2304513623e+00 */ , /*atan_b[34]*/ {{0x02B00A17,0x3FEC6D64}} /* +8.8835335278e-01 */,{{0xC1E56981,0x3C5CF722}} /* +6.2808643065e-18 */ , } ,{ /*a[35] */ {{0xD38A35D7,0x3FF434B0}} /* +1.2628639472e+00 */ , /*b[35] : */ {{0x16D89BC7,0x3FF4BDC7}} /* +1.2963324444e+00 */ , /*atan_b[35]*/ {{0xECC0B1F8,0x3FED3D50}} /* +9.1373487702e-01 */,{{0xC689AE1B,0x3C8FFD9A}} /* +5.5494919315e-17 */ , } ,{ /*a[36] */ {{0x6F41F96D,0x3FF54B73}} /* +1.3309206339e+00 */ , /*b[36] : */ {{0x11C53212,0x3FF5DDFE}} /* +1.3666973776e+00 */ , /*atan_b[36]*/ {{0xD6D24151,0x3FEE0D3D}} /* +9.3911640126e-01 */,{{0xC830B564,0xBC654F0F}} /* -9.2412338910e-18 */ , } ,{ /*a[37] */ {{0x165CA5E1,0x3FF675B5}} /* +1.4037371515e+00 */ , /*b[37] : */ {{0x13170C5B,0x3FF712ED}} /* +1.4421206232e+00 */ , /*atan_b[37]*/ {{0xC0E4E05B,0x3FEEDD2A}} /* +9.6449792552e-01 */,{{0xBF676FFE,0xBC8FEAC3}} /* -5.5367254830e-17 */ , } ,{ /*a[38] */ {{0xD0DEA3C6,0x3FF7B601}} /* +1.4819353255e+00 */ , /*b[38] : */ {{0x11FBEA40,0x3FF85F57}} /* +1.5232763960e+00 */ , /*atan_b[38]*/ {{0xAAF8B69E,0x3FEFAD17}} /* +9.8987944978e-01 */,{{0xE69F3AF7,0x3C8B8DA3}} /* +4.7797325436e-17 */ , } ,{ /*a[39] */ {{0x79506F51,0x3FF90F59}} /* +1.5662474383e+00 */ , /*b[39] : */ {{0x8AF460DF,0x3FF9C67F}} /* +1.6109614780e+00 */ , /*atan_b[39]*/ {{0x4A86F56B,0x3FF03E82}} /* +1.0152609740e+00 */,{{0xDE1DF40B,0x3C8C4641}} /* +4.9048339280e-17 */ , } ,{ /*a[40] */ {{0xD74CF791,0x3FFA854A}} /* +1.6575420771e+00 */ , /*b[40] : */ {{0x4A696F14,0x3FFB4C49}} /* +1.7061245829e+00 */ , /*atan_b[40]*/ {{0xBF92516C,0x3FF0A678}} /* +1.0406424983e+00 */,{{0x6A0966AF,0xBC9194FF}} /* -6.0999893718e-17 */ , } ,{ /*a[41] */ {{0xB3972246,0x3FFC1C16}} /* +1.7568575874e+00 */ , /*b[41] : */ {{0x80F0B83E,0x3FFCF55E}} /* +1.8099045788e+00 */ , /*atan_b[41]*/ {{0x349E81BA,0x3FF10E6F}} /* +1.0660240226e+00 */,{{0x3CD05C13,0x3C9C7D12}} /* +9.8839546037e-17 */ , } ,{ /*a[42] */ {{0xC6DB1831,0x3FFDD8DD}} /* +1.8654458778e+00 */ , /*b[42] : */ {{0x927D039C,0x3FFEC765}} /* +1.9236808512e+00 */ , /*atan_b[42]*/ {{0xA9AB9836,0x3FF17665}} /* +1.0914055469e+00 */,{{0x7B9C115B,0xBC924DFA}} /* -6.3506850178e-17 */ , } ,{ /*a[43] */ {{0xA4F6D032,0x3FFFC1DD}} /* +1.9848305172e+00 */ , /*b[43] : */ {{0xCDEC630C,0x400064A3}} /* +2.0491405571e+00 */ , /*atan_b[43]*/ {{0x1EB9A624,0x3FF1DE5C}} /* +1.1167870712e+00 */,{{0x595EC15D,0xBC7002F6}} /* -1.3887824475e-17 */ , } ,{ /*a[44] */ {{0x56AEFAF2,0x4000EF61}} /* +2.1168848774e+00 */ , /*b[44] : */ {{0x02FA3F97,0x400181C8}} /* +2.1883697732e+00 */ , /*atan_b[44]*/ {{0x93C8BC28,0x3FF24652}} /* +1.1421685956e+00 */,{{0xC61E8575,0xBC8FE336}} /* -5.5316089441e-17 */ , } ,{ /*a[45] */ {{0xFD9A80C1,0x40021C8B}} /* +2.2639388860e+00 */ , /*b[45] : */ {{0x188015C0,0x4002C078}} /* +2.3439790644e+00 */ , /*atan_b[45]*/ {{0x08D8EA37,0x3FF2AE49}} /* +1.1675501199e+00 */,{{0x56281657,0xBC99C943}} /* -8.9463796524e-17 */ , } ,{ /*a[46] */ {{0x7D67269C,0x40036E71}} /* +2.4289274022e+00 */ , /*b[46] : */ {{0x17EDBBF3,0x4004277C}} /* +2.5192796583e+00 */ , /*atan_b[46]*/ {{0x7DEA3F8C,0x3FF3163F}} /* +1.1929316443e+00 */,{{0x90EB721B,0x3C9AD329}} /* +9.3067404471e-17 */ , } ,{ /*a[47] */ {{0xF069F1E4,0x4004ECBF}} /* +2.6156004698e+00 */ , /*b[47] : */ {{0xA99113B9,0x4005BF8F}} /* +2.7185357330e+00 */ , /*atan_b[47]*/ {{0xF2FCCAA3,0x3FF37E35}} /* +1.2183131687e+00 */,{{0x8B3674F4,0xBC96C4D7}} /* -7.8995539059e-17 */ , } ,{ /*a[48] */ {{0x780169B7,0x4006A170}} /* +2.8288277984e+00 */ , /*b[48] : */ {{0xEECFDE39,0x40079423}} /* +2.9473341615e+00 */ , /*atan_b[48]*/ {{0x68109926,0x3FF3E62C}} /* +1.2436946931e+00 */,{{0x46562D7D,0x3C9D395E}} /* +1.0139144652e-16 */ , } ,{ /*a[49] */ {{0x319C3F02,0x400899B4}} /* +3.0750507236e+00 */ , /*b[49] : */ {{0x34491C9A,0x4009B483}} /* +3.2131408772e+00 */ , /*atan_b[49]*/ {{0xDD25B7F0,0x3FF44E22}} /* +1.2690762175e+00 */,{{0x96299AC9,0xBC9AC408}} /* -9.2862370643e-17 */ , } ,{ /*a[50] */ {{0x05B0834A,0x400AE75E}} /* +3.3629723019e+00 */ , /*b[50] : */ {{0x6451B6E9,0x400C3595}} /* +3.5261638486e+00 */ , /*atan_b[50]*/ {{0x523C32F8,0x3FF4B619}} /* +1.2944577420e+00 */,{{0x9A6CF82B,0x3C98372D}} /* +8.4014530055e-17 */ , } ,{ /*a[51] */ {{0x739BD0E3,0x400DA31D}} /* +3.7046460182e+00 */ , /*b[51] : */ {{0x088B2A13,0x400F34B7}} /* +3.9007397335e+00 */ , /*atan_b[51]*/ {{0xC7541555,0x3FF51E0F}} /* +1.3198392664e+00 */,{{0xD97CC177,0xBC4DA0E1}} /* -3.2123225727e-18 */ , } ,{ /*a[52] */ {{0x1886BC57,0x40107813}} /* +4.1172603447e+00 */ , /*b[52] : */ {{0x8D819944,0x40116E3D}} /* +4.3576566801e+00 */ , /*atan_b[52]*/ {{0x3C6D692D,0x3FF58606}} /* +1.3452207909e+00 */,{{0xD9D13C46,0xBC7DAB9D}} /* -2.5734950076e-17 */ , } ,{ /*a[53] */ {{0x8BCE2241,0x4012813A}} /* +4.6261998982e+00 */ , /*b[53] : */ {{0x9F0E4EBF,0x4013B685}} /* +4.9282440999e+00 */ , /*atan_b[53]*/ {{0xB18837B4,0x3FF5EDFC}} /* +1.3706023154e+00 */,{{0xBC854F71,0xBC858200}} /* -3.7310126753e-17 */ , } ,{ /*a[54] */ {{0x4ACECE78,0x40151516}} /* +5.2705928506e+00 */ , /*b[54] : */ {{0xF3CD0189,0x4016A5E9}} /* +5.6620252699e+00 */ , /*atan_b[54]*/ {{0x26A48924,0x3FF655F3}} /* +1.3959838399e+00 */,{{0x0EF07703,0xBC95DCD4}} /* -7.5851168241e-17 */ , } ,{ /*a[55] */ {{0x9526FAB9,0x401874CE}} /* +6.1140693002e+00 */ , /*b[55] : */ {{0xBA057809,0x401A9194}} /* +6.6421689096e+00 */ , /*atan_b[55]*/ {{0x9BC264B7,0x3FF6BDE9}} /* +1.4213653645e+00 */,{{0x555821B5,0x3C839FB7}} /* +3.4042024747e-17 */ , } ,{ /*a[56] */ {{0xE094C913,0x401D11EB}} /* +7.2675013629e+00 */ , /*b[56] : */ {{0xA01EFACA,0x40200A31}} /* +8.0199098623e+00 */ , /*atan_b[56]*/ {{0x10E1D0A5,0x3FF725E0}} /* +1.4467468891e+00 */,{{0x56DADB03,0x3C86B63B}} /* +3.9398767140e-17 */ , } ,{ /*a[57] */ {{0x220DFA19,0x4021E2BC}} /* +8.9428415911e+00 */ , /*b[57] : */ {{0xFBA72898,0x40243445}} /* +1.0102096428e+01 */ , /*atan_b[57]*/ {{0x8602D21D,0x3FF78DD6}} /* +1.4721284137e+00 */,{{0x4D2EA6E0,0xBC9FD7D6}} /* -1.1047799388e-16 */ , } ,{ /*a[58] */ {{0xD0337C49,0x40273463}} /* +1.1602324015e+01 */ , /*b[58] : */ {{0x4A4A5A1D,0x402B3DC7}} /* +1.3620661089e+01 */ , /*atan_b[58]*/ {{0xFB256D40,0x3FF7F5CC}} /* +1.4975099383e+00 */,{{0xA28CF77C,0x3C954E9E}} /* +7.3923881174e-17 */ , } ,{ /*a[59] */ {{0x26350916,0x40307B8E}} /* +1.6482637775e+01 */ , /*b[59] : */ {{0x24D415BF,0x4034DBD6}} /* +2.0858736326e+01 */ , /*atan_b[59]*/ {{0x7049A526,0x3FF85DC3}} /* +1.5228914629e+00 */,{{0xE9374500,0xBC8424E5}} /* -3.4944500702e-17 */ , } ,{ /*a[60] */ {{0x497BF2F2,0x403C62CF}} /* +2.8385975449e+01 */ , /*b[60] : */ {{0x6C3EC43C,0x40463208}} /* +4.4390882044e+01 */ , /*atan_b[60]*/ {{0xE56F7BD2,0x3FF8C5B9}} /* +1.5482729876e+00 */,{{0x2F7EC153,0xBC81D57A}} /* -3.0936877458e-17 */ , } ,{ /*a[61] */ {{0xFA9E0EF4,0x40596CC3}} /* +1.0169946161e+02 */ , /*b[61] : */ {{0x7BFF8329,0x4054B2C4}} /* +8.2793242454e+01 */ , /*atan_b[61]*/ {{0xF333CBBA,0x3FF8F082}} /* +1.5587186337e+00 */,{{0x3909BC3A,0x3C952577}} /* +7.3366141099e-17 */ , } , }; #endif #endif /* def _ATAN_FAST_H */ interval-3.2.0/src/crlibm/configure.ac0000644000000000000000000003026513316017127016022 0ustar 00000000000000dnl Process this file with autoconf to produce a configure script. # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA AC_INIT(crlibm, 1.0beta5) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([crlibm_config.h]) AC_SUBST(VERSION) ISODATE=`date +%Y-%m-%d` AC_SUBST(ISODATE) dnl Silence warning: ar: 'u' modifier ignored since 'D' is the default AC_SUBST(ARFLAGS, [cr]) dnl Check for system information AC_CANONICAL_HOST case $host_os in hpux*) AC_DEFINE_UNQUOTED(CRLIBM_TYPEOS_HPUX,1,[OS type]);; *cygwin* | *mingw* | *uwin* | *djgpp | *emx*) AC_DEFINE_UNQUOTED(CRLIBM_TYPEOS_CYGWIN,1,[OS type]);; freebsd*|netbsd*|darwin*) AC_DEFINE_UNQUOTED(CRLIBM_TYPEOS_BSD,1,[OS type]);; esac; case $host_cpu in alpha) AC_DEFINE_UNQUOTED(CRLIBM_TYPECPU_ALPHA,1,[Processor type]) ;; sparc) AC_DEFINE_UNQUOTED(CRLIBM_TYPECPU_SPARC,1,[Processor type]) ;; powerpc*) AC_DEFINE_UNQUOTED(CRLIBM_TYPECPU_POWERPC,1,[Processor type]);; i*86|k6|k7|pentium*|athlon*) AC_DEFINE_UNQUOTED(CRLIBM_TYPECPU_X86,1,[Processor type]) has_ia32_de=true;; x86_64|amd64) AC_DEFINE_UNQUOTED(CRLIBM_TYPECPU_AMD64,1,[Processor type]) has_ia32_de=true;; ia64) AC_DEFINE_UNQUOTED(CRLIBM_TYPECPU_ITANIUM,1,[Processor type]) has_ia64_de=true;; esac; AC_CONFIG_SRCDIR([crlibm.h]) AC_PROG_MAKE_SET dnl Check for compiler AC_PROG_CC(gcc icc cc) # Try to set compiler flags to get floating point arithmetics # to work. This is an old heritage and should become useless within 30 years # if test "${GCC}" != "yes" ; then case "${build}" in *-*-hpux* ) AM_CFLAGS="${AM_CFLAGS} -Wp,-H30000" ;; *-dec-osf* ) AM_CFLAGS="${AM_CFLAGS} -ieee" ;; *-apple-darwin* ) AM_CFLAGS="${AM_CFLAGS} -fno-common" ;; *-sgi-irix* ) ;; esac else case "${CC}" in *icc* ) # -Wall causes relocation errors with icc. AM_CFLAGS="${AM_CFLAGS} -wd269" ;; * ) case "${build}" in *-dec-osf* ) AM_CFLAGS="${AM_CFLAGS} -mieee -Wall" ;; *alpha*-*-linux* ) AM_CFLAGS="${AM_CFLAGS} -mieee -Wall" ;; *alpha*-*-freebsd* ) AM_CFLAGS="${AM_CFLAGS} -mieee -Wall" ;; *-apple-darwin* ) AM_CFLAGS="${AM_CFLAGS} -fno-common -Wall" ;; * ) AM_CFLAGS="${AM_CFLAGS} -Wall" ;; esac ;; esac fi dnl send this information to automake to set up compilation flags dnl (add your compiler here) AM_CONDITIONAL(COMPILER_ICC, test x$CC = xicc) dnl Checks for programs. AC_PROG_INSTALL AC_PROG_RANLIB AC_PROG_LN_S dnl Checks for standard C stuff. AC_HEADER_STDC AC_C_CONST AC_C_INLINE AC_CHECK_FUNCS([sqrt]) AC_CHECK_HEADERS([fenv.h]) AC_CHECK_HEADERS([float.h]) AC_CHECK_HEADER(fpu_control.h, has_fpu_control=yes, has_fpu_control=no) dnl Send this information to automake AM_CONDITIONAL(HAS_FPU_CONTROL, test x$has_fpu_control = xyes) if test x$has_fpu_control = xyes ; then AC_DEFINE_UNQUOTED(CRLIBM_HAS_FPU_CONTROL,1,[architecture- and system-specific FPU control header file]) fi dnl adds -lm AC_CHECK_LIB([m], [log]) dnl Other checks AC_C_BIGENDIAN(,,) dnl defines WORDS_BIGENDIAN, or not AC_C_LONG_DOUBLE dnl defines HAVE_LONG_DOUBLE, or not AC_CHECK_SIZEOF(int) dnl defines SIZEOF_INT to be the size in bytes of int dnl All the rest is related to MPFR and to Ziv's lib, useful for testing. dnl Sometimes the following function is provided by aclocal, sometimes not. dnl Copying it here is probably a bad way of managing this problem AC_DEFUN([AC_ADD_PATH_LIBS], [ if ` test "$1" ` then AC_MSG_CHECKING($2 library) if test -r "$1/lib$2.a" -o -r "$1/lib$2.so" then LDFLAGS="$LDFLAGS -L$1" LIBS ="$LIBS -l$2" else AC_MSG_ERROR($2 not found) fi AC_MSG_RESULT(yes) else AC_CHECK_LIB($2, main, , AC_MSG_ERROR($2 not found)) fi ] ) dnl Command-line arguments to ./configure: dnl switch for SSE2 AC_ARG_ENABLE(sse2, [ --enable-sse2 forces the use of sse2 arith [[default=no]]], [case $enableval in yes) AC_DEFINE_UNQUOTED(HAS_SSE2,1,[Use the sse2 operators ]);; no) ;; *) AC_MSG_ERROR([bad value $enableval for --enable-sse2, need yes or no]) ;; esac], [enable_sse2=no]) dnl Send this information to automake AM_CONDITIONAL(USE_SSE2, test x$enable_sse2 = xyes ) dnl switch for compiling the interval functions AC_ARG_ENABLE(interval-functions, [ --enable-interval-functions enables filib-compatible interval functions (DOES NOT WORK YET) [[default=no]]], [case $enableval in yes) AC_DEFINE_UNQUOTED(BUILD_INTERVAL_FUNCTIONS,1,[Compile the filib-compatible interval functions]);; no) ;; *) AC_MSG_ERROR([bad value $enableval for --enable-interval-functions, need yes or no]) ;; esac], [enable_interval_functions=no]) dnl Send this information to automake AM_CONDITIONAL(USE_INTERVAL_FUNCTIONS, test x$enable_interval_functions = xyes ) dnl A switch to disable use of double-extended optimised version AC_ARG_ENABLE(double-extended, [ --enable-double-extended enable double-extended optimised versions of functions if hardware supports it [[default=yes]]], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([bad value $enableval for --enable-double-extended, need yes or no]) ;; esac], [enable_double_extended=yes]) dnl following line needs a little bit more work on log-de.c and double-extended.h dnl AM_CONDITIONAL(USE_HARDWARE_DE, test x$has_ia32_de = xtrue -a x$enable_double_extended = xyes -a x$has_fpu_control=xyes -o x$has_ia64_de = xtrue -a x$CC = xicc -a x$enable_double_extended = xyes ) AM_CONDITIONAL(USE_HARDWARE_DE, test x$has_ia32_de = xtrue -a x$has_fpu_control = xyes -a x$enable_double_extended = xyes -a x$enable_interval_functions = xno ) dnl Note that at the moment, enabling intervals disables double-extended dnl If at some point we wish to include SPARC optimization back, dnl the default should take the value 10 and 25 in this case dnl for around 200 bits of precision AC_ARG_ENABLE(nbdigits, [ --enable-nbdigits=N set the number of digits in the SCS structure to N [[default=8]] ], [case $enableval in *[[0-9]]) AC_DEFINE_UNQUOTED(SCS_NB_WORDS, $enableval, [Number of digits in the SCS structure]);; *) AC_MSG_ERROR([bad value $enableval for --enable-nbdigits, number expected]) ;; esac], [AC_DEFINE_UNQUOTED(SCS_NB_WORDS, 8, [Number of digits in the SCS structure])] ) AC_ARG_ENABLE(digitsize, [ --enable-digitsize=N set the size of a digit to N bits [[default=30]] ], [case $enableval in *[[0-9]]) AC_DEFINE_UNQUOTED(SCS_NB_BITS, $enableval, [Size of an SCS digit]);; *) AC_MSG_ERROR([bad value $enableval for --enable-digitsize, number expected]) ;; esac], [AC_DEFINE_UNQUOTED(SCS_NB_BITS, 30, [Size of an SCS digit])] ) dnl ... for MPFR AC_ARG_ENABLE(mpfr, [ --enable-mpfr enable MPFR function [[default=no]]], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([bad value $enableval for --enable-mpfr, need yes or no]) ;; esac], [enable_mpfr=no]) dnl ... for GMP AC_ARG_ENABLE(gmp, [ --enable-gmp enable GMP function [[default=no]]], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([bad value $enableval for --enable-gmp, need yes or no]) ;; esac], [enable_gmp=no]) dnl ... for IBM Accurate Portable Library AC_ARG_ENABLE(ultim, [ --enable-ultim enable comparison with libultim, IBM's Accurate Portable Math Library [[default=no]]], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([bad value $enableval for --enable-ultim, need yes or no]) ;; esac], [enable_ultim=no]) dnl ... for Sun's libmcr AC_ARG_ENABLE(mcr, [ --enable-mcr enable comparison with Sun's LIBMCR [[default=no]]], [case $enableval in yes|no) ;; *) AC_MSG_ERROR([bad value $enableval for --enable-mcr, need yes or no]) ;; esac], [enable_mcr=no]) dnl Now consider the result of the previous to set directories: dnl ... for GMP if test "$enable_gmp" = "yes" -o "$enable_mpfr" = "yes"; then AC_ARG_WITH(gmp_include, [ --with-gmp-include=DIR GMP include directory ], with_gmp_include=$withval) AC_ARG_WITH(gmp_lib, [ --with-gmp-lib=DIR GMP lib directory ], with_gmp_lib=$withval) AC_ARG_WITH(gmp, [ --with-gmp=DIR GMP directory ], with_gmp_include=$withval/include with_gmp_lib=$withval/lib) if test -d "$with_gmp_include"; then CPPFLAGS="$CPPFLAGS -I$with_gmp_include" else with_gmp_include= fi AC_ADD_PATH_LIBS($with_gmp_lib, gmp) dnl If gmp.h is found, #defines HAVE_GMP_H AC_CHECK_HEADERS([gmp.h]) dnl If libgmp is found, adds -lgmp to LIBS dnl correct in theory: AC_CHECK_LIB([gmp], [__gmp_fprintf]) AC_CHECK_LIB([gmp], [main]) dnl end of test for gmp fi dnl and for MPFR if test "$enable_mpfr" = "yes"; then AC_ARG_WITH(mpfr_include, [ --with-mpfr-include=DIR MPFR include directory ], with_mpfr_include=$withval) AC_ARG_WITH(mpfr_lib, [ --with-mpfr-lib=DIR MPFR lib directory ], with_mpfr_lib=$withval) AC_ARG_WITH(mpfr, [ --with-mpfr=DIR MPFR directory ], with_mpfr_include=$withval/include with_mpfr_lib=$withval/lib) if test -d "$with_mpfr_include"; then CPPFLAGS="$CPPFLAGS -I$with_mpfr_include" else with_mpfr_include= fi AC_ADD_PATH_LIBS($with_mpfr_lib, mpfr) dnl If mpfr.h is found, #defines HAVE_MPFR_H dnl this line should be dnl AC_CHECK_HEADERS([mpfr.h], [], [], [#if HAVE_GMP_H #include #endif]) dnl but it doesn't work properly so we assume that gmp is installed on the system dnl is mpfr is !!! AC_CHECK_HEADERS([mpfr.h], [], [], [#include]) dnl If MPFR is found, adds -lmpfr to LIBS dnl correct in theory: AC_CHECK_LIB([mpfr], [mpfr_init2]) AC_CHECK_LIB([mpfr], [main]) dnl end of test for mpfr fi dnl ... for IBM if test "$enable_ultim" = "yes"; then AC_ARG_WITH(ultim_include, [ --with-ultim-include=DIR ULTIM include directory ], with_ultim_include=$withval) AC_ARG_WITH(ultim_lib, [ --with-ultim-lib=DIR ULTIM lib directory ], with_ultim_lib=$withval) AC_ARG_WITH(ultim, [ --with-ultim=DIR ULTIM directory ], with_ultim_include=$withval/include with_ultim_lib=$withval/lib) if test -d "$with_ultim_include"; then CPPFLAGS="$CPPFLAGS -I$with_ultim_include" else with_ultim_include= fi AC_ADD_PATH_LIBS($with_ultim_lib, ultim) AC_CHECK_HEADERS([MathLib.h]) AC_CHECK_LIB([ultim], [main]) dnl end of test for IBM libultim fi dnl ... for SUN if test "$enable_mcr" = "yes"; then AC_ARG_WITH(mcr_include, [ --with-mcr-include=DIR LIBMCR include directory ], with_mcr_include=$withval) AC_ARG_WITH(mcr_lib, [ --with-mcr-lib=DIR LIBMCR lib directory ], with_mcr_lib=$withval) AC_ARG_WITH(mcr, [ --with-mcr=DIR LIBMCR directory ], with_mcr_include=$withval/include with_mcr_lib=$withval/lib) if test -d "$with_mcr_include"; then CPPFLAGS="$CPPFLAGS -I$with_mcr_include" else with_mcr_include= fi AC_ADD_PATH_LIBS($with_mcr_lib, mcr) AC_CHECK_HEADERS([libmcr.h]) AC_CHECK_LIB([mcr], [main]) dnl end of test for IBM libultim fi #AC_CONFIG_SUBDIRS([scs_lib]) AC_CONFIG_FILES([Makefile scs_lib/Makefile]) AC_OUTPUT interval-3.2.0/src/crlibm/crlibm.h0000644000000000000000000001614213316017127015153 0ustar 00000000000000/* * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author : David Defour, Catherine Daramy, Florent de Dinechin, Christoph Lauter * Contact: David.Defour@ens-lyon.fr, catherine_daramy@ens-lyon.fr * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CRLIBM_H #define CRLIBM_H #if defined (__cplusplus) extern "C" { #endif /* An init function which sets FPU flags when needed (mostly on Intel architectures with default double extended) */ extern unsigned long long crlibm_init(void); /* An exit function which restores FPU flags when needed (mostly on Intel architectures with default double extended) */ extern void crlibm_exit(unsigned long long); /* Finished functions */ /* These functions are computed in two steps and have an average execution time comparable to that of a standard libm */ /* exponential */ extern double exp_rn(double); /* to nearest */ extern double exp_rd(double); /* toward -inf */ extern double exp_ru(double); /* toward +inf */ #define exp_rz exp_rd /* toward zero */ /* logarithm */ extern double log_rn(double); /* to nearest */ extern double log_rd(double); /* toward -inf */ extern double log_ru(double); /* toward +inf */ extern double log_rz(double); /* toward zero */ /* cosine */ extern double cos_rn(double); /* to nearest */ extern double cos_rd(double); /* toward -inf */ extern double cos_ru(double); /* toward +inf */ extern double cos_rz(double); /* toward zero */ /* sine */ extern double sin_rn(double); /* to nearest */ extern double sin_rd(double); /* toward -inf */ extern double sin_ru(double); /* toward +inf */ extern double sin_rz(double); /* toward zero */ /* tangent */ extern double tan_rn(double); /* to nearest */ extern double tan_rd(double); /* toward -inf */ extern double tan_ru(double); /* toward +inf */ extern double tan_rz(double); /* toward zero */ /* cosine of pi times x */ extern double cospi_rn(double); /* to nearest */ extern double cospi_rd(double); /* toward -inf */ extern double cospi_ru(double); /* toward +inf */ extern double cospi_rz(double); /* toward zero */ /* sine of pi times x */ extern double sinpi_rn(double); /* to nearest */ extern double sinpi_rd(double); /* toward -inf */ extern double sinpi_ru(double); /* toward +inf */ extern double sinpi_rz(double); /* toward zero */ /* tangent of pi times x */ extern double tanpi_rn(double); /* to nearest */ extern double tanpi_rd(double); /* toward -inf */ extern double tanpi_ru(double); /* toward +inf */ extern double tanpi_rz(double); /* toward zero */ /* /\* cotangent *\/ */ /* extern double cotan_rn(double); /\* to nearest *\/ */ /* extern double cotan_rd(double); /\* toward -inf *\/ */ /* extern double cotan_ru(double); /\* toward +inf *\/ */ /* extern double cotan_rz(double); /\* toward zero *\/ */ /* arctangent */ extern double atan_rn(double); /* to nearest */ extern double atan_rd(double); /* toward -inf */ extern double atan_ru(double); /* toward +inf */ extern double atan_rz(double); /* toward zero */ /* arctangentPi */ extern double atanpi_rn(double); /* to nearest */ extern double atanpi_rd(double); /* toward -inf */ extern double atanpi_ru(double); /* toward +inf */ extern double atanpi_rz(double); /* toward zero */ /* hyperbolic cosine*/ extern double cosh_rn(double); /* to nearest */ extern double cosh_rd(double); /* toward -inf */ extern double cosh_ru(double); /* toward +inf */ extern double cosh_rz(double); /* toward zero */ /* hyperbolic sine */ extern double sinh_rn(double); /* to nearest */ extern double sinh_rd(double); /* toward -inf */ extern double sinh_ru(double); /* toward +inf */ extern double sinh_rz(double); /* toward zero */ /* base 2 logarithm */ extern double log2_rn(double); /* to nearest */ extern double log2_rd(double); /* toward -inf */ extern double log2_ru(double); /* toward +inf */ extern double log2_rz(double); /* towards zero */ /* base 10 logarithm */ extern double log10_rn(double); /* to nearest */ extern double log10_rd(double); /* toward -inf */ extern double log10_ru(double); /* toward +inf */ extern double log10_rz(double); /* towards zero */ /* arcsine */ extern double asin_rn(double); /* to nearest */ extern double asin_rd(double); /* toward -inf */ extern double asin_ru(double); /* toward +inf */ extern double asin_rz(double); /* toward zero */ /* arccosine */ extern double acos_rn(double); /* to nearest */ extern double acos_rd(double); /* toward -inf */ extern double acos_ru(double); /* toward +inf */ #define acos_rz acos_rd /* toward zero */ /* arcsine/PI */ extern double asinpi_rn(double); /* to nearest */ extern double asinpi_rd(double); /* toward -inf */ extern double asinpi_ru(double); /* toward +inf */ extern double asinpi_rz(double); /* toward zero */ /* arccosine/PI */ extern double acospi_rn(double); /* to nearest */ extern double acospi_rd(double); /* toward -inf */ extern double acospi_ru(double); /* toward +inf */ #define acospi_rz acospi_rd /* toward zero */ /* expm1 = e^x -1 */ extern double expm1_rn(double); /* to nearest */ extern double expm1_rd(double); /* toward -inf */ extern double expm1_ru(double); /* toward +inf */ extern double expm1_rz(double); /* toward zero */ /* log1p = log(1 + x) */ extern double log1p_rn(double); /* to nearest */ extern double log1p_rd(double); /* toward -inf */ extern double log1p_ru(double); /* toward +inf */ extern double log1p_rz(double); /* toward zero */ /* Unfinished functions */ /* These functions provide correct rounding but are very slow (typically 100 times slower that the standard libm) */ extern double exp2_rn(double); /* to nearest */ extern double exp2_rd(double); /* toward -inf */ extern double exp2_ru(double); /* toward +inf */ /* pow */ /* ATTENTION: THIS FUNCTION IS UNDER DEVELOPMENT AND CURRENTLY NOT PROVEN CORRECTLY ROUNDED FOR ALL CASES See the documentation */ extern double pow_rn(double, double); /* fi_lib-compatible interval functions (EXPERIMENTAL) */ #ifdef BUILD_INTERVAL_FUNCTIONS #include "interval.h" interval j_log(interval x); interval j_exp(interval x); #endif /* BUILD_INTERVAL_FUNCTIONS */ #if defined (__cplusplus) } #endif #endif /* ifdef CRLIBM_H*/ interval-3.2.0/src/crlibm/crlibm.spec0000644000000000000000000000145313316017127015655 0ustar 00000000000000Summary: cr-libm, a portable, efficient, correctly rounded mathematical library. Name: crlibm Version: 0.8 Release: 1 License: GNU LESSER GENERAL PUBLIC LICENSE Group: System/Mathematics URL: http://lipforge.ens-lyon.fr/projects/crlibm Source0: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot %description The goal of the crlibm project is to design a mathematical library which offers proven correct rounding, with performance and memory usage comparable to current libraries. %prep %setup -q %build %configure make %install rm -rf $RPM_BUILD_ROOT %makeinstall %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %{_bindir}/* %{_libdir}/* %{_includedir}/* %changelog * Thu Oct 28 2004 Philippe Defert - Initial build. interval-3.2.0/src/crlibm/crlibm_private.c0000644000000000000000000002504213316017127016677 0ustar 00000000000000/* * Variables and common functions shared by many functions * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" /* I wish I could use C99 fenv.h, but as of 2004 it doesn't specify anything about precision, only rounding direction. */ #ifdef HAVE_FENV_H #include #endif /* Tell the compiler that we're going to mess with FP status register */ #ifdef FENV_H #pragma STDC FENV_ACCESS ON #endif /* TODO proper init and exit functions - for Itanium, sf0 is set to RNDouble, sf1 to RNdoubleExt, set sf2 and/or sf3 for directed functions, one should be kept for saving the fpsr when speculating, study operating systems) - for PowerPC: nothing to do usually, however if for some reason the CPU was not in the default state then crlibm won't work */ /* An init function which sets FPU flags when needed */ unsigned long long crlibm_init() { #ifndef CRLIBM_TYPEOS_BSD #if defined(CRLIBM_HAS_FPU_CONTROL) && (defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)) unsigned short oldcw, cw; #if 1 /* gcc */ /* save old state */ _FPU_GETCW(oldcw); /* Set FPU flags to use double, not double extended, with rounding to nearest */ cw = (_FPU_DEFAULT & ~_FPU_EXTENDED)|_FPU_DOUBLE; _FPU_SETCW(cw); return (unsigned long long) oldcw; #else /* Sun Studio */ __asm__ ("movw $639, -22(%ebp)"); __asm__ ("fldcw -22(%ebp)"); #endif #elif defined(CRLIBM_TYPECPU_ITANIUM) /* On Itanium we assume that SF2 is used fo speculation, and use only SF3 */ unsigned long long int old_fpsr; #if defined(__INTEL_COMPILER) _Asm_fsetc( 0x00, 0x28, 3 /*_SF3*/ ); /* sf3 = round up, double-precision */ // _Asm_mov_to_ar(40, // (old_fpsr & 0xfd000000FFFFFFFFULL) || ((0x18ULL<<32) + (0x28ULL<<45)) ); #elif defined(__GNUC__) __asm__ ("fsetc.s3 0, 40\n"); #endif /* defined(__INTEL_COMPILER) */ old_fpsr = 0 ; /* TODO */ return old_fpsr; #else return 0; #endif /* CRLIBM_TYPECPU_X86 || CRLIBM_TYPECPU_AMD64 */ #else return 0; #endif } /* An exit function which sets FPU flags to initial value */ void crlibm_exit(unsigned long long int oldcw) { #ifndef CRLIBM_TYPEOS_BSD #if defined(CRLIBM_HAS_FPU_CONTROL) && (defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)) /* Set FPU flags to use double, not double extended, with rounding to nearest */ unsigned short t = (unsigned short)oldcw; _FPU_SETCW(t); #endif #endif } #if ADD22_AS_FUNCTIONS /* * computes double-double addition: zh+zl = xh+xl + yh+yl * relative error is smaller than 2^-103 */ void Add22Cond(double *zh, double *zl, double xh, double xl, double yh, double yl) { double r,s; r = xh+yh; if ((ABS(xh)) > (ABS(yh))) {s= ((((xh-r)+yh)+yl)+xl); } else {s=((((yh-r)+xh)+xl)+yl);} *zh = r+s; *zl = r - (*zh) + s; } /* * computes double-double addition: zh+zl = xh+xl + yh+yl * knowing that xh>yh * relative error is smaller than 2^-103 */ void Add22(double *zh, double *zl, double xh, double xl, double yh, double yl) { double r,s; r = xh+yh; s = xh-r+yh+yl+xl; *zh = r+s; *zl = r - (*zh) + s; } #endif /*ADD22_AS_FUNCTIONS*/ #if DEKKER_AS_FUNCTIONS && (!defined PROCESSOR_HAS_FMA) /* else it is defined in crlibm_private.h */ /* * computes rh and rl such that rh + rl = a * b with rh = a @* b exactly * under the conditions : a < 2^970 et b < 2^970 */ void Mul12(double *rh, double *rl, double u, double v){ const double c = 134217729.; /* 1+2^27 */ double up, u1, u2, vp, v1, v2; up = u*c; vp = v*c; u1 = (u-up)+up; v1 = (v-vp)+vp; u2 = u-u1; v2 = v-v1; *rh = u*v; *rl = (((u1*v1-*rh)+(u1*v2))+(u2*v1))+(u2*v2); } /* * Computes rh and rl such that rh + rl = a * b and rh = a @* b exactly */ void Mul12Cond(double *rh, double *rl, double a, double b){ const double two_970 = 0.997920154767359905828186356518419283e292; const double two_em53 = 0.11102230246251565404236316680908203125e-15; const double two_e53 = 9007199254740992.; double u, v; if (a>two_970) u = a*two_em53; else u = a; if (b>two_970) v = b*two_em53; else v = b; Mul12(rh, rl, u, v); if (a>two_970) {*rh *= two_e53; *rl *= two_e53;} if (b>two_970) {*rh *= two_e53; *rl *= two_e53;} } /* * computes double-double multiplication: zh+zl = (xh+xl) * (yh+yl) * under the conditions : xh < 2^970 et xl < 2^970 * relative error is smaller than 2^-102 */ void Mul22(double *zh, double *zl, double xh, double xl, double yh, double yl) { double mh, ml; const double c = 134217729.; /* 0x41A00000, 0x02000000 */ double up, u1, u2, vp, v1, v2; up = xh*c; vp = yh*c; u1 = (xh-up)+up; v1 = (yh-vp)+vp; u2 = xh-u1; v2 = yh-v1; mh = xh*yh; ml = (((u1*v1-mh)+(u1*v2))+(u2*v1))+(u2*v2); ml += xh*yl + xl*yh; *zh = mh+ml; *zl = mh - (*zh) + ml; } /* * computes double-double division: pzh+pzl = (xh+xl) / (yh+yl) * relative error is smaller than 2^-104 */ void Div22(double* pzh, double* pzl, double xh, double xl, double yh, double yl){ double _ch,_cl,_uh,_ul; _ch=(xh)/(yh); Mul12(&_uh,&_ul,_ch,(yh)); _cl=(((((xh)-_uh)-_ul)+(xl))-_ch*(yl))/(yh); *pzh=_ch+_cl; *pzl=(_ch-(*pzh))+_cl; } #endif /* DEKKER_AS_FUNCTIONS && (!defined PROCESSOR_HAS_FMA) */ #if SQRT_AS_FUNCTIONS /* Computes sqrt(x) with a result in double-double precision Should be provable to be exact to at least 100 bits. Only handles the following special cases: - x == 0 - subnormal x The following cases are not handled: - x < 0 - x = +/-Infty, NaN */ void sqrt12(double *resh, double *resl, double x) { db_number xdb; int E; double m, r0, r1, r2, r3h, r3l, r4h, r4l, srtmh, srtml; double r2PHr2h, r2PHr2l, r2Sqh, r2Sql; double mMr2h, mMr2l, mMr2Ch, mMr2Cl; double MHmMr2Ch, MHmMr2Cl; double r3Sqh, r3Sql, mMr3Sqh, mMr3Sql; /* Special case x = 0 */ if (x == 0) { *resh = x; *resl = 0; } else { E = 0; /* Convert to integer format */ xdb.d = x; /* Handle subnormal case */ if (xdb.i[HI] < 0x00100000) { E = -52; xdb.d *= ((db_number) ((double) SQRTTWO52)).d; /* make x a normal number */ } /* Extract exponent E and mantissa m */ E += (xdb.i[HI]>>20)-1023; xdb.i[HI] = (xdb.i[HI] & 0x000fffff) | 0x3ff00000; m = xdb.d; /* Make exponent even */ if (E & 0x00000001) { E++; m *= 0.5; /* Suppose now 1/2 <= m <= 2 */ } /* Construct sqrt(2^E) = 2^(E/2) */ xdb.i[HI] = (E/2 + 1023) << 20; xdb.i[LO] = 0; /* Compute initial approximation to r = 1/sqrt(m) */ r0 = SQRTPOLYC0 + m * (SQRTPOLYC1 + m * (SQRTPOLYC2 + m * (SQRTPOLYC3 + m * SQRTPOLYC4))); /* Iterate two times on double precision */ r1 = 0.5 * r0 * (3 - m * (r0 * r0)); r2 = 0.5 * r1 * (3 - m * (r1 * r1)); /* Iterate two times on double-double precision */ Mul12(&r2Sqh, &r2Sql, r2, r2); Add12(r2PHr2h, r2PHr2l, r2, 0.5 * r2); Mul12(&mMr2h, &mMr2l, m, r2); Mul22(&mMr2Ch, &mMr2Cl, mMr2h, mMr2l, r2Sqh, r2Sql); MHmMr2Ch = -0.5 * mMr2Ch; MHmMr2Cl = -0.5 * mMr2Cl; Add22(&r3h, &r3l, r2PHr2h, r2PHr2l, MHmMr2Ch, MHmMr2Cl); Mul22(&r3Sqh, &r3Sql, r3h, r3l, r3h, r3l); Mul22(&mMr3Sqh, &mMr3Sql, m, 0, r3Sqh, r3Sql); /* To prove: mMr3Sqh = 1.0 in each case */ Mul22(&r4h, &r4l, r3h, r3l, 1, -0.5 * mMr3Sql); /* Multiply obtained reciprocal square root by m */ Mul22(&srtmh,&srtml,m,0,r4h,r4l); /* Multiply componentwise by sqrt(2^E), which is an integer power of 2 that may not produce a subnormal */ *resh = xdb.d * srtmh; *resl = xdb.d * srtml; } /* End: special case 0 */ } #endif /* SQRT_AS_FUNCTIONS */ #if EVAL_PERF==1 /* counter of calls to the second step (accurate step) */ int crlibm_second_step_taken; #endif /* A debug functions */ void printHexa(char* s, double x) { db_number xdb; xdb.d = x; printf("%s = %08x%08x (%1.8e) exponent = %d exponent of ulp = %d\n", s, xdb.i[HI], xdb.i[LO], x, ((xdb.i[HI] & 0x7ff00000) >> 20) - 1023, ((xdb.i[HI] & 0x7ff00000) >> 20) - 1023 - 52); } #ifdef SCS_TYPECPU_SPARC const scs /* 0 */ scs_zer ={{0x00000000, 0x00000000, 0x00000000, 0x00000000}, {{0, 0}}, 0, 1 }, /* 1/2 */ scs_half={{0x02000000, 0x00000000, 0x00000000, 0x00000000}, DB_ONE, -1, 1 }, /* 1 */ scs_one ={{0x00000001, 0x00000000, 0x00000000, 0x00000000}, DB_ONE, 0, 1 }, /* 2 */ scs_two ={{0x00000002, 0x00000000, 0x00000000, 0x00000000}, DB_ONE, 0, 1 }, /* ~1.666667e-01 */ scs_sixinv ={{0x0aaaaaaa, 0x2aaaaaaa, 0x2aaaaaaa, 0x2aaaaaaa}, DB_ONE, -1, 1 }; #else const struct scs /* 0 */ scs_zer ={{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {{0, 0}}, 0, 1 }, /* 1/2 */ scs_half={{0x20000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, DB_ONE, -1, 1 }, /* 1 */ scs_one ={{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, DB_ONE, 0, 1 }, /* 2 */ scs_two ={{0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, DB_ONE, 0, 1 }, /* 0.166666*/ scs_sixinv ={{0x0aaaaaaa, 0x2aaaaaaa, 0x2aaaaaaa, 0x2aaaaaaa, 0x2aaaaaaa, 0x2aaaaaaa, 0x2aaaaaaa, 0x2aaaaaaa}, DB_ONE, -1, 1 }; #endif interval-3.2.0/src/crlibm/crlibm_private.h0000644000000000000000000015242513316017127016712 0ustar 00000000000000/* * This file contains useful tools and data for the crlibm functions. * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CRLIBM_PRIVATE_H #define CRLIBM_PRIVATE_H 1 #include "scs_lib/scs.h" #include "scs_lib/scs_private.h" #ifdef HAVE_CONFIG_H #include "crlibm_config.h" #endif /* otherwise CMake is used, and defines all the useful variables using -D switch */ #ifdef HAVE_INTTYPES_H #include #endif #if (defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)) # ifdef CRLIBM_HAS_FPU_CONTROL # include # ifndef _FPU_SETCW # define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) # endif # ifndef _FPU_GETCW # define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) # endif # endif #endif /* 64 bit arithmetic may be standardised, but people still do what they want */ #ifdef HAVE_INTTYPES_H #define ULL(bits) 0x##bits##uLL #elif defined(_WIN32) /* Windows garbage there */ typedef long long int int64_t; typedef unsigned long long int uint64_t; #define ULL(bits) 0x##bits##i64 /* Default, hoping it works, hopefully less and less relevant */ #else typedef long long int int64_t; typedef unsigned long long int uint64_t; #define ULL(bits) 0x##bits##uLL #endif #ifndef SCS_DEF_INT64 #define SCS_DEF_INT64 #ifdef CRLIBM_TYPEOS_HPUX #ifndef __LP64__ /* To solve the problem with 64 bits integer on HPPA */ typedef long long int64_t; typedef unsigned long long uint64_t; #define ULL(bits) 0x##bits##uLL #endif #endif #endif /* The Add22 and Add22 functions, as well as double-double multiplications of the Dekker family may be either defined as functions, or as #defines. Which one is better depends on the processor/compiler/OS. As #define has to be used with more care (not type-safe), the two following variables should be set to 1 in the development/debugging phase, until no type warning remains. */ #define ADD22_AS_FUNCTIONS 0 #define DEKKER_AS_FUNCTIONS 0 #define SQRT_AS_FUNCTIONS 0 /* The conditional version of the Add12 can be implemented either using 3 floating point additions, a absolute value test and a branch or using 6 floating point additions but no branch. The Add22 sequence is similar. The branchless versions might be faster on some systems. The function versions of Add12Cond and Add22Cond are not implemented in branchless versions. */ #define AVOID_BRANCHES 1 /* setting the following variable adds variables and code for monitoring the performance. Note that sometimes only round to nearest is instrumented */ #define EVAL_PERF 1 #if EVAL_PERF==1 /* counter of calls to the second step (accurate step) */ extern int crlibm_second_step_taken; #endif /* The prototypes of the second steps */ /* extern void exp_SC(scs_ptr res_scs, double x);*/ /* * i = d in rounding to nearest The constant added is 2^52 + 2^51 */ #define DOUBLE2INT(_i, _d) \ {db_number _t; \ _t.d = (_d+6755399441055744.0); \ _i = _t.i[LO];} /* Same idea but beware: works only for |_i| < 2^51 -1 */ #define DOUBLE2LONGINT(_i, _d) \ { \ db_number _t; \ _t.d = (_d+6755399441055744.0); \ if (_d >= 0) /* sign extend */ \ _i = _t.l & ULL(0007FFFFFFFFFFFF); \ else \ _i = (_t.l & ULL(0007FFFFFFFFFFFF)) | (ULL(FFF8000000000000)); \ } /* Macros for the rounding tests in directed modes */ /* After Evgeny Gvozdev pointed out a bug in the rounding procedures I decided to centralize them here Note that these tests launch the accurate phase when yl=0, in particular in the exceptional cases when the image of a double is a double. See the chapter about the log for an example All this does not work for denormals, of course */ #define TEST_AND_RETURN_RU(__yh__, __yl__, __eps__) \ { \ db_number __yhdb__, __yldb__, u53; int yh_neg, yl_neg; \ __yhdb__.d = __yh__; __yldb__.d = __yl__; \ yh_neg = (__yhdb__.i[HI] & 0x80000000); \ yl_neg = (__yldb__.i[HI] & 0x80000000); \ __yhdb__.l = __yhdb__.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ __yldb__.l = __yldb__.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53.l = (__yhdb__.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ if(__yldb__.d > __eps__ * u53.d){ \ if(!yl_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next up */ \ __yhdb__.d = __yh__; \ if(yh_neg) __yhdb__.l--; else __yhdb__.l++; /* Beware: fails for zero */ \ return __yhdb__.d ; \ } \ else return __yh__; \ } \ } #define TEST_AND_RETURN_RD(__yh__, __yl__, __eps__) \ { \ db_number __yhdb__, __yldb__, u53; int yh_neg, yl_neg; \ __yhdb__.d = __yh__; __yldb__.d = __yl__; \ yh_neg = (__yhdb__.i[HI] & 0x80000000); \ yl_neg = (__yldb__.i[HI] & 0x80000000); \ __yhdb__.l = __yhdb__.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ __yldb__.l = __yldb__.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53.l = (__yhdb__.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ if(__yldb__.d > __eps__ * u53.d){ \ if(yl_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next down */ \ __yhdb__.d = __yh__; \ if(yh_neg) __yhdb__.l++; else __yhdb__.l--; /* Beware: fails for zero */ \ return __yhdb__.d ; \ } \ else return __yh__; \ } \ } #define TEST_AND_RETURN_RZ(__yh__, __yl__, __eps__) \ { \ db_number __yhdb__, __yldb__, u53; int yh_neg, yl_neg; \ __yhdb__.d = __yh__; __yldb__.d = __yl__; \ yh_neg = (__yhdb__.i[HI] & 0x80000000); \ yl_neg = (__yldb__.i[HI] & 0x80000000); \ __yhdb__.l = __yhdb__.l & ULL(7fffffffffffffff); /* compute the absolute value*/\ __yldb__.l = __yldb__.l & ULL(7fffffffffffffff); /* compute the absolute value*/\ u53.l = (__yhdb__.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ if(__yldb__.d > __eps__ * u53.d){ \ if(yl_neg!=yh_neg) { \ __yhdb__.d = __yh__; \ __yhdb__.l--; /* Beware: fails for zero */ \ return __yhdb__.d ; \ } \ else return __yh__; \ } \ } #define TEST_AND_COPY_RU(__cond__, __res__, __yh__, __yl__, __eps__) \ { \ db_number __yhdb__, __yldb__, u53; int yh_neg, yl_neg; \ __yhdb__.d = __yh__; __yldb__.d = __yl__; \ yh_neg = (__yhdb__.i[HI] & 0x80000000); \ yl_neg = (__yldb__.i[HI] & 0x80000000); \ __yhdb__.l = __yhdb__.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ __yldb__.l = __yldb__.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53.l = (__yhdb__.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ __cond__ = 0; \ if(__yldb__.d > __eps__ * u53.d){ \ __cond__ = 1; \ if(!yl_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next up */ \ __yhdb__.d = __yh__; \ if(yh_neg) __yhdb__.l--; else __yhdb__.l++; /* Beware: fails for zero */ \ __res__ = __yhdb__.d ; \ } \ else { \ __res__ = __yh__; \ } \ } \ } #define TEST_AND_COPY_RD(__cond__, __res__, __yh__, __yl__, __eps__) \ { \ db_number __yhdb__, __yldb__, u53; int yh_neg, yl_neg; \ __yhdb__.d = __yh__; __yldb__.d = __yl__; \ yh_neg = (__yhdb__.i[HI] & 0x80000000); \ yl_neg = (__yldb__.i[HI] & 0x80000000); \ __yhdb__.l = __yhdb__.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ __yldb__.l = __yldb__.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53.l = (__yhdb__.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ __cond__ = 0; \ if(__yldb__.d > __eps__ * u53.d){ \ __cond__ = 1; \ if(yl_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next down */ \ __yhdb__.d = __yh__; \ if(yh_neg) __yhdb__.l++; else __yhdb__.l--; /* Beware: fails for zero */ \ __res__ = __yhdb__.d ; \ } \ else { \ __res__ = __yh__; \ } \ } \ } #define TEST_AND_COPY_RZ(__cond__, __res__, __yh__, __yl__, __eps__) \ { \ db_number __yhdb__, __yldb__, u53; int yh_neg, yl_neg; \ __yhdb__.d = __yh__; __yldb__.d = __yl__; \ yh_neg = (__yhdb__.i[HI] & 0x80000000); \ yl_neg = (__yldb__.i[HI] & 0x80000000); \ __yhdb__.l = __yhdb__.l & ULL(7fffffffffffffff); /* compute the absolute value*/\ __yldb__.l = __yldb__.l & ULL(7fffffffffffffff); /* compute the absolute value*/\ u53.l = (__yhdb__.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ __cond__ = 0; \ if(__yldb__.d > __eps__ * u53.d){ \ if(yl_neg!=yh_neg) { \ __yhdb__.d = __yh__; \ __yhdb__.l--; /* Beware: fails for zero */ \ __res__ = __yhdb__.d ; \ __cond__ = 1; \ } \ else { \ __res__ = __yh__; \ __cond__ = 1; \ } \ } /* If the processor has a FMA, use it ! **/ /* All this probably works only with gcc. See Markstein book for the case of HP's compiler */ #if defined(CRLIBM_TYPECPU_POWERPC) && defined(__GNUC__) #define PROCESSOR_HAS_FMA 1 #define FMA(a,b,c) /* r = a*b + c*/ \ ({ \ double _a, _b,_c,_r; \ _a=a; _b=b;_c=c; \ __asm__ ("fmadd %0, %1, %2, %3\n ;;\n" \ : "=f"(_r) \ : "f"(_a), "f"(_b), "f"(_c) \ ); \ _r; \ }) #define FMS(a,b,c) /* r = a*b - c*/ \ ({ \ double _a, _b,_c,_r; \ _a=a; _b=b;_c=c; \ __asm__ ("fmsub %0, %1, %2, %3\n ;;\n" \ : "=f"(_r) \ : "f"(_a), "f"(_b), "f"(_c) \ ); \ _r; \ }) #endif /* defined(CRLIBM_TYPECPU_POWERPC) && defined(__GCC__) */ /* On the Itanium 1 / gcc3.2 we lose 10 cycles when using the FMA !?! It probably breaks the scheduling algorithms somehow... To test again with higher gcc versions */ #if defined(CRLIBM_TYPECPU_ITANIUM) && defined(__GNUC__) && !defined(__INTEL_COMPILER) && 0 #define PROCESSOR_HAS_FMA 1 #define FMA(a,b,c) /* r = a*b + c*/ \ ({ \ double _a, _b,_c,_r; \ _a=a; _b=b;_c=c; \ __asm__ ("fma %0 = %1, %2, %3\n ;;\n" \ : "=f"(_r) \ : "f"(_a), "f"(_b), "f"(_c) \ ); \ _r; \ }) #define FMS(a,b,c) /* r = a*b - c*/ \ ({ \ double _a, _b, _c, _r; \ _a=a; _b=b;_c=c; \ __asm__ ("fms %0 = %1, %2, %3\n ;;\n" \ : "=f"(_r) \ : "f"(_a), "f"(_b), "f"(_c) \ ); \ _r; \ }) #endif /* defined(CRLIBM_TYPECPU_ITANIUM) && defined(__GCC__) && !defined(__INTEL_COMPILER) */ #if defined(CRLIBM_TYPECPU_ITANIUM) && defined(__INTEL_COMPILER) #define PROCESSOR_HAS_FMA 1 #if 0 /* Commented out because it shouldn't be there: There should be a standard #include doing all this, but as of april 2005 it doesn't exist, say intel people). Leave it as documentation, though, until it is replaced by #include */ /* Table 1-17: legal floating-point precision completers (.pc) */ typedef enum { _PC_S = 1 /* single .s */ ,_PC_D = 2 /* double .d */ ,_PC_NONE = 3 /* dynamic */ } _Asm_pc; /* Table 1-22: legal getf/setf floating-point register access completers */ typedef enum { _FR_S = 1 /* single form .s */ ,_FR_D = 2 /* double form .d */ ,_FR_EXP = 3 /* exponent form .exp */ ,_FR_SIG = 4 /* significand form .sig */ } _Asm_fr_access; /* Table 1-24: legal floating-point FPSR status field completers (.sf) */ typedef enum { _SF0 = 0 /* FPSR status field 0 .s0 */ ,_SF1 = 1 /* FPSR status field 1 .s1 */ ,_SF2 = 2 /* FPSR status field 2 .s2 */ ,_SF3 = 3 /* FPSR status field 3 .s3 */ } _Asm_sf; #endif #define FMA(a,b,c) /* r = a*b + c*/ \ _Asm_fma( 2/*_PC_D*/, a, b, c, 0/*_SF0*/ ); #define FMS(a,b,c) /* r = a*b - c*/ \ _Asm_fms( 2/*_PC_D*/, a, b, c, 0/*_SF0*/); #endif /*defined(CRLIBM_TYPECPU_ITANIUM) && defined(__INTEL_COMPILER)*/ #ifdef WORDS_BIGENDIAN #define DB_ONE {{0x3ff00000, 0x00000000}} #else #define DB_ONE {{0x00000000 ,0x3ff00000}} #endif extern const scs scs_zer, scs_half, scs_one, scs_two, scs_sixinv; #define SCS_ZERO (scs_ptr)(&scs_zer) #define SCS_HALF (scs_ptr)(&scs_half) #define SCS_ONE (scs_ptr)(&scs_one) #define SCS_TWO (scs_ptr)(&scs_two) #define SCS_SIXINV (scs_ptr)(&scs_sixinv) #if defined(__GNUC__) #define ABS(x) (__builtin_fabs((x))) #else #define ABS(x) (((x)>0) ? (x) : (-(x))) #endif /* * In the following, when an operator is preceded by a '@' it means that we * are considering the IEEE-compliant machine operator, otherwise it * is the mathematical operator. * */ /* * computes s and r such that s + r = a + b, with s = a @+ b exactly */ #if AVOID_BRANCHES #define Add12Cond(s, r, a, b) \ { \ double _u1, _u2, _u3, _u4; \ double _a=a, _b=b; \ \ s = _a + _b; \ _u1 = s - _a; \ _u2 = s - _u1; \ _u3 = _b - _u1; \ _u4 = _a - _u2; \ r = _u4 + _u3; \ } #else #define Add12Cond(s, r, a, b) \ {double _z, _a=a, _b=b; \ s = _a + _b; \ if (ABS(a) > ABS(b)){ \ _z = s - _a; \ r = _b - _z; \ }else { \ _z = s - _b; \ r = _a - _z;}} #endif /* * computes s and r such that s + r = a + b, with s = a @+ b exactly * under the condition a >= b */ #define Add12(s, r, a, b) \ {double _z, _a=a, _b=b; \ s = _a + _b; \ _z = s - _a; \ r = _b - _z; } /* * computes r1, r2, r3 such that r1 + r2 + r3 = a + b + c exactly */ #define Fast3Sum(r1, r2, r3, a, b, c) \ {double u, v, w; \ Fast2Sum(u, v, b, c); \ Fast2Sum(r1, w, a, u); \ Fast2Sum(r2, r3, w, v); } /* * Functions to computes double-double addition: zh+zl = xh+xl + yh+yl * knowing that xh>yh * relative error is smaller than 2^-103 */ #if ADD22_AS_FUNCTIONS extern void Add22(double *zh, double *zl, double xh, double xl, double yh, double yl); extern void Add22Cond(double *zh, double *zl, double xh, double xl, double yh, double yl); #else /* ADD22_AS_FUNCTIONS */ #if AVOID_BRANCHES #define Add22Cond(zh,zl,xh,xl,yh,yl) \ do { \ double _v1, _v2, _v3, _v4; \ \ Add12Cond(_v1, _v2, (xh), (yh)); \ _v3 = (xl) + (yl); \ _v4 = _v2 + _v3; \ Add12((*(zh)),(*(zl)),_v1,_v4); \ } while (2+2==5) #else #define Add22Cond(zh,zl,xh,xl,yh,yl) \ do { \ double _r,_s; \ _r = (xh)+(yh); \ _s = ((ABS(xh)) > (ABS(yh)))? ((xh)-_r+(yh)+(yl)+(xl)) : ((yh)-_r+(xh)+(xl)+(yl)); \ *zh = _r+_s; \ *zl = (_r - (*zh)) + _s; \ } while(2+2==5) #endif #define Add22(zh,zl,xh,xl,yh,yl) \ do { \ double _r,_s; \ _r = (xh)+(yh); \ _s = ((((xh)-_r) +(yh)) + (yl)) + (xl); \ *zh = _r+_s; \ *zl = (_r - (*zh)) + _s; \ } while(0) #endif /* ADD22_AS_FUNCTIONS */ #ifdef PROCESSOR_HAS_FMA /* One of the nice things with the fused multiply-and-add is that it greatly simplifies the double-double multiplications : */ #define Mul12(rh,rl,u,v) \ { \ *rh = u*v; \ *rl = FMS(u,v, *rh); \ } #define Mul22(pzh,pzl, xh,xl, yh,yl) \ { \ double ph, pl; \ ph = xh*yh; \ pl = FMS(xh, yh, ph); \ pl = FMA(xh,yl, pl); \ pl = FMA(xl,yh,pl); \ *pzh = ph+pl; \ *pzl = ph - (*pzh); \ *pzl += pl; \ } /* besides we don't care anymore about overflows in the mult */ #define Mul12Cond Mul12 #define Mul22cond Mul22 #else /* ! PROCESSOR_HAS_FMA */ #if DEKKER_AS_FUNCTIONS extern void Mul12(double *rh, double *rl, double u, double v); extern void Mul12Cond(double *rh, double *rl, double a, double b); extern void Mul22(double *zh, double *zl, double xh, double xl, double yh, double yl); #else /* if DEKKER_AS_FUNCTIONS */ /* * computes rh and rl such that rh + rl = a * b with rh = a @* b exactly * under the conditions : a < 2^970 et b < 2^970 */ #if 1 #define Mul12(rh,rl,u,v) \ { \ const double c = 134217729.; /* 2^27 +1 */ \ double up, u1, u2, vp, v1, v2; \ double _u=u, _v=v; \ up = _u*c; vp = _v*c; \ u1 = (_u-up)+up; v1 = (_v-vp)+vp; \ u2 = _u-u1; v2 = _v-v1; \ \ *rh = _u*_v; \ *rl = (((u1*v1-*rh)+(u1*v2))+(u2*v1))+(u2*v2);\ } #else /* This works but is much slower. Problem: SSE2 instructions are two-address, and intrinsincs are 3-address */ #include #define Mul12(rh,rl,u,v) \ { \ const double c = 134217729.; /* 2^27 +1 */ \ __m128d _u_v = _mm_set_pd (u,v); \ __m128d c2=_mm_set1_pd(c); \ c2 = _mm_mul_pd(c2, _u_v); \ __m128d u1v1 = _mm_sub_pd(_u_v, c2); \ u1v1 = _mm_add_pd(u1v1, c2); \ __m128d u2v2 = _mm_sub_pd(_u_v, u1v1); \ __m128d _v_u = _mm_shuffle_pd(_u_v, _u_v, _MM_SHUFFLE2 (0,1)); \ __m128d rhrh = _mm_mul_pd(_v_u, _u_v); \ _mm_store_sd (rh, rhrh); \ __m128d v2u2 = _mm_shuffle_pd(u2v2, u2v2, _MM_SHUFFLE2 (0,1)); \ __m128d u1v2u2v1 = _mm_mul_pd(u1v1, v2u2); \ __m128d u2v1u1v2 = _mm_shuffle_pd(u1v2u2v1, u1v2u2v1, _MM_SHUFFLE2 (0,1)); \ __m128d uvmed = _mm_add_pd(u1v2u2v1, u2v1u1v2); \ __m128d u1u2 = _mm_shuffle_pd(u1v1, u2v2, _MM_SHUFFLE2 (1,1)); \ __m128d v1v2 = _mm_shuffle_pd(u1v1, u2v2, _MM_SHUFFLE2 (0,0)); \ __m128d u1v1u2v2 = _mm_mul_pd(u1u2, v1v2); \ __m128d tmp = _mm_sub_pd(u1v1u2v2, rhrh); \ tmp = _mm_add_pd(tmp, uvmed); \ __m128d u2v2u2v2 = _mm_mul_pd(u2v2, v2u2); \ tmp = _mm_add_pd(tmp, u2v2u2v2); \ _mm_store_sd (rl, tmp); \ } #endif /* double _u =u, _v=v; \ __m128d _u_v = _mm_set_pd(_u, _v); \ */ \ /* * Computes rh and rl such that rh + rl = a * b and rh = a @* b exactly */ #define Mul12Cond(rh, rl, a, b) \ {\ const double two_em53 = 1.1102230246251565404e-16; /* 0x3CA00000, 0x00000000 */\ const double two_e53 = 9007199254740992.; /* 0x43400000, 0x00000000 */\ double u, v; \ db_number _a=a, _b=b; \ \ if (_a.i[HI]>0x7C900000) u = _a*two_em53; \ else u = _a; \ if (_b.i[HI]>0x7C900000) v = _b*two_em53; \ else v = _b; \ \ Mul12(rh, rl, u, v); \ \ if (_a.i[HI]>0x7C900000) {*rh *= two_e53; *rl *= two_e53;} \ if (_b.i[HI]>0x7C900000) {*rh *= two_e53; *rl *= two_e53;} \ } /* * computes double-double multiplication: zh+zl = (xh+xl) * (yh+yl) * relative error is smaller than 2^-102 */ #define Mul22(zh,zl,xh,xl,yh,yl) \ { \ double mh, ml; \ \ const double c = 134217729.; \ double up, u1, u2, vp, v1, v2; \ \ up = (xh)*c; vp = (yh)*c; \ u1 = ((xh)-up)+up; v1 = ((yh)-vp)+vp; \ u2 = (xh)-u1; v2 = (yh)-v1; \ \ mh = (xh)*(yh); \ ml = (((u1*v1-mh)+(u1*v2))+(u2*v1))+(u2*v2); \ \ ml += (xh)*(yl) + (xl)*(yh); \ *zh = mh+ml; \ *zl = mh - (*zh) + ml; \ } #endif /* DEKKER_AS_FUNCTIONS */ #endif /* PROCESSOR_HAS_FMA */ /* Additional double-double operators */ /* Eps Mul122 <= 2^-102 */ #define Mul122(resh,resl,a,bh,bl) \ { \ double _t1, _t2, _t3, _t4; \ \ Mul12(&_t1,&_t2,(a),(bh)); \ _t3 = (a) * (bl); \ _t4 = _t2 + _t3; \ Add12((*(resh)),(*(resl)),_t1,_t4); \ } /* Eps MulAdd212 <= 2^-100 for |a * (bh + bl)| <= 1/4 * |ch + cl| */ #define MulAdd212(resh,resl,ch,cl,a,bh,bl) \ { \ double _t1, _t2, _t3, _t4, _t5, _t6, _t7, _t8; \ \ Mul12(&_t1,&_t2,(a),(bh)); \ Add12(_t3,_t4,(ch),_t1); \ _t5 = (bl) * (a); \ _t6 = (cl) + _t2; \ _t7 = _t5 + _t6; \ _t8 = _t7 + _t4; \ Add12((*(resh)),(*(resl)),_t3,_t8); \ } /* Eps MulAdd212 <= 2^-100 for |(ah + bh) * (bh + bl)| <= 1/4 * |ch + cl| */ #define MulAdd22(resh,resl,ch,cl,ah,al,bh,bl) \ { \ double _t1, _t2, _t3, _t4, _t5, _t6, _t7, _t8; \ double _t9, _t10; \ \ Mul12(&_t1,&_t2,(ah),(bh)); \ Add12(_t3,_t4,(ch),_t1); \ _t5 = (ah) * (bl); \ _t6 = (al) * (bh); \ _t7 = _t2 + (cl); \ _t8 = _t4 + _t7; \ _t9 = _t5 + _t6; \ _t10 = _t8 + _t9; \ Add12((*(resh)),(*(resl)),_t3,_t10); \ } #define Add122(resh,resl,a,bh,bl) \ { \ double _t1, _t2, _t3; \ \ Add12(_t1,_t2,(a),(bh)); \ _t3 = _t2 + (bl); \ Add12((*(resh)),(*(resl)),_t1,_t3); \ } #define Add122Cond(resh,resl,a,bh,bl) \ { \ double _t1, _t2, _t3; \ \ Add12Cond(_t1,_t2,(a),(bh)); \ _t3 = _t2 + (bl); \ Add12((*(resh)),(*(resl)),_t1,_t3); \ } #define Add212(resh,resl,ah,al,b) \ { \ double _t1, _t2, _t3; \ \ Add12(_t1,_t2,(ah),b); \ _t3 = _t2 + (al); \ Add12((*(resh)),(*(resl)),_t1,_t3); \ } /* In the following the one-line computation of _cl was split so that icc(8.1) would compile it properly. It's a bug of icc */ #if DEKKER_AS_FUNCTIONS extern void Div22(double *z, double *zz, double x, double xx, double y, double yy); #else #define Div22(pzh,pzl,xh,xl,yh,yl) { \ double _ch,_cl,_uh,_ul; \ _ch=(xh)/(yh); Mul12(&_uh,&_ul,_ch,(yh)); \ _cl=((xh)-_uh); \ _cl -= _ul; \ _cl += (xl); \ _cl -= _ch*(yl); \ _cl /= (yh); \ *pzh=_ch+_cl; *pzl=(_ch-(*pzh))+_cl; \ } #endif /* DEKKER_AS_FUNCTIONS */ /* Coefficients for 1/sqrt(m) with 1/2 < m < 2 The corresponding relative polynomial approximation error is less than eps < 2^(-8.3127) (cf. Maple file) The Itanium instruction frsqrta is slightly more accurate; it can therefore easily replace the polynomial evaluation. */ #define SQRTPOLYC0 2.50385236695888790947606139525305479764938354492188e+00 #define SQRTPOLYC1 -3.29763389114324168005509818613063544034957885742188e+00 #define SQRTPOLYC2 2.75726076139124520736345402838196605443954467773438e+00 #define SQRTPOLYC3 -1.15233725777933848632983426796272397041320800781250e+00 #define SQRTPOLYC4 1.86900066679800969104974228685023263096809387207031e-01 #define SQRTTWO52 4.50359962737049600000000000000000000000000000000000e+15 #if SQRT_AS_FUNCTIONS extern void sqrt12(double *resh, double *resl, double x); #else /* Concerning special case handling see crlibm_private.h */ #define sqrt12(resh, resl, x) { \ db_number _xdb; \ int _E; \ double _m, _r0, _r1, _r2, _r3h, _r3l, _r4h, _r4l, _srtmh, _srtml; \ double _r2PHr2h, _r2PHr2l, _r2Sqh, _r2Sql; \ double _mMr2h, _mMr2l, _mMr2Ch, _mMr2Cl; \ double _MHmMr2Ch, _MHmMr2Cl; \ double _r3Sqh, _r3Sql, _mMr3Sqh, _mMr3Sql; \ double _half; \ \ /* Special case x = 0 */ \ if ((x) == 0.0) { \ (*(resh)) = (x); \ (*(resl)) = 0.0; \ } else { \ \ _E = 0; \ \ /* Convert to integer format */ \ _xdb.d = (x); \ \ /* Handle subnormal case */ \ if (_xdb.i[HI] < 0x00100000) { \ _E = -52; \ _xdb.d *= ((db_number) ((double) SQRTTWO52)).d; \ /* make x a normal number */ \ } \ \ /* Extract exponent E and mantissa m */ \ _E += (_xdb.i[HI]>>20)-1023; \ _xdb.i[HI] = (_xdb.i[HI] & 0x000fffff) | 0x3ff00000; \ _m = _xdb.d; \ \ _half = 0.5; \ /* Make exponent even */ \ if (_E & 0x00000001) { \ _E++; \ _m *= _half; /* Suppose now 1/2 <= m <= 2 */ \ } \ \ /* Construct sqrt(2^E) = 2^(E/2) */ \ _xdb.i[HI] = (_E/2 + 1023) << 20; \ _xdb.i[LO] = 0; \ \ /* Compute initial approximation to r = 1/sqrt(m) */ \ \ _r0 = SQRTPOLYC0 + \ _m * (SQRTPOLYC1 + _m * (SQRTPOLYC2 + _m * (SQRTPOLYC3 + _m * SQRTPOLYC4))); \ \ /* Iterate two times on double precision */ \ \ _r1 = _half * _r0 * (3.0 - _m * (_r0 * _r0)); \ _r2 = _half * _r1 * (3.0 - _m * (_r1 * _r1)); \ \ /* Iterate two times on double-double precision */ \ \ Mul12(&_r2Sqh, &_r2Sql, _r2, _r2); \ Add12(_r2PHr2h, _r2PHr2l, _r2, (_half * _r2)); \ Mul12(&_mMr2h, &_mMr2l, _m, _r2); \ Mul22(&_mMr2Ch, &_mMr2Cl, _mMr2h, _mMr2l, _r2Sqh, _r2Sql); \ \ _MHmMr2Ch = -_half * _mMr2Ch; \ _MHmMr2Cl = -_half * _mMr2Cl; \ \ Add22(&_r3h, &_r3l, _r2PHr2h, _r2PHr2l, _MHmMr2Ch, _MHmMr2Cl); \ \ Mul22(&_r3Sqh, &_r3Sql, _r3h, _r3l, _r3h, _r3l); \ Mul22(&_mMr3Sqh, &_mMr3Sql, _m, 0.0, _r3Sqh, _r3Sql); \ /* To prove: mMr3Sqh = 1.0 in each case */ \ \ Mul22(&_r4h, &_r4l, _r3h, _r3l, 1.0, (-_half * _mMr3Sql)); \ \ /* Multiply obtained reciprocal square root by m */ \ \ Mul22(&_srtmh,&_srtml,_m,0.0,_r4h,_r4l); \ \ /* Multiply componentwise by sqrt(2^E) */ \ /* which is an integer power of 2 that may not produce a subnormal */ \ \ (*(resh)) = _xdb.d * _srtmh; \ (*(resl)) = _xdb.d * _srtml; \ \ } /* End: special case 0 */ \ } #define sqrt12_64(resh, resl, x) { \ db_number _xdb; \ int _E; \ double _m, _r0, _r1, _r2, _r3h, _r3l, _r4h, _r4l, _srtmh, _srtml; \ double _r2PHr2h, _r2PHr2l, _r2Sqh, _r2Sql; \ double _mMr2h, _mMr2l, _mMr2Ch, _mMr2Cl; \ double _MHmMr2Ch, _MHmMr2Cl; \ double _r3Sqh, _r3Sql, _mMr3Sqh, _mMr3Sql; \ double _half; \ \ /* Special case x = 0 */ \ if ((x) == 0.0) { \ (*(resh)) = (x); \ (*(resl)) = 0.0; \ } else { \ \ _E = 0.0; \ \ /* Convert to integer format */ \ _xdb.d = (x); \ \ /* Handle subnormal case */ \ if (_xdb.i[HI] < 0x00100000) { \ _E = -52; \ _xdb.d *= ((db_number) ((double) SQRTTWO52)).d; \ /* make x a normal number */ \ } \ \ /* Extract exponent E and mantissa m */ \ _E += (_xdb.i[HI]>>20)-1023; \ _xdb.i[HI] = (_xdb.i[HI] & 0x000fffff) | 0x3ff00000; \ _m = _xdb.d; \ \ _half = 0.5; \ /* Make exponent even */ \ if (_E & 0x00000001) { \ _E++; \ _m *= _half; /* Suppose now 1/2 <= m <= 2 */ \ } \ \ /* Construct sqrt(2^E) = 2^(E/2) */ \ _xdb.i[HI] = (_E/2 + 1023) << 20; \ _xdb.i[LO] = 0; \ \ /* Compute initial approximation to r = 1/sqrt(m) */ \ \ _r0 = SQRTPOLYC0 + \ _m * (SQRTPOLYC1 + _m * (SQRTPOLYC2 + _m * (SQRTPOLYC3 + _m * SQRTPOLYC4))); \ \ /* Iterate two times on double precision */ \ \ _r1 = _half * _r0 * (3.0 - _m * (_r0 * _r0)); \ _r2 = _half * _r1 * (3.0 - _m * (_r1 * _r1)); \ \ /* Iterate once on double-double precision */ \ \ Mul12(&_r2Sqh, &_r2Sql, _r2, _r2); \ Add12(_r2PHr2h, _r2PHr2l, _r2, (_half * _r2)); \ Mul12(&_mMr2h, &_mMr2l, _m, _r2); \ Mul22(&_mMr2Ch, &_mMr2Cl, _mMr2h, _mMr2l, _r2Sqh, _r2Sql); \ \ _MHmMr2Ch = -_half * _mMr2Ch; \ _MHmMr2Cl = -_half * _mMr2Cl; \ \ Add22(&_r3h, &_r3l, _r2PHr2h, _r2PHr2l, _MHmMr2Ch, _MHmMr2Cl); \ \ /* Multiply obtained reciprocal square root by m */ \ \ Mul22(&_srtmh,&_srtml,_m,0.0,_r3h,_r3l); \ \ /* Multiply componentwise by sqrt(2^E) */ \ /* which is an integer power of 2 that may not produce a subnormal */ \ \ (*(resh)) = _xdb.d * _srtmh; \ (*(resl)) = _xdb.d * _srtml; \ \ } /* End: special case 0 */ \ } /* sqrt12_64_unfiltered = sqrt(x) * (1 + eps) where abs(eps) <= 2^(-64) if x is neither subnormal nor 0 */ #define sqrt12_64_unfiltered(resh, resl, x) { \ db_number _xdb; \ int _E; \ double _m, _r0, _r1, _r2, _r3h, _r3l, _srtmh, _srtml; \ double _r2PHr2h, _r2PHr2l, _r2Sqh, _r2Sql; \ double _mMr2h, _mMr2l, _mMr2Ch, _mMr2Cl; \ double _MHmMr2Ch, _MHmMr2Cl; \ double _half; \ \ \ \ /* Convert to integer format */ \ _xdb.d = (x); \ \ \ /* Extract exponent E and mantissa m */ \ _E = (_xdb.i[HI]>>20)-1023; \ _xdb.i[HI] = (_xdb.i[HI] & 0x000fffff) | 0x3ff00000; \ _m = _xdb.d; \ \ _half = 0.5; \ /* Make exponent even */ \ if (_E & 0x00000001) { \ _E++; \ _m *= _half; /* Suppose now 1/2 <= m <= 2 */ \ } \ \ /* Construct sqrt(2^E) = 2^(E/2) */ \ _xdb.i[HI] = (_E/2 + 1023) << 20; \ _xdb.i[LO] = 0; \ \ /* Compute initial approximation to r = 1/sqrt(m) */ \ \ _r0 = SQRTPOLYC0 + \ _m * (SQRTPOLYC1 + _m * (SQRTPOLYC2 + _m * (SQRTPOLYC3 + _m * SQRTPOLYC4))); \ \ /* Iterate two times on double precision */ \ \ _r1 = _half * _r0 * (3.0 - _m * (_r0 * _r0)); \ _r2 = _half * _r1 * (3.0 - _m * (_r1 * _r1)); \ \ /* Iterate once on double-double precision */ \ \ Mul12(&_r2Sqh, &_r2Sql, _r2, _r2); \ Add12(_r2PHr2h, _r2PHr2l, _r2, (_half * _r2)); \ Mul12(&_mMr2h, &_mMr2l, _m, _r2); \ Mul22(&_mMr2Ch, &_mMr2Cl, _mMr2h, _mMr2l, _r2Sqh, _r2Sql); \ \ _MHmMr2Ch = -_half * _mMr2Ch; \ _MHmMr2Cl = -_half * _mMr2Cl; \ \ Add22(&_r3h, &_r3l, _r2PHr2h, _r2PHr2l, _MHmMr2Ch, _MHmMr2Cl); \ \ /* Multiply obtained reciprocal square root by m */ \ \ Mul122(&_srtmh,&_srtml,_m,_r3h,_r3l); \ \ /* Multiply componentwise by sqrt(2^E) */ \ /* which is an integer power of 2 that may not produce a subnormal */ \ \ (*(resh)) = _xdb.d * _srtmh; \ (*(resl)) = _xdb.d * _srtml; \ \ } #endif /*SQRT_AS_FUNCTIONS*/ /* Declaration of the debug function */ void printHexa(char* s, double x); #endif /*CRLIBM_PRIVATE_H*/ interval-3.2.0/src/crlibm/csh_fast.c0000644000000000000000000005431213316017127015471 0ustar 00000000000000/* * Correctly rounded hyperbolic sine and cosine * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Matthieu Gallet, Florent de Dinechin * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "csh_fast.h" #include "triple-double.h" void exp13(int *exponent, double *exp_h, double *exp_m, double *exp_l, double x); void expm1_13(double *exp_h, double *exp_m, double *exp_l, double x); /* switches on various printfs. Default 0 */ #define DEBUG 0 static const double largest_double = 0x1.fffffffffffffp1023; static const double tiniest_double = 0x1.0p-1074; enum{RN,RD,RU,RZ}; static void do_cosh(double x, double* preshi, double* preslo){ int k; db_number y; double ch_hi, ch_lo, sh_hi, sh_lo;/* cosh(x) = (ch_hi + ch_lo)*(cosh(k*ln(2)) + (sh_hi + sh_lo)*(sinh(k*ln(2))) */ db_number table_index_float; int table_index; double temp_hi, temp_lo, temp;/* some temporary variables */ double b_hi, b_lo,b_ca_hi, b_ca_lo, b_sa_hi, b_sa_lo; double ca_hi, ca_lo, sa_hi, sa_lo; /*will be the tabulated values */ double tcb_hi, tsb_hi; /*results of polynomial approximations*/ double square_b_hi; double ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo; double sh_2_pk_hi, sh_2_pk_lo, sh_2_mk_hi, sh_2_mk_lo; db_number two_p_plus_k, two_p_minus_k; /* 2^(k-1) + 2^(-k-1) */ /* First range reduction*/ DOUBLE2INT(k, x * inv_ln_2.d) if (k != 0){ /* b_hi+b_lo = x - (ln2_hi + ln2_lo) * k */ temp_hi = x - ln2_hi.d * k; temp_lo = -ln2_lo.d * k; Add12Cond(b_hi, b_lo, temp_hi, temp_lo); } else { b_hi = x; b_lo = 0.; } /*we'll construct 2 constants for the last reconstruction */ two_p_plus_k.i[LO] = 0; two_p_plus_k.i[HI] = (k-1+1023) << 20; two_p_minus_k.i[LO] = 0; two_p_minus_k.i[HI] = (-k-1+1023) << 20; /* at this stage, we've done the first range reduction : we have b_hi + b_lo between -ln(2)/2 and ln(2)/2 */ /* now we can do the second range reduction */ /* we'll get the 8 leading bits of b_hi */ table_index_float.d = b_hi + two_43_44.d; /*this add do the float equivalent of a rotation to the right, since -0.5 <= b_hi <= 0.5*/ table_index = table_index_float.i[LO];/* -89 <= table_index <= 89 */ table_index_float.d -= two_43_44.d; table_index += bias; /* to have only positive values */ b_hi -= table_index_float.d;/* to remove the 8 leading bits*/ /* since b_hi was between -2^-1 and 2^1, we now have b_hi between -2^-9 and 2^-9 */ y.d = b_hi; /* first, y² */ square_b_hi = b_hi * b_hi; /* effective computation of the polynomial approximation */ if (((y.i[HI])&(0x7FFFFFFF)) < (two_minus_30.i[HI])) { tcb_hi = 0; tsb_hi = 0; } else { /* second, cosh(y) = y² * (1/2 + y² * (1/24 + y² * 1/720)) */ tcb_hi = (square_b_hi)* (c2.d + square_b_hi * (c4.d + square_b_hi * c6.d)); tsb_hi = square_b_hi * (s3.d + square_b_hi * (s5.d + square_b_hi * s7.d)); } if( table_index != bias) { /* we get the tabulated the tabulated values */ ca_hi = cosh_sinh_table[table_index][0].d; ca_lo = cosh_sinh_table[table_index][1].d; sa_hi = cosh_sinh_table[table_index][2].d; sa_lo = cosh_sinh_table[table_index][3].d; /* first reconstruction of the cosh (corresponding to the second range reduction) */ Mul12(&b_sa_hi,&b_sa_lo, sa_hi, b_hi); temp = ((((((ca_lo + (b_hi * sa_lo)) + b_lo * sa_hi) + b_sa_lo) + (b_sa_hi * tsb_hi)) + ca_hi * tcb_hi) + b_sa_hi); Add12Cond(ch_hi, ch_lo, ca_hi, temp); /* first reconstruction for the sinh (corresponding to the second range reduction) */ } else { Add12Cond(ch_hi, ch_lo, (double) 1, tcb_hi); } if(k != 0) { if( table_index != bias) { /* first reconstruction for the sinh (corresponding to the second range reduction) */ Mul12(&b_ca_hi , &b_ca_lo, ca_hi, b_hi); temp = (((((sa_lo + (b_lo * ca_hi)) + (b_hi * ca_lo)) + b_ca_lo) + (sa_hi*tcb_hi)) + (b_ca_hi * tsb_hi)); Add12(temp_hi, temp_lo, b_ca_hi, temp); Add22Cond(&sh_hi, &sh_lo, sa_hi, (double) 0, temp_hi, temp_lo); } else { Add12Cond(sh_hi, sh_lo, b_hi, tsb_hi * b_hi + b_lo); } if((k < 35) && (k > -35) ) { ch_2_pk_hi = ch_hi * two_p_plus_k.d; ch_2_pk_lo = ch_lo * two_p_plus_k.d; ch_2_mk_hi = ch_hi * two_p_minus_k.d; ch_2_mk_lo = ch_lo * two_p_minus_k.d; sh_2_pk_hi = sh_hi * two_p_plus_k.d; sh_2_pk_lo = sh_lo * two_p_plus_k.d; sh_2_mk_hi = - sh_hi * two_p_minus_k.d; sh_2_mk_lo = - sh_lo * two_p_minus_k.d; Add22Cond(preshi, preslo, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo); Add22Cond(&ch_2_mk_hi, &ch_2_mk_lo , sh_2_pk_hi, sh_2_pk_lo, *preshi, *preslo); Add22Cond(preshi, preslo, ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo); } else if (k >= 35) { ch_2_pk_hi = ch_hi * two_p_plus_k.d; ch_2_pk_lo = ch_lo * two_p_plus_k.d; sh_2_pk_hi = sh_hi * two_p_plus_k.d; sh_2_pk_lo = sh_lo * two_p_plus_k.d; Add22Cond(preshi, preslo, ch_2_pk_hi, ch_2_pk_lo, sh_2_pk_hi, sh_2_pk_lo); } else /* if (k <= -35) */ { ch_2_mk_hi = ch_hi * two_p_minus_k.d; ch_2_mk_lo = ch_lo * two_p_minus_k.d; sh_2_mk_hi = - sh_hi * two_p_minus_k.d; sh_2_mk_lo = - sh_lo * two_p_minus_k.d; Add22Cond(preshi, preslo, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo); } } else { *preshi = ch_hi; *preslo = ch_lo; } return; } static void do_cosh_accurate(int* pexponent, double* presh, double* presm, double* presl, double x){ double exph, expm, expl; double expph, exppm, exppl; int exponentm, deltaexponent; db_number expmh, expmm, expml; #if EVAL_PERF==1 crlibm_second_step_taken++; #endif if(x<0) x=-x; if (x > 40.0) { /* then exp(-x) < 2^-118 exp(x) */ exp13(pexponent, presh, presm, presl, x); } else { exp13(pexponent, &expph, &exppm, &exppl, x); exp13(&exponentm, &(expmh.d), &(expmm.d), &(expml.d), -x); /* align the mantissas. The exponent is increased but stays well below overflow threshold */ deltaexponent = exponentm - *pexponent ; expmh.i[HI] += (deltaexponent) << 20; expmm.i[HI] += (deltaexponent) << 20; expml.i[HI] += (deltaexponent) << 20; Add33(&exph, &expm, &expl, expph, exppm, exppl, expmh.d, expmm.d, expml.d); Renormalize3(presh,presm,presl, exph, expm, expl); } } double cosh_rn(double x){ db_number y; int hx; double rh, rl; y.d = x; hx = y.i[HI] & 0x7FFFFFFF; /* Filter special cases */ if (hx > max_input_csh.i[HI]) { /* strictly greater, implies x > max_input_csh */ if (hx >= 0x7ff00000){ /* Infty or NaN */ if (((hx&0x000fffff)|y.i[LO])!=0) return x+x; /* Nan */ else {/* otherwise the result should be +infty */ y.i[HI] = 0x7FF00000; return (y.d); } } } if (x >= max_input_csh.d || x <= -max_input_csh.d) return largest_double * largest_double; /* overflow */ if (hx<0x3e500000) { if(x==0) return 1.0; /* exact */ else return (1.0+tiniest_double); /* to raise inexact flag */ } do_cosh(x, &rh, &rl); if (rh == (rh + (rl * round_cst_csh))) return rh; else{ int exponent; db_number res; double resh, resm, resl; do_cosh_accurate(&exponent, &resh,&resm, &resl, x); RoundToNearest3(&(res.d), resh, resm, resl); /* Now we have to set the exponent of res as exponent -1 (division by 2). However, as res may sometimes end up infinite, we first set the exponent to exponent -11 and then multiply by 2^10, which will cater for overflow */ res.i[HI] += (exponent-11) << 20; return 1024. * res.d; } } double cosh_ru(double x){ db_number y; int hx; double rh, rl; y.d = x; hx = y.i[HI] & 0x7FFFFFFF; if (hx > max_input_csh.i[HI]) { /* if NaN, return it */ if (((hx&0x7FF00000) == 0x7FF00000) && (((y.i[HI] & 0x000FFFFF)!=0) || (y.i[LO]!=0)) ) return x; else {/* otherwise the result should be +infty */ y.i[LO] = 0; y.i[HI] = 0x7FF00000; return (y.d); } } if (x >= max_input_csh.d || x <= -max_input_csh.d) return largest_double * largest_double; /* overflow */ if (hx<0x3e500000) { /* return the successor of 1 */ if(x==0.) return 1.0; else{ y.l = 0x3ff0000000000001LL; return y.d; } } do_cosh(x, &rh, &rl); TEST_AND_RETURN_RU(rh, rl, maxepsilon_csh); /* if the previous block didn't return a value, launch accurate phase */ { int exponent; db_number res; double resh, resm, resl; do_cosh_accurate(&exponent, &resh,&resm, &resl, x); RoundUpwards3(&(res.d), resh,resm,resl); /* Now we have to set the exponent of res as exponent -1 (division by 2). However, as res may sometimes end up infinite, we first set the exponent to exponent -11 and then multiply by 2^10, which will cater for overflow */ res.i[HI] += (exponent-11) << 20; return 1024. * res.d; } } double cosh_rd(double x){ db_number y; int hx; double rh, rl; y.d = x; hx = y.i[HI] & 0x7FFFFFFF; if (hx > max_input_csh.i[HI]) { if (hx >= 0x7FF00000) { /*particular cases : QNaN, SNaN, +- oo*/ if (((hx&0x7FF00000) == 0x7FF00000) && (((y.i[HI] & 0x000FFFFF)!=0) || (y.i[LO]!=0)) ) return x; /* NaN */ else { /* infinity */ y.i[HI] = hx; return (y.d); } } } if (y.d >= max_input_csh.d || y.d <= - max_input_csh.d) { /* out of range */ y.i[LO] = 0xFFFFFFFF; y.i[HI] = 0x7FEFFFFF ; return (y.d); } if (hx<0x3e500000) return (1.0); do_cosh(x, &rh, &rl); TEST_AND_RETURN_RD(rh, rl, maxepsilon_csh); /* if the previous block didn't return a value, launch accurate phase */ { int exponent; db_number res; double resh, resm, resl; do_cosh_accurate(&exponent, &resh,&resm, &resl, x); RoundDownwards3(&(res.d), resh,resm,resl); /* Now we have to set the exponent of res as exponent -1 (division by 2). However, as res may sometimes end up infinite, we first set the exponent to exponent -11 and then multiply by 2^10, which will cater for overflow */ res.i[HI] += (exponent-11) << 20; return 1024. * res.d; } } double cosh_rz(double x){ return(cosh_rd(x));/* cosh is always positive, so rounding to -infinite is equivalent to rounding to zero */ } static void do_sinh(double x, double* prh, double* prl){ int k; db_number y; double temp1; double ch_hi, ch_lo, sh_hi, sh_lo;/* cosh(x) = (sh_hi + sh_lo)*(cosh(k*ln(2)) + (ch_hi + ch_lo)*(sinh(k*ln(2))) */ db_number table_index_float; int table_index; double ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo; double sh_2_pk_hi, sh_2_pk_lo, sh_2_mk_hi, sh_2_mk_lo; double b_hi, b_lo; double ca_b_hi, ca_b_lo, temp_hi, temp_lo, sa_b_hi, sa_b_lo; double ca_hi, ca_lo, sa_hi, sa_lo; /*tabulated values */ double tcb_hi, tsb_hi; /*results of polynomial approximations*/ db_number two_p_plus_k, two_p_minus_k; /* 2^(k-1) + 2^(-k-1) */ double square_y_hi; /* Now we can do the first range reduction*/ DOUBLE2INT(k, x * inv_ln_2.d) if (k != 0){ /* b_hi + b_lo = x - (ln2_hi + ln2_lo) * k */ temp_hi = x - ln2_hi.d * k; temp_lo = -ln2_lo.d * k; Add12Cond(b_hi, b_lo, temp_hi, temp_lo); } else { b_hi = x; b_lo = 0.; } /*we'll construct 2 constants for the last reconstruction */ two_p_plus_k.i[LO] = 0; two_p_plus_k.i[HI] = (k-1+1023) << 20; two_p_minus_k.i[LO] = 0; two_p_minus_k.i[HI] = (-k-1+1023) << 20; /* at this stage, we've done the first range reduction : we have b_hi + b_lo between -ln(2)/2 and ln(2)/2 */ /* now we can do the second range reduction */ /* we'll get the 8 leading bits of r_hi */ table_index_float.d = b_hi + two_43_44.d; /*this add do the float equivalent of a rotation to the right, since -0.5 <= b_hi <= 0.5*/ table_index = table_index_float.i[LO];/* -89 <= table_index <= 89 */ table_index_float.d -= two_43_44.d; table_index += bias; /* to have only positive values */ b_hi -= table_index_float.d;/* to remove the 8 leading bits*/ /* since b_hi was between -2^-1 and 2^1, we now have b_hi between -2^-9 and 2^-9 */ y.d = b_hi; /* first, y² = square_y_hi + square_y_lo */ square_y_hi = b_hi * b_hi; /* effective computation of the polyomial approximation */ if (((y.i[HI])&(0x7FFFFFFF)) <= (two_minus_30.i[HI])) { tsb_hi = 0; tcb_hi = 0; } else { tsb_hi = square_y_hi * (s3.d + square_y_hi * (s5.d + square_y_hi * s7.d)); /* second, cosh(y) = y² * (1/2 + y² * (1/24 + y² * 1/720)) */ tcb_hi = (square_y_hi)* (c2.d + square_y_hi * (c4.d + square_y_hi * c6.d)); } if( table_index != bias) { /* we get the tabulated the tabulated values*/ ca_hi = cosh_sinh_table[table_index][0].d; ca_lo = cosh_sinh_table[table_index][1].d; sa_hi = cosh_sinh_table[table_index][2].d; sa_lo = cosh_sinh_table[table_index][3].d; /* first reconstruction for the sinh (corresponding to the second range reduction) */ temp1 = sa_lo; temp1 += b_lo * ca_hi; temp1 += b_hi * ca_lo; Mul12(&ca_b_hi, &ca_b_lo, ca_hi, b_hi); temp1 += ca_b_lo; temp1 += sa_hi * tcb_hi; temp1 += ca_b_hi * tsb_hi; Add12Cond(temp_hi, temp_lo, ca_b_hi, temp1); Add22Cond(&sh_hi, &sh_lo, sa_hi, (double) 0, temp_hi, temp_lo); /* first reconstruction of the cosh (corresponding to the second range reduction) */ temp1 = ca_lo; Mul12(&sa_b_hi,&sa_b_lo, sa_hi, b_hi); temp1 += b_hi * sa_lo; temp1 += b_lo * sa_hi; temp1 += sa_b_lo; temp1 += sa_b_hi * tsb_hi; temp1 += ca_hi * tcb_hi; temp1 += sa_b_hi; Add12Cond(ch_hi, ch_lo, ca_hi, temp1); } else { Add12Cond(sh_hi, sh_lo, b_hi, tsb_hi * b_hi + b_lo); Add12Cond(ch_hi, ch_lo, (double) 1, tcb_hi); } if(k != 0) { if( (k < 35) && (k > -35) ) { ch_2_pk_hi = ch_hi * two_p_plus_k.d; ch_2_pk_lo = ch_lo * two_p_plus_k.d; ch_2_mk_hi = - ch_hi * two_p_minus_k.d; ch_2_mk_lo = - ch_lo * two_p_minus_k.d; sh_2_pk_hi = sh_hi * two_p_plus_k.d; sh_2_pk_lo = sh_lo * two_p_plus_k.d; sh_2_mk_hi = sh_hi * two_p_minus_k.d; sh_2_mk_lo = sh_lo * two_p_minus_k.d; Add22Cond(prh, prl, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo); Add22Cond(&ch_2_mk_hi, &ch_2_mk_lo , sh_2_pk_hi, sh_2_pk_lo, *prh, *prl); Add22Cond(prh, prl, ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo); } else if (k >= 35) { ch_2_pk_hi = ch_hi * two_p_plus_k.d; ch_2_pk_lo = ch_lo * two_p_plus_k.d; sh_2_pk_hi = sh_hi * two_p_plus_k.d; sh_2_pk_lo = sh_lo * two_p_plus_k.d; Add22Cond(prh, prl, ch_2_pk_hi, ch_2_pk_lo, sh_2_pk_hi, sh_2_pk_lo); } else { ch_2_mk_hi = - ch_hi * two_p_minus_k.d; ch_2_mk_lo = - ch_lo * two_p_minus_k.d; sh_2_mk_hi = sh_hi * two_p_minus_k.d; sh_2_mk_lo = sh_lo * two_p_minus_k.d; Add22Cond(prh, prl, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo); } } else { *prh = sh_hi; *prl = sh_lo; } } static void do_sinh_accurate(int* pexponent, double* presh, double* presm, double* presl, double x){ double exph, expm, expl; double expph, exppm, exppl, expmh, expmm, expml; #if EVAL_PERF==1 crlibm_second_step_taken++; #endif if(x > 40.0) { /* then exp(-x) < 2^-129 exp(x) */ exp13(pexponent, presh, presm, presl, x); return; } if(x < -40.0) { /* then exp(x) < 2^-129 exp(-x) */ exp13(pexponent, presh, presm, presl, -x); *presh = -*presh; *presm = -*presm; *presl = -*presl; return; } /* Otherwise we are between -40 and 40, and we also know that |x| > 2^-25 */ if(x>0.0) { expm1_13(&expph, &exppm, &exppl, x); expm1_13(&expmh, &expmm, &expml, -x); /* The following is OK because expph and -expmh have the same sign */ Add33(&exph, &expm, &expl, expph, exppm, exppl, -expmh, -expmm, -expml); Renormalize3(presh,presm,presl, exph, expm, expl); *pexponent=0; return; } else { /* x<0 */ expm1_13(&expph, &exppm, &exppl, x); expm1_13(&expmh, &expmm, &expml, -x); /* The following is OK because expph and -expmh have the same sign */ Add33(&exph, &expm, &expl, -expmh, -expmm, -expml, expph, exppm, exppl); Renormalize3(presh,presm,presl, exph, expm, expl); *pexponent=0; return; } } double sinh_rn(double x){ db_number y; int hx; double rh, rl; y.d = x; hx = y.i[HI] & 0x7FFFFFFF; /* Filter special cases */ if (hx > max_input_csh.i[HI]) { /* strictly greater, implies x > max_input_csh */ if (hx >= 0x7ff00000){ /* infinity or NaN */ if (((hx&0x000fffff)|y.i[LO])!=0) return x+x; /* NaN */ else {/* otherwise the result should be +infty */ return (y.d); } } if (x > max_input_csh.d) return largest_double * largest_double; /* overflow */ if (x < -max_input_csh.d) return -largest_double * largest_double; /* overflow */ } if (hx<0x3e500000) { return x; /* exact, we should find some way of raising the inexact flag */ } do_sinh(x, &rh, &rl); if (rh == (rh + (rl * round_cst_csh))) return rh; else{ int exponent; db_number res; double resh, resm, resl; do_sinh_accurate(&exponent, &resh,&resm, &resl, x); RoundToNearest3(&(res.d), resh, resm, resl); /* Now we have to set the exponent of res as exponent -1 (division by 2). However, as res may sometimes end up infinite, we first set the exponent to exponent -11 and then multiply by 2^10, which will cater for overflow */ res.i[HI] += (exponent-11) << 20; return 1024. * res.d; } } double sinh_ru(double x){ db_number y; double rh, rl; y.d = x; y.i[HI] = y.i[HI] & 0x7FFFFFFF; /* to get the absolute value of the input */ if ((y.i[HI] & 0x7FF00000) >= (0x7FF00000)) { /*particular cases : QNaN, SNaN, +- oo*/ return (x); } if (y.d > max_input_csh.d) { /* out of range */ if(x>0) { y.i[LO] = 0; y.i[HI] = 0x7FF00000; return (y.d); } else { y.i[LO] = 0xFFFFFFFF; y.i[HI] = 0xFFEFFFFF ; return (y.d); } } if(y.i[HI] < 0x3e500000) /* 2^(-26) */ { /* Add one ulp if x positive */ if(x>0) { y.l++; return y.d; } else return x; } do_sinh(x, &rh, &rl); TEST_AND_RETURN_RU(rh, rl, maxepsilon_csh); /* if the previous block didn't return a value, launch accurate phase */ { int exponent; db_number res; double resh, resm, resl; do_sinh_accurate(&exponent, &resh,&resm, &resl, x); RoundUpwards3(&(res.d), resh,resm,resl); /* Now we have to set the exponent of res as exponent -1 (division by 2). However, as res may sometimes end up infinite, we first set the exponent to exponent -11 and then multiply by 2^10, which will cater for overflow */ res.i[HI] += (exponent-11) << 20; return 1024. * res.d; } } double sinh_rd(double x){ db_number y; double rh, rl; y.d = x; y.i[HI] = y.i[HI] & 0x7FFFFFFF; /* to get the absolute value of the input */ if ((y.i[HI] & 0x7FF00000) >= (0x7FF00000)) { /*particular cases : QNaN, SNaN, +- oo*/ y.d = x; return (y.d); } if (y.d > max_input_csh.d) { /* out of range */ if(x>0) { y.i[LO] = 0xFFFFFFFF; y.i[HI] = 0x7FEFFFFF ; return (y.d); } else { y.i[LO] = 0; y.i[HI] = 0xFFF00000; return (y.d); } } if(y.i[HI] < 0x3e500000) /* 2^(-26) */ { /* Add one ulp and restore the sign if x negative */ if(x<0){ y.l = (y.l+1); return -y.d; } else return x; } do_sinh(x, &rh, &rl); TEST_AND_RETURN_RD(rh, rl, maxepsilon_csh); /* if the previous block didn't return a value, launch accurate phase */ { int exponent; db_number res; double resh, resm, resl; do_sinh_accurate(&exponent, &resh,&resm, &resl, x); RoundDownwards3(&(res.d), resh,resm,resl); /* Now we have to set the exponent of res as exponent -1 (division by 2). However, as res may sometimes end up infinite, we first set the exponent to exponent -11 and then multiply by 2^10, which will cater for overflow */ res.i[HI] += (exponent-11) << 20; return 1024. * res.d; } } double sinh_rz(double x){ if( x > 0) { return(sinh_rd(x)); } else { return(sinh_ru(x)); } } interval-3.2.0/src/crlibm/csh_fast.h0000644000000000000000000013321413316017127015475 0ustar 00000000000000/* * Correctly rounded hyperbolic sine and cosine * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* File generated by maple/csh.mpl */ static double maxepsilon_csh = 7.691977781471974651029816959786e-19 ; static double round_cst_csh = 1.014076581900344724984466743033e+00 ; #ifdef WORDS_BIGENDIAN static db_number const inv_ln_2 = {{0x3FF71547,0x652B82FE}}; /*1.4426950409e+00*/ static db_number const ln2_hi = {{0x3FE62E42,0xFEFA3800}}; /*6.9314718056e-01*/ static db_number const ln2_lo = {{0x3D2EF357,0x93C76730}}; /*5.4979230187e-14*/ static db_number const two_43_44 = {{0x42B80000,0x00000000}}; /*2.6388279067e+13*/ static db_number const two_minus_30 = {{0x3D700000,0x00000000}}; /*9.0949470177e-13*/ static int const bias = 89 ; /* some bounds */ static db_number const max_input_csh = {{0x408633CE,0x8FB9F87E}}; /*7.1047586007e+02*/ static const db_number cosh_sinh_table[179][4] = { {{{0x3FF0FA08, 0xD2F35F97}}, {{0x3C9B39D1, 0x9DAB3AF1}}, {{0xBFD6B36F, 0xBB84C928}}, {{0xBC68DAF8, 0xFEFE1E5F}}}, {{{0x3FF0F464, 0x73177841}}, {{0xBC97DF60, 0x29551C51}}, {{0xBFD66F92, 0xE6A06FC9}}, {{0x3C70A785, 0xD9A66B42}}}, {{{0x3FF0EED1, 0x07A16DB4}}, {{0x3C988108, 0xD3E071F5}}, {{0xBFD62BCC, 0x8150DBAB}}, {{0xBC7700BD, 0xF95D00CA}}}, {{{0x3FF0E94E, 0x8AFDD406}}, {{0xBC9330CB, 0xB0B14F49}}, {{0xBFD5E81C, 0x47CFA1DB}}, {{0x3C791EC5, 0x4E7B2C63}}}, {{{0x3FF0E3DC, 0xF7AA2E1B}}, {{0x3C9C05BD, 0xF7FB3140}}, {{0xBFD5A481, 0xF66C8331}}, {{0xBC6E8E0C, 0xCFF78DD1}}}, {{{0x3FF0DE7C, 0x4834E82E}}, {{0xBC877BEC, 0x5F430E44}}, {{0xBFD560FD, 0x498D28AA}}, {{0x3C4F07B3, 0xCCEA8A26}}}, {{{0x3FF0D92C, 0x773D5255}}, {{0xBC84956C, 0x3D5D1DA2}}, {{0xBFD51D8D, 0xFDACDFC5}}, {{0x3C419F0E, 0x98966B86}}}, {{{0x3FF0D3ED, 0x7F739B28}}, {{0xBC99722F, 0xEA8A9ED5}}, {{0xBFD4DA33, 0xCF5C5703}}, {{0xBC7B1F07, 0x7BE71FBE}}}, {{{0x3FF0CEBF, 0x5B98CA6C}}, {{0x3C9E8080, 0x09B9F220}}, {{0xBFD496EE, 0x7B415A78}}, {{0x3C51C3BA, 0xBDFE61F1}}}, {{{0x3FF0C9A2, 0x067EBBDA}}, {{0x3C813CD8, 0x803D61F3}}, {{0xBFD453BD, 0xBE16906C}}, {{0xBC78D781, 0x45D8536E}}}, {{{0x3FF0C495, 0x7B0819E9}}, {{0x3C9A26E0, 0x6E52BA24}}, {{0xBFD410A1, 0x54AB361D}}, {{0x3C78DCB6, 0xCF7DA2E8}}}, {{{0x3FF0BF99, 0xB42858B8}}, {{0xBC67AD83, 0x0B1F30A5}}, {{0xBFD3CD98, 0xFBE2DC86}}, {{0x3C7D0A5E, 0x269038FC}}}, {{{0x3FF0BAAE, 0xACE3B0FC}}, {{0xBC93292F, 0x75521E77}}, {{0xBFD38AA4, 0x70B52549}}, {{0x3C67F94B, 0x0B01B8A6}}}, {{{0x3FF0B5D4, 0x604F1B07}}, {{0x3C732C14, 0x07EECFA5}}, {{0xBFD347C3, 0x702D7FA4}}, {{0xBC7435BE, 0x701422C8}}}, {{{0x3FF0B10A, 0xC99049DE}}, {{0xBC617C2D, 0x610FCC2E}}, {{0xBFD304F5, 0xB76AE57E}}, {{0x3C75EB09, 0x42E4CA9C}}}, {{{0x3FF0AC51, 0xE3DDA65B}}, {{0x3C9B22C0, 0x9DACA977}}, {{0xBFD2C23B, 0x039F9881}}, {{0xBC577301, 0x9B082732}}}, {{{0x3FF0A7A9, 0xAA7E4A68}}, {{0x3C71B296, 0x281520E0}}, {{0xBFD27F93, 0x1210DF54}}, {{0x3C6EF999, 0x502A1E59}}}, {{{0x3FF0A312, 0x18C9FC41}}, {{0x3C885259, 0x09E044C2}}, {{0xBFD23CFD, 0xA016C2D9}}, {{0x3C500762, 0x449D986B}}}, {{{0x3FF09E8B, 0x2A2929D1}}, {{0xBC9EE5F5, 0x535446B4}}, {{0xBFD1FA7A, 0x6B1BCB8A}}, {{0xBC50621A, 0x5A4CB636}}}, {{{0x3FF09A14, 0xDA14E415}}, {{0xBC965668, 0x233B29C8}}, {{0xBFD1B809, 0x309CBEE1}}, {{0xBC6E5B16, 0xBBB1CB75}}}, {{{0x3FF095AF, 0x2416DA9A}}, {{0x3C8024A0, 0x39DC7749}}, {{0xBFD175A9, 0xAE285CD6}}, {{0x3C3DB749, 0xC4496E39}}}, {{{0x3FF0915A, 0x03C95705}}, {{0x3C78A8A6, 0x0BD1CD00}}, {{0xBFD1335B, 0xA15F1D6C}}, {{0x3C53CE0F, 0x341ED7B6}}}, {{{0x3FF08D15, 0x74D738AC}}, {{0xBC984BD5, 0xC4A8C043}}, {{0xBFD0F11E, 0xC7F2EE53}}, {{0xBC75BADF, 0xC5355AFC}}}, {{{0x3FF088E1, 0x72FBF041}}, {{0xBC9DE12F, 0x0D55140F}}, {{0xBFD0AEF2, 0xDFA6F09B}}, {{0x3C414E60, 0xA7827088}}}, {{{0x3FF084BD, 0xFA037B8F}}, {{0xBC7D97E2, 0xE3C5EBFC}}, {{0xBFD06CD7, 0xA64F3673}}, {{0xBC6370BA, 0x839871E4}}}, {{{0x3FF080AB, 0x05CA6146}}, {{0xBC723216, 0xFC66378F}}, {{0xBFD02ACC, 0xD9D08102}}, {{0x3C5998B3, 0x20C03715}}}, {{{0x3FF07CA8, 0x923DACD6}}, {{0xBC9653A7, 0xE736D67A}}, {{0xBFCFD1A4, 0x703FFC8F}}, {{0xBC59EA3B, 0xA8860819}}}, {{{0x3FF078B6, 0x9B5AEA5C}}, {{0xBC8880D6, 0x6B6D819B}}, {{0xBFCF4DCE, 0xFE860E28}}, {{0xBC6883D4, 0xC6A2C678}}}, {{{0x3FF074D5, 0x1D3022A1}}, {{0x3C9E93F8, 0x2426EF93}}, {{0xBFCECA18, 0xDA9DBA19}}, {{0x3C36D470, 0x491D8A98}}}, {{{0x3FF07104, 0x13DBD729}}, {{0x3C766560, 0xCA5328ED}}, {{0xBFCE4681, 0x80D0D17F}}, {{0x3C605627, 0x658D0660}}}, {{{0x3FF06D43, 0x7B8CFE4D}}, {{0xBC73ADF7, 0xD1025E7E}}, {{0xBFCDC308, 0x6D87EF96}}, {{0x3C6C0BD9, 0x2A97B34C}}}, {{{0x3FF06993, 0x5082FF6E}}, {{0x3C7685C4, 0xD7395A9F}}, {{0xBFCD3FAD, 0x1D49F620}}, {{0x3C5DE851, 0x26ECE4F0}}}, {{{0x3FF065F3, 0x8F0DAF34}}, {{0xBC7821B3, 0xAF1520A9}}, {{0xBFCCBC6F, 0x0CBB89ED}}, {{0xBC4B40A0, 0x51092884}}}, {{{0x3FF06264, 0x338D4BDC}}, {{0xBC90000F, 0xF34422A4}}, {{0xBFCC394D, 0xB89E8F7F}}, {{0xBC646F77, 0x52292D2D}}}, {{{0x3FF05EE5, 0x3A727999}}, {{0x3C92512F, 0x6647668D}}, {{0xBFCBB648, 0x9DD1A7CC}}, {{0x3C234425, 0x3ED3824D}}}, {{{0x3FF05B76, 0xA03E3F07}}, {{0x3C7CA615, 0x2B52E765}}, {{0xBFCB335F, 0x394FAD1B}}, {{0xBC47F257, 0x34B51ACE}}}, {{{0x3FF05818, 0x618201A8}}, {{0xBC8BFA98, 0x5A557953}}, {{0xBFCAB091, 0x082F3002}}, {{0x3C4B6626, 0x60BF022C}}}, {{{0x3FF054CA, 0x7ADF8277}}, {{0x3C89C0C1, 0x377A9F8C}}, {{0xBFCA2DDD, 0x87A1F479}}, {{0xBC67E5CE, 0xF07409B2}}}, {{{0x3FF0518C, 0xE908DA8C}}, {{0x3C987D18, 0x25A535E2}}, {{0xBFC9AB44, 0x34F46F10}}, {{0xBC1274BC, 0x57573053}}}, {{{0x3FF04E5F, 0xA8C077CC}}, {{0xBC9D8190, 0xECF07BF2}}, {{0xBFC928C4, 0x8D8D4236}}, {{0xBC556048, 0x370EDF81}}}, {{{0x3FF04B42, 0xB6D919A9}}, {{0xBC9F2338, 0x92AA0A0B}}, {{0xBFC8A65E, 0x0EECBBA5}}, {{0x3C6339DB, 0x0663DF15}}}, {{{0x3FF04836, 0x1035CDFA}}, {{0xBC9E50AA, 0xBBC5EC1C}}, {{0xBFC82410, 0x36AC51DD}}, {{0xBC5A42DC, 0xDF8CB355}}}, {{{0x3FF04539, 0xB1C9EDDA}}, {{0x3C8D2224, 0xC7598281}}, {{0xBFC7A1DA, 0x827E21C3}}, {{0xBC6CB79F, 0x06D46085}}}, {{{0x3FF0424D, 0x98991A9F}}, {{0x3C66BB23, 0xA130683D}}, {{0xBFC71FBC, 0x702C6C4F}}, {{0xBC6BAA2A, 0x00C832DD}}}, {{{0x3FF03F71, 0xC1B73AD9}}, {{0xBC885168, 0xA8202E85}}, {{0xBFC69DB5, 0x7D991458}}, {{0x3C69321C, 0x97B08BD2}}}, {{{0x3FF03CA6, 0x2A487769}}, {{0xBC9585FD, 0xB95A2E63}}, {{0xBFC61BC5, 0x28BD1C73}}, {{0x3C625559, 0x2267ECEB}}}, {{{0x3FF039EA, 0xCF8138A4}}, {{0x3C8ACC0C, 0x8FE6098D}}, {{0xBFC599EA, 0xEFA824F1}}, {{0x3C5F28E7, 0x2B9BA1A8}}}, {{{0x3FF0373F, 0xAEA6238A}}, {{0xBC73E9A1, 0x72989A92}}, {{0xBFC51826, 0x507FE9EB}}, {{0x3C6AC219, 0x6946DA28}}}, {{{0x3FF034A4, 0xC50C1706}}, {{0xBC8A9076, 0x7ECC2F29}}, {{0xBFC49676, 0xC97FC168}}, {{0x3C6B5D13, 0x93C07384}}}, {{{0x3FF0321A, 0x10182946}}, {{0x3C88FA5C, 0xFE5F3FF1}}, {{0xBFC414DB, 0xD8F81999}}, {{0x3C3E1438, 0x0B2260AC}}}, {{{0x3FF02F9F, 0x8D3FA521}}, {{0xBC58A44A, 0x88A18235}}, {{0xBFC39354, 0xFD4DF72A}}, {{0xBC4EAAC2, 0x64EC3B0C}}}, {{{0x3FF02D35, 0x3A080789}}, {{0xBC907780, 0xF6C7E6F8}}, {{0xBFC311E1, 0xB4FA73A6}}, {{0x3C61065E, 0x4C87081D}}}, {{{0x3FF02ADB, 0x1406FD12}}, {{0x3C969329, 0x720D8336}}, {{0xBFC29081, 0x7E8A3BEF}}, {{0x3C65A4E2, 0x8F21151D}}}, {{{0x3FF02891, 0x18E25F8B}}, {{0xBC9A7DA4, 0x524ABA66}}, {{0xBFC20F33, 0xD89D0ECD}}, {{0x3C6557F7, 0x55A9198D}}}, {{{0x3FF02657, 0x4650339C}}, {{0xBC31EC5D, 0x0688DD52}}, {{0xBFC18DF8, 0x41E53B8C}}, {{0xBC49852D, 0x50E682BB}}}, {{{0x3FF0242D, 0x9A16A685}}, {{0xBC7352FD, 0x295277DB}}, {{0xBFC10CCE, 0x392720B0}}, {{0xBC55A291, 0x1E4C8E28}}}, {{{0x3FF02214, 0x120C0BDE}}, {{0xBC9456D2, 0x6B72974E}}, {{0xBFC08BB5, 0x3D38AAB7}}, {{0xBC60FB6D, 0xD37D3177}}}, {{{0x3FF0200A, 0xAC16DB6F}}, {{0xBC809B4F, 0x99576FC1}}, {{0xBFC00AAC, 0xCD00D2F1}}, {{0x3C53EA29, 0x146349DE}}}, {{{0x3FF01E11, 0x662DAF18}}, {{0xBC833F82, 0x3120653C}}, {{0xBFBF1368, 0xCEEE3CC9}}, {{0x3C5213E7, 0x7BD924AB}}}, {{{0x3FF01C28, 0x3E5740C5}}, {{0x3C95D295, 0x9EC02117}}, {{0xBFBE1197, 0x17463991}}, {{0xBC5E1FCA, 0x410E61A9}}}, {{{0x3FF01A4F, 0x32AA6878}}, {{0x3C833FDA, 0x67BCC8B5}}, {{0xBFBD0FE3, 0x7137CF18}}, {{0x3C4AE71D, 0x698E234C}}}, {{{0x3FF01886, 0x414E1A5C}}, {{0x3C4976C5, 0xE0B191DA}}, {{0xBFBC0E4C, 0xDB0F41D4}}, {{0x3C586525, 0xC9BFC58B}}}, {{{0x3FF016CD, 0x687964EF}}, {{0xBC9D38AB, 0x209297AD}}, {{0xBFBB0CD2, 0x5335E625}}, {{0xBC480157, 0xFBDC145A}}}, {{{0x3FF01524, 0xA6736F36}}, {{0x3C930803, 0xC450FC30}}, {{0xBFBA0B72, 0xD8311EBE}}, {{0xBC507AA8, 0x50193D71}}}, {{{0x3FF0138B, 0xF993770A}}, {{0xBC7502E0, 0xB809A4D7}}, {{0xBFB90A2D, 0x68A15B27}}, {{0xBC5B1BE3, 0x7F556554}}}, {{{0x3FF01203, 0x6040CF67}}, {{0x3C9847C0, 0x422FB0BC}}, {{0xBFB80901, 0x03411660}}, {{0xBC5DD342, 0x10739476}}}, {{{0x3FF0108A, 0xD8F2DEDB}}, {{0x3C93DC21, 0x53B40698}}, {{0xBFB707EC, 0xA6E3D59B}}, {{0x3C5030B2, 0xF456FFFF}}}, {{{0x3FF00F22, 0x62311DF8}}, {{0x3C99322E, 0xA7C410F3}}, {{0xBFB606EF, 0x5275270D}}, {{0x3C56910E, 0xE6EE4DC3}}}, {{{0x3FF00DC9, 0xFA9315DF}}, {{0xBC84D0E2, 0x602B4C56}}, {{0xBFB50608, 0x04F7A0DD}}, {{0xBC239FF7, 0xEDAF37D2}}}, {{{0x3FF00C81, 0xA0C05ED4}}, {{0xBC7736A7, 0x7A57AC2E}}, {{0xBFB40535, 0xBD83E026}}, {{0x3C4B9B73, 0x5F0B8AC5}}}, {{{0x3FF00B49, 0x53709EEA}}, {{0xBC9DF4D4, 0xF8CDACD0}}, {{0xBFB30477, 0x7B47880C}}, {{0xBC517BE5, 0x3B77E1B2}}}, {{{0x3FF00A21, 0x116B88B6}}, {{0xBC71D458, 0xAAAEC5A4}}, {{0xBFB203CC, 0x3D8440EF}}, {{0x3C1EF162, 0x41B5A4E1}}}, {{{0x3FF00908, 0xD988DA1B}}, {{0x3C9519B1, 0x94C96CA5}}, {{0xBFB10333, 0x038EB7A7}}, {{0x3C044B95, 0x317BAEA7}}}, {{{0x3FF00800, 0xAAB05B20}}, {{0xBC936EB9, 0x9FEBDB21}}, {{0xBFB002AA, 0xCCCD9CDD}}, {{0x3C53A7FD, 0xFAC9C47C}}}, {{{0x3FF00708, 0x83D9DCD5}}, {{0xBC9EC747, 0x430DE399}}, {{0xBFAE0465, 0x317148DD}}, {{0x3C4B5DB1, 0x7929765A}}}, {{{0x3FF00620, 0x640D384F}}, {{0xBC97FCBC, 0x170FB049}}, {{0xBFAC0392, 0xCDAF09CF}}, {{0x3C2B59CD, 0x7D4F7337}}}, {{{0x3FF00548, 0x4A624DAE}}, {{0x3C5D0575, 0x23E9C180}}, {{0xBFAA02DC, 0x6D81EE12}}, {{0x3C2A5E3B, 0x7E00BA39}}}, {{{0x3FF00480, 0x36010336}}, {{0xBC89227D, 0x10BEB244}}, {{0xBFA80240, 0x10336ABF}}, {{0x3C4941AF, 0xC229B627}}}, {{{0x3FF003C8, 0x26214474}}, {{0xBC4AE17A, 0x45DFB29B}}, {{0xBFA601BB, 0xB526F7CF}}, {{0x3C39422F, 0x2DA1796B}}}, {{{0x3FF00320, 0x1A0B0179}}, {{0x3C9FA45B, 0xD21A4C9A}}, {{0xBFA4014D, 0x5BD80F80}}, {{0xBC45A2E6, 0xA4813A5B}}}, {{{0x3FF00288, 0x11162E22}}, {{0x3C6F0E22, 0x2A930764}}, {{0xBFA200F3, 0x03D82DD0}}, {{0xBC4BE9EF, 0x0CBDB96B}}}, {{{0x3FF00200, 0x0AAAC16C}}, {{0x3C88618F, 0x578DDD8D}}, {{0xBFA000AA, 0xACCCD00D}}, {{0xBBFD9E59, 0x1EFF67C8}}}, {{{0x3FF00188, 0x0640B4E1}}, {{0x3C7FB10F, 0x8827C989}}, {{0xBF9C00E4, 0xACDAE8F4}}, {{0xBBE94741, 0x22A0BAC6}}}, {{{0x3FF00120, 0x0360040D}}, {{0xBC884C57, 0x402EAB5F}}, {{0xBF980090, 0x01033411}}, {{0xBC37E141, 0xDD340191}}}, {{{0x3FF000C8, 0x01A0AC06}}, {{0xBC7BD6C4, 0x673A2EEE}}, {{0xBF940053, 0x55BD803E}}, {{0xBBD1997B, 0xCA73460D}}}, {{{0x3FF00080, 0x00AAAB06}}, {{0xBC93E2BE, 0x2ABAD90D}}, {{0xBF90002A, 0xAACCCCDA}}, {{0x3C293021, 0x3AC1711C}}}, {{{0x3FF00048, 0x00360010}}, {{0x3C899AE6, 0xDB8F0A40}}, {{0xBF880024, 0x00103337}}, {{0x3C250734, 0xAF88B300}}}, {{{0x3FF00020, 0x000AAAAC}}, {{0x3C76C186, 0x1862ADFD}}, {{0xBF80000A, 0xAAACCCCD}}, {{0xBBBA01FC, 0x9193923E}}}, {{{0x3FF00008, 0x0000AAAB}}, {{0xBC93E93E, 0x8D68D67B}}, {{0xBF700002, 0xAAAACCCD}}, {{0x3C093193, 0x17BFB4DB}}}, {{{0x3FF00000, 0x00000000}}, {{0x00000000, 0x00000000}}, {{0x00000000, 0x00000000}}, {{0x00000000, 0x00000000}}}, {{{0x3FF00008, 0x0000AAAB}}, {{0xBC93E93E, 0x8D68D67B}}, {{0x3F700002, 0xAAAACCCD}}, {{0xBC093193, 0x17BFB4DB}}}, {{{0x3FF00020, 0x000AAAAC}}, {{0x3C76C186, 0x1862ADFD}}, {{0x3F80000A, 0xAAACCCCD}}, {{0x3BBA01FC, 0x9193923E}}}, {{{0x3FF00048, 0x00360010}}, {{0x3C899AE6, 0xDB8F0A40}}, {{0x3F880024, 0x00103337}}, {{0xBC250734, 0xAF88B300}}}, {{{0x3FF00080, 0x00AAAB06}}, {{0xBC93E2BE, 0x2ABAD90D}}, {{0x3F90002A, 0xAACCCCDA}}, {{0xBC293021, 0x3AC1711C}}}, {{{0x3FF000C8, 0x01A0AC06}}, {{0xBC7BD6C4, 0x673A2EEE}}, {{0x3F940053, 0x55BD803E}}, {{0x3BD1997B, 0xCA73460D}}}, {{{0x3FF00120, 0x0360040D}}, {{0xBC884C57, 0x402EAB5F}}, {{0x3F980090, 0x01033411}}, {{0x3C37E141, 0xDD340191}}}, {{{0x3FF00188, 0x0640B4E1}}, {{0x3C7FB10F, 0x8827C989}}, {{0x3F9C00E4, 0xACDAE8F4}}, {{0x3BE94741, 0x22A0BAC6}}}, {{{0x3FF00200, 0x0AAAC16C}}, {{0x3C88618F, 0x578DDD8D}}, {{0x3FA000AA, 0xACCCD00D}}, {{0x3BFD9E59, 0x1EFF67C8}}}, {{{0x3FF00288, 0x11162E22}}, {{0x3C6F0E22, 0x2A930764}}, {{0x3FA200F3, 0x03D82DD0}}, {{0x3C4BE9EF, 0x0CBDB96B}}}, {{{0x3FF00320, 0x1A0B0179}}, {{0x3C9FA45B, 0xD21A4C9A}}, {{0x3FA4014D, 0x5BD80F80}}, {{0x3C45A2E6, 0xA4813A5B}}}, {{{0x3FF003C8, 0x26214474}}, {{0xBC4AE17A, 0x45DFB29B}}, {{0x3FA601BB, 0xB526F7CF}}, {{0xBC39422F, 0x2DA1796B}}}, {{{0x3FF00480, 0x36010336}}, {{0xBC89227D, 0x10BEB244}}, {{0x3FA80240, 0x10336ABF}}, {{0xBC4941AF, 0xC229B627}}}, {{{0x3FF00548, 0x4A624DAE}}, {{0x3C5D0575, 0x23E9C180}}, {{0x3FAA02DC, 0x6D81EE12}}, {{0xBC2A5E3B, 0x7E00BA39}}}, {{{0x3FF00620, 0x640D384F}}, {{0xBC97FCBC, 0x170FB049}}, {{0x3FAC0392, 0xCDAF09CF}}, {{0xBC2B59CD, 0x7D4F7337}}}, {{{0x3FF00708, 0x83D9DCD5}}, {{0xBC9EC747, 0x430DE399}}, {{0x3FAE0465, 0x317148DD}}, {{0xBC4B5DB1, 0x7929765A}}}, {{{0x3FF00800, 0xAAB05B20}}, {{0xBC936EB9, 0x9FEBDB21}}, {{0x3FB002AA, 0xCCCD9CDD}}, {{0xBC53A7FD, 0xFAC9C47C}}}, {{{0x3FF00908, 0xD988DA1B}}, {{0x3C9519B1, 0x94C96CA5}}, {{0x3FB10333, 0x038EB7A7}}, {{0xBC044B95, 0x317BAEA7}}}, {{{0x3FF00A21, 0x116B88B6}}, {{0xBC71D458, 0xAAAEC5A4}}, {{0x3FB203CC, 0x3D8440EF}}, {{0xBC1EF162, 0x41B5A4E1}}}, {{{0x3FF00B49, 0x53709EEA}}, {{0xBC9DF4D4, 0xF8CDACD0}}, {{0x3FB30477, 0x7B47880C}}, {{0x3C517BE5, 0x3B77E1B2}}}, {{{0x3FF00C81, 0xA0C05ED4}}, {{0xBC7736A7, 0x7A57AC2E}}, {{0x3FB40535, 0xBD83E026}}, {{0xBC4B9B73, 0x5F0B8AC5}}}, {{{0x3FF00DC9, 0xFA9315DF}}, {{0xBC84D0E2, 0x602B4C56}}, {{0x3FB50608, 0x04F7A0DD}}, {{0x3C239FF7, 0xEDAF37D2}}}, {{{0x3FF00F22, 0x62311DF8}}, {{0x3C99322E, 0xA7C410F3}}, {{0x3FB606EF, 0x5275270D}}, {{0xBC56910E, 0xE6EE4DC3}}}, {{{0x3FF0108A, 0xD8F2DEDB}}, {{0x3C93DC21, 0x53B40698}}, {{0x3FB707EC, 0xA6E3D59B}}, {{0xBC5030B2, 0xF456FFFF}}}, {{{0x3FF01203, 0x6040CF67}}, {{0x3C9847C0, 0x422FB0BC}}, {{0x3FB80901, 0x03411660}}, {{0x3C5DD342, 0x10739476}}}, {{{0x3FF0138B, 0xF993770A}}, {{0xBC7502E0, 0xB809A4D7}}, {{0x3FB90A2D, 0x68A15B27}}, {{0x3C5B1BE3, 0x7F556554}}}, {{{0x3FF01524, 0xA6736F36}}, {{0x3C930803, 0xC450FC30}}, {{0x3FBA0B72, 0xD8311EBE}}, {{0x3C507AA8, 0x50193D71}}}, {{{0x3FF016CD, 0x687964EF}}, {{0xBC9D38AB, 0x209297AD}}, {{0x3FBB0CD2, 0x5335E625}}, {{0x3C480157, 0xFBDC145A}}}, {{{0x3FF01886, 0x414E1A5C}}, {{0x3C4976C5, 0xE0B191DA}}, {{0x3FBC0E4C, 0xDB0F41D4}}, {{0xBC586525, 0xC9BFC58B}}}, {{{0x3FF01A4F, 0x32AA6878}}, {{0x3C833FDA, 0x67BCC8B5}}, {{0x3FBD0FE3, 0x7137CF18}}, {{0xBC4AE71D, 0x698E234C}}}, {{{0x3FF01C28, 0x3E5740C5}}, {{0x3C95D295, 0x9EC02117}}, {{0x3FBE1197, 0x17463991}}, {{0x3C5E1FCA, 0x410E61A9}}}, {{{0x3FF01E11, 0x662DAF18}}, {{0xBC833F82, 0x3120653C}}, {{0x3FBF1368, 0xCEEE3CC9}}, {{0xBC5213E7, 0x7BD924AB}}}, {{{0x3FF0200A, 0xAC16DB6F}}, {{0xBC809B4F, 0x99576FC1}}, {{0x3FC00AAC, 0xCD00D2F1}}, {{0xBC53EA29, 0x146349DE}}}, {{{0x3FF02214, 0x120C0BDE}}, {{0xBC9456D2, 0x6B72974E}}, {{0x3FC08BB5, 0x3D38AAB7}}, {{0x3C60FB6D, 0xD37D3177}}}, {{{0x3FF0242D, 0x9A16A685}}, {{0xBC7352FD, 0x295277DB}}, {{0x3FC10CCE, 0x392720B0}}, {{0x3C55A291, 0x1E4C8E28}}}, {{{0x3FF02657, 0x4650339C}}, {{0xBC31EC5D, 0x0688DD52}}, {{0x3FC18DF8, 0x41E53B8C}}, {{0x3C49852D, 0x50E682BB}}}, {{{0x3FF02891, 0x18E25F8B}}, {{0xBC9A7DA4, 0x524ABA66}}, {{0x3FC20F33, 0xD89D0ECD}}, {{0xBC6557F7, 0x55A9198D}}}, {{{0x3FF02ADB, 0x1406FD12}}, {{0x3C969329, 0x720D8336}}, {{0x3FC29081, 0x7E8A3BEF}}, {{0xBC65A4E2, 0x8F21151D}}}, {{{0x3FF02D35, 0x3A080789}}, {{0xBC907780, 0xF6C7E6F8}}, {{0x3FC311E1, 0xB4FA73A6}}, {{0xBC61065E, 0x4C87081D}}}, {{{0x3FF02F9F, 0x8D3FA521}}, {{0xBC58A44A, 0x88A18235}}, {{0x3FC39354, 0xFD4DF72A}}, {{0x3C4EAAC2, 0x64EC3B0C}}}, {{{0x3FF0321A, 0x10182946}}, {{0x3C88FA5C, 0xFE5F3FF1}}, {{0x3FC414DB, 0xD8F81999}}, {{0xBC3E1438, 0x0B2260AC}}}, {{{0x3FF034A4, 0xC50C1706}}, {{0xBC8A9076, 0x7ECC2F29}}, {{0x3FC49676, 0xC97FC168}}, {{0xBC6B5D13, 0x93C07384}}}, {{{0x3FF0373F, 0xAEA6238A}}, {{0xBC73E9A1, 0x72989A92}}, {{0x3FC51826, 0x507FE9EB}}, {{0xBC6AC219, 0x6946DA28}}}, {{{0x3FF039EA, 0xCF8138A4}}, {{0x3C8ACC0C, 0x8FE6098D}}, {{0x3FC599EA, 0xEFA824F1}}, {{0xBC5F28E7, 0x2B9BA1A8}}}, {{{0x3FF03CA6, 0x2A487769}}, {{0xBC9585FD, 0xB95A2E63}}, {{0x3FC61BC5, 0x28BD1C73}}, {{0xBC625559, 0x2267ECEB}}}, {{{0x3FF03F71, 0xC1B73AD9}}, {{0xBC885168, 0xA8202E85}}, {{0x3FC69DB5, 0x7D991458}}, {{0xBC69321C, 0x97B08BD2}}}, {{{0x3FF0424D, 0x98991A9F}}, {{0x3C66BB23, 0xA130683D}}, {{0x3FC71FBC, 0x702C6C4F}}, {{0x3C6BAA2A, 0x00C832DD}}}, {{{0x3FF04539, 0xB1C9EDDA}}, {{0x3C8D2224, 0xC7598281}}, {{0x3FC7A1DA, 0x827E21C3}}, {{0x3C6CB79F, 0x06D46085}}}, {{{0x3FF04836, 0x1035CDFA}}, {{0xBC9E50AA, 0xBBC5EC1C}}, {{0x3FC82410, 0x36AC51DD}}, {{0x3C5A42DC, 0xDF8CB355}}}, {{{0x3FF04B42, 0xB6D919A9}}, {{0xBC9F2338, 0x92AA0A0B}}, {{0x3FC8A65E, 0x0EECBBA5}}, {{0xBC6339DB, 0x0663DF15}}}, {{{0x3FF04E5F, 0xA8C077CC}}, {{0xBC9D8190, 0xECF07BF2}}, {{0x3FC928C4, 0x8D8D4236}}, {{0x3C556048, 0x370EDF81}}}, {{{0x3FF0518C, 0xE908DA8C}}, {{0x3C987D18, 0x25A535E2}}, {{0x3FC9AB44, 0x34F46F10}}, {{0x3C1274BC, 0x57573053}}}, {{{0x3FF054CA, 0x7ADF8277}}, {{0x3C89C0C1, 0x377A9F8C}}, {{0x3FCA2DDD, 0x87A1F479}}, {{0x3C67E5CE, 0xF07409B2}}}, {{{0x3FF05818, 0x618201A8}}, {{0xBC8BFA98, 0x5A557953}}, {{0x3FCAB091, 0x082F3002}}, {{0xBC4B6626, 0x60BF022C}}}, {{{0x3FF05B76, 0xA03E3F07}}, {{0x3C7CA615, 0x2B52E765}}, {{0x3FCB335F, 0x394FAD1B}}, {{0x3C47F257, 0x34B51ACE}}}, {{{0x3FF05EE5, 0x3A727999}}, {{0x3C92512F, 0x6647668D}}, {{0x3FCBB648, 0x9DD1A7CC}}, {{0xBC234425, 0x3ED3824D}}}, {{{0x3FF06264, 0x338D4BDC}}, {{0xBC90000F, 0xF34422A4}}, {{0x3FCC394D, 0xB89E8F7F}}, {{0x3C646F77, 0x52292D2D}}}, {{{0x3FF065F3, 0x8F0DAF34}}, {{0xBC7821B3, 0xAF1520A9}}, {{0x3FCCBC6F, 0x0CBB89ED}}, {{0x3C4B40A0, 0x51092884}}}, {{{0x3FF06993, 0x5082FF6E}}, {{0x3C7685C4, 0xD7395A9F}}, {{0x3FCD3FAD, 0x1D49F620}}, {{0xBC5DE851, 0x26ECE4F0}}}, {{{0x3FF06D43, 0x7B8CFE4D}}, {{0xBC73ADF7, 0xD1025E7E}}, {{0x3FCDC308, 0x6D87EF96}}, {{0xBC6C0BD9, 0x2A97B34C}}}, {{{0x3FF07104, 0x13DBD729}}, {{0x3C766560, 0xCA5328ED}}, {{0x3FCE4681, 0x80D0D17F}}, {{0xBC605627, 0x658D0660}}}, {{{0x3FF074D5, 0x1D3022A1}}, {{0x3C9E93F8, 0x2426EF93}}, {{0x3FCECA18, 0xDA9DBA19}}, {{0xBC36D470, 0x491D8A98}}}, {{{0x3FF078B6, 0x9B5AEA5C}}, {{0xBC8880D6, 0x6B6D819B}}, {{0x3FCF4DCE, 0xFE860E28}}, {{0x3C6883D4, 0xC6A2C678}}}, {{{0x3FF07CA8, 0x923DACD6}}, {{0xBC9653A7, 0xE736D67A}}, {{0x3FCFD1A4, 0x703FFC8F}}, {{0x3C59EA3B, 0xA8860819}}}, {{{0x3FF080AB, 0x05CA6146}}, {{0xBC723216, 0xFC66378F}}, {{0x3FD02ACC, 0xD9D08102}}, {{0xBC5998B3, 0x20C03715}}}, {{{0x3FF084BD, 0xFA037B8F}}, {{0xBC7D97E2, 0xE3C5EBFC}}, {{0x3FD06CD7, 0xA64F3673}}, {{0x3C6370BA, 0x839871E4}}}, {{{0x3FF088E1, 0x72FBF041}}, {{0xBC9DE12F, 0x0D55140F}}, {{0x3FD0AEF2, 0xDFA6F09B}}, {{0xBC414E60, 0xA7827088}}}, {{{0x3FF08D15, 0x74D738AC}}, {{0xBC984BD5, 0xC4A8C043}}, {{0x3FD0F11E, 0xC7F2EE53}}, {{0x3C75BADF, 0xC5355AFC}}}, {{{0x3FF0915A, 0x03C95705}}, {{0x3C78A8A6, 0x0BD1CD00}}, {{0x3FD1335B, 0xA15F1D6C}}, {{0xBC53CE0F, 0x341ED7B6}}}, {{{0x3FF095AF, 0x2416DA9A}}, {{0x3C8024A0, 0x39DC7749}}, {{0x3FD175A9, 0xAE285CD6}}, {{0xBC3DB749, 0xC4496E39}}}, {{{0x3FF09A14, 0xDA14E415}}, {{0xBC965668, 0x233B29C8}}, {{0x3FD1B809, 0x309CBEE1}}, {{0x3C6E5B16, 0xBBB1CB75}}}, {{{0x3FF09E8B, 0x2A2929D1}}, {{0xBC9EE5F5, 0x535446B4}}, {{0x3FD1FA7A, 0x6B1BCB8A}}, {{0x3C50621A, 0x5A4CB636}}}, {{{0x3FF0A312, 0x18C9FC41}}, {{0x3C885259, 0x09E044C2}}, {{0x3FD23CFD, 0xA016C2D9}}, {{0xBC500762, 0x449D986B}}}, {{{0x3FF0A7A9, 0xAA7E4A68}}, {{0x3C71B296, 0x281520E0}}, {{0x3FD27F93, 0x1210DF54}}, {{0xBC6EF999, 0x502A1E59}}}, {{{0x3FF0AC51, 0xE3DDA65B}}, {{0x3C9B22C0, 0x9DACA977}}, {{0x3FD2C23B, 0x039F9881}}, {{0x3C577301, 0x9B082732}}}, {{{0x3FF0B10A, 0xC99049DE}}, {{0xBC617C2D, 0x610FCC2E}}, {{0x3FD304F5, 0xB76AE57E}}, {{0xBC75EB09, 0x42E4CA9C}}}, {{{0x3FF0B5D4, 0x604F1B07}}, {{0x3C732C14, 0x07EECFA5}}, {{0x3FD347C3, 0x702D7FA4}}, {{0x3C7435BE, 0x701422C8}}}, {{{0x3FF0BAAE, 0xACE3B0FC}}, {{0xBC93292F, 0x75521E77}}, {{0x3FD38AA4, 0x70B52549}}, {{0xBC67F94B, 0x0B01B8A6}}}, {{{0x3FF0BF99, 0xB42858B8}}, {{0xBC67AD83, 0x0B1F30A5}}, {{0x3FD3CD98, 0xFBE2DC86}}, {{0xBC7D0A5E, 0x269038FC}}}, {{{0x3FF0C495, 0x7B0819E9}}, {{0x3C9A26E0, 0x6E52BA24}}, {{0x3FD410A1, 0x54AB361D}}, {{0xBC78DCB6, 0xCF7DA2E8}}}, {{{0x3FF0C9A2, 0x067EBBDA}}, {{0x3C813CD8, 0x803D61F3}}, {{0x3FD453BD, 0xBE16906C}}, {{0x3C78D781, 0x45D8536E}}}, {{{0x3FF0CEBF, 0x5B98CA6C}}, {{0x3C9E8080, 0x09B9F220}}, {{0x3FD496EE, 0x7B415A78}}, {{0xBC51C3BA, 0xBDFE61F1}}}, {{{0x3FF0D3ED, 0x7F739B28}}, {{0xBC99722F, 0xEA8A9ED5}}, {{0x3FD4DA33, 0xCF5C5703}}, {{0x3C7B1F07, 0x7BE71FBE}}}, {{{0x3FF0D92C, 0x773D5255}}, {{0xBC84956C, 0x3D5D1DA2}}, {{0x3FD51D8D, 0xFDACDFC5}}, {{0xBC419F0E, 0x98966B86}}}, {{{0x3FF0DE7C, 0x4834E82E}}, {{0xBC877BEC, 0x5F430E44}}, {{0x3FD560FD, 0x498D28AA}}, {{0xBC4F07B3, 0xCCEA8A26}}}, {{{0x3FF0E3DC, 0xF7AA2E1B}}, {{0x3C9C05BD, 0xF7FB3140}}, {{0x3FD5A481, 0xF66C8331}}, {{0x3C6E8E0C, 0xCFF78DD1}}}, {{{0x3FF0E94E, 0x8AFDD406}}, {{0xBC9330CB, 0xB0B14F49}}, {{0x3FD5E81C, 0x47CFA1DB}}, {{0xBC791EC5, 0x4E7B2C63}}}, {{{0x3FF0EED1, 0x07A16DB4}}, {{0x3C988108, 0xD3E071F5}}, {{0x3FD62BCC, 0x8150DBAB}}, {{0x3C7700BD, 0xF95D00CA}}}, {{{0x3FF0F464, 0x73177841}}, {{0xBC97DF60, 0x29551C51}}, {{0x3FD66F92, 0xE6A06FC9}}, {{0xBC70A785, 0xD9A66B42}}}, {{{0x3FF0FA08, 0xD2F35F97}}, {{0x3C9B39D1, 0x9DAB3AF1}}, {{0x3FD6B36F, 0xBB84C928}}, {{0x3C68DAF8, 0xFEFE1E5F}}}, }; /* the coefficients for the cosh-approximations */ static const db_number c0 = {{0x3FF00000,0x00000000}}; /*1.0000000000e+00*/ static const db_number c2 = {{0x3FE00000,0x00000000}}; /*5.0000000000e-01*/ static const db_number c4 = {{0x3FA55555,0x55555555}}; /*4.1666666667e-02*/ static const db_number c6 = {{0x3F56C16C,0x16C16C17}}; /*1.3888888889e-03*/ static const db_number c8 = {{0x3EFA01A0,0x1A01A01A}}; /*2.4801587302e-05*/ /* the coefficients for the sinh-approximations */ static const db_number s1 = {{0x3FF00000,0x00000000}}; /*1.0000000000e+00*/ static const db_number s3 = {{0x3FC55555,0x55555555}}; /*1.6666666667e-01*/ static const db_number s5 = {{0x3F811111,0x11111111}}; /*8.3333333333e-03*/ static const db_number s7 = {{0x3F2A01A0,0x1A01A01A}}; /*1.9841269841e-04*/ #else static db_number const inv_ln_2 = {{0x652B82FE,0x3FF71547}}; /*1.4426950409e+00*/ static db_number const ln2_hi = {{0xFEFA3800,0x3FE62E42}}; /*6.9314718056e-01*/ static db_number const ln2_lo = {{0x93C76730,0x3D2EF357}}; /*5.4979230187e-14*/ static db_number const two_43_44 = {{0x00000000,0x42B80000}}; /*2.6388279067e+13*/ static db_number const two_minus_30 = {{0x00000000,0x3D700000}}; /*9.0949470177e-13*/ static int const bias = 89 ; /* some bounds */ static db_number const max_input_csh = {{0x8FB9F87E,0x408633CE}}; /*7.1047586007e+02*/ static const db_number cosh_sinh_table[179][4] = { {{{0xD2F35F97, 0x3FF0FA08}}, {{0x9DAB3AF1, 0x3C9B39D1}}, {{0xBB84C928, 0xBFD6B36F}}, {{0xFEFE1E5F, 0xBC68DAF8}}}, {{{0x73177841, 0x3FF0F464}}, {{0x29551C51, 0xBC97DF60}}, {{0xE6A06FC9, 0xBFD66F92}}, {{0xD9A66B42, 0x3C70A785}}}, {{{0x07A16DB4, 0x3FF0EED1}}, {{0xD3E071F5, 0x3C988108}}, {{0x8150DBAB, 0xBFD62BCC}}, {{0xF95D00CA, 0xBC7700BD}}}, {{{0x8AFDD406, 0x3FF0E94E}}, {{0xB0B14F49, 0xBC9330CB}}, {{0x47CFA1DB, 0xBFD5E81C}}, {{0x4E7B2C63, 0x3C791EC5}}}, {{{0xF7AA2E1B, 0x3FF0E3DC}}, {{0xF7FB3140, 0x3C9C05BD}}, {{0xF66C8331, 0xBFD5A481}}, {{0xCFF78DD1, 0xBC6E8E0C}}}, {{{0x4834E82E, 0x3FF0DE7C}}, {{0x5F430E44, 0xBC877BEC}}, {{0x498D28AA, 0xBFD560FD}}, {{0xCCEA8A26, 0x3C4F07B3}}}, {{{0x773D5255, 0x3FF0D92C}}, {{0x3D5D1DA2, 0xBC84956C}}, {{0xFDACDFC5, 0xBFD51D8D}}, {{0x98966B86, 0x3C419F0E}}}, {{{0x7F739B28, 0x3FF0D3ED}}, {{0xEA8A9ED5, 0xBC99722F}}, {{0xCF5C5703, 0xBFD4DA33}}, {{0x7BE71FBE, 0xBC7B1F07}}}, {{{0x5B98CA6C, 0x3FF0CEBF}}, {{0x09B9F220, 0x3C9E8080}}, {{0x7B415A78, 0xBFD496EE}}, {{0xBDFE61F1, 0x3C51C3BA}}}, {{{0x067EBBDA, 0x3FF0C9A2}}, {{0x803D61F3, 0x3C813CD8}}, {{0xBE16906C, 0xBFD453BD}}, {{0x45D8536E, 0xBC78D781}}}, {{{0x7B0819E9, 0x3FF0C495}}, {{0x6E52BA24, 0x3C9A26E0}}, {{0x54AB361D, 0xBFD410A1}}, {{0xCF7DA2E8, 0x3C78DCB6}}}, {{{0xB42858B8, 0x3FF0BF99}}, {{0x0B1F30A5, 0xBC67AD83}}, {{0xFBE2DC86, 0xBFD3CD98}}, {{0x269038FC, 0x3C7D0A5E}}}, {{{0xACE3B0FC, 0x3FF0BAAE}}, {{0x75521E77, 0xBC93292F}}, {{0x70B52549, 0xBFD38AA4}}, {{0x0B01B8A6, 0x3C67F94B}}}, {{{0x604F1B07, 0x3FF0B5D4}}, {{0x07EECFA5, 0x3C732C14}}, {{0x702D7FA4, 0xBFD347C3}}, {{0x701422C8, 0xBC7435BE}}}, {{{0xC99049DE, 0x3FF0B10A}}, {{0x610FCC2E, 0xBC617C2D}}, {{0xB76AE57E, 0xBFD304F5}}, {{0x42E4CA9C, 0x3C75EB09}}}, {{{0xE3DDA65B, 0x3FF0AC51}}, {{0x9DACA977, 0x3C9B22C0}}, {{0x039F9881, 0xBFD2C23B}}, {{0x9B082732, 0xBC577301}}}, {{{0xAA7E4A68, 0x3FF0A7A9}}, {{0x281520E0, 0x3C71B296}}, {{0x1210DF54, 0xBFD27F93}}, {{0x502A1E59, 0x3C6EF999}}}, {{{0x18C9FC41, 0x3FF0A312}}, {{0x09E044C2, 0x3C885259}}, {{0xA016C2D9, 0xBFD23CFD}}, {{0x449D986B, 0x3C500762}}}, {{{0x2A2929D1, 0x3FF09E8B}}, {{0x535446B4, 0xBC9EE5F5}}, {{0x6B1BCB8A, 0xBFD1FA7A}}, {{0x5A4CB636, 0xBC50621A}}}, {{{0xDA14E415, 0x3FF09A14}}, {{0x233B29C8, 0xBC965668}}, {{0x309CBEE1, 0xBFD1B809}}, {{0xBBB1CB75, 0xBC6E5B16}}}, {{{0x2416DA9A, 0x3FF095AF}}, {{0x39DC7749, 0x3C8024A0}}, {{0xAE285CD6, 0xBFD175A9}}, {{0xC4496E39, 0x3C3DB749}}}, {{{0x03C95705, 0x3FF0915A}}, {{0x0BD1CD00, 0x3C78A8A6}}, {{0xA15F1D6C, 0xBFD1335B}}, {{0x341ED7B6, 0x3C53CE0F}}}, {{{0x74D738AC, 0x3FF08D15}}, {{0xC4A8C043, 0xBC984BD5}}, {{0xC7F2EE53, 0xBFD0F11E}}, {{0xC5355AFC, 0xBC75BADF}}}, {{{0x72FBF041, 0x3FF088E1}}, {{0x0D55140F, 0xBC9DE12F}}, {{0xDFA6F09B, 0xBFD0AEF2}}, {{0xA7827088, 0x3C414E60}}}, {{{0xFA037B8F, 0x3FF084BD}}, {{0xE3C5EBFC, 0xBC7D97E2}}, {{0xA64F3673, 0xBFD06CD7}}, {{0x839871E4, 0xBC6370BA}}}, {{{0x05CA6146, 0x3FF080AB}}, {{0xFC66378F, 0xBC723216}}, {{0xD9D08102, 0xBFD02ACC}}, {{0x20C03715, 0x3C5998B3}}}, {{{0x923DACD6, 0x3FF07CA8}}, {{0xE736D67A, 0xBC9653A7}}, {{0x703FFC8F, 0xBFCFD1A4}}, {{0xA8860819, 0xBC59EA3B}}}, {{{0x9B5AEA5C, 0x3FF078B6}}, {{0x6B6D819B, 0xBC8880D6}}, {{0xFE860E28, 0xBFCF4DCE}}, {{0xC6A2C678, 0xBC6883D4}}}, {{{0x1D3022A1, 0x3FF074D5}}, {{0x2426EF93, 0x3C9E93F8}}, {{0xDA9DBA19, 0xBFCECA18}}, {{0x491D8A98, 0x3C36D470}}}, {{{0x13DBD729, 0x3FF07104}}, {{0xCA5328ED, 0x3C766560}}, {{0x80D0D17F, 0xBFCE4681}}, {{0x658D0660, 0x3C605627}}}, {{{0x7B8CFE4D, 0x3FF06D43}}, {{0xD1025E7E, 0xBC73ADF7}}, {{0x6D87EF96, 0xBFCDC308}}, {{0x2A97B34C, 0x3C6C0BD9}}}, {{{0x5082FF6E, 0x3FF06993}}, {{0xD7395A9F, 0x3C7685C4}}, {{0x1D49F620, 0xBFCD3FAD}}, {{0x26ECE4F0, 0x3C5DE851}}}, {{{0x8F0DAF34, 0x3FF065F3}}, {{0xAF1520A9, 0xBC7821B3}}, {{0x0CBB89ED, 0xBFCCBC6F}}, {{0x51092884, 0xBC4B40A0}}}, {{{0x338D4BDC, 0x3FF06264}}, {{0xF34422A4, 0xBC90000F}}, {{0xB89E8F7F, 0xBFCC394D}}, {{0x52292D2D, 0xBC646F77}}}, {{{0x3A727999, 0x3FF05EE5}}, {{0x6647668D, 0x3C92512F}}, {{0x9DD1A7CC, 0xBFCBB648}}, {{0x3ED3824D, 0x3C234425}}}, {{{0xA03E3F07, 0x3FF05B76}}, {{0x2B52E765, 0x3C7CA615}}, {{0x394FAD1B, 0xBFCB335F}}, {{0x34B51ACE, 0xBC47F257}}}, {{{0x618201A8, 0x3FF05818}}, {{0x5A557953, 0xBC8BFA98}}, {{0x082F3002, 0xBFCAB091}}, {{0x60BF022C, 0x3C4B6626}}}, {{{0x7ADF8277, 0x3FF054CA}}, {{0x377A9F8C, 0x3C89C0C1}}, {{0x87A1F479, 0xBFCA2DDD}}, {{0xF07409B2, 0xBC67E5CE}}}, {{{0xE908DA8C, 0x3FF0518C}}, {{0x25A535E2, 0x3C987D18}}, {{0x34F46F10, 0xBFC9AB44}}, {{0x57573053, 0xBC1274BC}}}, {{{0xA8C077CC, 0x3FF04E5F}}, {{0xECF07BF2, 0xBC9D8190}}, {{0x8D8D4236, 0xBFC928C4}}, {{0x370EDF81, 0xBC556048}}}, {{{0xB6D919A9, 0x3FF04B42}}, {{0x92AA0A0B, 0xBC9F2338}}, {{0x0EECBBA5, 0xBFC8A65E}}, {{0x0663DF15, 0x3C6339DB}}}, {{{0x1035CDFA, 0x3FF04836}}, {{0xBBC5EC1C, 0xBC9E50AA}}, {{0x36AC51DD, 0xBFC82410}}, {{0xDF8CB355, 0xBC5A42DC}}}, {{{0xB1C9EDDA, 0x3FF04539}}, {{0xC7598281, 0x3C8D2224}}, {{0x827E21C3, 0xBFC7A1DA}}, {{0x06D46085, 0xBC6CB79F}}}, {{{0x98991A9F, 0x3FF0424D}}, {{0xA130683D, 0x3C66BB23}}, {{0x702C6C4F, 0xBFC71FBC}}, {{0x00C832DD, 0xBC6BAA2A}}}, {{{0xC1B73AD9, 0x3FF03F71}}, {{0xA8202E85, 0xBC885168}}, {{0x7D991458, 0xBFC69DB5}}, {{0x97B08BD2, 0x3C69321C}}}, {{{0x2A487769, 0x3FF03CA6}}, {{0xB95A2E63, 0xBC9585FD}}, {{0x28BD1C73, 0xBFC61BC5}}, {{0x2267ECEB, 0x3C625559}}}, {{{0xCF8138A4, 0x3FF039EA}}, {{0x8FE6098D, 0x3C8ACC0C}}, {{0xEFA824F1, 0xBFC599EA}}, {{0x2B9BA1A8, 0x3C5F28E7}}}, {{{0xAEA6238A, 0x3FF0373F}}, {{0x72989A92, 0xBC73E9A1}}, {{0x507FE9EB, 0xBFC51826}}, {{0x6946DA28, 0x3C6AC219}}}, {{{0xC50C1706, 0x3FF034A4}}, {{0x7ECC2F29, 0xBC8A9076}}, {{0xC97FC168, 0xBFC49676}}, {{0x93C07384, 0x3C6B5D13}}}, {{{0x10182946, 0x3FF0321A}}, {{0xFE5F3FF1, 0x3C88FA5C}}, {{0xD8F81999, 0xBFC414DB}}, {{0x0B2260AC, 0x3C3E1438}}}, {{{0x8D3FA521, 0x3FF02F9F}}, {{0x88A18235, 0xBC58A44A}}, {{0xFD4DF72A, 0xBFC39354}}, {{0x64EC3B0C, 0xBC4EAAC2}}}, {{{0x3A080789, 0x3FF02D35}}, {{0xF6C7E6F8, 0xBC907780}}, {{0xB4FA73A6, 0xBFC311E1}}, {{0x4C87081D, 0x3C61065E}}}, {{{0x1406FD12, 0x3FF02ADB}}, {{0x720D8336, 0x3C969329}}, {{0x7E8A3BEF, 0xBFC29081}}, {{0x8F21151D, 0x3C65A4E2}}}, {{{0x18E25F8B, 0x3FF02891}}, {{0x524ABA66, 0xBC9A7DA4}}, {{0xD89D0ECD, 0xBFC20F33}}, {{0x55A9198D, 0x3C6557F7}}}, {{{0x4650339C, 0x3FF02657}}, {{0x0688DD52, 0xBC31EC5D}}, {{0x41E53B8C, 0xBFC18DF8}}, {{0x50E682BB, 0xBC49852D}}}, {{{0x9A16A685, 0x3FF0242D}}, {{0x295277DB, 0xBC7352FD}}, {{0x392720B0, 0xBFC10CCE}}, {{0x1E4C8E28, 0xBC55A291}}}, {{{0x120C0BDE, 0x3FF02214}}, {{0x6B72974E, 0xBC9456D2}}, {{0x3D38AAB7, 0xBFC08BB5}}, {{0xD37D3177, 0xBC60FB6D}}}, {{{0xAC16DB6F, 0x3FF0200A}}, {{0x99576FC1, 0xBC809B4F}}, {{0xCD00D2F1, 0xBFC00AAC}}, {{0x146349DE, 0x3C53EA29}}}, {{{0x662DAF18, 0x3FF01E11}}, {{0x3120653C, 0xBC833F82}}, {{0xCEEE3CC9, 0xBFBF1368}}, {{0x7BD924AB, 0x3C5213E7}}}, {{{0x3E5740C5, 0x3FF01C28}}, {{0x9EC02117, 0x3C95D295}}, {{0x17463991, 0xBFBE1197}}, {{0x410E61A9, 0xBC5E1FCA}}}, {{{0x32AA6878, 0x3FF01A4F}}, {{0x67BCC8B5, 0x3C833FDA}}, {{0x7137CF18, 0xBFBD0FE3}}, {{0x698E234C, 0x3C4AE71D}}}, {{{0x414E1A5C, 0x3FF01886}}, {{0xE0B191DA, 0x3C4976C5}}, {{0xDB0F41D4, 0xBFBC0E4C}}, {{0xC9BFC58B, 0x3C586525}}}, {{{0x687964EF, 0x3FF016CD}}, {{0x209297AD, 0xBC9D38AB}}, {{0x5335E625, 0xBFBB0CD2}}, {{0xFBDC145A, 0xBC480157}}}, {{{0xA6736F36, 0x3FF01524}}, {{0xC450FC30, 0x3C930803}}, {{0xD8311EBE, 0xBFBA0B72}}, {{0x50193D71, 0xBC507AA8}}}, {{{0xF993770A, 0x3FF0138B}}, {{0xB809A4D7, 0xBC7502E0}}, {{0x68A15B27, 0xBFB90A2D}}, {{0x7F556554, 0xBC5B1BE3}}}, {{{0x6040CF67, 0x3FF01203}}, {{0x422FB0BC, 0x3C9847C0}}, {{0x03411660, 0xBFB80901}}, {{0x10739476, 0xBC5DD342}}}, {{{0xD8F2DEDB, 0x3FF0108A}}, {{0x53B40698, 0x3C93DC21}}, {{0xA6E3D59B, 0xBFB707EC}}, {{0xF456FFFF, 0x3C5030B2}}}, {{{0x62311DF8, 0x3FF00F22}}, {{0xA7C410F3, 0x3C99322E}}, {{0x5275270D, 0xBFB606EF}}, {{0xE6EE4DC3, 0x3C56910E}}}, {{{0xFA9315DF, 0x3FF00DC9}}, {{0x602B4C56, 0xBC84D0E2}}, {{0x04F7A0DD, 0xBFB50608}}, {{0xEDAF37D2, 0xBC239FF7}}}, {{{0xA0C05ED4, 0x3FF00C81}}, {{0x7A57AC2E, 0xBC7736A7}}, {{0xBD83E026, 0xBFB40535}}, {{0x5F0B8AC5, 0x3C4B9B73}}}, {{{0x53709EEA, 0x3FF00B49}}, {{0xF8CDACD0, 0xBC9DF4D4}}, {{0x7B47880C, 0xBFB30477}}, {{0x3B77E1B2, 0xBC517BE5}}}, {{{0x116B88B6, 0x3FF00A21}}, {{0xAAAEC5A4, 0xBC71D458}}, {{0x3D8440EF, 0xBFB203CC}}, {{0x41B5A4E1, 0x3C1EF162}}}, {{{0xD988DA1B, 0x3FF00908}}, {{0x94C96CA5, 0x3C9519B1}}, {{0x038EB7A7, 0xBFB10333}}, {{0x317BAEA7, 0x3C044B95}}}, {{{0xAAB05B20, 0x3FF00800}}, {{0x9FEBDB21, 0xBC936EB9}}, {{0xCCCD9CDD, 0xBFB002AA}}, {{0xFAC9C47C, 0x3C53A7FD}}}, {{{0x83D9DCD5, 0x3FF00708}}, {{0x430DE399, 0xBC9EC747}}, {{0x317148DD, 0xBFAE0465}}, {{0x7929765A, 0x3C4B5DB1}}}, {{{0x640D384F, 0x3FF00620}}, {{0x170FB049, 0xBC97FCBC}}, {{0xCDAF09CF, 0xBFAC0392}}, {{0x7D4F7337, 0x3C2B59CD}}}, {{{0x4A624DAE, 0x3FF00548}}, {{0x23E9C180, 0x3C5D0575}}, {{0x6D81EE12, 0xBFAA02DC}}, {{0x7E00BA39, 0x3C2A5E3B}}}, {{{0x36010336, 0x3FF00480}}, {{0x10BEB244, 0xBC89227D}}, {{0x10336ABF, 0xBFA80240}}, {{0xC229B627, 0x3C4941AF}}}, {{{0x26214474, 0x3FF003C8}}, {{0x45DFB29B, 0xBC4AE17A}}, {{0xB526F7CF, 0xBFA601BB}}, {{0x2DA1796B, 0x3C39422F}}}, {{{0x1A0B0179, 0x3FF00320}}, {{0xD21A4C9A, 0x3C9FA45B}}, {{0x5BD80F80, 0xBFA4014D}}, {{0xA4813A5B, 0xBC45A2E6}}}, {{{0x11162E22, 0x3FF00288}}, {{0x2A930764, 0x3C6F0E22}}, {{0x03D82DD0, 0xBFA200F3}}, {{0x0CBDB96B, 0xBC4BE9EF}}}, {{{0x0AAAC16C, 0x3FF00200}}, {{0x578DDD8D, 0x3C88618F}}, {{0xACCCD00D, 0xBFA000AA}}, {{0x1EFF67C8, 0xBBFD9E59}}}, {{{0x0640B4E1, 0x3FF00188}}, {{0x8827C989, 0x3C7FB10F}}, {{0xACDAE8F4, 0xBF9C00E4}}, {{0x22A0BAC6, 0xBBE94741}}}, {{{0x0360040D, 0x3FF00120}}, {{0x402EAB5F, 0xBC884C57}}, {{0x01033411, 0xBF980090}}, {{0xDD340191, 0xBC37E141}}}, {{{0x01A0AC06, 0x3FF000C8}}, {{0x673A2EEE, 0xBC7BD6C4}}, {{0x55BD803E, 0xBF940053}}, {{0xCA73460D, 0xBBD1997B}}}, {{{0x00AAAB06, 0x3FF00080}}, {{0x2ABAD90D, 0xBC93E2BE}}, {{0xAACCCCDA, 0xBF90002A}}, {{0x3AC1711C, 0x3C293021}}}, {{{0x00360010, 0x3FF00048}}, {{0xDB8F0A40, 0x3C899AE6}}, {{0x00103337, 0xBF880024}}, {{0xAF88B300, 0x3C250734}}}, {{{0x000AAAAC, 0x3FF00020}}, {{0x1862ADFD, 0x3C76C186}}, {{0xAAACCCCD, 0xBF80000A}}, {{0x9193923E, 0xBBBA01FC}}}, {{{0x0000AAAB, 0x3FF00008}}, {{0x8D68D67B, 0xBC93E93E}}, {{0xAAAACCCD, 0xBF700002}}, {{0x17BFB4DB, 0x3C093193}}}, {{{0x00000000, 0x3FF00000}}, {{0x00000000, 0x00000000}}, {{0x00000000, 0x00000000}}, {{0x00000000, 0x00000000}}}, {{{0x0000AAAB, 0x3FF00008}}, {{0x8D68D67B, 0xBC93E93E}}, {{0xAAAACCCD, 0x3F700002}}, {{0x17BFB4DB, 0xBC093193}}}, {{{0x000AAAAC, 0x3FF00020}}, {{0x1862ADFD, 0x3C76C186}}, {{0xAAACCCCD, 0x3F80000A}}, {{0x9193923E, 0x3BBA01FC}}}, {{{0x00360010, 0x3FF00048}}, {{0xDB8F0A40, 0x3C899AE6}}, {{0x00103337, 0x3F880024}}, {{0xAF88B300, 0xBC250734}}}, {{{0x00AAAB06, 0x3FF00080}}, {{0x2ABAD90D, 0xBC93E2BE}}, {{0xAACCCCDA, 0x3F90002A}}, {{0x3AC1711C, 0xBC293021}}}, {{{0x01A0AC06, 0x3FF000C8}}, {{0x673A2EEE, 0xBC7BD6C4}}, {{0x55BD803E, 0x3F940053}}, {{0xCA73460D, 0x3BD1997B}}}, {{{0x0360040D, 0x3FF00120}}, {{0x402EAB5F, 0xBC884C57}}, {{0x01033411, 0x3F980090}}, {{0xDD340191, 0x3C37E141}}}, {{{0x0640B4E1, 0x3FF00188}}, {{0x8827C989, 0x3C7FB10F}}, {{0xACDAE8F4, 0x3F9C00E4}}, {{0x22A0BAC6, 0x3BE94741}}}, {{{0x0AAAC16C, 0x3FF00200}}, {{0x578DDD8D, 0x3C88618F}}, {{0xACCCD00D, 0x3FA000AA}}, {{0x1EFF67C8, 0x3BFD9E59}}}, {{{0x11162E22, 0x3FF00288}}, {{0x2A930764, 0x3C6F0E22}}, {{0x03D82DD0, 0x3FA200F3}}, {{0x0CBDB96B, 0x3C4BE9EF}}}, {{{0x1A0B0179, 0x3FF00320}}, {{0xD21A4C9A, 0x3C9FA45B}}, {{0x5BD80F80, 0x3FA4014D}}, {{0xA4813A5B, 0x3C45A2E6}}}, {{{0x26214474, 0x3FF003C8}}, {{0x45DFB29B, 0xBC4AE17A}}, {{0xB526F7CF, 0x3FA601BB}}, {{0x2DA1796B, 0xBC39422F}}}, {{{0x36010336, 0x3FF00480}}, {{0x10BEB244, 0xBC89227D}}, {{0x10336ABF, 0x3FA80240}}, {{0xC229B627, 0xBC4941AF}}}, {{{0x4A624DAE, 0x3FF00548}}, {{0x23E9C180, 0x3C5D0575}}, {{0x6D81EE12, 0x3FAA02DC}}, {{0x7E00BA39, 0xBC2A5E3B}}}, {{{0x640D384F, 0x3FF00620}}, {{0x170FB049, 0xBC97FCBC}}, {{0xCDAF09CF, 0x3FAC0392}}, {{0x7D4F7337, 0xBC2B59CD}}}, {{{0x83D9DCD5, 0x3FF00708}}, {{0x430DE399, 0xBC9EC747}}, {{0x317148DD, 0x3FAE0465}}, {{0x7929765A, 0xBC4B5DB1}}}, {{{0xAAB05B20, 0x3FF00800}}, {{0x9FEBDB21, 0xBC936EB9}}, {{0xCCCD9CDD, 0x3FB002AA}}, {{0xFAC9C47C, 0xBC53A7FD}}}, {{{0xD988DA1B, 0x3FF00908}}, {{0x94C96CA5, 0x3C9519B1}}, {{0x038EB7A7, 0x3FB10333}}, {{0x317BAEA7, 0xBC044B95}}}, {{{0x116B88B6, 0x3FF00A21}}, {{0xAAAEC5A4, 0xBC71D458}}, {{0x3D8440EF, 0x3FB203CC}}, {{0x41B5A4E1, 0xBC1EF162}}}, {{{0x53709EEA, 0x3FF00B49}}, {{0xF8CDACD0, 0xBC9DF4D4}}, {{0x7B47880C, 0x3FB30477}}, {{0x3B77E1B2, 0x3C517BE5}}}, {{{0xA0C05ED4, 0x3FF00C81}}, {{0x7A57AC2E, 0xBC7736A7}}, {{0xBD83E026, 0x3FB40535}}, {{0x5F0B8AC5, 0xBC4B9B73}}}, {{{0xFA9315DF, 0x3FF00DC9}}, {{0x602B4C56, 0xBC84D0E2}}, {{0x04F7A0DD, 0x3FB50608}}, {{0xEDAF37D2, 0x3C239FF7}}}, {{{0x62311DF8, 0x3FF00F22}}, {{0xA7C410F3, 0x3C99322E}}, {{0x5275270D, 0x3FB606EF}}, {{0xE6EE4DC3, 0xBC56910E}}}, {{{0xD8F2DEDB, 0x3FF0108A}}, {{0x53B40698, 0x3C93DC21}}, {{0xA6E3D59B, 0x3FB707EC}}, {{0xF456FFFF, 0xBC5030B2}}}, {{{0x6040CF67, 0x3FF01203}}, {{0x422FB0BC, 0x3C9847C0}}, {{0x03411660, 0x3FB80901}}, {{0x10739476, 0x3C5DD342}}}, {{{0xF993770A, 0x3FF0138B}}, {{0xB809A4D7, 0xBC7502E0}}, {{0x68A15B27, 0x3FB90A2D}}, {{0x7F556554, 0x3C5B1BE3}}}, {{{0xA6736F36, 0x3FF01524}}, {{0xC450FC30, 0x3C930803}}, {{0xD8311EBE, 0x3FBA0B72}}, {{0x50193D71, 0x3C507AA8}}}, {{{0x687964EF, 0x3FF016CD}}, {{0x209297AD, 0xBC9D38AB}}, {{0x5335E625, 0x3FBB0CD2}}, {{0xFBDC145A, 0x3C480157}}}, {{{0x414E1A5C, 0x3FF01886}}, {{0xE0B191DA, 0x3C4976C5}}, {{0xDB0F41D4, 0x3FBC0E4C}}, {{0xC9BFC58B, 0xBC586525}}}, {{{0x32AA6878, 0x3FF01A4F}}, {{0x67BCC8B5, 0x3C833FDA}}, {{0x7137CF18, 0x3FBD0FE3}}, {{0x698E234C, 0xBC4AE71D}}}, {{{0x3E5740C5, 0x3FF01C28}}, {{0x9EC02117, 0x3C95D295}}, {{0x17463991, 0x3FBE1197}}, {{0x410E61A9, 0x3C5E1FCA}}}, {{{0x662DAF18, 0x3FF01E11}}, {{0x3120653C, 0xBC833F82}}, {{0xCEEE3CC9, 0x3FBF1368}}, {{0x7BD924AB, 0xBC5213E7}}}, {{{0xAC16DB6F, 0x3FF0200A}}, {{0x99576FC1, 0xBC809B4F}}, {{0xCD00D2F1, 0x3FC00AAC}}, {{0x146349DE, 0xBC53EA29}}}, {{{0x120C0BDE, 0x3FF02214}}, {{0x6B72974E, 0xBC9456D2}}, {{0x3D38AAB7, 0x3FC08BB5}}, {{0xD37D3177, 0x3C60FB6D}}}, {{{0x9A16A685, 0x3FF0242D}}, {{0x295277DB, 0xBC7352FD}}, {{0x392720B0, 0x3FC10CCE}}, {{0x1E4C8E28, 0x3C55A291}}}, {{{0x4650339C, 0x3FF02657}}, {{0x0688DD52, 0xBC31EC5D}}, {{0x41E53B8C, 0x3FC18DF8}}, {{0x50E682BB, 0x3C49852D}}}, {{{0x18E25F8B, 0x3FF02891}}, {{0x524ABA66, 0xBC9A7DA4}}, {{0xD89D0ECD, 0x3FC20F33}}, {{0x55A9198D, 0xBC6557F7}}}, {{{0x1406FD12, 0x3FF02ADB}}, {{0x720D8336, 0x3C969329}}, {{0x7E8A3BEF, 0x3FC29081}}, {{0x8F21151D, 0xBC65A4E2}}}, {{{0x3A080789, 0x3FF02D35}}, {{0xF6C7E6F8, 0xBC907780}}, {{0xB4FA73A6, 0x3FC311E1}}, {{0x4C87081D, 0xBC61065E}}}, {{{0x8D3FA521, 0x3FF02F9F}}, {{0x88A18235, 0xBC58A44A}}, {{0xFD4DF72A, 0x3FC39354}}, {{0x64EC3B0C, 0x3C4EAAC2}}}, {{{0x10182946, 0x3FF0321A}}, {{0xFE5F3FF1, 0x3C88FA5C}}, {{0xD8F81999, 0x3FC414DB}}, {{0x0B2260AC, 0xBC3E1438}}}, {{{0xC50C1706, 0x3FF034A4}}, {{0x7ECC2F29, 0xBC8A9076}}, {{0xC97FC168, 0x3FC49676}}, {{0x93C07384, 0xBC6B5D13}}}, {{{0xAEA6238A, 0x3FF0373F}}, {{0x72989A92, 0xBC73E9A1}}, {{0x507FE9EB, 0x3FC51826}}, {{0x6946DA28, 0xBC6AC219}}}, {{{0xCF8138A4, 0x3FF039EA}}, {{0x8FE6098D, 0x3C8ACC0C}}, {{0xEFA824F1, 0x3FC599EA}}, {{0x2B9BA1A8, 0xBC5F28E7}}}, {{{0x2A487769, 0x3FF03CA6}}, {{0xB95A2E63, 0xBC9585FD}}, {{0x28BD1C73, 0x3FC61BC5}}, {{0x2267ECEB, 0xBC625559}}}, {{{0xC1B73AD9, 0x3FF03F71}}, {{0xA8202E85, 0xBC885168}}, {{0x7D991458, 0x3FC69DB5}}, {{0x97B08BD2, 0xBC69321C}}}, {{{0x98991A9F, 0x3FF0424D}}, {{0xA130683D, 0x3C66BB23}}, {{0x702C6C4F, 0x3FC71FBC}}, {{0x00C832DD, 0x3C6BAA2A}}}, {{{0xB1C9EDDA, 0x3FF04539}}, {{0xC7598281, 0x3C8D2224}}, {{0x827E21C3, 0x3FC7A1DA}}, {{0x06D46085, 0x3C6CB79F}}}, {{{0x1035CDFA, 0x3FF04836}}, {{0xBBC5EC1C, 0xBC9E50AA}}, {{0x36AC51DD, 0x3FC82410}}, {{0xDF8CB355, 0x3C5A42DC}}}, {{{0xB6D919A9, 0x3FF04B42}}, {{0x92AA0A0B, 0xBC9F2338}}, {{0x0EECBBA5, 0x3FC8A65E}}, {{0x0663DF15, 0xBC6339DB}}}, {{{0xA8C077CC, 0x3FF04E5F}}, {{0xECF07BF2, 0xBC9D8190}}, {{0x8D8D4236, 0x3FC928C4}}, {{0x370EDF81, 0x3C556048}}}, {{{0xE908DA8C, 0x3FF0518C}}, {{0x25A535E2, 0x3C987D18}}, {{0x34F46F10, 0x3FC9AB44}}, {{0x57573053, 0x3C1274BC}}}, {{{0x7ADF8277, 0x3FF054CA}}, {{0x377A9F8C, 0x3C89C0C1}}, {{0x87A1F479, 0x3FCA2DDD}}, {{0xF07409B2, 0x3C67E5CE}}}, {{{0x618201A8, 0x3FF05818}}, {{0x5A557953, 0xBC8BFA98}}, {{0x082F3002, 0x3FCAB091}}, {{0x60BF022C, 0xBC4B6626}}}, {{{0xA03E3F07, 0x3FF05B76}}, {{0x2B52E765, 0x3C7CA615}}, {{0x394FAD1B, 0x3FCB335F}}, {{0x34B51ACE, 0x3C47F257}}}, {{{0x3A727999, 0x3FF05EE5}}, {{0x6647668D, 0x3C92512F}}, {{0x9DD1A7CC, 0x3FCBB648}}, {{0x3ED3824D, 0xBC234425}}}, {{{0x338D4BDC, 0x3FF06264}}, {{0xF34422A4, 0xBC90000F}}, {{0xB89E8F7F, 0x3FCC394D}}, {{0x52292D2D, 0x3C646F77}}}, {{{0x8F0DAF34, 0x3FF065F3}}, {{0xAF1520A9, 0xBC7821B3}}, {{0x0CBB89ED, 0x3FCCBC6F}}, {{0x51092884, 0x3C4B40A0}}}, {{{0x5082FF6E, 0x3FF06993}}, {{0xD7395A9F, 0x3C7685C4}}, {{0x1D49F620, 0x3FCD3FAD}}, {{0x26ECE4F0, 0xBC5DE851}}}, {{{0x7B8CFE4D, 0x3FF06D43}}, {{0xD1025E7E, 0xBC73ADF7}}, {{0x6D87EF96, 0x3FCDC308}}, {{0x2A97B34C, 0xBC6C0BD9}}}, {{{0x13DBD729, 0x3FF07104}}, {{0xCA5328ED, 0x3C766560}}, {{0x80D0D17F, 0x3FCE4681}}, {{0x658D0660, 0xBC605627}}}, {{{0x1D3022A1, 0x3FF074D5}}, {{0x2426EF93, 0x3C9E93F8}}, {{0xDA9DBA19, 0x3FCECA18}}, {{0x491D8A98, 0xBC36D470}}}, {{{0x9B5AEA5C, 0x3FF078B6}}, {{0x6B6D819B, 0xBC8880D6}}, {{0xFE860E28, 0x3FCF4DCE}}, {{0xC6A2C678, 0x3C6883D4}}}, {{{0x923DACD6, 0x3FF07CA8}}, {{0xE736D67A, 0xBC9653A7}}, {{0x703FFC8F, 0x3FCFD1A4}}, {{0xA8860819, 0x3C59EA3B}}}, {{{0x05CA6146, 0x3FF080AB}}, {{0xFC66378F, 0xBC723216}}, {{0xD9D08102, 0x3FD02ACC}}, {{0x20C03715, 0xBC5998B3}}}, {{{0xFA037B8F, 0x3FF084BD}}, {{0xE3C5EBFC, 0xBC7D97E2}}, {{0xA64F3673, 0x3FD06CD7}}, {{0x839871E4, 0x3C6370BA}}}, {{{0x72FBF041, 0x3FF088E1}}, {{0x0D55140F, 0xBC9DE12F}}, {{0xDFA6F09B, 0x3FD0AEF2}}, {{0xA7827088, 0xBC414E60}}}, {{{0x74D738AC, 0x3FF08D15}}, {{0xC4A8C043, 0xBC984BD5}}, {{0xC7F2EE53, 0x3FD0F11E}}, {{0xC5355AFC, 0x3C75BADF}}}, {{{0x03C95705, 0x3FF0915A}}, {{0x0BD1CD00, 0x3C78A8A6}}, {{0xA15F1D6C, 0x3FD1335B}}, {{0x341ED7B6, 0xBC53CE0F}}}, {{{0x2416DA9A, 0x3FF095AF}}, {{0x39DC7749, 0x3C8024A0}}, {{0xAE285CD6, 0x3FD175A9}}, {{0xC4496E39, 0xBC3DB749}}}, {{{0xDA14E415, 0x3FF09A14}}, {{0x233B29C8, 0xBC965668}}, {{0x309CBEE1, 0x3FD1B809}}, {{0xBBB1CB75, 0x3C6E5B16}}}, {{{0x2A2929D1, 0x3FF09E8B}}, {{0x535446B4, 0xBC9EE5F5}}, {{0x6B1BCB8A, 0x3FD1FA7A}}, {{0x5A4CB636, 0x3C50621A}}}, {{{0x18C9FC41, 0x3FF0A312}}, {{0x09E044C2, 0x3C885259}}, {{0xA016C2D9, 0x3FD23CFD}}, {{0x449D986B, 0xBC500762}}}, {{{0xAA7E4A68, 0x3FF0A7A9}}, {{0x281520E0, 0x3C71B296}}, {{0x1210DF54, 0x3FD27F93}}, {{0x502A1E59, 0xBC6EF999}}}, {{{0xE3DDA65B, 0x3FF0AC51}}, {{0x9DACA977, 0x3C9B22C0}}, {{0x039F9881, 0x3FD2C23B}}, {{0x9B082732, 0x3C577301}}}, {{{0xC99049DE, 0x3FF0B10A}}, {{0x610FCC2E, 0xBC617C2D}}, {{0xB76AE57E, 0x3FD304F5}}, {{0x42E4CA9C, 0xBC75EB09}}}, {{{0x604F1B07, 0x3FF0B5D4}}, {{0x07EECFA5, 0x3C732C14}}, {{0x702D7FA4, 0x3FD347C3}}, {{0x701422C8, 0x3C7435BE}}}, {{{0xACE3B0FC, 0x3FF0BAAE}}, {{0x75521E77, 0xBC93292F}}, {{0x70B52549, 0x3FD38AA4}}, {{0x0B01B8A6, 0xBC67F94B}}}, {{{0xB42858B8, 0x3FF0BF99}}, {{0x0B1F30A5, 0xBC67AD83}}, {{0xFBE2DC86, 0x3FD3CD98}}, {{0x269038FC, 0xBC7D0A5E}}}, {{{0x7B0819E9, 0x3FF0C495}}, {{0x6E52BA24, 0x3C9A26E0}}, {{0x54AB361D, 0x3FD410A1}}, {{0xCF7DA2E8, 0xBC78DCB6}}}, {{{0x067EBBDA, 0x3FF0C9A2}}, {{0x803D61F3, 0x3C813CD8}}, {{0xBE16906C, 0x3FD453BD}}, {{0x45D8536E, 0x3C78D781}}}, {{{0x5B98CA6C, 0x3FF0CEBF}}, {{0x09B9F220, 0x3C9E8080}}, {{0x7B415A78, 0x3FD496EE}}, {{0xBDFE61F1, 0xBC51C3BA}}}, {{{0x7F739B28, 0x3FF0D3ED}}, {{0xEA8A9ED5, 0xBC99722F}}, {{0xCF5C5703, 0x3FD4DA33}}, {{0x7BE71FBE, 0x3C7B1F07}}}, {{{0x773D5255, 0x3FF0D92C}}, {{0x3D5D1DA2, 0xBC84956C}}, {{0xFDACDFC5, 0x3FD51D8D}}, {{0x98966B86, 0xBC419F0E}}}, {{{0x4834E82E, 0x3FF0DE7C}}, {{0x5F430E44, 0xBC877BEC}}, {{0x498D28AA, 0x3FD560FD}}, {{0xCCEA8A26, 0xBC4F07B3}}}, {{{0xF7AA2E1B, 0x3FF0E3DC}}, {{0xF7FB3140, 0x3C9C05BD}}, {{0xF66C8331, 0x3FD5A481}}, {{0xCFF78DD1, 0x3C6E8E0C}}}, {{{0x8AFDD406, 0x3FF0E94E}}, {{0xB0B14F49, 0xBC9330CB}}, {{0x47CFA1DB, 0x3FD5E81C}}, {{0x4E7B2C63, 0xBC791EC5}}}, {{{0x07A16DB4, 0x3FF0EED1}}, {{0xD3E071F5, 0x3C988108}}, {{0x8150DBAB, 0x3FD62BCC}}, {{0xF95D00CA, 0x3C7700BD}}}, {{{0x73177841, 0x3FF0F464}}, {{0x29551C51, 0xBC97DF60}}, {{0xE6A06FC9, 0x3FD66F92}}, {{0xD9A66B42, 0xBC70A785}}}, {{{0xD2F35F97, 0x3FF0FA08}}, {{0x9DAB3AF1, 0x3C9B39D1}}, {{0xBB84C928, 0x3FD6B36F}}, {{0xFEFE1E5F, 0x3C68DAF8}}}, }; /* the coefficients for the cosh-approximations */ static const db_number c0 = {{0x00000000,0x3FF00000}}; /*1.0000000000e+00*/ static const db_number c2 = {{0x00000000,0x3FE00000}}; /*5.0000000000e-01*/ static const db_number c4 = {{0x55555555,0x3FA55555}}; /*4.1666666667e-02*/ static const db_number c6 = {{0x16C16C17,0x3F56C16C}}; /*1.3888888889e-03*/ static const db_number c8 = {{0x1A01A01A,0x3EFA01A0}}; /*2.4801587302e-05*/ /* the coefficients for the sinh-approximations */ static const db_number s1 = {{0x00000000,0x3FF00000}}; /*1.0000000000e+00*/ static const db_number s3 = {{0x55555555,0x3FC55555}}; /*1.6666666667e-01*/ static const db_number s5 = {{0x11111111,0x3F811111}}; /*8.3333333333e-03*/ static const db_number s7 = {{0x1A01A01A,0x3F2A01A0}}; /*1.9841269841e-04*/ #endif interval-3.2.0/src/crlibm/docs/latex/0_getting-started.tex0000644000000000000000000002720213316017127021644 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA \section{What is \crlibm?} The \crlibm\ project aims at developing a portable, proven, correctly rounded, and efficient mathematical library (\texttt{libm}) for double precision. \begin{description} \item[correctly rounded] Current \texttt{libm} implementation do not always return the floating-point number that is closest to the exact mathematical result. As a consequence, different \texttt{libm} implementation will return different results for the same input, which prevents full portability of floating-point applications. In addition, few libraries support but the round-to-nearest mode of the IEEE754/IEC 60559 standard for floating-point arithmetic (hereafter usually referred to as the IEEE-754 standard). \crlibm\ provides the four rounding modes: To nearest, to $+\infty$, to $-\infty$ and to zero. \item[portable] \crlibm\ is written in C and will be compiled by any compiler fulfilling basic requirements of the ISO/IEC 9899:1999 (hereafter referred to as C99) standard. This is the case of \texttt{gcc} version 3 and higher which is available on most computer systems. It also requires a floating-point implementation respecting the IEEE-754 standard, which is also available on most modern systems. \crlibm\ has been tested on a large range of systems. \item[proven] Other libraries attempt to provide correctly-rounded result. For theoretical and practical reasons, this behaviour is difficult to prove, and in extreme cases termination is not even guaranteed. \crlibm\ intends to provide a comprehensive proof of the theoretical possibility of correct rounding, the algorithms used, and the implementation, assuming C99 and IEEE-754 compliance. \item[efficient] performance and resource usage of \crlibm\ should be comparable to existing \texttt{libm} implementations, both in average and in the worst case. In contrast, other correctly-rounded libraries have worst case performance and memory consumption several order of magnitude larger than standard \texttt{libm}s. \end{description} The ultimate goal of the \crlibm\ project is to push towards the standardization of correctly-rounded elementary functions. \section{Compilation and installation} See the \texttt{INSTALL} file in the main directory. This library is developed using the GNU autotools, and can therefore be compiled on most Unix-like systems by \texttt{./configure; make}. The command \texttt{make check} will launch the selftest. For more advanced testing you will need to have MPFR installed (see \url{www.mpfr.org}) and to pass the \texttt{--enable-mpfr} flag to \texttt{configure}. For other flags, see \texttt{./configure --help} . \section{Using \texttt{crlibm} functions in your program} Currently \texttt{crlibm} functions have different names from the standard \texttt{math.h} functions. For example, for the sine function (\texttt{double sin(double)} in the standard \texttt{math.h}), you have four different functions in \texttt{crlibm} for the four different rounding modes. These functions are named \texttt{sin\_rn}, \texttt{sin\_ru}, \texttt{sin\_rd} and \texttt{sin\_rz} for round to the nearest, round up, round down and round to zero respectively. These functions are declared in the C header file \texttt{crlibm.h}. The \texttt{crlibm} library relies on double-precision IEEE-754 compliant floating-point operations. For some processors and some operating systems (most notably IA32 and IA64 processors under GNU/Linux), the default precision is set to double-extended. On such systems you will need to call the \texttt{crlibm\_init()} function before using any \texttt{crlibm} function to ensure such compliance. This has the effect of setting the processor flags to IEEE-754 double-precision with rounding to the nearest mode. This function returns the previous processor status, so that previous mode can be restored using the function \texttt{crlibm\_exit()}. Note that you probably only need one call to \texttt{crlibm\_init()} at the beginning of your program, not one call before each call to a mathematical function. Here is a non-exhaustive list of systems on which \texttt{crlibm\_init()} is NOT needed, and which can therefore use \crlibm\ as a transparent replacement of the standard \texttt{libm}: \begin{itemize} \item Most Power/PowerPC based systems, including those from Apple or from IBM; \item All the 64-bit Linux versions: the reason is that all x86-compatible processors (by AMD and Intel) supporting 64-bit addressing also feature SSE2 FP instructions, which are cleaner and more efficient than the legacy x87 FPU. On such systems, SSE2 is therefore used by default by \texttt{gcc} for double-precision FP computing. \item On recent 32-bit x86 processors also featuring SSE2 extensions (including pentium 4 and later, and generally most processors produced after 2005), you can try to force the use of SSE2 instructions using \texttt{configure --enable-sse2}. Beware, the code produced will not run on older hardware. \end{itemize} Here's an example function named \texttt{compare.c} using the cosine function from \texttt{crlibm} library. \begin{lstlisting}[label={chap0:lst:prog_example},caption={compare.c},firstnumber=1] #include #include #include int main(void){ double x, res_libm, res_crlibm; printf("Enter a floating point number: "); scanf("%lf", &x); res_libm = cos(x); crlibm_init(); /* no need here to save the old processor state returned by crlibm_init() */ res_crlibm = cos_rn(x); printf("\n x=%.25e \n", x); printf("\n cos(x) with the system : %.25e \n", res_libm); printf("\n cos(x) with crlibm : %.25e \n", res_crlibm); return 0; } \end{lstlisting} This example will be compiled with \texttt{gcc compare.c -lm -lcrlibm -o compare} \section{Currently available functions} The currently available functions are summarized in Table~\ref{tab:currentstate}. \begin{table}[t] \begin{center} \renewcommand{\arraystretch}{1.2} \begin{tabular}{|c|c|c|c|c||c|c|} \hline & \multicolumn{4}{c||}{\crlibm\ name} &\multicolumn{2}{c|}{State of the proof} \\ \cline{2-7} \raisebox{5pt}{C99} & to nearest & to $+ \infty$ & to $- \infty$ & to zero & Worst cases & Proof of the code \\ \hline\hline exp & exp\_rn & exp\_ru & exp\_rd & exp\_rz & complete& complete (formal)\\ \hline expm1 & expm1\_rn & expm1\_ru & expm1\_rd & expm1\_rz & complete & partial\\ \hline log & log\_rn & log\_ru & log\_rd & log\_rz & complete& complete\\ \hline log1p & log1p\_rn & log1p\_ru & log1p\_rd & log1p\_rz & complete& partial \\ \hline log2 & log2\_rn & log2\_ru & log2\_rd & log2\_rz & complete& partial\\ \hline log10 & log10\_rn & log10\_ru & log10\_rd & log10\_rz& complete& partial \\ \hline sin & sin\_rn & sin\_ru & sin\_rd & sin\_rz & $[-\pi, \pi]$& complete (paper+formal)\\ \hline cos & cos\_rn & cos\_ru & cos\_rd & cos\_rz & $[-\pi/2, \pi/2]$& complete (paper+formal)\\ \hline tan & tan\_rn & tan\_ru & tan\_rd & tan\_rz & $[-\pi/2, \pi/2]$& complete (paper+formal)\\ \hline asin & asin\_rn & asin\_ru & asin\_rd & asin\_rz & complete & partial \\ \hline acos & acos\_rn & acos\_ru & acos\_rd & acos\_rz & complete & partial\\ \hline atan & atan\_rn & atan\_ru & atan\_rd & atan\_rz & complete & complete (paper)\\ \hline sinh & sinh\_rn & sinh\_ru & sinh\_rd & sinh\_rz & complete & complete (paper)\\ \hline cosh & cosh\_rn & cosh\_ru & cosh\_rd & cosh\_rz & complete & complete (paper)\\ \hline sinpi & sinpi\_rn & sinpi\_ru & sinpi\_rd & sinpi\_rz & complete & complete (formal)\\ \hline cospi & cospi\_rn & cospi\_ru & cospi\_rd & cospi\_rz & complete & complete (formal)\\ \hline tanpi & tanpi\_rn & tanpi\_ru & tanpi\_rd & tanpi\_rz & $[2^{-25},2^{-5}]$& complete (formal)\\ \hline % asinpi & asinpi\_rn & asinpi\_ru & asinpi\_rd & asinpi\_rz & complete & partial \\ \hline % acospi & acospi\_rn & acospi\_ru & acospi\_rd & acospi\_rz & complete & partial\\ \hline atanpi & atanpi\_rn & atanpi\_ru & atanpi\_rd & atanpi\_rz & $[\tan(2^{-25}\pi),\tan(2^{-5}\pi)]$ & complete (paper)\\ \hline pow & pow\_rn & & & & see chapter \ref{chap:pow} & see chapter \ref{chap:pow}\\ \hline \end{tabular} \end{center} \caption{Current state of \crlibm.} \label{tab:currentstate} \end{table} Here are some comments on this table: \begin{itemize} \item Every function takes a double-precision number and returns a double-precision number. \item For trigonometric functions the angles are expressed in radian. \item The two last columns describe the state of the proof: \begin{itemize} \item The first indicates the state of the search for worst cases for correct rounding \cite{LMT98,Lef2000}. If it indicates ``complete'', it means that the function is guaranteed to return correct rounding on its whole floating-point input range. Otherwise, it mentions the interval on which the function is guaranteed to return correct rounding. Note that \crlibm\ is designed in such a way that there is a very high probability that it is correctly rounded everywhere, however this is not yet proven formally. This question is explained in details in section \ref{section:crlibm-presentation}. \item The second indicates the state of the proof of the code itself. Some (older) functions have a lengthy paper proof in this document, some other have a partial or complete formal proof using the Gappa proof assistant \cite{Melqu05,DinLauMel2005}. \end{itemize} \end{itemize} \section{Writing portable floating-point programs} Here are some rules to help you design programs which have to produce exactly the same results on different architectures and different operating systems. \begin{itemize} \item Try to use the same compiler on all the systems. \item Demand C99 compliance (pass the \texttt{-C99}, \texttt{-std=c99}, or similar flag to the compiler). For Fortran, demand F90 compliance. \item Call \texttt{crlibm\_init()} before you begin floating-point computation. This ensures that the computations will all be done in IEEE-754 double-precision with round to nearest mode, which is the largest precision well supported by most systems. On IA32 processors, problems may still occur for extremely large or extremely small values. \item Do not hesitate to rely heavily on parentheses (the compiler should respect them according to the standards, although of course some won't). Many times, wondering where the parentheses should go in an expression like \texttt{a+b+c+d} will even help you improve the accuracy of your code. \item Use \texttt{crlibm} functions in place of \texttt{math.h} functions. \end{itemize} %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/0_intro.tex0000644000000000000000000006631713316017127017704 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA \section{Correct rounding and elementary functions} \label{sect:intro} The need for accurate elementary functions is important in many critical programs. Methods for computing these functions include table-based methods\cite{Far81,Tan91}, polynomial approximations and mixed methods\cite{DauMor2k}. See the books by Muller\cite{Muller97} or Markstein\cite{Markstein2000} for recent surveys on the subject. The IEEE-754 standard for floating-point arithmetic\cite{IEEE754} defines the usual floating-point formats (single and double precision). It also specifies the behavior of the four basic operators ($+,-,\times,\div$) and the square root in four rounding modes (to the nearest, towards $+\infty$, towards $-\infty$ and towards $0$). Its adoption and widespread use have increased the numerical quality of, and confidence in floating-point code. In particular, it has improved \emph{portability} of such code and allowed construction of \emph{proofs} on its numerical behavior. Directed rounding modes (towards $+\infty$, $-\infty$ and $0$) also enabled efficient \emph{interval arithmetic}\cite{Moore66,KKLRW93}. However, the IEEE-754 standard specifies nothing about elementary functions, which limits these advances to code excluding such functions. Currently, several options exist: on one hand, one can use today's mathematical libraries that are efficient but without any warranty on the correctness of the results. To be fair, most modern libraries are \emph{accurate-faithful}: trying to round to nearest, they return a number that is one of the two FP numbers surrounding the exact mathematical result, and indeed return the correctly rounded result most of the time. This behaviour is sometimes described using phrases like \emph{99\% correct rounding} or \emph{0.501 ulp accuracy}. When stricter guarantees are needed, some multiple-precision packages like MPFR \cite{MPFRweb} offer correct rounding in all rounding modes, but are several orders of magnitude slower than the usual mathematical libraries for the same precision. Finally, there are are currently three attempts to develop a correctly-rounded \texttt{libm}. The first was IBM's \texttt{libultim}\cite{IBMlibultimweb} which is both portable and fast, if bulky, but lacks directed rounding modes needed for interval arithmetic. The second was Ar\'enaire's \texttt{crlibm}, which was first distributed in 2003. The third is Sun correctly-rounded mathematical library called \texttt{libmcr}, whose first beta version appeared in 2004. These libraries are reviewed in \ref{section:lib-overview}. The goal of the \crlibm\ project is to build on a combination of several recent theoretical and algorithmic advances to design a proven correctly rounded mathematical library, with an overhead in terms of performance and resources acceptable enough to replace existing libraries transparently. More generally, the \crlibm\ project serves as an open-source framework for research on software elementary functions. As a side effect, it may be used as a tutorial on elementary function development. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{A methodology for efficient correctly-rounded functions} \label{section:methodology} \subsection{The Table Maker's Dilemma} With a few exceptions, the image $\hat{y}$ of a floating-point number $x$ by a transcendental function $f$ is a transcendental number, and can therefore not be represented exactly in standard numeration systems. The only hope is to compute the floating-point number that is closest to (resp. immediately above or immediately below) the mathematical value, which we call the result \emph{correctly rounded} to the nearest (resp. towards $+\infty$ or towards $-\infty$). It is only possible to compute an approximation ${y}$ to the real number $\hat{y}$ with precision $\maxeps{}$. This ensures that the real value $\hat{y}$ belongs to the interval $[{y}(1-\maxeps{}) , {y}(1+\maxeps{})]$. Sometimes however, this information is not enough to decide correct rounding. For example, if $[{y}(1-\maxeps{}) , {y}(1+\maxeps{})]$ contains the middle of two consecutive floating-point numbers, it is impossible to decide which of these two numbers is the correctly rounded to the nearest of $\hat{y}$. This is known as the Table Maker's Dilemma (TMD). For example, if we consider a numeration system in radix $2$ with $n$-bit mantissa floating point number and $m$ the number of significant bit in $y$ such that $\maxeps{} \leq 2^m$, then the TMD occurs: \begin{itemize} \item for rounding toward $+\infty$, $-\infty$, $0$, when the result is of the form: $$\overbrace{\underbrace{1.xxx...xx}_{n~bits}111111...11}^{m~bits}xxx...$$ or: $$\overbrace{\underbrace{1.xxx...xx}_{n~bits}000000...00}^{m~bits}xxx...$$ \item for rounding to nearest, when the result is of the form: $$\overbrace{\underbrace{1.xxx...xx}_{n~bits}011111...11}^{m~bits}xxx...$$ or : $$\overbrace{\underbrace{1.xxx...xx}_{n~bits}100000...00}^{m~bits}xxx...$$ \end{itemize} \subsection{The onion peeling strategy} A method described by Ziv \cite{Ziv91} is to increase the precision $\maxeps$ of the approximation until the correctly rounded value can be decided. Given a function $f$ and an argument $x$, the value of $f(x)$ is first evaluated using a quick approximation of precision $\maxeps_1$. Knowing $\maxeps_1$, it is possible to decide if rounding is possible, or if more precision is required, in which case the computation is restarted using a slower approximation of precision $\maxeps_2$ greater than $\maxeps_1$, and so on. This approach makes sense even in terms of average performance, as the slower steps are rarely taken. However there was until recently no practical bound on the termination time of such an algorithm. This iteration has been proven to terminate, but the actual maximal precision required in the worst case is unknown. This might prevent using this method in critical application. \section{The Correctly Rounded Mathematical Library} \label{section:crlibm-presentation} Our own library, called \crlibm\ for \emph{correctly rounded mathematical library}, is based on the work of Lef\`evre and Muller \cite{LMT98,Lef2000} who computed the worst-case $\maxeps$ required for correctly rounding several functions in double-precision over selected intervals in the four IEEE-754 rounding modes. For example, they proved that 157 bits are enough to ensure correct rounding of the exponential function on all of its domain for the four IEEE-754 rounding modes. \subsection{Two steps are enough} Thanks to such results, we are able to guarantee correct rounding in two iterations only, which we may then optimize separately. The first of these iterations is relatively fast and provides between 60 and 80 bits of accuracy (depending on the function), which is sufficient in most cases. It will be referred throughout this document as the \quick\ phase of the algorithm. The second phase, referred to as the \accurate\ phase, is dedicated to challenging cases. It is slower but has a reasonably bounded execution time, tightly targeted at Lef\`evre's worst cases. Having a proven worst-case execution time lifts the last obstacle to a generalization of correctly rounded transcendentals. Besides, having only two steps allows us to publish, along with each function, a proof of its correctly rounding behavior. \subsection{Portable IEEE-754 FP for a fast first step} The computation of a tight bound on the approximation error of the first step ($\maxeps_1$) is crucial for the efficiency of the onion peeling strategy: overestimating $\maxeps_1$ means going more often than needed through the second step, as will be detailed below in \ref{sec:error-accuracy-perf}. As we want the proof to be portable as well as the code, our first steps are written in strict IEEE-754 arithmetic. On some systems, this means preventing the compiler/processor combination to use advanced floating-point features such as fused multiply-and-add or extended double precision. It also means that the performance of our portable library will be lower than optimized libraries using these features (see \cite{DinErshGast2005} for recent research on processor-specific correct-rounding). To ease these proofs, our first steps make wide use of classical, well proven results like Sterbenz' lemma or other floating-point theorems. When a result is needed in a precision higher than double precision (as is the case of $y_1$, the result of the first step), it is represented as as the sum of two floating-point numbers, also called a \emph{double-double} number. There are well-known algorithms for computing on double-doubles, and they are presented in the next chapter. An advantage of properly encapsulating double-double arithmetic is that we can actually exploit fused multiply-and-add operators in a transparent manner (this experimental feature is currently available for the Itanium and PowerPC platforms, when using the \texttt{gcc} compiler). At the end of the \quick\ phase, a sequence of simple tests on $y_1$ knowing $\maxeps_1$ allows to decide whether to go for the second step. The sequence corresponding to each rounding mode is shared by most functions and is also carefully proven in the next chapter. \subsection{Ad-hoc, fast multiple precision for accurate second step} For the second step, we may use two specific multiple-precision libraries: \begin{itemize} \item We first designed an ad-hoc multiple-precision library called Software Carry-Save library \emph{(scslib)} which is lighter and faster than other available libraries for this specific application \cite{DefDin2002,DinDef2003}. This choice is motivated by considerations of code size and performance, but also by the need to be independent of other libraries: Again, we need a library on which we may rely at the proof level. This library is included in \crlibm, but also distributed separately \cite{SCSweb}. This library is described in more details in \ref{sec:SCSLib}. \item More recently, we have been using redundant triple-double arithmetic for the second step. This approach is lighter, about ten times faster, and has the advantage of making it easier to reuse information from the fast step in the accurate one. The drawback is that it is more difficult to master. The basic triple-double procedures, and associated usage theorems, are described in a separate document (\texttt{tripledoubleprocedures.pdf}) also available in this distribution. \end{itemize} \subsection{Relaxing portability} The \crlibm\ framework has been used to study the performance advantage of using double-extended (DE) arithmetic when available. More specifically, the first case may be implemented fully in DE precision, and the second step may be implemented fully in double-DE arithmetic. Experiments have been performed on the logarithm and arctangent functions \cite{DinErshGast2005}. On some systems (mostly Linux on an IA32 processor) the logarithm will by default use this technology. Another useful, non-portable hardware feature is the fused multiply-and-add available on Power/PowerPC and Itanium. The \crlibm\ code does its best to use it when available. \subsection{Proving the correct rounding property} Throughout this document, what we call ``proving'' a function mostly means proving a tight bound on the total relative error of our evaluation scheme. The actual proof of the correct rounding property is then dependent on the availability of an actual worst-case accuracy for correctly rounding this function, as computed by Lef\`evre and Muller. Three cases may happen: \begin{itemize} \item The worst case have been computed over the whole domain of the function. In this case the correct rounding property for this function is fully proven. The state of this search for worst cases is described in Table~\ref{tab:currentstate} page~\pageref{tab:currentstate}. \item The worst cases have been computed only over a subdomain of the function. Then the correct rounding property is proven on this subdomain. Outside of this domain \texttt{crlibm} offers ``astronomical confidence'' that the function is correctly rounded: to the best of current knowledge \cite{Gal86, DinErshGast2005}, the probability of the existence of a misrounded value in the function's domain is lower than $2^{-40}$. This is the case of the trigonometric functions, for instance. The actual domain on which the proof is complete is mentionned in the respective chapter of this document, and summed up in Table~\ref{tab:currentstate}. \item The search for worst cases hasn't begun yet. \end{itemize} We acknowledge that the notion of astronomical confidence breaks the objective of guaranteed correct rounding, and we sidestep this problem by publishing along with the library (in this document) the domain of full confidence, which will only expand as time goes. Such behaviour has been proposed as a standard in \cite{DefHanLefMulRevZim2004}. The main advantage of this approach is that it ensures bounded and consistent worst-case execution time (within a factor 100 of that of the best available faithful \texttt{libm}s), which we believe is crucial to the generalization of correctly rounded functions. The alternative to our approach would be to implement a multi-layer onion-peeling strategy, as do GNU MPFR and Sun's \texttt{libmcr}. There are however many drawbacks to this approach, too: \begin{itemize} \item One may argue that, due to the finite nature of computers, it only pushes the bounds of astronomy a little bit further. \item The multilayer approach is only proven to terminate on elementary functions: the termination proof needs a theorem stating for example that the image of a rational by the function (with some well-known exceptions) will not be a rational. For other library functions like special functions, we have no such theorem. For these functions, we prefer take the risk of a misrounded value than the risk of an infinite loop. \item Similarly, the multilayer approach has potentially unbounded execution time and memory consumption which make it unsuitable for real-time or safety-critical applications, whereas crlibm will only be unsuitable if the safety depends on correct rounding, which is much less likely. \item Multilayer code is probably much more complex and error prone. One important problem is that it contains code that, according all probabilities, will never be run. Therefore, testing this code can not be done on the final production executable, but on a different executable in which previous layers have been disabled. This introduces the possibility of undetected bugs in the final production executable. \end{itemize} In the future, we will add, to those \texttt{crlibm} functions for which the required worst-case accuracy is unknown, a misround detection test at the end of the second step. This test will either print out on standard error a lengthy warning inviting to report this case, or launch MPFR computation, depending on a compilation switch. % TODO \subsection{Error analysis and the accuracy/performance tradeoff \label{sec:error-accuracy-perf}} As there are two steps on the evaluation, the proof also usually consists of two parts. The code of the second, accurate step is usually very simple and straightforward: \begin{itemize} \item Performance is not that much of an issue, since this step is rarely taken. \item All the special cases have already been filtered by the first step. \item The \texttt{scslib} library provides an overkill of precision. \end{itemize} Therefore, the error analysis of the second step, which ultimately proves the correct rounding property, is not very difficult. For the first step, however, things are more complicated: \begin{itemize} \item We have to handle special cases (infinities, NaNs, signed zeroes, over- and underflows). \item Performance is a primary concern, sometimes leading to ``dirty tricks'' obfuscating the code. \item We have to compute a \emph{tight} error bound, as explained below. \end{itemize} Why do we need a tight error bound? Because the decision to launch the second step is taken by a \emph{rounding test} depending on \begin{itemize} \item the approximation $y_h+y_l$ computed in the first step, and \item this error bound $\maxeps_1$, which is computed statically. \end{itemize} The various rounding tests are detailed and proven in \ref{section:testrounding}. The important notion here is that \emph{the probability of launching the second, slower step will be proportional to the error bound $\maxeps_1$ computed for the first step}. This defines the main performance tradeoff one has to manage when designing a correctly-rounded function: The average evaluation time will be \begin{equation} T_{\mbox{\small avg}} = T_1 + p_2T_2 \label{eq:Tavg} \end{equation} where $T_1$ and $T_2$ are the execution time of the first and second phase respectively (with $T_2\approx 100T_1$ in \crlibm), and $p_2$ is the probability of launching the second phase (typically we aim at $p_2=1/1000$ so that the average cost of the second step is less than $10\%$ of the total. As $p_2$ is almost proportional to $\maxeps_1$, to minimise the average time, we have to \begin{itemize} \item balance $T_1$ and $p_2$: this is a performance/precision tradeoff (the faster the first step, the less accurate) \item and compute a tight bound on the overall error $\maxeps_1$. \end{itemize} Computing this tight bound is the most time-consuming part in the design of a correctly-rounded elementary function. The proof of the correct rounding property only needs a proven bound, but a loose bound will mean a larger $p_2$ than strictly required, which directly impacts average performance. Compare $p_2=1/1000$ and $p_2=1/500$ for $T_2=100T_1$, for instance. As a consequence, when there are multiple computation paths in the algorithm, it makes sense to precompute different values of $\maxeps_1$ on these different paths (see for instance the arctangent and the logarithm). Apart from these considerations, computing the errors is mostly textbook science. Care must be taken that only \emph{absolute} error terms (noted $\delta$) can be added, although some error terms (like the rounding error of an IEEE operation) are best expressed as \emph{relative} (noted $\epsilon$). Remark also that the error needed for the theorems in \ref{section:testrounding} is a \emph{relative} error. Managing the relative and absolute error terms is very dependent on the function, and usually involves keeping upper and lower bounds on the values manipulated along with the error terms. Error terms to consider are the following: \begin{itemize} \item approximation errors (minimax or Taylor), \item rounding error, which fall into two categories: \begin{itemize} \item roundoff errors in values tabulated as doubles or double-doubles (with the exception of roundoff errors on the coefficient of a polynomial, which are counted in the appproximation error), \item roundoff errors in IEEE-compliant operations. \end{itemize} \end{itemize} \section{An overview of other available mathematical libraries\label{section:lib-overview}} Many high-quality mathematical libraries are freely available and have been a source of inspiration for this work. Most mathematical libraries do not offer correct rounding. They can be classified as \begin{itemize} \item portable libraries assuming IEEE-754 arithmetic, like \emph{fdlibm}, written by Sun\cite{FDLIBMweb}; \item Processor-specific libraries, by Intel\cite{HarKubStoTan99,IntelOpenSource} and HP\cite{Markstein2000,Markstein2001} among other. \end{itemize} Operating systems often include several mathematical libraries, some of which are derivatives of one of the previous. To our knowledge, three libraries currently offer correct rounding: \begin{itemize} \item The \emph{libultim} library, also called MathLib, is developed at IBM by Ziv and others \cite{IBMlibultimweb}. It provides correct rounding, under the assumption that 800 bits are enough in all case. This approach suffers two weaknesses. The first is the absence of proof that 800 bits are enough: all there is is a very high probability. The second is that, as we will see in the sequel, for challenging cases, 800 bits are much of an overkill, which can increase the execution time up to 20,000 times a normal execution. This will prevent such a library from being used in real-time applications. Besides, to prevent this worst case from degrading average performance, there is usually some intermediate levels of precision in MathLib's elementary functions, which makes the code larger, more complex, and more difficult to prove (and indeed this library is scarcely documented). In addition this library provides correct rounding only to nearest. This is the most used rounding mode, but it might not be the most important as far as correct rounding is concerned: correct rounding provides a precision improvement over current mathematical libraries of only a fraction of a {unit in the last place} \emph{(ulp)}. Conversely, the three other rounding modes are needed to guarantee intervals in interval arithmetic. Without correct rounding in these directed rounding modes, interval arithmetic looses up to one \emph{ulp} of precision in each computation. \item \emph{MPFR} is a multiprecision package safer than \emph{libultilm} as it uses arbitrary multiprecision. It provides most of elementary functions for the four rounding modes defined by the IEEE-754 standard. However this library is not optimized for double precision arithmetic. In addition, as its exponent range is much wider than that of IEEE-754, the subtleties of subnormal numbers are difficult to handle properly using such a multiprecision package. \item The \texttt{libmcr} library, by K.C. Ng, Neil Toda and others at Sun Microsystems, had its first beta version published in december 2004. Its purpose is to be a reference implementation for correctly rounded functions in double precision. It has very clean code, offers arbitrary multiple precision unlike \texttt{libultim}, at the expense of slow performance (due to, for example dynamic allocation of memory). It offers the directed rounding modes, and rounds in the mode read from the processor status flag. \end{itemize} \section{Various policies in \crlibm} \subsection{Naming the functions} Current \crlibm\ doesn't by default replace your existing \texttt{libm}: the functions in \crlibm\ have the C99 name, suffixed with \texttt{\_rn}, \texttt{\_ru}, \texttt{\_rd}, and \texttt{\_rz} for rounding to the nearest, up, down and to zero respectively. They require the processor to be in round to nearest mode. Starting with version 0.9 we should provide a compile-time flag which will overload the default \texttt{libm} functions with the crlibm ones with rounding to nearest. It is interesting to compare this to the behaviour of Sun's library: First, Sun's \texttt{libmcr} provides only one function for each C99 function instead of four in \crlibm, and rounds according to the processor's current mode. This is probably closer to the expected long-term behaviour of a correctly-rounded mathematical library, but with current processors it may have a tremendous impact on performance. Besides, the notion of ``current processor rounding mode'' is no longer relevant on recent processors like the Itanium family, which have up to four different modes at the same time. A second feature of \texttt{libmcr} is that it overloads by default the system \texttt{libm}. The policy implemented in current \crlibm\ intends to provide best performance to the two classes of users who will be requiring correct rounding: Those who want predictible, portable behaviour of floating-point code, and those who implement interval arithmetic. Of course, we appreciate any feedback on this subject. \subsection{Policy concerning IEEE-754 flags} Currently, the \crlibm\ functions try to raise the Overflow and Underflow flags properly. Raising the other flags (especially the Inexact flag) is possible but considered too costly for the expected use, and will usually not be implemented. We also appreciate feedback on this subject. \subsection{Policy concerning conflicts between correct rounding and expected mathematical properties} As remarked in \cite{DefHanLefMulRevZim2004}, it may happen that the requirement of correct rounding conflicts with a basic mathematical property of the function, such as its domain and range. A typical example is the arctangent of a very large number which, rounded up, will be a number larger than $\pi/2$ (fortunately, $\round(\pi/2) < \pi/2$). The policy that will be implemented in \crlibm\ will be \begin{itemize} \item to give priority to the mathematical property in round to nearest mode (so as not to hurt the innocent user who may expect such a property to be respected), and \item to give priority to correct rounding in the directed rounding modes, in order to provide trustful bounds to interval arithmetic. \end{itemize} Again, this policy is open to discussion. \section{Organization of the source code} For recent functions implemented using triple-double arithmetic, both quick and accurate phase are provided in a single source file, \emph{e.g.} \texttt{exp-td.c}. For older functions using the SCS library, each function is implemented as two files, one with the \texttt{\_accurate} suffix (for instance \texttt{trigo\_accurate.c}), the other named with the \texttt{\_fast} suffix (for instance \texttt{trigo\_fast.c}). The \emph{software carry-save} multiple-precision library is contained in a subdirectory called \texttt{scs\_lib}. The common C routines that are detailed in Chapter~\ref{chap:common} of this document are defined in \texttt{crlibm\_private.c} and \texttt{crlibm\_private.h}. Many of the constants used in the C code have been computed thanks to Maple procedures which are contained in the \texttt{maple} subdirectory. Some of these procedures are explained in Chapter~\ref{chap:common}. For some functions, a Maple procedure mimicking the C code, and used for debugging or optimization purpose, is also available. The code also includes programs to test the \texttt{crlibm} functions against MPFR, \texttt{libultim} or \texttt{libmcr}, in terms of correctness and performance. They are located in the \texttt{tests} directory. Gappa proof scripts are located in the \texttt{gappa} directory. %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/1_common.tex0000644000000000000000000025155613316017127020043 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA % Common notations, theorems and procedures \section{Notations\label{section:notations}} The following notations will be used throughout this document: \begin{itemize} \item $+$, $-$ and $\times$ denote the usual mathematical operations. \item $\oplus$, $\ominus$ and $\otimes$ denote the corresponding floating-point operations in IEEE-754 double precision, in the IEEE-754 \emph{round to nearest} mode. \item $\round(x)$, $\roundup(x)$ and $\rounddown(x)$ denote the value of $x$ rounded to the nearest, resp. rounded up and down. \item $\epsilon$ (usually with some index) denotes a relative error, $\delta$ denotes an absolute error. Upper bounds on the absolute value of these errors will be denoted $\maxeps$ and $\maxdelta$. \item $\maxeps_{-k}$ -- with a negative index -- represents an error $e$ such that $|e| \leq 2^{-k}$. \item For a floating-point number $x$, the value of the least significant bit of its mantissa is classically denoted $\ulp(x)$. \end{itemize} \section{Common C procedures for double-precision numbers\label{section:commonCdouble}} \subsection{Sterbenz Lemma \label{sec:sterbenz}} \begin{theorem}[Sterbenz Lemma~\cite{Ste74,Gol91}] \label{sterbenz} If $x$ and $y$ are floating-point numbers, and if ${y}/{2} \leq x \leq 2y$ then $x\ominus y$ is computed exactly, without any rounding error. \end{theorem} \subsection{Double-precision numbers in memory\label{section:memory}} A double precision floating-point number uses $64$ bits. The unit of memory in most current architectures is a 32-bit word. The order in which the two $32$ bits words of a double are stored in memory depends on the architecture. An architecture is said \emph{Little Endian} if the lower part of the number is stored in memory at the smallest address; It is the case of the x86 processors. Conversely, an architecture with the high part of the number stored in memory at the smallest address is said \emph{Big Endian}; It is the case of the PowerPC processors. In \crlibm, we extract the higher and lower parts of a double by using an union in memory: the type \texttt{db\_number}. The following code extracts the upper and lower part from a double precision number $x$. \begin{lstlisting}[label={chap0:lst:endian}, caption={Extract upper and lower part of a double precision number $x$},firstnumber=1] /* HI and LO are defined automatically by autoconf/automake. */ db_number xx; int x_hi, x_lo; xx.d = x; x_hi = xx.i[HI] x_lo = xx.i[LO] \end{lstlisting} \subsection{Conversion from floating-point to integer \label{sec:double2int}} \begin{theorem}[Conversion floating-point to integer] The following algorithm, taken from \cite{AMDoptim2001}, converts a double-precision floating-point number $d$ into a 32-bit integer $i$ with rounding to nearest mode. It works for all the doubles whose nearest integer fits on a 32-bit machine signed integer. \begin{lstlisting}[label={chap0:lst:conversion2},caption={Conversion from FP to int},firstnumber=1] #define DOUBLE2INT(i, d) \ {double t=(d+6755399441055744.0); i=LO(t);} \end{lstlisting} \end{theorem} This algorithm adds the constant $2^{52}+2^{51}$ to the floating-point number to put the integer part of $x$, in the lower part of the floating-point number. We use $2^{52}+2^{51}$ and not $2^{52}$, because the value $2^{51}$ is used to contain possible carry propagations with negative numbers. \subsection{Conversion from floating-point to 64-bit integer \label{sec:double2longint}} \begin{theorem}[Conversion floating-point to a long long integer] The following algorithm, is derived from the previous. It works for any double whose nearest integer is smaller than $2^{51} -1$. \begin{lstlisting}[label={chap0:lst:conversion3},caption={Conversion from FP to long long int},firstnumber=1] #define DOUBLE2LONGINT(i, d) \ { \ db_number t; \ t.d = (d+6755399441055744.0); \ if (d >= 0) /* sign extend */ \ i = t.l & 0x0007FFFFFFFFFFFFLL; \ else \ i = (t.l & 0x0007FFFFFFFFFFFFLL) | (0xFFF8000000000000LL); \ } \end{lstlisting} \end{theorem} \subsection{Methods to raise IEEE-754 flags} The IEEE standard imposes, in certain cases, to raise flags and/or exceptions for the $4$ operators ($+$, $\times$, $\div$, $\sqrt{~}$). Therefore, it is legitimate to require the same for elementary functions. In ISO C99, the following instructions raise exceptions and flags: \begin{itemize} \item {\bf underflow} : the multiplication $\pm smallest \times smallest$ where $smallest$ correspond to the smallest subnormal number, \item {\bf overflow} : the multiplication $\pm largest \times largest$ where $largest$ correspond to the largest normalized number, \item {\bf division by zero} : the division $\pm 1.0/0.0$, \item {\bf inexact} : the addition $(x + smallest) - smallest$ where $x$ is the result and $smallest$ the smallest subnormal number, \item {\bf invalid} : the division $\pm 0.0/0.0$. \end{itemize} \section{Common C procedures for double-double arithmetic\label{section:commonCdoubledouble}} Hardware operators are usualy limited to double precision. To perform operations with more precision, then software solutions need to be used. One among them is to represent a floating point number as the sum of two non-overlapping floating-point numbers (or \emph{double-double} numbers). The algorithms are given as plain C functions, but it may be preferable, for performance issue, to implement them as macros, as in \texttt{libultim}. The code offers both versions, selected by the \texttt{DEKKER\_AS\_FUNCTIONS} constant which is set by default to 1 (functions). A more recent proof is available in \cite{Lauter2005LIP:tripledouble}. \subsection{Exact sum algorithm {Add12}} This algorithm is also known as the Fast2Sum algorithm in the litterature. \begin{theorem}[Exact sum~\cite{Knu73, Boldo2001}] Let $a$ and $b$ be floating-point numbers, then the following method computes two floating-point numbers $s$ and $r$, such that $s+r = a+b$ exactly, and $s$ is the floating-point number which is closest to $a+b$. \begin{lstlisting}[label={lst:Add12Cond},caption={Add12Cond},firstnumber=1] void Add12Cond(double *s, double *r, a, b) { double z; s = a + b; if (ABS(a) > ABS(b)){ z = s - a; r = b - z; }else { z = s - b; r = a - z; } } \end{lstlisting} Here ABS is a macro that returns the absolute value of a floating-point number. This algorithm requires $4$ floating-point additions and $2$ floating point tests (some of which are hidden in the ABS macro). Note that if it is more efficient on a given architecture, the test can be replaced with a test on the exponents of $a$ and $b$. \end{theorem} If we are able to prove that the exponent of $a$ is always greater than that of $b$, then the previous algorithm to perform an exact addition of 2 floating-point numbers becomes : \begin{lstlisting}[label={lst:Add12},caption={Add12},firstnumber=1] void Add12(double *s, double *r, a, b) { double z; s = a + b; z = s - a; r = b - z; } \end{lstlisting} The cost of this algorithm is $3$ floating-point additions. \subsection{Exact product algorithm {Mul12}} This algorithm is sometimes also known as the Dekker algorithm \cite{Dek71}. It was proven by Dekker but the proof predates the IEEE-754 standard and is difficult to read. An easier proof is available in \cite{Gol91} (see Th. 14). \begin{theorem}[Restricted exact product] Let $a$ and $b$ be two double-precision floating-point numbers, with 53 bits of mantissa. Let $c=2^{\lceil\frac{ 53}{2} \rceil}+1$. Assuming that $a<2^{970}$ and $b<2^{970}$, the following procedure computes the two floating-point numbers $rh$ and $rl$ such that $rh + rl = a + b$ with $rh = a \otimes b$: \begin{lstlisting}[label={lst:Mul12},caption={Mul12},firstnumber=1] void Mul12(double *rh, double *rl, double u, double v){ const double c = 134217729.; /* 1+2^27 */ double up, u1, u2, vp, v1, v2; up = u*c; vp = v*c; u1 = (u-up)+up; v1 = (v-vp)+vp; u2 = u-u1; v2 = v-v1; *rh = u*v; *rl = (((u1*v1-*rh)+(u1*v2))+(u2*v1))+(u2*v2); } \end{lstlisting} \end{theorem} The cost of this algorithm is $10$ floating-point additions and $7$ floating-point multiplications. The condition $a<2^{970}$ and $b<2^{970}$ prevents overflows when multiplying by $c$. If it cannot be proved statically, then we have to first test $a$ and $b$, and prescale them so that the condition is true. \begin{theorem}[Exact product] Let $a$ and $b$ be two double-precision floating-point numbers, with 53 bits of mantissa. Let $c=2^{\lceil\frac{ 53 }{2}\rceil}+1$. The following procedure computes the two floating-point numbers $rh$ and $rl$ such that $rh + rl = a + b$ with $rh = a \otimes b$: \begin{lstlisting}[label={lst:Mul12Cond},caption={Mul12Cond},firstnumber=1] void Mul12Cond(double *rh, double *rl, double a, double b){ const double two_970 = 0.997920154767359905828186356518419283e292; const double two_em53 = 0.11102230246251565404236316680908203125e-15; const double two_e53 = 9007199254740992.; double u, v; if (a>two_970) u = a*two_em53; else u = a; if (b>two_970) v = b*two_em53; else v = b; Mul12(rh, rl, u, v); if (a>two_970) {*rh *= two_e53; *rl *= two_e53;} if (b>two_970) {*rh *= two_e53; *rl *= two_e53;} }\end{lstlisting} \end{theorem} The cost in the worst case is then $4$ tests over integers, $10$ floating-point additions and $13$ floating-point multiplications. Finally, note that a fused multiply-and-add provides the Mul12 and Mul12Cond in only two instructions \cite{CorneaHarrisonTang2002}. Here is the example code for the Itanium processor. \begin{lstlisting}[label={lst:Mul12CondFMA},caption={Mul12 on the Itanium},firstnumber=1] #define Mul12Cond(rh,rl,u,v) \ { \ *rh = u*v; \ /* The following means: *rl = FMS(u*v-*rh) */ \ __asm__ __volatile__("fms %0 = %1, %2, %3\n ;;\n" \ : "=f"(*rl) \ : "f"(u), "f"(v), "f"(*rh) \ ); \ } #define Mul12 Mul12Cond \end{lstlisting} The \crlibm\ distribution attempts to use the FMA for systems on which it is availables (currently Itanium and PowerPC). \subsection{Double-double addition {Add22}} This algorithm, also due to Dekker \cite{Dek71}, computes the sum of two double-double numbers as a double-double, with a relative error smaller than $2^{-103}$ (there is a proof in \cite{Dek71}, a more recent one can be found in in \cite{Lauter2005LIP:tripledouble}). \begin{lstlisting}[label={Add22Cond},caption={Add22Cond},firstnumber=1] void Add22Cond(double *zh, double *zl, double xh, double xl, double yh, double yl) { double r,s; r = xh+yh; s = (ABS(xh) > ABS(yh))? (xh-r+yh+yl+xl) : (yh-r+xh+xl+yl); *zh = r+s; *zl = r - (*zh) + s; } \end{lstlisting} Here ABS is a macro that returns the absolute value of a floating-point number. Again, if this test can be resolved at compile-time, we get the faster \texttt{Add22} procedure: \begin{lstlisting}[label={Add22},caption={Add22},firstnumber=1] void Add22(double *zh, double *zl, double xh, double xl, double yh, double yl) { double r,s; r = xh+yh; s = xh-r+yh+yl+xl; *zh = r+s; *zl = r - (*zh) + s; } \end{lstlisting} \subsection{Double-double multiplication {Mul22}} This algorithm, also due to Dekker \cite{Dek71}, computes the product of two double-double numbers as a double-double, with a relative error smaller than $2^{-102}$, under the condition $x_h<2^{970}$ and $y_h<2^{970}$ (there is a proof in \cite{Dek71}, a more recent one can be found in in \cite{Lauter2005LIP:tripledouble}). \begin{lstlisting}[label={Mul22},caption={Mul22},firstnumber=1] void Mul22(double *zh, double *zl, double xh, double xl, double yh, double yl) { double mh, ml; const double c = 134217729.; /* 0x41A00000, 0x02000000 */ double up, u1, u2, vp, v1, v2; up = xh*c; vp = yh*c; u1 = (xh-up)+up; v1 = (yh-vp)+vp; u2 = xh-u1; v2 = yh-v1; mh = xh*yh; ml = (((u1*v1-mh)+(u1*v2))+(u2*v1))+(u2*v2); ml += xh*yl + xl*yh; *zh = mh+ml; *zl = mh - (*zh) + ml; } \end{lstlisting} Note that the bulk of this algorithm is a \texttt{Mul12(mh,ml,xh,yh)}. Of course there is a conditional version of this procedure but we have not needed it so far. %Our algorithms will sometimes need to multiply a double by a %double-double. In this case we use \texttt{Mul22} with one of the %arguments set to zero, which only performs one useless multiplication %by zero and one useless addition: a specific procedure is not needed. \subsection{The multiplication procedure \MuldDD} \begin{algorithm}[\MuldDD] \label{muldDDref} ~ \\ {\bf In:} a double precision number $a$ and a double-double number $b_\hi + b_\lo$ \\ {\bf Out:} a double-double number $r_\hi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert b_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert b_\hi \right \vert \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{60mm} $\left( t_1, t_2 \right) \gets \mMul\left( a, b_\hi \right)$ \\ $t_3 \gets a \otimes b_\lo$ \\ $t_4 \gets t_2 \oplus t_3$ \\ $\left( r_\hi, r_\lo \right) \gets \mAdd\left( t_1, t_4 \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{muldDDref} \MuldDD] ~ \\ Let be $a$ and $b_\hi + b_\lo$ the values taken by the arguments of algorithm \ref{muldDDref} \MuldDD \\ So the following holds for the values returned $r_\hi$ and $r_\lo$: $$r_\hi + r_\lo = \left( a \cdot \left( b_\hi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq 2^{-102}$$ The values returned $r_\hi$ and $r_\lo$ will not overlap at all. \end{theorem} \subsection{Double-double Horner step procedures\label{sec:double-double-horner}} \subsubsection{The multiply-and-add operator \MulAddDdD} \begin{algorithm}[\MulAddDdD] \label{MulAddDdDref} ~ \\ {\bf In:} a double-double number $c_\hi + c_\lo$, a double precision number $a$ and a double-double number $b_\hi + b_\lo$ \\ {\bf Out:} a double-double number $r_\hi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert b_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert b_\hi \right \vert \\ \left \vert c_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert c_\hi \right \vert \\ \left \vert a \cdot \left( b_\hi + b_\lo \right) \right \vert & \leq & 2^{-2} \cdot \left \vert c_\hi + c_\lo \right \vert \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left(t_1, t_2 \right) \gets \mMul\left( a , b_\hi \right)$ \\ $\left(t_3, t_4 \right) \gets \mAdd\left( c_\hi , t_1 \right)$ \\ $t_5 \gets b_\lo \otimes a$ \\ $t_6 \gets c_\lo \oplus t_2$ \\ $t_7 \gets t_5 \oplus t_6$ \\ $t_8 \gets t_7 \oplus t_4$ \\ $\left(r_\hi, r_\lo \right) \gets \mAdd\left( t_3 , t_8 \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{MulAddDdDref} \MulAddDdD\label{theoMulAddDdDref}] ~ \\ Let be $c_\hi + c_\lo$, $a$ and $b_\hi + b_\lo$ the arguments of algorithm \ref{MulAddDdDref} \MulAddDdD~ verifying the given preconditions.\\ So the following egality will hold for the returned values $r_\hi$ and $r_\lo$ $$r_\hi + r_\lo = \left( \left( c_\hi + c_\lo \right) + a \cdot \left( b_\hi + b_\lo \right) \right) \cdot \left( 1 + \epsilon \right)$$ where $\epsilon$ is bounded by: $$\left \vert \epsilon \right \vert \leq 2^{-100}$$ The returned values $r_\hi$ and $r_\lo$ will not overlap at all. \end{theorem} \subsubsection{The multiply-and-add operator \MulAddDD} \begin{algorithm}[\MulAddDD] \label{MulAddDDref} ~ \\ {\bf In:} three double-double numbers $c_\hi + c_\lo$, $a_\hi + a_\lo$ and $b_\hi + b_\lo$ \\ {\bf Out:} a double-double number $r_\hi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert a_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert b_\hi \right \vert \\ \left \vert c_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert c_\hi \right \vert \\ \left \vert \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right) \right \vert & \leq & 2^{-2} \cdot \left \vert c_\hi + c_\lo \right \vert \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left(t_1, t_2 \right) \gets \mMul\left( a_\hi , b_\hi \right)$ \\ $\left(t_3, t_4 \right) \gets \mAdd\left( c_\hi , t_1 \right)$ \\ $t_5 \gets a_\hi \otimes b_\lo$ \\ $t_6 \gets a_\lo \otimes b_\hi$ \\ $t_7 \gets t_2 \oplus c_\lo$ \\ $t_8 \gets t_4 \oplus t_7$ \\ $t_9 \gets t_5 \oplus t_6$ \\ $t_{10} \gets t_8 \oplus t_9$ \\ $\left(r_\hi, r_\lo \right) \gets \mAdd\left( t_3 , t_{10} \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{MulAddDDref} \MulAddDD\label{theoMulAddDDref}] ~ \\ Let be $c_\hi + c_\lo$, $a_\hi + a_\lo$ and $b_\hi + b_\lo$ the arguments of algorithm \ref{MulAddDDref} \MulAddDD~ verifying the given preconditions.\\ So the following egality will hold for the returned values $r_\hi$ and $r_\lo$ $$r_\hi + r_\lo = \left( \left( c_\hi + c_\lo \right) + \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right) \right) \cdot \left( 1 + \epsilon \right)$$ where $\epsilon$ is bounded by: $$\left \vert \epsilon \right \vert \leq 2^{-100}$$ The returned values $r_\hi$ and $r_\lo$ will not overlap at all. \end{theorem} \subsection{Multiplication of a double-double by an integer} Use Cody and Waite algorithm. See for instance the $\log$ and the trigonometric argument reduction (chapter \ref{chap:log}, p. \pageref{chap:log}). \section{Common C procedures for triple-double arithmetic\label{section:commonCtripledouble}} These procedures are used to reach accuracies of about 150 bits. They are detailed and proven in \cite{Lauter2005LIP:tripledouble}. \begin{algorithm}[Renormalization] \label{renormalg}~\\ {\bf In: $a_\hi, a_\mi, a_\lo \in \F$} verifying the following preconditions:\\ {\bf Preconditions: } \begin{itemize} \item None of the numbers $a_\hi, a_\mi, a_\lo$ is subnormal \item $a_\hi$ et $a_\mi$ do not overlap in more than $51$ bits \item $a_\mi$ et $a_\lo$ do not overlap in more than $51$ bits \end{itemize} which means formally: \begin{eqnarray*} \left \vert a_\mi \right \vert & \leq & 2^{-2} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-2} \cdot \left \vert a_\mi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-4} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} {\bf Out: $r_\hi, r_\mi, r_\lo \in \F$} \begin{eqnarray*} \left(t_{1\hi}, t_{1\lo}\right) & \gets & \mAdd\left(a_\mi,a_\lo\right) \\ \left(r_\hi, t_{2\lo}\right) & \gets & \mAdd\left(a_\hi, t_{1\hi}\right) \\ \left(r_\mi, r_\lo\right) & \gets & \mAdd\left(t_{2\lo}, t_{1\lo}\right) \end{eqnarray*} \end{algorithm} \begin{theorem}[Correctness of the renormalization algorithm \ref{renormalg} \Renormalize] ~\\ For all arguments verifying the preconditions of procedure \Renormalize, the values returned $r_\hi$, $r_\mi$ and $r_\lo$ will not overlap unless they are all equal to $0$ and their sum will be exactly the sum of the values in argument $a_\hi$, $a_\mi$ et $a_\lo$. This implies: $$\left \vert r_\mi \right \vert \leq 2^{-52} \cdot \left \vert r_\hi \right \vert$$ $$\left \vert r_\lo \right \vert \leq 2^{-53} \cdot \left \vert r_\mi \right \vert$$ \end{theorem} \subsection{The addition operator \AddTT} \begin{algorithm}[\AddTT] \label{addTTref} ~ \\ {\bf In:} two triple-double numbers, $a_\hi + a_\mi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert b_\hi \right \vert & \leq & \frac{3}{4} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\mi \right \vert & \leq & 2^{-\alpha_o} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-\alpha_u} \cdot \left \vert a_\mi \right \vert \\ \left \vert b_\mi \right \vert & \leq & 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-\beta_u} \cdot \left \vert b_\mi \right \vert \\ \alpha_o & \geq & 4 \\ \alpha_u & \geq & 1 \\ \beta_o & \geq & 4 \\ \beta_u & \geq & 1 \\ \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left(r_\hi, t_1 \right) \gets \mAdd\left( a_\hi, b_\hi \right)$ \\ $\left(t_2, t_3 \right) \gets \mAdd\left( a_\mi, b_\mi \right)$ \\ $\left(t_7, t_4 \right) \gets \mAdd\left( t_1, t_2 \right)$ \\ $t_6 \gets a_\lo \oplus b_\lo$ \\ $t_5 \gets t_3 \oplus t_4$ \\ $t_8 \gets t_5 \oplus t_6$ \\ $\left( r_\mi, r_\lo \right) \gets \mAdd\left( t_7, t_8 \right)$ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{addTTref} \AddTT\label{theoAddTT}] ~ \\ Let be $a_\hi + a_\mi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ the triple-double arguments of algorithm \ref{addTTref} \AddTT~ verifying the given preconditions.\\ So the following egality will hold for the returned values $r_\hi$, $r_\mi$ and $r_\lo$ $$r_\hi + r_\mi + r_\lo = \left(\left(a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded by: $$\left \vert \epsilon \right \vert \leq 2^{-\min\left(\alpha_o + \alpha_u,\beta_o + \beta_u\right) - 47} + 2^{-\min\left( \alpha_o, \beta_o\right) - 98}$$ The returned values $r_\mi$ and $r_\lo$ will not overlap at all and the overlap of $r_\hi$ and $r_\mi$ will be bounded by the following expression: $$\left \vert r_\mi \right \vert \leq 2^{-\min\left( \alpha_o, \beta_o \right) + 5} \cdot \left \vert r_\hi \right \vert$$ \end{theorem} \subsection{The addition operator \AddDTT} \begin{algorithm}[\AddDTT] \label{addDTTref} ~ \\ {\bf In:} a double-double number $a_\hi + a_\lo$ and a triple-double number $b_\hi + b_\mi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert b_\hi \right \vert & \leq & 2^{-2} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ \left \vert b_\mi \right \vert & \leq & 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-\beta_u} \cdot \left \vert b_\mi \right \vert \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left( r_\hi, t_1 \right) \gets \mAdd\left( a_\hi, b_\hi \right)$ \\ $\left( t_2, t_3 \right) \gets \mAdd\left( a_\lo, b_\mi \right)$ \\ $\left( t_4, t_5 \right) \gets \mAdd\left( t_1, t_2 \right)$ \\ $t_6 \gets t_3 \oplus b_\lo$ \\ $t_7 \gets t_6 \oplus t_5$ \\ $\left( r_\mi, r_\lo \right) \gets \mAdd\left( t_4, t_7 \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{addDTTref} \AddDTT] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ the values taken in argument of algorithm \ref{addDTTref} \AddDTT. Let the preconditions hold for this values.\\ So the following holds for the values returned by the algorithm $r_\hi$, $r_\mi$ and $r_\lo$ $$r_\hi + r_\mi + r_\lo = \left(\left(a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded by $$\left \vert \epsilon \right \vert \leq 2^{-\beta_o - \beta_u - 52} + 2^{-\beta_o - 104} + 2^{-153}$$ The values $r_\mi$ and $r_\lo$ will not overlap at all and the overlap of $r_\hi$ and $r_\mi$ will be bounded by: $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ with $$\gamma \geq \min\left( 45, \beta_o - 4, \beta_o + \beta_u - 2 \right)$$ \end{theorem} \subsection{The addition operator \AdddTT} \begin{algorithm}[\AdddTT] \label{adddTTref} ~ \\ {\bf In:} a double precision number $a$ and a triple-double number $b_\hi + b_\mi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert b_\hi \right \vert & \leq & 2^{-2} \cdot \left \vert a \right \vert \\ \left \vert b_\mi \right \vert & \leq & 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-\beta_u} \cdot \left \vert b_\mi \right \vert \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left( r_\hi, t_1 \right) \gets \mAdd\left( a, b_\hi \right)$ \\ $\left( t_2, t_3 \right) \gets \mAdd\left( t_1, b_\mi \right)$ \\ $t_4 \gets t_3 \oplus b_\lo$ \\ $\left( r_\mi, r_\lo \right) \gets \mAdd\left( t_2, t_4 \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{adddTTref} \AdddTT] ~ \\ Let be $a$ and $b_\hi + b_\mi + b_\lo$ the values taken in argument of algorithm \ref{adddTTref} \AdddTT. Let the preconditions hold for this values.\\ So the following holds for the values returned by the algorithm $r_\hi$, $r_\mi$ and $r_\lo$ $$r_\hi + r_\mi + r_\lo = \left(a + \left( b_\hi + b_\mi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded by $$\left \vert \epsilon \right \vert \leq 2^{-\beta_o - \beta_u - 52} + 2^{-154}$$ The values $r_\mi$ and $r_\lo$ will not overlap at all and the overlap of $r_\hi$ and $r_\mi$ will be bounded by: $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ with $$\gamma \geq \min\left( 47, \beta_o - 2, \beta_o + \beta_u - 1 \right)$$ \end{theorem} \subsection{The multiplication procedure \MulTT} \begin{algorithm}[\MulTT] \label{mulTTref} ~ \\ {\bf In:} two triple-double numbers $a_\hi + a_\mi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert a_\mi \right \vert & \leq & 2^{-\alpha_o} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-\alpha_u} \cdot \left \vert a_\mi \right \vert \\ \left \vert b_\mi \right \vert & \leq & 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-\beta_u} \cdot \left \vert b_\mi \right \vert \end{eqnarray*} with \begin{eqnarray*} \alpha_o & \geq & 2 \\ \alpha_u & \geq & 2 \\ \beta_o & \geq & 2 \\ \beta_u & \geq & 2 \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{60mm} $\left( r_\hi, t_1 \right) \gets \mMul\left( a_\hi, b_\hi \right)$ \\ $\left( t_2, t_3 \right) \gets \mMul\left( a_\hi, b_\mi \right)$ \\ $\left( t_4, t_5 \right) \gets \mMul\left( a_\mi, b_\hi \right)$ \\ $\left( t_6, t_7 \right) \gets \mMul\left( a_\mi, b_\mi \right)$ \\ $t_8 \gets a_\hi \otimes b_\lo$ \\ $t_9 \gets a_\lo \otimes b_\hi$ \\ $t_{10} \gets a_\mi \otimes b_\lo$ \\ $t_{11} \gets a_\lo \otimes b_\mi$ \\ $t_{12} \gets t_8 \oplus t_9$ \\ $t_{13} \gets t_{10} \oplus t_{11}$ \\ $\left( t_{14}, t_{15} \right) \gets \mAdd\left( t_1, t_6 \right)$ \\ $t_{16} \gets t_7 \oplus t_{15}$ \\ $t_{17} \gets t_{12} \oplus t_{13}$ \\ $t_{18} \gets t_{16} \oplus t_{17}$ \\ $\left( t_{19}, t_{20} \right) \gets \mAdd\left( t_{14}, t_{18} \right)$ \\ $\left( t_{21}, t_{22} \right) \gets \mAddDD\left( t_2, t_3, t_4, t_5 \right)$ \\ $\left( r_\mi, r_\lo \right) \gets \mAddDD\left( t_{21}, t_{22}, t_{19}, t_{20} \right)$ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{mulTTref} \MulTT] ~ \\ Let be $a_\hi + a_\mi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ the values taken by the arguments of algorithm \ref{mulTTref} \MulTT \\ So the following holds for the values returned $r_\hi$, $r_\mi$ and $r_\lo$: $$r_\hi + r_\mi + r_\lo = \left(\left(a_\hi + a_\mi + a_\lo \right) \cdot \left( b_\hi + b_\mi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: \begin{eqnarray*} \left \vert \epsilon \right \vert & \leq & 2^{-151} \\ & + & 2^{-99-\alpha_o} \\ & + & 2^{-99-\beta_o} \\ & + & 2^{-49-\alpha_o-\alpha_u} \\ & + & 2^{-49-\beta_o-\beta_u} \\ & + & 2^{-50-\alpha_o-\beta_o-\beta_u} \\ & + & 2^{-50-\alpha_o-\alpha_u-\beta_o} \\ & + & 2^{-101-\alpha_o-\beta_o} \\ & + & 2^{-52-\alpha_o-\alpha_u-\beta_o-\beta_u} \end{eqnarray*} The values returned $r_\mi$ and $r_\lo$ will not overlap at all and the overlap of $r_\hi$ and $r_\mi$ will be bounded as follows: $$\left \vert r_\mi \right \vert \leq 2^{-\gamma_o} \cdot \left \vert r_\hi \right \vert$$ with $$\gamma_o \geq \min\left( 48, \alpha_o-4, \beta_o-4,\alpha_o+\alpha_u-4,\beta_o+\beta_u-4,\alpha_o+\alpha_o-4 \right)$$ \end{theorem} \subsection{The multiplication procedure \MulDT} \begin{algorithm}[\MulDT] \label{mulDTref} ~ \\ {\bf In:} two double-double numbers $a_\hi + a_\lo$ and $b_\hi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert a_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert b_\hi \right \vert \\ \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left( r_\hi, t_1 \right) \gets \mMul\left( a_\hi, b_\hi \right)$ \\ $\left( t_2, t_3 \right) \gets \mMul\left( a_\hi, b_\lo \right)$ \\ $\left( t_4, t_5 \right) \gets \mMul\left( a_\lo, b_\hi \right)$ \\ $t_6 \gets a_\lo \otimes b_\lo$ \\ $\left( t_7, t_8 \right) \gets \mAddDD\left( t_2, t_3, t_4, t_5 \right)$ \\ $\left( t_9, t_{10} \right) \gets \mAdd\left( t_1, t_6 \right)$ \\ $\left( r_\mi, r_\lo \right) \gets \mAddDD\left( t_7, t_8, t_9, t_{10} \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{mulDTref} \MulDT] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\lo$ the values taken by arguments of algorithm \ref{mulDTref} \MulDT \\ So the following holds for the values returned $r_\hi$, $r_\mi$ and $r_\lo$: $$r_\hi + r_\mi + r_\lo = \left(\left(a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq 2^{-149}$$ The values returned $r_\mi$ and $r_\lo$ will not overlap at all and the overlap of $r_\hi$ and $r_\mi$ will be bounded as follows: $$\left \vert r_\mi \right \vert \leq 2^{-48} \cdot \left \vert r_\hi \right \vert$$ \end{theorem} \subsection{The multiplication procedure \MulDTT} \begin{algorithm}[\MulDTT] \label{mulDTTref} ~ \\ {\bf In:} a double-double number $a_\hi + a_\lo$ and a triple-double number $b_\hi + b_\mi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert a_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ \left \vert b_\mi \right \vert & \leq & 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-\beta_u} \cdot \left \vert b_\mi \right \vert \end{eqnarray*} with \begin{eqnarray*} \beta_o & \geq & 2 \\ \beta_u & \geq & 1 \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{60mm} $\left( r_\hi, t_1 \right) \gets \mMul\left( a_\hi, b_\hi \right)$ \\ $\left( t_2, t_3 \right) \gets \mMul\left( a_\hi, b_\mi \right)$ \\ $\left( t_4, t_5 \right) \gets \mMul\left( a_\hi, b_\lo \right)$ \\ $\left( t_6, t_7 \right) \gets \mMul\left( a_\lo, b_\hi \right)$ \\ $\left( t_8, t_9 \right) \gets \mMul\left( a_\lo, b_\mi \right)$ \\ $t_{10} \gets a_\lo \otimes b_\lo$ \\ $\left( t_{11}, t_{12} \right) \gets \mAddDD\left( t_2, t_3, t_4, t_5 \right)$ \\ $\left( t_{13}, t_{14} \right) \gets \mAddDD\left( t_6, t_7, t_8, t_9 \right)$ \\ $\left( t_{15}, t_{16} \right) \gets \mAddDD\left( t_{11}, t_{12}, t_{13}, t_{14} \right)$ \\ $\left( t_{17}, t_{18} \right) \gets \mAdd\left( t_1, t_{10} \right)$ \\ $\left( r_\mi, r_\lo \right) \gets \mAddDD\left( t_{17}, t_{18}, t_{15}, t_{16} \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{mulDTTref} \MulDTT] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ the values in argument of algorithm \ref{mulDTTref} \MulDTT~ such that the given preconditions hold.\\ So the following will hold for the values $r_\hi$, $r_\mi$ and $r_\lo$ returned $$r_\hi + r_\mi + r_\lo = \left(\left(a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\mi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq \frac{2^{-99 - \beta_o} + 2^{-99 - \beta_o - \beta_u} + 2^{-152}} {1 - 2^{-53} - 2^{-\beta_o + 1} - 2^{-\beta_o - \beta_u + 1}} \leq 2^{-97 - \beta_o} + 2^{-97 - \beta_o - \beta_u} + 2^{-150}$$ The values $r_\mi$ and $r_\lo$ will not overlap at all and the following bound will be verified for the overlap of $r_\hi$ and $r_\mi$: $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ where $$\gamma \geq \min\left( 48, \beta_o - 4, \beta_o + \beta_u - 4 \right)$$ \end{theorem} \subsection{The multiplication procedure \MuldTT} \begin{algorithm}[\MuldTT] \label{muldTTref} ~ \\ {\bf In:} a double number $a$ and a triple-double number $b_\hi + b_\mi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert b_\mi \right \vert & \leq & 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-\beta_u} \cdot \left \vert b_\mi \right \vert \end{eqnarray*} with \begin{eqnarray*} \beta_o & \geq & 2 \\ \beta_u & \geq & 2 \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{60mm} $\left( r_\hi, t_2 \right) \gets \mMul\left( a, b_\hi \right)$ \\ $\left( t_3, t_4 \right) \gets \mMul\left( a, b_\mi \right)$ \\ $t_5 \gets a \otimes b_\lo$ \\ $\left( t_9, t_7 \right) \gets \mAdd\left( t_2, t_3 \right)$ \\ $t_8 \gets t_4 \oplus t_5$ \\ $t_{10} \gets t_7 \oplus t_8$ \\ $\left( r_\mi, r_\lo \right) \gets \mAdd\left( t_9, t_{10} \right)$ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{muldTTref} \MuldTT] ~ \\ Let be $a$ and $b_\hi + b_\mi + b_\lo$ the values in argument of algorithm \ref{muldTTref} \MuldTT~ such that the given preconditions hold.\\ So the following will hold for the values $r_\hi$, $r_\mi$ and $r_\lo$ returned $$r_\hi + r_\mi + r_\lo = \left( a \cdot \left( b_\hi + b_\mi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq 2^{-101 - \beta_o} + 2^{-49 - \beta_o - \beta_u} + 2^{-156}$$ The values $r_\mi$ and $r_\lo$ will not overlap at all and the following bound will be verified for the overlap of $r_\hi$ and $r_\mi$: $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ where $$\gamma \geq \min\left( 47, \beta_o - 5, \beta_o + \beta_u - 5 \right)$$ \end{theorem} \subsection{The multiplication procedure \MuldDT} \begin{algorithm}[\MuldDT] \label{muldDTref} ~ \\ {\bf In:} a double number $a$ and a double-double number $b_\hi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert b_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert b_\hi \right \vert \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{60mm} $\left( r_\hi, t_1 \right) \gets \mMul\left( a, b_\hi \right)$ \\ $\left( t_2, t_3 \right) \gets \mMul\left( a, b_\lo \right)$ \\ $\left( t_5, t_4 \right) \gets \mAdd\left( t_1, t_2 \right)$ \\ $t_6 \gets t_3 \otimes t_4$ \\ $\left( r_\mi, r_\lo \right) \gets \mAdd\left( t_5, t_6 \right)$ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{muldDTref} \MuldDT] ~ \\ Let be $a$ and $b_\hi + b_\lo$ the values in argument of algorithm \ref{muldDTref} \MuldDT~ such that the given preconditions hold.\\ So the following will hold for the values $r_\hi$, $r_\mi$ and $r_\lo$ returned $$r_\hi + r_\mi + r_\lo = \left( a \cdot \left( b_\hi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq 2^{-154}$$ The values $r_\mi$ and $r_\lo$ will not overlap at all and the following bound will be verified for the overlap of $r_\hi$ and $r_\mi$: $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ where $$\gamma \geq 47$$ \end{theorem} \subsection{Final rounding to the nearest even} \begin{algorithm}[Final rounding to the nearest (even)] \label{algarrpres} ~ \\ {\bf In:} a triple-double number $x_\hi + x_\mi + x_\lo$ \\ {\bf Out:} a double precision number $x^\prime$ returned by the algorithm \\ {\bf Preconditions on the arguments:} \begin{itemize} \item $x_\hi$ and $x_\mi$ as well as $x_\mi$ and $x_\lo$ do not overlap \item $x_\mi = \circ \left( x_\mi + x_\lo \right)$ \item $x_\hi \not = 0$, $x_\mi \not = 0$ and $x_\lo \not = 0$ \item $\circ \left( x_\hi + x_\mi \right) \not \in \left \lbrace x_\hi^-, x_\hi, x_\hi^+ \right \rbrace \Rightarrow \left \vert \left( x_\hi + x_\mi \right) - \circ\left( x_\hi + x_\mi \right) \right \vert \not = \frac{1}{2} \cdot \mUlp\left( \circ \left( x_\hi + x_\mi \right) \right)$ \end{itemize} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{80mm} $t_1 \gets x_\hi^-$ \\ $t_2 \gets x_\hi \ominus t_1$ \\ $t_3 \gets t_2 \otimes \frac{1}{2}$ \\ $t_4 \gets x_\hi^+$ \\ $t_5 \gets t_4 \ominus x_\hi$ \\ $t_6 \gets t_5 \otimes \frac{1}{2}$ \\ ~ \\ {\bf if} $\left( x_\mi \not = -t_3 \right)$ {\bf and} $\left( x_\mi \not = t_6 \right)$ {\bf then} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{70mm} \vspace{-2.4mm} {\bf return } $\left( x_\hi \oplus x_\mi \right)$ \end{minipage} \end{center} \vspace{-2.4mm} {\bf else} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{70mm} {\bf if} $\left( x_\mi \otimes x_\lo > 0.0 \right)$ {\bf then} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{60mm} {\bf if} $\left( x_\hi \otimes x_\lo > 0.0 \right)$ {\bf then} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{50mm} \vspace{-2.4mm} {\bf return } $x_\hi^+ $ \end{minipage} \end{center} \vspace{-2.4mm} {\bf else} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{50mm} \vspace{-2.4mm} {\bf return } $x_\hi^- $ \end{minipage} \end{center} \vspace{-2.4mm} {\bf end if} \end{minipage} \end{center} \vspace{-2.4mm} {\bf else} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{60mm} \vspace{-2.4mm} {\bf return } $x_\hi $ \end{minipage} \end{center} \vspace{-2.4mm} {\bf end if} \end{minipage} \end{center} \vspace{-2.4mm} {\bf end if} \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Correctness of the final rounding procedure \ref{algarrpres}]\label{corralgpluspres} ~\\ Let be {\bf A} the algorithm \ref{algarrpres} said `` Final rounding to the nearest (even)''. Let be $x_\hi + x_\mi + x_\lo$ triple-double number for which the preconditions of algorithm {\bf A} hold. Let us notate $x^\prime$ the double precision number returned by the procedure. \\ So $$x^\prime = \circ \left( x_\hi + x_\mi + x_\lo \right)$$ i.e. {\bf A} is a correct rounding procedure for round-to-nearest-ties-to-even mode. \end{theorem} \subsection{Final rounding for the directed modes} \begin{theorem}[Directed final rounding of a triple-double number] \label{arrdir} ~ \\ Let be $x_\hi + x_\mi + x_\lo \in \F + \F + \F$ a non-overlapping triple-double number. \\ Let be $\diamond$ a directed rounding mode.\\ Let be {\bf A} the following instruction sequence: \begin{center} \begin{minipage}[b]{50mm} $\left( t_1, t_2 \right) \gets \mAdd\left( x_\hi, x_\mi \right)$ \\ $t_3 \gets t_2 \oplus x_\lo$ \\ {\bf return } $\diamond\left( t_1 + t_3 \right)$ \end{minipage} \end{center} So {\bf A} is a correct rounding procedure for the rounding mode $\diamond$. \end{theorem} \section{Horner polynomial approximations \label{sec:Horner}} Most function evaluation schemes include some kind of polynomial evaluation over a small interval. Classically, we use the Horner scheme, which is the best suited in this case. For a polynomial of degree $d$, noting $c_i$ its coefficients, the Horner scheme consists in computing $S_0$ using the following recursion: $$ \left\{ \begin{array}{rl} S_d(x) &\ = \ c_d\\ S_k(x) &\ =\ c_k+xS_{k+1}(x) \quad \mathrm{for}\quad 0\le k \maxeps y$. By definition of the \ulp\ of a positive normal number, we have $y_h \in [2^{52}u, (2^{53}-1)u]$. \end{minipage} & \begin{minipage}[t]{7.5cm} To prove that $y_h = \round(y)$, it is enough to prove that $|y_h-y|\le u/4$. As $y_l\le 0$, we have $y\le y_h$ and $|y_h-y| = y-y_h$. From fourth hypothesis, it is enough to prove that $u/4 + y_l > \maxeps y$. By our definition of the \ulp\ of a normal number, we have $y_h = 2^{52}u$ in this case. \end{minipage} \end{tabular}\\ \begin{tabular}{c||c} \begin{minipage}[t]{7.5cm} From the first hypothesis we have \begin{equation} y_l\le\frac{1}{2}u \label{eq:prooftest1} \end{equation} Therefore $y_h+y_l \le (2^{53}-1)u + \frac{1}{2}u$, and\\ $y < (y_h+y_l)/(1-\maxeps)$. Hence \\ $y <\ \dfrac{2^{53}-\frac{1}{2}}{1-\maxeps} u$ As a consequence, since $\maxeps \le 2^{-56}$, \begin{equation} y < 2^{53} u \label{eq:prooftest3} \end{equation} \end{minipage} & \begin{minipage}[t]{7.5cm} We have $y_h = 2^{52}u$ and $y_l\le 0$, therefore\\ $y_h+y_l \le 2^{52}u$, and \begin{equation} y < \frac{2^{52}u}{1-\maxeps} \label{eq:prooftest3p2} \end{equation} \end{minipage} \end{tabular}\\ \begin{tabular}{c||c} \begin{minipage}[t]{7.5cm} The easy case is when we have $y_h = \round(y)$ regardless of the result of the test. This is true as soon as $y_l$ is sufficiently distant from $u/2$. More specifically, if $0 \le y_l < \left(\frac{1}{2} - 2^{-k}\right)u$, we combine (\ref{eq:prooftest3}) with the fifth hypothesis to get $\maxeps y < 2^{-k}u$. From $y_l < \left(\frac{1}{2} - 2^{-k}\right)u$ we deduce\\ $u/2 -y_l > 2^{-k}u > \maxeps y$, which proves that $y_h=\round(y)$. \end{minipage} & \begin{minipage}[t]{7.5cm} The easy case is when we have $y_h = \round(y)$ regardless of the result of the test. This is true as soon as $y_l$ is sufficiently distant from $-u/4$. More specifically, if $ - \left(\frac{1}{4} - \frac{2^{-k-1}}{1-\maxeps}\right)u < y_l \le 0 $, after combining (\ref{eq:prooftest3p2}) with the fifth hypothesis to get $\maxeps y < \frac{2^{-k-1} u}{1-\maxeps}$, we deduce\\ $y_l + \frac{u}{4}> \frac{2^{-k-1}}{1-\maxeps}u > \maxeps y$, which proves that $y_h=\round(y)$. \end{minipage} \end{tabular}\\ \begin{tabular}{c||c} \begin{minipage}[t]{7.5cm} Now consider the case when $y_l \ge \left(\frac{1}{2} - 2^{-k}\right)u$. The condition $|y_h|\ge 2^{-1022+54}$ ensures that $u/4$ is a normal number, and now $y_l > u/4$, so in this case $y_l$ is a normal number. As $1 u/8$, so in this case $y_l$ is a normal number. As $1 __eps__ * u53.d){ \ if(!yl_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next up */ \ yh.d = __yh__; \ if(yh_neg) yh.l--; else yh.l++; /* Beware: Fails for zero */ \ return yh.d ; \ } \ else return __yh__; \ } \ } \end{lstlisting} \end{theorem} \begin{proof} The first lines compute $|y_h|$, $|y_l|$, boolean values holding the sign information of $y_h$ and $y_l$, and $u_{53}=2^{53}\ulp(y_h)$. Here we use integer 64-bit arithmetic for readability, but other implementations may be more efficient on some systems. Note that these computations don't work for infinities, zeroes or subnormals. As previously, by definition of the \ulp, we have $y<2^{53}u$. The main test which determines whether correct rounding is possible is line 10. If this test is true, then $y_l>(2^{53}u)\otimes\maxeps = 2^{53}\maxeps u $ (the multiplication by $u_{53}$, a power of two, is exact), hence $y_l>\maxeps y$ so we are in an easy case for directed rounding. The remaining computations and tests (lines 11 and following) compute \texttt{nextafter(yh,inf)} in an efficient way since an integer representation of $y_h$ is already available. For the other directed rounding modes, only these lines change in a straightforward way. \end{proof} \paragraph*{Notes} \begin{itemize} \item Rounding down and to zero are identical to the previous, except for the computation of the rounded value itself. \item These tests launch the accurate phase when yl=0, in particular in the exceptional cases when the image of a double is a double. See the chapter \ref{chap:log} % (page \pageref{pageref:log_of_one}) % TODO: still true? for an example where it may introduce a misround. \item These tests don't work if $y_h$ is a subnormal. If one cannot prove statically that this case doesn't appear, a sensible solution is to test for subnormals and launch the accurate phase. \item Finally, remark that for some functions, the tests on the sign of $y_h$ are statically predictable to be true because the function is always positive. We shall use this macro anyway for safety. Tanks to branch predictor logic in modern processors, it will make little difference from a performance point of view. \end{itemize} \section{The Software Carry Save library \label{sec:SCSLib}} The software carry-save internal representation of multiple-precision numbers was designed specifically for simple and fast implementations of addition and multiplication in the 100-500 bit precision range, as required by the \accurate\ phase of our algorithms. More details on software carry-save are available in \cite{DefDin2002,DinDef2003}. The parameters of \scslib\ are set up so that all the operators offer a relative error better than $2^{-208}$. This is a large overkill for all the functions in \crlibm, as the worst cases computed by Lefevre never require more than 158 bits of accuracy. This enables simple proofs for the second steps, assuming the operators in \scslib\ are correct. Another feature that makes accuracy proofs simple when using \scslib\ is the following: The range of SCS numbers includes the range of IEEE double-precision numbers, including subnormals and exceptional cases. Conversions between SCS format and IEEE-754 doubles, as well as arithmetic operations, follow the IEEE rules concerning the exceptional cases. SCS doesn't ensure correct rounding, but provides conversions to doubles in the four IEEE-754 rounding modes, which is enough for the purpose of \crlibm. However, a formal proof of correctness of the \scslib\ operators remains to be done. Currently there is nothing more than good confidence based on the simplicity of the code. \subsection{The SCS format} A MP number is represented in the proposed format as a \emph{Software Carry Save} (SCS) structure $R$, depicted on Figure~\ref{fig:scsrepresentation} and composed of the following fields: \begin{description} \item[\emph{R.digits[$n_r$]}] A table of $n_r$ digits with $m_r$ bits of precision. These digits can in principle be either integer or FP machine numbers, however integer is always faster and simpler. We will not mention FP digits anymore here, the interested reader is referred to \cite{DefDin2002,DinDef2003}. \item[\emph{R.index}] An integer storing the index of the first digit in the range of representable numbers, as depicted on Figure~\ref{fig:scsrepresentation}; \item[\emph{R.sign}] A sign information. \end{description} \begin{figure}[h] \begin{center} \includegraphics[width=0.7\textwidth]{fig_scs/exponent_representation} % image file name \caption{The proposed format \label{fig:scsrepresentation}} \end{center} \end{figure} In other words, the value $x$ of a representation $R$ is: \begin{equation} \label{eqn4} x = R.sign \times \sum_{j=1}^{n_r} R.digits[j] \times 2^{m_r * (R.index - j)} \end{equation} In such a \emph{normal} SCS number $R$, the bits from $m_I$ to $m_r$ of the $R.digits$ fields are thus set to zero. They will be exploited by the algorithms to store temporary \emph{carry} information, and are therefore called \emph{carry-save} bits. An SCS number where these bits are non-zero is said to be non-normal. The values of the parameters for use in \crlibm\ is $n_r=8$ digits of $m_i=30$ bits stored on $m_r=32$-bit words. The worst-case precision that this format may hold is when the most significant digit is equal to $1$, meaning that an SCS numbers holds only $1+7\times 30=211$ significant digits. \subsection{Arithmetic operations\label{sec:ops}} \subsubsection{Conversion from double to SCS} A first method for converting a double precision floating point number $d$ into an SCS representation is to extract the exponent $d_{exp}$ from $d$, and then determine the corresponding $R.index$ as the integer part of $\frac{d_{exp}}{2^{m_r}}$. Another method uses a variable number of multiplications by $2^{m_r}$ or $2^{-m_r}$. This method is faster than the previous one when the exponent of $d$ is close to $0$. After testing both methods in \crlibm, the first method was preferred. \subsubsection{Addition and subtraction} The addition of two SCS numbers of the same sign consists in aligning, then adding digits of the same order. Thanks to the carry-save bits, all these additions will be \emph{exact} and \emph{independent}. However the result will usually not be a normal SCS number: the sums will have overflown in the carry-save bits. A \emph{renormalization} procedure is presented in section \ref{renorm} to propagate these carry bits and get again a normal SCS number. However, the advantage of SCS representation is that many SCS numbers can be summed before needing to perform this expensive step (up to 7 with the choice of parameters made in \crlibm). The subtraction (addition of two numbers of opposite signs) is very similar to the addition algorithm. It may also classically lead to a cancellation, which may need an update of the index of the result. However, as in other floating-point formats, a subtraction involving a a cancellation is exact. Although all the digit operations are exact, the addition or subtraction of two numbers also classically involves a rounding error, due to aligning the digits of same magnitude. For performance reason this rounding is a truncation, so the worst-case relative error is one ulp of the least accurate representable number, or $2^{-211}$. %---------------- % MULTIPLICATION %---------------- \subsubsection{Multiplication} The multiplication of two normal SCS numbers involves the operations depicted on the Figure \ref{fig:scsmultiplication}: The partial products are computed (in parallel) and summed in columns. The parameters are set up so that none of these operation overflow. Again, the result is not a normal SCS number, and a renormalization procedure (described below) has to be applied to empty the carry bits. However, a few additions may follow a multiplication before this renormalization, which allows for further optimization of algorithms using SCS arithmetic. For instance, a polynomial evaluation can be implemented with a renormalization after one multiplication and one addition. \begin{figure}[h] \begin{center} \includegraphics[width=0.7\textwidth]{fig_scs/multiplication} \caption{SCS multiplication \label{fig:scsmultiplication}} \end{center} \end{figure} Here also, a rounding error is involved when two $n_r$-digit numbers are multiplied if the result is to fit on $n_r$ digits. The actual implementation tests if the most significant digit ($z_1$ on Figure~\ref{fig:scsmultiplication}) is null, in which case the index of the result is that of $z_2$. If the whole of the computations of Figure~\ref{fig:scsmultiplication} are implemented, the worst case for relative accuracy is again $2^{-211}$. However a further optimization is to avoid computing the columns of lower magnitude, at the expense of an increase in the rounding error. More specifically, we compute 9 columns instead of 16. The wors case is now when $z_1$ is null, in which case the relative error correspond to the truncation of the 8 leftmost columns, whose maximum value is smaller than 3 ulps of the SCS result. Therefore the relative error of the multiplication is bounded by $2^{-208}$ with this optimization, which is still a large overkill for the purpose of \crlibm. This optimization is therefore implemented if the loop are hand-unrolled. If they are not, the increased control complexity actually degrades performance. \subsubsection{Renormalization (carry propagation) \label{renorm}} Renormalization is a carry propagation from the low order to high order digits: Starting with an initially null carry, at each step, the previous carry is added to the current digit, and this sum is then split into two parts using masks. The low $m_r$ bits are a digit of the normalized result, and the upper part is the next carry. The actual algorithm is a little bit more complex. The initial non-normal number may not be representable exactly as a normal SCS number, therefore the index of the normalized result may have to be increased by one or two. Normalization thus again involves a rounding error. Note that this error was already taken into account in the previous discussions of addition and multiplication. %----------------- % CONVERSION BACK %----------------- \subsubsection{Conversion from SCS to floating-point} A few (4 in the worst case) multiplications and additions suffice to get the FP number closest to a SCS number. For instance, for $m_I=53$ and $m_r=26$, we need to compute $d = A.sign \times 2^{A.index \times m_r} \times ( A.digits[0]+ 2^{-m_r} \times A.digits[1]+ 2^{-2.m_r} \times A.digits[2]+ 2^{-3.m_r} \times A.digits[3])$. The number $2^{A.index \times m_r}$ is build using integer masks. The actual implementation of this formula is slightly less simple, but this conversion is still very fast. \subsubsection{Mixed 32- and 64-bit arithmetics} An improvement implemented in \scslib\ was the combined use of integer 32- and 64-bit arithmetics as follows: \begin{itemize} \item MP digits are stored as 32-bit numbers where only a few bits are reserved for carries. This removes the main problem of the initial implementation \cite{DefDin2002}, namely its memory inefficiency. \item Addition uses 32-bit arithmetic. \item In the MP multiplication, the partial products are products of two 32-bit digits, which are 64-bit numbers. The column sums need thus to be computed using 64-bit arithmetic. This can be expressed in the C language in a non-ISO-C99, but de-facto standard way, as follows: 32-bit numbers have the \texttt{unsigned int} type; 64-bit numbers have the \texttt{unsigned long long int} type. When multiplying two digits, one is first cast into this 64-bit type. For UltraSPARC architectures (detected at build time) the conversion is to floating-point, but we will not detail this peculiarity further. \end{itemize} This works well because all modern processors either have 64-bit integer units, or offer instructions which store the 64-bit product of two 32-bit integers into two 32-bit registers. The compiler does the rest well, because it is conceptually simple: casting unsigned 32-bit into unsigned 64-bit is trivial; 64-bit addition is translated straightforwardly into one 32-bit \emph{add} followed by one 32-bit \emph{add-with carry}. \subsubsection{Implementation considerations} For portability purposes, the implemention uses C as defined by the ISO C99 standard, and tries to use a recent version of \texttt{gcc}. We could not exhibit a case where a native compiler from the processor vendor (Intel or Sun) gave significantly better results than \texttt{gcc}, which is probably a consequence of the simplicity of our code. However, when tuning for performance, we observed that the same code which was efficient on one processor could lead to very poor results on another. Usually, this difference can be traced down to the capabilities of the processor itself. The typical example is the knowingly poor integer multiplication on UltraSPARC II. Sometimes however, the processor should be able to perform well, and it is the processor-specific backend of the compiler which is to blame, which can be checked by observing the assembly code produced. A typical example is the casting of 32-bits digits to 64-bit arithmetic (or to an FP number in the case of the UltraSPARC) in the multiplication algorithm. In these cases we tried to change the programming style in a way that works well on all processors. Sometimes it wasn't possible, in which case the code contains, along with a generic version, several processor-specific tricky versions of the problematic operation, selected at compile time thanks to the GNU \texttt{automake/autoconf} tools. More surprisingly, we were disappointed by the higher-level capabilities of the compilers, especially at unrolling loops. Our code exhibits many small \texttt{for} loops whose size is known at compile-time (usually $n$). This is the ideal situation for loop unrolling, a technique well known and described in most textbooks on compiler design. Options exist in most compilers to turn on this optimisation. Unfortunately, leaving loop unrolling to the compiler gives very poor results, even when compared to the non-unrolled case. Since unrolling the loops by hand in the C code takes a few minutes, we did it for the version of the library which we use ($m=30$, $n=8$). It marginally increases the code sizes for this small $n$, and sometimes provides a twofold improvement on speed, depending of the processor. Of course, this is not satisfactory: We don't want to do it for all values of $n$, nor do we want to study for each processor the tradeoffs involved as $n$ increase. We expect however future compilers to handle unrolling better, and we were surprised that no compiler had a clear edge on the other in this respect. Some argue, however, that this issue is pointless, as superscalarity, along with register renaming and branch prediction inside modern processors, sum up to the equivalent of dynamic unrolling of the code. In our tests (in 2003), it doesn't: unrolling does bring a speed-up. \section{Common Maple procedures \label{section:commonMaple}} \subsection{Conversions} Procedure \texttt{ieeedouble} returns the sign, the exponent and the mantissa of the IEEE-754 double-precision number closest to input value \texttt{x}. \begin{lstlisting}[caption={ieeedouble},firstnumber=1] ieeedouble:=proc(xx) local x, sgn, logabsx, exponent, mantissa, infmantissa,powermin,powermax,expmin,expmax,expmiddle,powermiddle; Digits := 100; x := evalf(xx); if (x=0) then sgn, exponent, mantissa := 1, -1022, 0 else if (x < 0) then sgn := -1 else sgn := 1 fi: x := abs(x); if x >= 2^(1023)*(2-2^(-53)) then mantissa := infinity; exponent := 1023 else if x <= 2^(-1075) then mantissa := 0; exponent := -1022 else if x <= 2^(-1022) then exponent := -1022 else # x is between 2^(-1022) and 2^(1024) powermin := 2^(-1022); expmin := -1022; powermax := 2^1024; expmax := 1024; while (expmax-expmin > 1) do expmiddle := round((expmax+expmin)/2); powermiddle := 2^expmiddle; if x >= powermiddle then powermin := powermiddle; expmin := expmiddle else powermax := powermiddle; expmax := expmiddle fi od; # now, expmax - expmin = 1 and powermin <= x < powermax, # powermin = 2^expmin and powermax = 2^expmax, so expmin is the exponent of x exponent := expmin; fi; infmantissa := x*2^(52-exponent); if frac(infmantissa) <> 0.5 then mantissa := round(infmantissa) else mantissa := floor(infmantissa); if type(mantissa,odd) then mantissa := mantissa+1 fi fi; mantissa := mantissa*2^(-52); fi; fi; fi; sgn,exponent,mantissa; end: \end{lstlisting} Procedure \texttt{ieeehexa} returns the hexadecimal representation of the nearest double to its input \texttt{x}. \begin{lstlisting}[caption={ieeehexa},firstnumber=1] ieeehexa:= proc(x) local hex2, xx, longint, expo, sgn, frac, resultat; if(x=0) then resultat:=["00000000","00000000"]; elif(x=-0) then resultat:=["80000000","00000000"]; # nice try else xx:=ieeedouble(x); sgn:=xx[1]: expo:=xx[2]: frac:=xx[3]: if (expo = -1023) then longint := (frac)*2^51 ; # subnormal else longint := (frac-1)*2^52 + (expo+1023)*2^52; fi: if (sgn=-1) then longint := longint + 2^63; fi: longint := longint + 2^64: # to get all the hexadecimal digits when we'll convert to string hex2:=convert(longint, hex); hex2:=convert(hex2, string): resultat:=[substring(hex2,2..9), substring(hex2,10..18)]: fi: resultat; end proc: \end{lstlisting} Procedure \texttt{hexa2ieee} performs the reciprocal conversion. Procedure \texttt{hi\_lo} returns two IEEE-double numbers $x\_hi$ and $x\_lo$ so that $x = x\_hi + x\_lo + \epsilon_{-103}$. \begin{lstlisting}[caption={hi\_lo},firstnumber=1] hi_lo:= proc(x) local x_hi, x_lo, res: x_hi:= nearest(evalf(x)): res:=x-x_hi: if (res = 0) then x_lo:=0: else x_lo:=nearest(evalf(res)): end if; x_hi,x_lo; end: \end{lstlisting} \vspace{0.5cm} Procedure \texttt{showHowDifficultToRound} takes a real number, and prints the bits after the 53th of its nearest IEEE floating-point number. \begin{lstlisting}[caption={showHowDifficultToRound},firstnumber=1] showHowDifficultToRound:=proc(x) local xb,xs,s,e,m: Digits:=200: s,e,m := ieeedouble(x): xb:=convert(evalf(x*2^(-e)),binary): xs:=convert(xb, string): substring(xs,55..153) end proc: \end{lstlisting} \subsection{Procedures for polynomial approximation} Procedure \texttt{Poly\_exact2} takes in arguments a polynomial \texttt{P} and a integer \texttt{n}. It returns a truncated polynomial, of which coefficients are exactly IEEE-double numbers. The \texttt{n} first coefficients are written over 2 IEEE-double numbers. \begin{lstlisting}[caption={poly\_exact2},firstnumber=1] poly_exact2:=proc(P,n) local deg,i, coef, coef_hi, coef_lo, Q: Q:= 0: convert(Q, polynom): deg:=degree(P,x): for i from 0 to deg do coef :=coeff(P,x,i): coef_hi, coef_lo:=hi_lo(coef): Q:= Q + coef_hi*x^i: if(i0) then p:=100: else p:=53: fi: if coeff(poly,x, 0) = 0 then deltap, Smin, Smax := compute_abs_rounding_error(poly/x,xmax, n-1): rho := (2^(-p)*(Smax+deltap) +deltap ) / Smin : else deltap, Smin, Smax := compute_abs_rounding_error(poly,xmax, n): rho := deltap / Smin: fi: rho; end proc: \end{lstlisting} \vspace{0.5cm} Procedures \texttt{compute\_abs\_rounding\_error\_firstmult} and \texttt{compute\_abs\_rounding\_error\_firstmult} are similar to the previous, but in the case when the first double-double operation is a multiplication. \subsection{Rounding} Procedure \texttt{compute\_rn\_constant} computes a good constant for the round-to-nearest test of Theorem~\ref{th:roundingRN1}. Its input is a bound of the overall relative error of the approximation scheme. \subsection{Using double-extended} The file \texttt{maple/double-extended.mpl} contains procedures similar to those previously described to handle double-extended precision (64 bits of mantissa and 15 bits of exponent). This is currently used in experimental code only: The \crlibm\ CVS repository at \url{http://lipforge.ens-lyon.fr/} contains such code for exponential and arctangent on Itanium, and arctangent on IA32 processors. For more details see \cite{DinDefLau2004LIP,DinErshGast2005}. %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/acos.tex0000644000000000000000000000033513316017127017243 0ustar 00000000000000TODO. This function was completely rewritten using machine-generated polynomials. Gappa proofs were automatically generated, too, and are available in the \texttt{gappa/asin} directory. This chapter will be updated soon. interval-3.2.0/src/crlibm/docs/latex/asin.tex0000644000000000000000000013213713316017127017256 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA This chapter is contributed by Ch. Q. Lauter. WARNING: This chapter is out-of-sync with the code. The function was completely rewritten using machine-generated polynomials. Gappa proofs were automatically generated, too, and are available in the \texttt{gappa/asin} directory. This chapter will be updated soon. \section{Overview of the algorithm\label{sec:asin-overview}} The arcsine $\arcsin\left( x \right) = \sum\limits_{i=0}^{\infty} \frac{\left( 2i - 1 \right)!!}{\left(2i+1\right) \cdot \left( 2i \right)!!} \cdot x^{2i+1}$ is defined on the domain $x \in \left[ -1; 1 \right]$. It is a odd function: $\arcsin\left(-x\right) = -\arcsin\left( x \right)$. Its value in $0$ is $\arcsin\left( 0 \right) = 0$. Its derivative tends to infinity when $x$ tends to $1$: $\lim\limits_{x \rightarrow 1} \left( \frac{d}{dx} \arcsin \right)\left(x\right) = \infty$; the function's value in $1$ is nevertheless finite: $\arcsin\left( 1 \right) = \frac{\pi}{2}$. There is no simple additive or multiplicative decomposition of this function. A correctly rounded implementation of $\arcsin$ must provide an accuracy of at least $126$ bits for $\left \vert x \right \vert \leq 2^{-18}$ and of at least $118$ bits for the rest of the definition domain in the accurate phase \cite{DinDefLau2004LIP}. The algorithm chosen principally consists of a piecewise polynomial approximation either of the function itself or of a asymptotic development of the function. More precisely, the following is done: \begin{itemize} \item Special cases, such as $\left \vert x \right \vert > 1$, $x = \pm \infty$, $x = \nan$, are handled. \item The sign of the argument $x$ is stripped off because $\arcsin\left(x\right) = \sgn\left(x\right) \cdot \arcsin\left( \left \vert x \right \vert \right)$. We will suppose in the following, that $x$ stands for a positive argument, $x \geq 0$. \item The argument is classified in one of $10$ subdomains of $\left[ 0; 1 \right]$. This means an integer $i \in \left[0\dots9\right]$ is computed such that $x \in I_i$ where $$\bigcup\limits_{i=0}^9 I_i = \left[0; 1 \right]$$ $$i \not= j \Rightarrow I_i \cap I_j = \emptyset$$ $$i < j \Rightarrow \forall x_i \in I_i, x_j \in I_j \mbox{ . } x_i < x_j$$ \item If $i = 0$, $\arcsin$ is directly approximated as $$\arcsin\left( x \right) \approx x + x^3 \cdot p_0\left( x^2 \right)$$ \item If $1 \leq i \leq 8$, an interval midpoint value $m_i \approx \frac{\inf I_i + \sup I_i}{2}$ is read in a table. The function is then approximated as $$\arcsin\left( x \right) \approx \arcsin\left( m_i \right) + \left(x - m_i \right) \cdot p_i\left( x - m_i \right)$$ \item If $i = 9$, $\arcsin$ is approximated as $$\arcsin\left( x \right) \approx p_9\left( 1 - x \right) \cdot \sqrt{2 - 2\cdot x} + \frac{\pi}{2}$$ \end{itemize} The polynomials $p_i$, $1 \leq i \leq 8$, for the middle intervals are all of the same degree and, loaded from a table, can be evaluated in the same computation path. The polynomials $p_0$ and $p_9$ are of different degree. So there are three distinct paths in the code. In the following, they are referred to as the low, middle and high path. Concerning the quick and accurate phase of the implementation, it must mentioned that code and cache size considerations do not allow for using different coefficient tables for the quick phase polynomials $p_{i\mbox{\tiny ~quick}}$ as for the accurate phase polynomials $p_{i\mbox{\tiny ~accurate}}$ that are obviously longer and must contain more accurately stored coefficients. So the quick phase polynomials are simply the accurate phase polynomials truncated to some degree and simplified by omitting low significance components of the coefficients. The double precision midpoint values $m_i \in \F$ for the middle path intervals $I_i$, $1 \leq i \leq 8$, are chosen such that a double-double approximation $asinm_{i\hi} + asinm_{i\lo}$ of $\arcsin\left( m_i \right)$ is accurate to at least $121$ bits. This allows for saving up memory in the tables used. The intervals $I_i$ are not uniformly distributed. This has the disadvantage that the computation of $i$ cannot be done by simple bitmasks on the arcsine's argument $x$ but that a dichotomy must be performed. On the other hand, this is the only way of using polynomials for the same degree for all middle intervals without wasting accuracy for the lower ones. In fact, the derivative of $\arcsin$ grows over-polynomially, which means that the polynomial degrees must increase for equally sized reduced arguments in order to achieve the same approximation error. The decomposition of the domain $\left[0;1\right]$ into the $I_i$s is relatively ad-hoc. The given implementation uses: $$I_i = \left[bound_i;bound_{i+1}\right]$$ with \begin{eqnarray*} bound_0 & = & 0 \\ bound_1 & = & 0.184999942779541015625 \\ bound_2 & = & 0.2997171878814697265625 \\ bound_3 & = & 0.40296268463134765625 \\ bound_4 & = & 0.4932067394256591796875 \\ bound_5 & = & 0.5696849822998046875 \\ bound_6 & = & 0.639662265777587890625 \\ bound_7 & = & 0.696256160736083984375 \\ bound_8 & = & 0.741760730743408203125 \\ bound_9 & = & 0.77999973297119140625 \\ bound_{10} & = & 1 \end{eqnarray*} One remarks that in order to simplify the dichotomy for computing $i$, the bounds of the intervals are chosen all such that the low order word of the double precision numbers they are stored in are $0$. See \ref{sec:asinargred}, page \pageref{sec:asinargred} for more precise considerations on that subject. Let be $$z_i = \left \lbrace \begin{array}{ll} x & \mbox{ if } i = 0 \\ x - m_i & \mbox{ if } 1 \leq i \leq 8 \\ 1 - x & \mbox{ if } i = 9 \end{array} \right.$$ This value $z_i$ is the argument to the polynomial $p_i$. With the given interval bounds, it is bounded by $$\left \vert z_1 \right \vert \leq 2^{-2.434403}$$ $$\left \vert z_2 \right \vert \leq 2^{-4.123846}$$ $$\left \vert z_3 \right \vert \leq 2^{-4.275849}$$ $$\left \vert z_4 \right \vert \leq 2^{-4.470024}$$ $$\left \vert z_5 \right \vert \leq 2^{-4.708807}$$ $$\left \vert z_6 \right \vert \leq 2^{-4.836970}$$ $$\left \vert z_7 \right \vert \leq 2^{-5.143210}$$ $$\left \vert z_8 \right \vert \leq 2^{-5.457845}$$ $$\left \vert z_9 \right \vert \leq 2^{-5.708811}$$ $$\left \vert z_{10} \right \vert \leq 2^{-2.184423}$$ The degrees of the polynomials $p_i$ and the number of double (D), double-double (DD) and triple-double (TD) coefficients stored in the table are listed below. Here the degree of the polynomial is the highest exponent of the monomial whose coefficient is not equal to $0$. We repeat that the $p_i$ are such that $$\arcsin\left( x \right) \approx x + x^3 \cdot p_0\left( x^2 \right)$$ $$\arcsin\left( x \right) \approx \arcsin\left( m_i \right) + \left(x - m_i \right) \cdot p_i\left( x - m_i \right), \mbox{~~} 1 \leq i \leq 8$$ $$\arcsin\left( x \right) \approx p_9\left( 1 - x \right) \cdot \sqrt{2 - 2\cdot x} + \frac{\pi}{2}$$ \begin{center} \begin{tabular}{|l|l|l|l|l|l|l|l|} \hline $i$ & quick phase & accurate phase & D quick & DD quick & D accur. & DD accur. & TD accur. \\ \hline \hline $0$ & 8 & 17 & 5 & 4 & 7 & 6 & 5 \\ \hline $1\dots8$ & 13 & 34 & 8 & 6 & 20 & 9 & 6 \\ \hline $9$ & 18 & 28 & 10 & 8 & 12 & 9 & 8 \\ \hline \end{tabular} \end{center} Remark that the listing does not account neither for the $8$ double-double values representing approximations to $\arcsin\left( m_i \right)$ nor for the $8$ double precision numbers $m_i$. Taking into account also these values, the overall table size for both quick and accurate phase is 4640 bytes. Some additional values, for example the triple-double $PiHalf_\hi + PiHalf_\mi + PiHalf_\lo \approx \frac{\pi}{2}$, interval bounds or table indices, are directly compiled into the code. Their overall size is 100 bytes. \section{Special case handling, interval discrimination and argument reduction}\label{sec:asinargred} As already mentioned, $\arcsin$ is only defined on the domain $\left[ -1; 1 \right]$. For other arguments, including $\pm \infty$ and $\nan$, $\nan$ must be returned. This is implemented in the code as follows: the sign of $x$ is stripped off by integer computations and stored in variable {\tt sign}. Than, $\left \vert x \right \vert$ is compared to $1$ by integer comparisons. \begin{lstlisting}[caption={Handling special cases - definition domain},firstnumber=1] /* Transform the argument into integer */ xdb.d = x; /* Special case handling */ /* Strip off the sign of argument x */ if (xdb.i[HI] & 0x80000000) sign = -1; else sign = 1; xdb.i[HI] &= 0x7fffffff; /* asin is defined on -1 <= x <= 1, elsewhere it is NaN */ if ((xdb.i[HI] > 0x3ff00000) || ((xdb.i[HI] == 0x3ff00000) && (xdb.i[LO] != 0x00000000))) { return (x-x)/0.0; /* return NaN */ } \end{lstlisting} Concerning subnormals in argument and in result of the function, the following is to be mentioned. The Taylor series of $\arcsin$ developed in $0$ is $$\arcsin\left( x \right) = x \cdot \left( 1 + \frac{1}{6} \cdot x^2 + \sum\limits_{n=2}^\infty \frac{\left( 2n - 1 \right)!!}{\left(2n\right)!! \cdot \left( 2n + 1 \right)} \cdot x^{2n}\right)$$ It is easy to check that $\sum\limits_{n=2}^\infty \frac{\left( 2n - 1 \right)!!}{\left(2n\right)!! \cdot \left( 2n + 1 \right)} \cdot x^{2n} < \frac{1}{3} \cdot x^2$ for $\left \vert x \right \vert < \frac{1}{2}$. So for $\left \vert x \right \vert \leq 2^{-28}$, one gets $\arcsin\left( x \right) \leq x \cdot \left( 1 + \frac{1}{2} \cdot x^2 \right) \leq x \cdot \left( 1 + 2^{-57} \right) < x + \frac{1}{2} \mUlp\left(x\right)$. So the rounding can be decided without even computing the cubic term of the Taylor development. Thus subnormals in argument and in result can be avoided by performing a simple test on the absolute value of $x$. In particular, since $\sum\limits_{n=1}^\infty \frac{\left( 2n - 1 \right)!!}{\left(2n\right)!! \cdot \left( 2n + 1 \right)} \cdot x^{2n}$ is an even function, the sign of the truncation rest is known, which allows for simplifications in the directed rounding modes. Here, only some special care is needed for the case where $x$ is exactly equal to $0$. The test and the rounding are implemented as follows. Let us first consider the round-to-nearest case: \begin{lstlisting}[caption={Handling special cases - rounding (to nearest)},firstnumber=1] if (xdb.i[HI] < 0x3e300000) { return x; } \end{lstlisting} In the round-upward case, a correction of $x$ is potentially necessary. We implement: \begin{lstlisting}[caption={Handling special cases - rounding (upwards)},firstnumber=1] /* If x == 0 then we got the algebraic result arcsin(0) = 0 If x < 0 then the truncation rest is negative but less than 1 ulp; we round upwards by returning x */ if (x <= 0) return x; /* Otherwise the rest is positive, less than 1 ulp and the image is not algebraic We return x + 1ulp */ xdb.l++; return xdb.d; \end{lstlisting} The other directed rounding cases are analogous to the round-upwards case. For the discrimination of the argument $\left \vert x \right \vert$ in the 10 possible approximation intervals $I_i$, the following technique is used. The intervals at the definition domain borders $I_0$ and $I_9$ are first filtered out by tests checking the high order word of $x$ against the corresponding bounds. If $x$ is found to be in one of these two intervals, the function is approximated in quick and if needed in accurate phase and the correctly rounded value is returned. In any case, the two intervals have particular properties in comparison to the other 8 middle intervals, so this technique should not be considered as a performance disadvantage. The polynomial coefficients' indices in the main coefficient table are fixed in this case and directly compiled into the code via macros. If $x$ does not fall in one of the both border intervals $I_0$ and $I_9$, the corresponding interval $I_i$, $1 \leq i \leq 8$ is computed by a 3-level dichotomy on the bounds $bound_2 \dots bound_8$. Its result is not a number $i$ in $1 \leq i \leq 8$ but an index {\tt i} to the main coefficient table. Beginning at the point indexed, the table reads the midpoint value $m_i$ and the polynomial coefficients for the corresponding interval $I_i$. The correponding code is the following: \begin{lstlisting}[caption={Interval discrimination},firstnumber=1] /* Recast x */ x = xdb.d; /* Find correspondant interval and compute index to the table We start by filtering the two special cases around 0 and 1 */ if (xdb.i[HI] < BOUND1) { (*@-- Compute quick and potentially accurate phase polynomial approximation $p_0$ and return --@*) } if (xdb.i[HI] > BOUND9) { (*@-- Reduce the argument, compute quick and potentially accurate phase approximation using $p_9$, reconstruct and return --@*) } /* General 8 main intervals We can already suppose that BOUND1 <= x <= BOUND9 */ if (xdb.i[HI] < BOUND5) { if (xdb.i[HI] < BOUND3) { if (xdb.i[HI] < BOUND2) i = TBLIDX2; else i = TBLIDX3; } else { if (xdb.i[HI] < BOUND4) i = TBLIDX4; else i = TBLIDX5; } } else { if (xdb.i[HI] < BOUND7) { if (xdb.i[HI] < BOUND6) i = TBLIDX6; else i = TBLIDX7; } else { if (xdb.i[HI] < BOUND8) i = TBLIDX8; else i = TBLIDX9; } } (*@-- Reduce the argument, compute quick and potentially accurate~ phase polynomial approximation $p_i$ and return --@*) \end{lstlisting} In the case of $x$ being classified in either the middle or the higher intervals $I_i$, $1 \leq i \leq 9$, an argument reduction is to be performed. Let us consider it first for the high path interval $I_9$ and then for the middle path intervals $I_i$, $1 \leq i \leq 8$. In both cases, we will show that the argument reduction is mathematically exact and that it may not produce a subnormal different from $0$. In the high path, we know that $1 \geq x > bound_9 > 0.77$. The argument reduction to be performed is $z = 1 - x$. Since $\frac{1}{2} \leq x \leq 2$ is verified, we can implement it exactly thanks to Sterbenz' lemma. If $x$ is exactly equal to $1$ is produces exactly $0$. Otherwise, it may not produce a subnormal, because $x \leq 1 - \frac{1}{2} \cdot \mUlp\left( 1 \right) \leq 1 - 2^{-53}$. Thus $z = 1 - x > 2^{-53} > 2^{-1021}$. In the middle path intervals, the argument reduction to be performed is $z_i = x - m_i$. Since $\left \vert z \right \vert \leq 0.058$ and $x \geq 0.18$, Sterbenz' lemma is verified in each interval $I_i$ and we can still implement the argument reduction exactly in double precision arithmetic. Since, $x > 0.18 > \frac{1}{8}$, a similar argument as the one given above shows that the result of the reduction is either exactly $0$ or a non-subnormal double precision number. The value $m_i$ is read in the main table at the index {\tt i} computed by the interval discrimination phase. We implement thus: \begin{lstlisting}[caption={Argument reduction},firstnumber=1] /* Argument reduction i points to the interval midpoint value in the table */ z = x - tbl[i]; \end{lstlisting} Concerning the higher path interval $I_9$ where $\arcsin$ is approximated as $$\arcsin\left( x \right) \approx p_9\left( 1 - x \right) \cdot \sqrt{2 - 2\cdot x} + \frac{\pi}{2}$$ let us remark that $2 - 2\cdot x = 2 \cdot z$ can also be computed exactly. Trivially, since $z$ less than $2^{1023}$, the multiplication by a positive integer power of $2$ is errorfree. If $z$ is not exactly $0$, its result may not be subnormal because $z$ cannot. Since the argument reduction has been shown to be exact, its result can clearly be reused in the accurate phase. \section{Polynomial approximation and reconstruction}\label{sec:asinpolynomial} \subsection{Quick phase polynomial approximation and reconstruction}\label{subsec:asinquickpolynomial} As already mentioned, the quick phase polynomials $p_{i\mbox{\tiny ~quick}}$ are truncated versions of the accurate phase polynomials $p_{i\mbox{\tiny ~accurate}}$ with coefficients rounded from triple-double to double-double or from double-double to double. This means simply that not all coefficients are read and used. \subsubsection{Low path - interval $I_0$} The polynomial $p_{0\mbox{\tiny ~quick}}$ approximates $\arcsin$ in the interval $I_0$ as follows: $$\arcsin\left( x \right) \approx x + x^3 \cdot p_{0\mbox{\tiny ~quick}}\left( x^2 \right)$$ It is of degree $8$ with $5$ double-double and $4$ double precision coefficients. For arguments $\left \vert x \right \vert \leq 2^{-10}$, the polynomial needs not be evaluated fully to provide enough accuracy. Here, only its constant and linear term are evaluated. So we get in this case $$\arcsin\left( x \right) \approx x + x^3 \cdot \left( \left( c_{0\hi} + c_{0\lo} \right) + x^2 \cdot \left( c_{1\hi} + c_{1\lo} \right) \right)$$ This special path yields to a significant performance gain on average. In fact, since floating point numbers are not equispaced but distributed logarithmatically around $0$, speeding up a function for low arguments is worth it. The square of $x$, $x^2$ can be computed exactly by use of a \Mul~ sequence, which will produce a double-double $xSq_\hi + xSq_\lo = x^2$. The polynomial $p_{0\mbox{\tiny ~quick}}\left( xSq_\hi + xSq_\lo \right)$ is evaluated using Horner's scheme and neglecting $xSq_\lo$ for the $8$ higher degree coefficients if these need to be evaluated. The double-double precision Horner steps are implemented the double-double multiply-and-add macros \MulAddDD~ and \MulAddDdD~ (see section \ref{sec:double-double-horner}, page \pageref{sec:double-double-horner}). It is easy to check that the preconditions on the arguments of these macros are verified: $x^2$ is bounded by $x^2 \leq \left(2^{-2.434403}\right)^2 \leq 2^{-4}$ in this path. Further, in the order of the Horner evaluation, the coefficients $c_i$ of the polynomial are stricly increasing in magnitude and all less than $1$. Concerning the accuracy of this operations, see section \ref{subsec:asinquickphaseaccu}, page \pageref{subsec:asinquickphaseaccu}. Including the test $\left \vert x \right \vert \stackrel{?}{\leq} 2^{-10}$, the code computing an approximation $t_{5\hi} + t_{5\lo} \approx p_{0\mbox{\tiny ~quick}}\left( x^2 \right)$ reads: \begin{lstlisting}[caption={Low path quick phase polynomial approximation (higher degrees)},firstnumber=1] Mul12(&xSqh,&xSql,x,x); tmp4 = tbl[3]; tmp5 = tbl[4]; t4h = tmp4; t4l = tmp5; if (xdb.i[HI] > EXTRABOUND) { /* Double precision evaluation */ highPoly = tbl[15] + xSqh * (tbl[17] + xSqh * (tbl[19] + xSqh * (tbl[21] + xSqh * tbl[23]))); /* Double-double precision evaluation */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[12],tbl[13],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[9],tbl[10],xSqh,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[6],tbl[7],xSqh,t2h,t2l); MulAdd22(&t4h,&t4l,tmp4,tmp5,xSqh,xSql,t3h,t3l); } MulAdd22(&t5h,&t5l,tbl[0],tbl[1],xSqh,xSql,t4h,t4l); \end{lstlisting} Once $t_{5\hi} + t_{5\lo}$ are computed, they must be multiplied by $x^3$ and the result must be added to $x$. The value $x^3$ is computed approximatively as a double-double $xCube_\hi + xCube_\lo$ by multiplying $x$ by $xSq_\hi + xSq_\lo = x^2$. This value $xCube_\hi + xCube_\lo$ is than multiplied by $t_{5\hi} + t_{5\lo}$, yielding to $tt_{6\hi} + tt_{6\lo}$. The last addition implying $x$ and $tt_{6\hi} + tt_{6\lo}$ is implemented in an ad-hoc way by means of two exact additions and a double precision addition on the lower part of the addition of the higher significant parts. The code reads: \begin{lstlisting}[caption={Low path quick phase polynomial approximation (lower degrees)},firstnumber=1] Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt6h,&tt6l,xCubeh,xCubel,t5h,t5l); Add12(tmp1,tmp2,x,tt6h); tmp3 = tmp2 + tt6l; Add12(polyh,polyl,tmp1,tmp3); \end{lstlisting} The obtained polynomial approximation value is then multiplied by the sign of $x$ the argument reduction had stripped off and the rounding test is performed. If it fails, the accurate phase is launched; see section \ref{sec:asinacculowpath}, page \pageref{sec:asinacculowpath}, for its implementation. The code for the last steps in round-to-nearest mode is given below. The code for the direct rounding modes is analogous. One remarks that the rounding test constants, computed by the corresponding Maple scripts in function of the relative error bounds to be shown in section \ref{subsec:asinquickphaseaccu}, page \pageref{subsec:asinquickphaseaccu}, are stored also in double precision and also read from the main table. \begin{lstlisting}[caption={Low path quick phase rounding test},firstnumber=1] /* Multiply by sign */ asinh = sign * polyh; asinm = sign * polyl; /* Rounding test The RN rounding constant is at tbl[34] */ if(asinh == (asinh + (asinm * tbl[34]))) return asinh; /* Launch accurate phase */ \end{lstlisting} \subsubsection{Middle path - interval $I_i$, $1 \leq i \leq 8$} In the quick phase middle path, i.e. for arguments $x \in I_i$, $1 \leq i \leq 8$, $\arcsin$ is approximated by the polynomial $p_{i\mbox{\tiny ~quick}}$ as follows: $$\arcsin\left( x \right) \approx \arcsin\left( m_i \right) + z_i \cdot p_{i\mbox{\tiny ~quick}}\left( z_i \right)$$ where $z_i = x - m_i$ is a double precision number. Further an approximation $asm_{i\hi} + asm_{i\lo}$ to $\arcsin\left( m_i \right)$ is used. It is read in the main table at {\tt tbl[i+1]} and {\tt tbl[i+2]} where {\tt i} is the index computed at the interval discrimination phase. The polynomial $p_{i\mbox{\tiny ~quick}}$ is of degree $13$ with $6$ double-double and $8$ double coefficients. It is always evaluated completely by means of Horner's scheme. Once again, the \MulAddDdD~ operator allows for evaluating the $5$ last double-double steps. The first double-double step is evaluated in a more ad-hoc way because of the entering only double precision current intermediate result. The preconditions for the \MulAddDdD~ operator can again be checked easily: $z_i$ is bounded in magnitude by $2^{-4.123846}$, the coefficients increase in the order of Horner's scheme evaluation and are all less than $1$. So in each step, the product of $z_i$ and the current value is less than $\frac{1}{4}$ the next coefficient as asked for by the precondition. The multiplication of the result of the polynomial $p_{i\mbox{\tiny ~quick}}$ by $z_i$ and the addition of $asm_{i\hi} + asm_{i\lo}$ can also be considered as a Horner step and are therefore implemented using the \MulAddDdD~ macro, too. The corresponding evaluation code reads thus: \begin{lstlisting}[caption={Middle path quick phase polynomial approximation},firstnumber=1] highPoly = tbl[i+21] + z * (tbl[i+23] + z * (tbl[i+25] + z * ( tbl[i+27] + z * (tbl[i+29] + z * (tbl[i+31] + z * ( tbl[i+33] + z * tbl[i+35])))))); Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+18],tbl[i+19],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+15],tbl[i+16],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+12],tbl[i+13],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+9],tbl[i+10],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+6],tbl[i+7],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+3],tbl[i+4],z,t5h,t5l); MulAdd212(&polyh,&polyl,tbl[i+1],tbl[i+2],z,t6h,t6l); \end{lstlisting} One remarks that in this case, since the polynomial evaluation code is the same for all intervals $I_i$, $1 \leq i \leq 8$, the coefficients read in the table are not at fixed indices but indexed by {\tt i}, value computed in the interval discrimination phase. The result of this approximation whose accuracy will be analysed in section \ref{subsec:asinquickphaseaccu}, page \pageref{subsec:asinquickphaseaccu}, is then multiplied by the sign of the the original argument and submitted to the rounding test whose rounding constant is read in the main table dependingly on the interval $I_i$. The corresponding code for round-to-nearest is given below. The directed rounding cases are analogous. \begin{lstlisting}[caption={Middle path quick phase rounding test},firstnumber=1] asinh = sign * polyh; asinm = sign * polyl; /* Rounding test The RN rounding constant is at tbl[i+59] */ if(asinh == (asinh + (asinm * tbl[i+59]))) return asinh; /* Launch accurate phase */ \end{lstlisting} \subsubsection{High path - interval $I_9$} In the high path $\arcsin$ is approximated as $$\arcsin\left( x \right) \approx p_{9\mbox{\tiny ~quick}}\left( z \right) \cdot \sqrt{2 \cdot z} + \frac{\pi}{2}$$ Herein, $z = 1 - x$ is the exactly computed double precision reduced argument. The constant $\frac{\pi}{2}$ is approximated by the double-double number $PiHalf_\hi + PiHalf_\mi = \frac{\pi}{2} \cdot \left( 1 + \epsilon \right)$ with $\left \vert \epsilon \right \vert \leq 2^{-109}$. It has already been shown that $z$ and $twoZ = 2 \cdot z$ can be computed exactly. The square root $\sqrt{2 \cdot z}$ is approximated in double-double precision using the \SqrtD~ macro operator described in section \ref{subsection:sqrt}, page \pageref{subsection:sqrt}. The polynomial $p_{9\mbox{\tiny ~quick}}$ has degree $18$ with $9$ double-double and $10$ double precision coefficients. Its constant term is exactly $-1$, so this coefficient is not stored in the table. It is always evaluated completely. Horner's scheme is used and implemented by means of the \MulAddDdD~ operator whose precodnitions can once again easily be verified by an analogous argument as the one given above for low and middle paths. The corresponding code reads: \begin{lstlisting}[caption={High path quick phase polynomial approximation},firstnumber=1] highPoly = tbl[TBLIDX10+24] + z * (tbl[TBLIDX10+26] + z * (tbl[TBLIDX10+28] + z * ( tbl[TBLIDX10+30] + z * (tbl[TBLIDX10+32] + z * (tbl[TBLIDX10+34] + z * ( tbl[TBLIDX10+36] + z * (tbl[TBLIDX10+38] + z * (tbl[TBLIDX10+40] + z * tbl[TBLIDX10+42])))))))); Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],z,t7h,t7l); MulAdd212(&polyh,&polyl,-1,0,z,t8h,t8l); \end{lstlisting} The result $poly_\hi + poly_\lo$ of the polynomial approximation is multiplied by $sqrtz_\hi + sqrtz_\lo$, the double-double approximation of $\sqrt{2 \cdot z}$ by the double-double multiplication operator \MulDD~ and then added to $PiHalf_\hi + PiHalf_\mi$ using the double-double addition operator \AddDD. In this addition no catastrophic cancellation can occur: since $x > 0.78 > \frac{\sqrt{2}}{2}$ in this interval, the result of the addition, a good approximation to $\arcsin\left( x \right)$ will always be greater than $\frac{\pi}{4}$ as per the monotony of arcsine. So $pTimesS_\hi + pTimesS_\lo \approx p_{9\mbox{\tiny ~quick}}\left( z \right) \cdot \sqrt{2 \cdot z}$ will always be less than $\frac{1}{2} \cdot \left( PiHalf_\hi + PiHalf_\mi \right)$. In this argumentation, approximation errors can be neglected since the bound to be shown is not tight at all. The corresponding implementation is the following: \begin{lstlisting}[caption={High path: square root extraction and reconstruction},firstnumber=1] twoZ = 2 * z; sqrt12(&sqrtzh,&sqrtzl,twoZ); /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul22(&pTimesSh,&pTimesSl,polyh,polyl,sqrtzh,sqrtzl); Add22(&allh,&alll,PIHALFH,PIHALFM,pTimesSh,pTimesSl); \end{lstlisting} In this path, too, the obtained result is multiplied by the sign which had stripped off from the function's argument $x$ and submitted to the rounding test using a rounding constant read in the main table. The code reads for round-to-nearest mode: \begin{lstlisting}[caption={Multiplication of the function's sign, rounding test (round-to-nearest)},firstnumber=1] asinh = sign * allh; asinm = sign * alll; /* Rounding test The RN rounding constant is at tbl[TBLIDX10+54] */ if(asinh == (asinh + (asinm * tbl[TBLIDX10+54]))) return asinh; /* Launch accurate phase */ \end{lstlisting} \subsection{Accurate phase polynomial approximation and reconstruction}\label{subsec:asinaccupolynomial} As already mentioned, in the accurate phase, the polynomials $p_{i\mbox{\tiny ~accurate}}$ for the different intervals $I_i$ whose coefficient are stored in the main table, are evaluated completely. This evaluation is done in double, double-double and triple-double precision using mainly Horner's scheme. The accurate phase is implemented in three different {\tt C} functions corresponding to the low, middle and high paths. These functions return a triple-double approximate $asin_\hi + asin_\mi + asin_\lo$ to $\arcsin$ which is accurate enough that the correct rounded result for $\arcsin$ is obtained when rounding the approximate. The final rounding for itself is implemented in the four functions containing the quick phase code and the call to the accurate phase for the four possible rounding modes. In round-to-nearest mode, for the high path the code reads: \begin{lstlisting}[caption={Final rounding of the accurate phase result (RN)},firstnumber=1] /* Launch accurate phase */ asin_accurate_higher(&asinh,&asinm,&asinl,z,sign); ReturnRoundToNearest3(asinh,asinm,asinl); \end{lstlisting} For the other rounding modes and evaluation paths the code is completely analogous. \subsubsection{Low path - interval $I_0$\label{sec:asinacculowpath}} For the low path, the polynomial $p_{0\mbox{\tiny ~accurate}}$ approximates $\arcsin$ as follows: $$\arcsin\left( x \right) \approx x + x^3 \cdot p_{0\mbox{\tiny ~accurate}}\left( x^2 \right)$$ is of degree $17$ with $7$ double precision coefficients and Horner steps, $6$ double-double coefficients and steps and $5$ triple-double coefficients and steps. It reuses the value $xSq_\hi + xSq_\lo = x^2$ which has already been computed in the quick phase. The lower significant term $xSq_\lo$ is neglected for the first $8$ double precision (and early double-double precision) steps. The double-double Horner steps are implemented using the \MulAddDD~ sequence. The triple-double steps used separate \AddTT~ and \MulTT~ macros. The value $x^3$ is computed out of $x$ and $x^2$ in triple-double precision using the \MuldDT~ operator. It is multiplied by the polynomial's result in triple-double by a \MulTT. The resulting triple-double is added to $x$ using the \AdddTT~ macro. In addition to the final renormalization which is needed before correct rounding to double precision is performed, one intermediate renormalization is necessary. Otherwise overlap in the triple-double intermediate values would deteriorate the accuracy to much. See section \ref{subsec:asinaccuratephaseaccu}, page \pageref{subsec:asinaccuratephaseaccu} for the overlap bounding. The code of the low path accurate phase polynomial approximation is the following: \begin{lstlisting}[caption={Low path accurate phase polynomial approximation},firstnumber=1] highPoly = tbl[28] + xSqh * (tbl[29] + xSqh * (tbl[30] + xSqh * (tbl[31] + xSqh * (tbl[32] + xSqh * tbl[33])))); /* Double-double computations */ Mul12(&tt1h,&tt1l,xSqh,highPoly); Add22(&t1h,&t1l,tbl[27],0,tt1h,tt1l); MulAdd22(&t2h,&t2l,tbl[25],tbl[26],xSqh,xSql,t1h,t1l); MulAdd22(&t3h,&t3l,tbl[23],tbl[24],xSqh,xSql,t2h,t2l); MulAdd22(&t4h,&t4l,tbl[21],tbl[22],xSqh,xSql,t3h,t3l); MulAdd22(&t5h,&t5l,tbl[19],tbl[20],xSqh,xSql,t4h,t4l); MulAdd22(&t6h,&t6l,tbl[17],tbl[18],xSqh,xSql,t5h,t5l); MulAdd22(&t7h,&t7l,tbl[15],tbl[16],xSqh,xSql,t6h,t6l); /* Triple-double computations */ Mul23(&tt8h,&tt8m,&tt8l,xSqh,xSql,t7h,t7l); Add33(&t8h,&t8m,&t8l,tbl[12],tbl[13],tbl[14],tt8h,tt8m,tt8l); Mul233(&tt9h,&tt9m,&tt9l,xSqh,xSql,t8h,t8m,t8l); Add33(&t9h,&t9m,&t9l,tbl[9],tbl[10],tbl[11],tt9h,tt9m,tt9l); Mul233(&tt10h,&tt10m,&tt10l,xSqh,xSql,t9h,t9m,t9l); Add33(&t10h,&t10m,&t10l,tbl[6],tbl[7],tbl[8],tt10h,tt10m,tt10l); Mul233(&tt11hover,&tt11mover,&tt11lover,xSqh,xSql,t10h,t10m,t10l); Renormalize3(&tt11h,&tt11m,&tt11l,tt11hover,tt11mover,tt11lover); Add33(&t11h,&t11m,&t11l,tbl[3],tbl[4],tbl[5],tt11h,tt11m,tt11l); Mul233(&tt12h,&tt12m,&tt12l,xSqh,xSql,t11h,t11m,t11l); Add33(&t12h,&t12m,&t12l,tbl[0],tbl[1],tbl[2],tt12h,tt12m,tt12l); Mul123(&xCubeh,&xCubem,&xCubel,x,xSqh,xSql); Mul33(&tt13h,&tt13m,&tt13l,xCubeh,xCubem,xCubel,t12h,t12m,t12l); Add133(&t13h,&t13m,&t13l,x,tt13h,tt13m,tt13l); Renormalize3(&polyh,&polym,&polyl,t13h,t13m,t13l); *asinh = sign * polyh; *asinm = sign * polym; *asinl = sign * polyl; \end{lstlisting} \subsubsection{Middle path - interval $I_i$, $1 \leq i \leq 8$} For the middle path for $x \in I_i$, $1 \leq i \leq 8$, we use the following polynomial approximation by $p_{i \mbox{\tiny ~accurate}}$: $$\arcsin\left( x \right) \approx \left( asm_{i\hi} + asm_{i\lo} \right) + z_i \cdot p_{i \mbox{\tiny ~accurate}}\left( z_i\right)$$ where $z_i = x - m_i$ and $asm_{i\hi} + asm_{i\lo} = \arcsin\left( m_i \right) \cdot \left( 1 + \epsilon \right)$ with $\left \vert \epsilon \right \vert \leq 2^{-121}$ by construction of $m_i$. The polynomial $p_{i \mbox{\tiny ~accurate}}$ is of degree $34$. In order of decreasing monomial degrees, its coefficients are stored on $20$ double precision numbers, $9$ double-double precision numbers and $6$ triple-double precision numbers. It is completely evaluated using Horner's scheme using the same intermediate precision for the computation as the one used for the coefficients. The last multiplication by $z$ and the addition of $asm_{i\hi} + asm_{i\lo}$ can be considered as an additional Horner step and is of course performed in triple-double precision. The double-double precision steps are implemented using the \MulAddDdD~ macro. The triple-double steps use separate addition and multiplication operators. In particular, \AddTT~ and \MuldTT~ come at hand. Overall, two triple-double renormalizations are necessary: one before final rounding can be performed and one other for avoiding a too great overlap in the components of the intermediate triple-double values. See section \ref{subsec:asinaccuratephaseaccu}, page \pageref{subsec:asinaccuratephaseaccu} for the overlap bounding. The coefficients of the polynomial $p_{i \mbox{\tiny ~accurate}}$ and the value $asm_{i\hi} + asm_{i\lo}$ are read in the main table using the index {\tt i} computated at the interval discrimination phase. The reduced argument $z_i$ has already been computed exactly at the quick phase and can be reused. The implementation of the accurate phase middle path polynomial approximation reads: \begin{lstlisting}[caption={Middle path accurate phase polynomial approximation},firstnumber=1] highPoly = tbl[i+39] + z * (tbl[i+40] + z * (tbl[i+41] + z * (tbl[i+42] + z * ( tbl[i+43] + z * (tbl[i+44] + z * (tbl[i+45] + z * (tbl[i+46] + z * ( tbl[i+47] + z * (tbl[i+48] + z * (tbl[i+49] + z * (tbl[i+50] + z * ( tbl[i+51] + z * (tbl[i+52] + z * (tbl[i+53] + z * (tbl[i+54] + z * ( tbl[i+55] + z * (tbl[i+56] + z * (tbl[i+57] + z * tbl[i+58])))))))))))))))))); /* Double-double computations */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[i+37],tbl[i+38],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[i+35],tbl[i+36],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[i+33],tbl[i+34],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[i+31],tbl[i+32],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[i+29],tbl[i+30],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[i+27],tbl[i+28],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[i+25],tbl[i+26],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[i+23],tbl[i+24],z,t7h,t7l); MulAdd212(&t9h,&t9l,tbl[i+21],tbl[i+22],z,t8h,t8l); /* Triple-double computations */ Mul123(&tt10h,&tt10m,&tt10l,z,t9h,t9l); Add33(&t10h,&t10m,&t10l,tbl[i+18],tbl[i+19],tbl[i+20],tt10h,tt10m,tt10l); Mul133(&tt11h,&tt11m,&tt11l,z,t10h,t10m,t10l); Add33(&t11h,&t11m,&t11l,tbl[i+15],tbl[i+16],tbl[i+17],tt11h,tt11m,tt11l); Mul133(&tt12h,&tt12m,&tt12l,z,t11h,t11m,t11l); Add33(&t12h,&t12m,&t12l,tbl[i+12],tbl[i+13],tbl[i+14],tt12h,tt12m,tt12l); Mul133(&tt13hover,&tt13mover,&tt13lover,z,t12h,t12m,t12l); Renormalize3(&tt13h,&tt13m,&tt13l,tt13hover,tt13mover,tt13lover); Add33(&t13h,&t13m,&t13l,tbl[i+9],tbl[i+10],tbl[i+11],tt13h,tt13m,tt13l); Mul133(&tt14h,&tt14m,&tt14l,z,t13h,t13m,t13l); Add33(&t14h,&t14m,&t14l,tbl[i+6],tbl[i+7],tbl[i+8],tt14h,tt14m,tt14l); Mul133(&tt15h,&tt15m,&tt15l,z,t14h,t14m,t14l); Add33(&t15h,&t15m,&t15l,tbl[i+3],tbl[i+4],tbl[i+5],tt15h,tt15m,tt15l); Mul133(&tt16h,&tt16m,&tt16l,z,t15h,t15m,t15l); Add233(&t16h,&t16m,&t16l,tbl[i+1],tbl[i+2],tt16h,tt16m,tt16l); Renormalize3(&polyh,&polym,&polyl,t16h,t16m,t16l); *asinh = sign * polyh; *asinm = sign * polym; *asinl = sign * polyl; \end{lstlisting} \subsubsection{High path - interval $I_9$} On the high path interval $I_9$, computing the approximation for $\arcsin$ means evaluating the polynomial $p_{9 \mbox{\tiny~accurate}}\left( z \right)$ and calculating a triple-double approximation to $\sqrt{2 \cdot z}$ where $z$ is the reduced argument. The function can then be reconstructed as follows: $$\arcsin\left( x \right) \approx p_{9 \mbox{\tiny~accurate}}\left( z \right) \cdot \sqrt{2\cdot z} + \left( PiHalf_\hi + PiHalf_\mi + PiHalf_\lo \right)$$ where $PiHalf_\hi + PiHalf_\mi + PiHalf_\lo = \frac{\pi}{2} \cdot \left( 1 + \epsilon \right)$, $\left \vert \epsilon \right \vert \leq 2^{-164}$ The polynomial $p_{9 \mbox{\tiny~accurate}}\left( z \right)$ is of degree $28$ with $12$ double precision, $9$ double-double precision and $8$ triple-double precision coefficients. The intermediate precisions used correspond to the precision the coefficients are stored in. The polynomial is completely evaluated in Horner's scheme. Once again, for doing so, the \MulAddDdD~ macro is used for the double-double steps whilst the triple-double stage is implemented by means of separate additions and multiplications mainly expressed with \AddTT~ and \MuldTT~ operators. The square root extraction yielding to the triple-double approximate $sqrtz_\hi + sqrtz_\mi + sqrtz_\lo = \sqrt{2 \cdot z } \cdot \left( 1 + \epsilon \right)$ is implemented using the \SqrtT~ macro. Unfortunately, this means recomputing some steps of the square root extraction already computed in the quick phase in the \SqrtD~ macro. The choice made is motivated by implementatory reasons. The multiplication of the polynomial's value and of the square root is performed in triple-double precision by means of the \MulTT~ macro. The following addition with the triple-double approximate of $\frac{\pi}{2}$ is implemented using the \AddTT~ operator. Overall, three renormalizations are needed. One of them renormalizes the final result, two allow for sufficient overlap bounding. Remark that the square root extraction by \SqrtT~ comprises an additional renormalization; see section \ref{subsection:sqrt}, page \pageref{subsection:sqrt} for further details. The overlap bounds will be given in section \ref{subsec:asinaccuratephaseaccu}, page \pageref{subsec:asinaccuratephaseaccu}. The code implementing this accurate phase path is the following: \begin{lstlisting}[caption={High path accurate phase polynomial approximation},firstnumber=1] highPoly = tbl[TBLIDX10+42] + z * (tbl[TBLIDX10+43] + z * (tbl[TBLIDX10+44] + z * ( tbl[TBLIDX10+45] + z * (tbl[TBLIDX10+46] + z * (tbl[TBLIDX10+47] + z * ( tbl[TBLIDX10+48] + z * (tbl[TBLIDX10+49] + z * (tbl[TBLIDX10+50] + z * ( tbl[TBLIDX10+51] + z * (tbl[TBLIDX10+52] + z * tbl[TBLIDX10+53])))))))))); /* Double-double computations */ Mul12(&tt1h,&tt1l,z,highPoly); Add22(&t1h,&t1l,tbl[TBLIDX10+40],tbl[TBLIDX10+41],tt1h,tt1l); MulAdd212(&t2h,&t2l,tbl[TBLIDX10+38],tbl[TBLIDX10+39],z,t1h,t1l); MulAdd212(&t3h,&t3l,tbl[TBLIDX10+36],tbl[TBLIDX10+37],z,t2h,t2l); MulAdd212(&t4h,&t4l,tbl[TBLIDX10+34],tbl[TBLIDX10+35],z,t3h,t3l); MulAdd212(&t5h,&t5l,tbl[TBLIDX10+32],tbl[TBLIDX10+33],z,t4h,t4l); MulAdd212(&t6h,&t6l,tbl[TBLIDX10+30],tbl[TBLIDX10+31],z,t5h,t5l); MulAdd212(&t7h,&t7l,tbl[TBLIDX10+28],tbl[TBLIDX10+29],z,t6h,t6l); MulAdd212(&t8h,&t8l,tbl[TBLIDX10+26],tbl[TBLIDX10+27],z,t7h,t7l); MulAdd212(&t9h,&t9l,tbl[TBLIDX10+24],tbl[TBLIDX10+25],z,t8h,t8l); /* Triple-double computations */ Mul123(&tt10h,&tt10m,&tt10l,z,t9h,t9l); Add33(&t10h,&t10m,&t10l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tbl[TBLIDX10+23],tt10h,tt10m,tt10l); Mul133(&tt11h,&tt11m,&tt11l,z,t10h,t10m,t10l); Add33(&t11h,&t11m,&t11l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],tbl[TBLIDX10+20],tt11h,tt11m,tt11l); Mul133(&tt12h,&tt12m,&tt12l,z,t11h,t11m,t11l); Add33(&t12h,&t12m,&t12l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],tbl[TBLIDX10+17],tt12h,tt12m,tt12l); Mul133(&tt13h,&tt13m,&tt13l,z,t12h,t12m,t12l); Add33(&t13hover,&t13mover,&t13lover, tbl[TBLIDX10+12],tbl[TBLIDX10+13],tbl[TBLIDX10+14],tt13h,tt13m,tt13l); Renormalize3(&t13h,&t13m,&t13l,t13hover,t13mover,t13lover); Mul133(&tt14h,&tt14m,&tt14l,z,t13h,t13m,t13l); Add33(&t14h,&t14m,&t14l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],tbl[TBLIDX10+11],tt14h,tt14m,tt14l); Mul133(&tt15h,&tt15m,&tt15l,z,t14h,t14m,t14l); Add33(&t15h,&t15m,&t15l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],tbl[TBLIDX10+8],tt15h,tt15m,tt15l); Mul133(&tt16h,&tt16m,&tt16l,z,t15h,t15m,t15l); Add33(&t16h,&t16m,&t16l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],tbl[TBLIDX10+5],tt16h,tt16m,tt16l); Mul133(&tt17hover,&tt17mover,&tt17lover,z,t16h,t16m,t16l); Renormalize3(&tt17h,&tt17m,&tt17l,tt17hover,tt17mover,tt17lover); Add33(&t17h,&t17m,&t17l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],tbl[TBLIDX10+2],tt17h,tt17m,tt17l); Mul133(&tt18h,&tt18m,&tt18l,z,t17h,t17m,t17l); Add133(&polyh,&polym,&polyl,-1,tt18h,tt18m,tt18l); /* Compute sqrt(2*z) as a triple-double */ twoZ = 2 * z; sqrt13(&sqrtzh,&sqrtzm,&sqrtzl,twoZ); /* Multiply p(z) by sqrt(2*z) and add Pi/2 */ Mul33(&pTimesSh,&pTimesSm,&pTimesSl,polyh,polym,polyl,sqrtzh,sqrtzm,sqrtzl); Add33(&allhover,&allmover,&alllover,PIHALFH,PIHALFM,PIHALFL,pTimesSh,pTimesSm,pTimesSl); /* Renormalize and multiply by sign */ Renormalize3(&allh,&allm,&alll,allhover,allmover,alllover); *asinh = sign * allh; *asinm = sign * allm; *asinl = sign * alll; \end{lstlisting} \section{Accuracy bounds}\label{sec:asinaccuracy} \subsection{Quick phase accuracy}\label{subsec:asinquickphaseaccu} TODO: see possibly available Gappa files meanwhile \subsection{Accurate phase accuracy}\label{subsec:asinaccuratephaseaccu} TODO: see possibly available Gappa files meanwhile \section{Timings and memory consumption}\label{sec:asintimingmemory} The given implementation of the arcsine uses tables and constants that consume 4740 bytes of memory. This values are fully shared between quick and accurate phase. The code size, including the tables, is about 22 kbytes when compiled to PowerPC machine code. The quick phase code for one rounding mode needs about 1.5 kbytes without the table. This means that there are about 12 kbytes of code for the accurate phase, which is shared between all rounding modes. Concerning the timing, we compare our implementation to IBM's {\tt libultim} and to MPFR. The values are given in arbitrary units and obtained on a IBM Power 5 processor with gcc 3.3.3 on a Linux Kernel 2.6.5. The timings on other systems are comparable. \begin{center} \begin{tabular}{|l|r|r|} \hline Library & avg time & max time \\ \hline \hline \texttt{MPFR} & 6322 & 83415 \\ \hline \texttt{crlibm} portable using triple-double & 45 & 300 \\ \hline default \texttt{libm} (IBM's {\tt libultim}) & 23 & 206239 \\ \hline \end{tabular} \end{center} It is worth mentioning that IBM's library uses about 20 kbytes of tables for its mere quick phase. %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/atan.tex0000644000000000000000000005150413316017127017245 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA This chapter is contributed by Nicolas Gast under the supervision of F. de~Dinechin. \newcommand{\xred}{X_{\mathrm{red}}} \newcommand{\xredhi}{{\mathrm{Xredhi}}} \newcommand{\xredlo}{{\mathrm{Xredlo}}} \section{Overview} For the arctangent, the quick phase has a precision of 64 bits, and the accurate phase computes to a precision of 136 bits. \subsubsection{Definition interval and exceptional cases} The inverse tangent is defined over all real numbers. \begin{itemize} \item If $x = NaN$ , then $\arctan(x)$ should return $NaN$ \item If $x = \pm\infty$ , then $\arctan(x)$ should return $\pm\round(\pi/2) = \pm\rounddown(\pi/2)$ in rounding to nearest mode. In directed rounding modes, we may return $\pm\roundup(\pi/2)$ which invalidates the inequation $|\arctan(x)|<\frac{\pi}{2}$ but respects the rounding. \item For $2^{54}<|x|<+\infty$ we choose to return $\pm\round(\pi/2)$ in all rounding modes. \item For $|x|<2^{-27}$ we have $|\arctan(x)-x|<2^{-53}x$ and $|\arctan(x)|<|x|$, which allows to decide to return either $x$ or the FP number next to $x$ towards zero. \end{itemize} \section{Quick phase} The code of the quick phase is organized in five functions. The function (\texttt{atan\_quick}) returns two doubles ($atanhi$ and $atanlo$) that represent $\arctan(x)$ with a precision of about 64 bits. Four other functions compute the correct rounding : \texttt{atan\_rn}, \texttt{atan\_ru}, \texttt{atan\_rd} and \texttt{atan\_rz}. \subsection{Overview of the algorithm for the quick phase.} This phase is computed in double or double-double. There are two steps in the algorithm: an argument reduction and a polynomial approximation with a polynomial of degree 9. We compute $\arctan(x)$ as \begin{equation} \arctan(x) = \arctan( b_i ) + \arctan(\frac{x-b_i}{1+x.b_i}) \label{eq:arctan_redu} \end{equation} The $b_i$ are exact doubles and the $\arctan(b_i)$ are stored in double-double. We define $\xred = \dfrac{x-b_i}{1+x.b_i}$ for the rest of this chapter. We tabulate intervals bounds $a_i$ and values $b_i$ such that \begin{equation} x \in [a_i;a_{i+1}] \Rightarrow \dfrac{x-b_i}{1+x.b_i} < e \quad . \label{atan_ineq_interval} \end{equation} The $i$ such that $x \in [a_i;a_{i+1}]$ will be found by dichotomy. Therefore we choose a power of two for the number of intervals: 64 intervals ensure $e=2^{-6.3}$. Then we use a polynomial of degree 9 for the approximation of $\arctan(\xred)$ which ensures 66 bits of precision: \begin{equation} \begin{split} \arctan(x)& \approx x - \dfrac{1}{3} .x^3 + \frac{1}{5}.x^5 - \frac{1}{7}.x^7 + \frac{1}{9}.x^9 \nonumber \\ & \approx x . + x.Q(x^2) \end{split} \label{eq:poly_eval1} \end{equation} Q is evaluated thanks to a Horner scheme: $ Q(z) = z. (-\frac{1}{3} + z.(\frac{1}{5} + z.(-\frac{1}{7} + z.\frac{1}{9}))) $ where each operation is computed in double. As $|z| \leq e$, $Q(z) \leq e^2$ At the end, the reconstruction implements equation (\ref{eq:poly_eval1}) and (\ref{eq:arctan_redu}) in double-double arithmetic. \subsection{Error analysis on atan\_quick} We choose four rounding constant: two when there is a argument reduction, two in the other case. For each case, we use two constants on order to improve performances. The error analysis presented here is implemented in \texttt{maple/atan.mpl} \paragraph{Notes on $b_i$, $a_i$ and $\arctan(b_i)$} The $b_i$ and $a_i$ are computed thanks to the \texttt{allbi} maple procedure (see \texttt{maple/atan.mpl}). There is no approximation error on the $b_i$ since we chose them to be FP numbers. The $\arctan (b_i)$ are stored in double-double so there is an approximation of $2^{-105}$ on them. The value of $e$ is fixed, then the $a_i$ are also chosen as FP numbers such that inequation (\ref{atan_ineq_interval}) is true. \subsubsection{Argument reduction} \begin{lstlisting}[caption={Reduction part 1},firstnumber=1] if (x > MIN_REDUCTION_NEEDED) /* test if reduction is necessary : */ { double xmBIhi,xmBIlo; if (x > arctan_table[61][B].d) { i=61; Add12( xmBihi , xmBilo , x , -arctan_table[61][B].d); } else { /* compute i so that a[i] < x < a[i+1] */ i=31; if (x < arctan_table[i][A].d) i-= 16; else i+=16; if (x < arctan_table[i][A].d) i-= 8; else i+= 8; if (x < arctan_table[i][A].d) i-= 4; else i+= 4; if (x < arctan_table[i][A].d) i-= 2; else i+= 2; if (x < arctan_table[i][A].d) i-= 1; else i+= 1; if (x < arctan_table[i][A].d) i-= 1 xmBihi = x-arctan_table[i][B].d; xmBilo = 0.0; } \end{lstlisting} \begin{tabular}{ll} Lines 1 & test if $x > 2^{-6.3}$ and so need to be reduced\\ Line 5 & test if $x>b[61]$ because when $i \in [0;60] : b_i/2 < x < b_i$ (or $ x/2 < b_i < x$) and then \\&$x-b_i$ is computed exactly thanks to Sterbenz lemma.\\ Line 10...21 & compute $i$ so that $\frac{x-b_i}{1+x.b_i} < 2^{-6.3} $\\ Line 7 and 23 & compute $xmBIhi + xmBIlo = x - b_i$ \end{tabular} We have no rounding error in the computation of $x-b_i$. \begin{lstlisting}[caption={Reduction part 2},firstnumber=1] Mul12(&tmphi,&tmplo, x, arctan_table[i][B].d); if (x > 1) Add22(&x0hi,&x0lo,tmphi,tmplo, 1.0,0.0); else {Add22( &x0hi , &x0lo , 1.0,0.0,tmphi,tmplo);} Div22( &Xredhi, &Xredlo, xmBihi , xmBilo , x0hi,x0lo); \end{lstlisting} \begin{tabular}{ll} Line 1 & compute $x.b_i$ exactly as a double-double\\ Line 3-5 & We need to have a Add22Comp but as we know that $x.b_i > 0$ (so $tmphi>0$), we test if\\& $tmphi$ is greater than 1 in order to be faster. The Add22 makes an error of $\epsilon_{Add22}=\epsilon_{103}$\\ Line 7 & We compute $\xred = \dfrac{x-b_i}{1+x.b_i}$. The Div22 makes $\epsilon_{104}$ (according to Ziv \cite{Ziv91}) error so we have : \end{tabular} \bigskip \begin{equation} \begin{split} \round\big(\xred\big) & = \frac{(x-b_i).(1+\epsilon_{105})}{(1+x.b_i).(1+\epsilon_{105}) .(1+\epsilon_{105}) )}.(1+\epsilon_{105}) \\ & = \frac{x-b_i}{1+x.b_i}.(1+\epsilon_{105})(1+\epsilon_{105}+\epsilon_{105}+\epsilon_{104})\\ & = \xred . (1+\epsilon_{101.9})\nonumber \end{split} \end{equation} So: \begin{equation} \epsilon_{\xred} = \epsilon_{102.6} \label{eps:equation} \end{equation} \subsubsection{Polynomial evaluation} The error due to the polynomial approximation is $\delta_{approx} = \infnorm{ \arctan(x) - x.(1+q)}= \delta_{72.38}$ \begin{lstlisting}[caption={Polynomial Evaluation},firstnumber=1] Xred2 = Xredhi*Xredhi; q = Xred2*(coef_poly[3]+Xred2* (coef_poly[2]+Xred2* (coef_poly[1]+Xred2* coef_poly[0]))) ; \end{lstlisting} \begin{tabular}{ll} Line 1 & The error between $\mathrm{Xred2}$ and the ideal value of $\xred^2$ comes from\\ & $\bullet$~ the error $\epsilon_{\xred}$ on $\xredhi+\xredlo$\\ & $\bullet$~ the truncation of $\xredlo$ adds $\epsilon_{53}$\\ & $\bullet$~ then the FP multiplication squares this term and adds a rounding error of $\epsilon_{53}$\\ & which sum up to $\epsilon_\mathrm{Xred2} = ((1+2^{-53}+2^{-105})^2)(1+2^{-53}) \approx \epsilon_{51.4}$ \\ Line 3 & Horner approximation with error on $\mathrm{Xred2}$: Maple computes an error around $\epsilon_{50.7}$\\ & or $\delta_{q}=\delta_{63.3}$\\ \end{tabular} \subsubsection{Reconstruction} The reconstruction adds $\arctan(b_i)$ (read as a double-double from a table) to $\arctan(\xred)$ (approximated by $(\xredhi+\xredlo)(1+q)$). The terms of this developed product are depicted in the following figure. \begin{center} \small \setlength{\unitlength}{3ex} \framebox{ \begin{picture}(22,3.5)(-3,-4.15) \put(9.5,-0.5){\line(0,-1){4}} \put(9,-1){$\epsilon$} \put(4,-2){$\arctan(b_i)_{hi}$} \put(0.05,-2.15){\framebox(7.9,0.7){}} \put(12,-2){$\arctan(b_i)_{lo}$} \put(8.05,-2.15){\framebox(7.9,0.7){}} \put(4,-3){$\xredhi$} \put(0.55,-3.15){\framebox(7.9,0.7){}} \put(12,-3){$\xredlo$} \put(8.55,-3.15){\framebox(7.9,0.7){}} \put(5,-4){$\xredhi.q$} \put(2.05,-4.15){\framebox(7.9,0.7){}} \put(13,-4){$\xredlo.q$} \put(10.05,-4.15){\framebox(7.9,0.7){}} \end{picture} } \end{center} Here the $\epsilon$ bar represents the target accuracy of $2^{-64}$. One can see that the term $\xredlo.q$ can be truncated. As $\xredlo < \xredhi.2^{-53}$ and $q 10$ the relative error is $\epsilon_{68.24}$ that leads to a rounding constant of $1.000068$. \subsubsection{Error when there is no reduction} \begin{lstlisting}[caption={No reduction},firstnumber=1] x2 = x*x; q = x2*(coef_poly[3]+x2* (coef_poly[2]+x2* (coef_poly[1]+x2* coef_poly[0]))) ; Add12(atanhi,atanlo, x , x*q); \end{lstlisting} The code is very simple so there are few error terms: \begin{tabular}{ll} Line 1 & $\epsilon_{53}$ \\ Line 2 & The Maple procedure to compute Horner approximation gives $\epsilon_{51}$\\ Line 3 & $\delta_{no\_reduction} = \epsilon_{105}.x + \epsilon_q.x^3 + \epsilon_{x.q}.x^3 + |arctan(x) - x.(1+q)| $ \end{tabular} When $x>2^{-10}$ the relative error is $\epsilon_{62.9}$. The constant is $1.0024$. When $x<2^{-10}$ the relative error is $\epsilon_{70.4}$. The constant is $1.000005$. \bigskip \subsection{Exceptional cases and rounding} \subsubsection{Rounding to nearest} \begin{lstlisting}[caption={Exceptional cases : rounding to nearest},firstnumber=1] db_number x_db; x_db.d = x; unsigned int hx = x_db.i[HI] & 0x7FFFFFFF; /* Filter cases */ if ( hx >= 0x43500000) /* x >= 2^54 */ { if ((hx > 0x7ff00000) || ((hx == 0x7ff00000) && (x_db.i[LO] != 0))) return x+x; /* NaN */ else return HALFPI.d; /* \arctan(x) = Pi/2 */ } else if ( hx < 0x3E400000 ) {return x; /* x<2^-27 then \arctan(x) =~ x */} \end{lstlisting} \begin{tabular}{ll} Lines 3 & Test if x is greatear than $2^{54}$, $\infty$ or $NaN$. \\ Line 5,6 & return $\arctan(NaN) = NaN$\\ Line 8 & \texttt{HALFPI} is the greatest double smaller than $\frac{\pi}{2}$ in order not to have $\arctan(x) > \dfrac{pi}{2}$ \\ Line 11 & When $x<2^{-27}$ : $x^2 < 2^{-54}$ so $o(\arctan(x)) = x$ \end{tabular} \\ \textbf{Proof} we know that $\arctan(x) = \displaystyle {\sum_{i=0}^{\infty} \frac{x^{2i+1}}{2i+1}(-1)^i}$. So: \begin{equation} \begin{split} \Big| \frac{\arctan(x)-x}{x} \Big| & = \Bigg|\frac{ \displaystyle {\sum_{i=0}^{\infty} \Big( \frac{x^{2i+1}}{2i+1}(-1)^i} \Big) - x}{x} \Bigg| \nonumber\\ & = \Big|\displaystyle {\sum_{i=1}^{\infty}} \frac{x^{2i}}{2i+1}(-1)^i\Big|\nonumber \\ & < \frac{x^2}{3}\nonumber \\ & < 2^{-54} \nonumber \end{split} \end{equation} Then : $\arctan(x) \approx x $ \bigskip \subsubsection{Rounding toward $-\infty$} \begin{lstlisting}[caption={Exceptional cases : rounding down},firstnumber=1] if ( hx >= 0x43500000) /* x >= 2^54 */ { if ((hx > 0x7ff00000) || ((hx == 0x7ff00000) && (x_db.i[LO] != 0))) return x+x; /* NaN */ else if (x>0) return HALFPI.d; else return -HALFPI_TO_PLUS_INFINITY.d; /* atan(x) = Pi/2 */ } else if ( hx < 0x3E400000 ) {if (sign>0) {if(x==0) {x_db.i[HI] = 0x80000000; x_db.i[LO] = 0;} else x_db.l--; return x_db.d; } else return x; } \end{lstlisting} The differences with rounding to nearest mode are for $frac{pi}{2}$ for $x<2^(-27)$. \begin{lstlisting}[caption={Test for rounding down},firstnumber=1] absyh.d=atanhi; absyl.d=atanlo; absyh.l = absyh.l & 0x7fffffffffffffffLL; absyl.l = absyl.l & 0x7fffffffffffffffLL; u53.l = (absyh.l & 0x7ff0000000000000LL) + 0x0010000000000000LL; u.l = u53.l - 0x0350000000000000LL; if(absyl.d > roundcst*u53.d){ if(atanlo<0.) {atanhi -= u.d;} return atanhi; } else { return scs_atan_rd(sign*x); } \end{lstlisting} \subsubsection{Rounding toward $-\infty$} \begin{lstlisting}[caption={Exceptional cases : rounding up},firstnumber=1] if ( hx >= 0x43500000) /* x >= 2^54 */ { if ((hx > 0x7ff00000) || ((hx == 0x7ff00000) && (x_db.i[LO] != 0))) return x+x; /* NaN */ else if (x>0) return HALFPI.d; else return -HALFPI_TO_PLUS_INFINITY.d; /* atan(x) = Pi/2 */ } else if ( hx < 0x3E400000 ) {if (sign<0) {x_db.l--; return -x_db.d; } else if(x==0) return 0; return x; } \end{lstlisting} There are the same differences for rounding down. \subsubsection{Rounding to zero} This function is quite simple: it call one of the two function defineded before. \begin{lstlisting}[caption={Rounding to zero},firstnumber=1] extern double atan_rz(double x) { if (x>0) return atan_rd(x); else return atan_ru(x); } \end{lstlisting} \subsubsection{Test if rounding is possible} This test use the theorem \ref{th:roundingRN1}. The code is the same than in the theorem except that we have 4 rounding constants : \begin{itemize} \item 1.0047 when $i<10$ \item 1.000068 when $i\geq10$ \item 1.0024 when $x>2^{-10}$ \item 1.0000132 when $x<2^{-10}$ \end{itemize} \section{Accurate phase} The accurate phase is the same as the quick phase, except that number are scs and not double. The intervals are the same as in quick phase. The only difference is that $\arctan(b_i)$ as a third double to improve the precision of $\arctan(b_i)$ to 150 bits. Then we use less memory, that is why we can use the same intervals as in the quick phase. The polynomial degree is 19 in order to have 136 bits of precision. \begin{equation} \arctan(x) \approx x-\frac{1}{3}.x^3+\frac{1}{5}.x^5-\frac{1}{7}.x^7+\frac{1}{9}.x^9-\frac{1}{11}.x^{11}+\frac{1}{13}.x^{13}-\frac{1}{15}.x^{15}+\frac{1}{17}.x^{17}-\frac{1}{19}.x^{19} \label{eq:arctan_scspoly} \end{equation} \section{Analysis of the performance} \subsection{Speed} Table \ref{tbl:arctan_abstime} (produced by the \texttt{crlibm\_testperf} executable) gives absolute timings for a variety of processors. The test computed 50000 atan in rounding to nearest mode. The second step of \texttt{crlibm} was taken 1 time on 50000. \begin{table}[!htb] \begin{center} \renewcommand{\arraystretch}{1.2} \begin{tabular}{|l|r|r|r|} \hline \hline \multicolumn{4}{|c|}{Pentium 4 Xeon / Linux Debian / gcc 2.95} \\ \hline & min time & max time & avg time \\ \hline & min time & max time & avg time \\ \hline \texttt{libm} & 180 & 344 & 231 \\ \hline \texttt{mpfr} & 417016 & 3956992 & 446362 \\ \hline \texttt{libultim} & 48 & 257616 & 189 \\ \hline \texttt{crlibm} & 36 & 46428 & 381 \\ \hline \hline \multicolumn{4}{|c|}{PowerPC G4 / MacOS X / gcc2.95} \\ \hline & min time & max time & avg time \\ \hline \texttt{libm} & 6 & 11 & 9 \\ \hline \texttt{mpfr} & 35291 & 303019 & 37022 \\ \hline \texttt{libultim} & 7 & 13251 & 14 \\ \hline \texttt{crlibm} & 5 & 1037 & 19 \\ \hline \hline \end{tabular} \end{center} \caption{Absolute timings for the inverse tangent (arbitrary units) \label{tbl:arctan_abstime}} \end{table} \subsection{Memory requirements} Table size is \begin{itemize} \item for the \quick\ phase, $62\times (1+1+2) \times8=1984$ bytes for the 62 $a_i$, $b_i$, $\arctan(b_i)$ (hi and lo), plus another $8$ bytes for the rounding constant, plus $4\times8$ for the polynomial, $8$ bytes for $\frac{\pi}{2}$ and $64$ for the rounding constants or $2096$ bytes in total. \item for the \accurate\ phase, we just have $10$ SCS constants for the polynomial, and 62 other double for $\arctan(b_i)_{lo_{lo}}$. If we add all : $10*11*8 + 62*8 = 1376$ \end{itemize} If we add the fast phase and the acurate one, we have a total of 3472 bytes. \section{Conclusion and perspectives} Our $\arctan$ is reasonably fast. Libultim is faster but requires ten times more memory (241 polynomials of degree 7 and 241 of degree 16 that represents more than 40KB !). Instead, our argument reduction performs a division, which is an expensive operation. To improve performances we could inline the code of \texttt{atan\_quick}, but we prefer to keep it as it is in order to ease the evolution of the algorithm. The main problem of our $\arctan$ is the worst case time which is about 100 times slower than the average time. Thus to improve performances we could try to use double-extended. A double-extended has a mantissa of 64 bits which could transform all double-double operation in double-extended operation. This format number is present in most of the Intel recent processors. %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/crlibm.tex0000644000000000000000000002362213316017127017572 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA \documentclass[a4paper]{book} \usepackage{fontspec} \usepackage{fullpage} %\usepackage{isolatin1} \usepackage{graphicx} \usepackage{mathpazo} \usepackage{listings} \usepackage{longtable} %pour les preuves des programmes \usepackage{lscape} % pour le mode landscape \usepackage{makeidx} \usepackage{color} \usepackage{amstext,url,latexsym,amsfonts,amssymb,amsmath,amsthm} \usepackage{hyperref} \newtheorem{example}{Example} \newtheorem{theorem}{Theorem} \newtheorem{algorithm}{Algorithm} \newtheorem{propriete}{Property} \DeclareMathOperator{\sinpi}{sinpi} \DeclareMathOperator{\cospi}{cospi} \DeclareMathOperator{\tanpi}{tanpi} \DeclareMathOperator{\asinpi}{asinpi} \DeclareMathOperator{\acospi}{acospi} \DeclareMathOperator{\atanpi}{atanpi} \DeclareMathOperator{\arccosh}{arccosh} \newcommand{\pref}[1]{$<$\ref{#1}$>$} \newcommand{\quick}{{quick}} \newcommand{\accurate}{{accurate}} \newcommand{\ulp}{\mbox{ulp}} \newcommand{\crlibm}{\texttt{crlibm}} \newcommand{\scslib}{\texttt{scslib}} \renewcommand{\epsilon}{\varepsilon} \newcommand{\round}{\circ} \newcommand{\roundup}{\bigtriangleup} \newcommand{\rounddown}{\bigtriangledown} \newcommand{\intpart}[1]{\left\lceil #1 \right\rfloor} \newcommand{\maxv}[1]{{\overline{#1}}} \newcommand{\maxx}{\maxv{x}} \newcommand{\maxeps}{\maxv{\epsilon}} \newcommand{\maxdelta}{\maxv{\delta}} \newcommand{\maxz}{{\overline{z}}} \newcommand{\maxs}[1]{\overline{s}_{#1}} \newcommand{\mins}[1]{\underline{s}_{#1}} \newcommand{\maxp}{\overline{|P|}} \newcommand{\minp}{\underline{|P|}} \newcommand{\infnorm}[1]{||{#1}||^{\infty}} \newcommand{\abserr}[1]{\delta_{\mathrm{#1}}} \newcommand{\relerr}[1]{\epsilon_{\mathrm{#1}}} \newcommand{\maxabserr}[1]{\maxv{\delta}_{\mathrm{#1}}} \newcommand{\maxrelerr}[1]{\maxv{\epsilon}_{\mathrm{#1}}} \newcommand{\N}{\ensuremath{\mathbb {N}}} \newcommand{\Z}{\ensuremath{\mathbb {Z}}} \newcommand{\F}{\ensuremath{\mathbb {F}}} \newcommand{\R}{\ensuremath{\mathbb {R}}} \newcommand{\hi}{\ensuremath{\mathit{h}}} \newcommand{\mi}{\ensuremath{\mathit{m}}} \newcommand{\lo}{\ensuremath{\mathit{l}}} \newcommand{\E}{\ensuremath{\mathcal{E}}} \newcommand{\Add}{{\bf Add12}} \newcommand{\AddDD}{{\bf Add22}} \newcommand{\AddDTT}{{\bf Add233}} \newcommand{\AddDTTCond}{{\bf Add233Cond}} \newcommand{\AdddTT}{{\bf Add133}} \newcommand{\AddTT}{{\bf Add33}} \newcommand{\MulDT}{{\bf Mul23}} \newcommand{\Mul}{{\bf Mul12}} \newcommand{\MulDD}{{\bf Mul22}} \newcommand{\MulDTT}{{\bf Mul233}} \newcommand{\MuldTT}{{\bf Mul133}} \newcommand{\MuldDD}{{\bf Mul122}} \newcommand{\MuldDT}{{\bf Mul123}} \newcommand{\MulTT}{{\bf Mul33}} \newcommand{\MulAddDdD}{{\bf MulAdd212}} \newcommand{\MulAddDD}{{\bf MulAdd22}} \newcommand{\SqrtD}{{\bf sqrt12}} \newcommand{\SqrtT}{{\bf sqrt13}} \newcommand{\Renormalize}{{\bf Renormalize3}} \newcommand{\mAdd}{\ensuremath{\mathbf{Add12}}} \newcommand{\mAddDD}{\ensuremath{\mathbf{Add22}}} \newcommand{\mAddDTT}{\ensuremath{\mathbf{Add233}}} \newcommand{\mAddDTTCond}{\ensuremath{\mathbf{Add233Cond}}} \newcommand{\mAdddTT}{\ensuremath{\mathbf{Add133}}} \newcommand{\mAddTT}{\ensuremath{\mathbf{Add33}}} \newcommand{\mMul}{\ensuremath{\mathbf{Mul12}}} \newcommand{\mMulDD}{\ensuremath{\mathbf{Mul22}}} \newcommand{\mMulDT}{\ensuremath{\mathbf{Mul23}}} \newcommand{\mMulDTT}{\ensuremath{\mathbf{Mul233}}} \newcommand{\mMuldTT}{\ensuremath{\mathbf{Mul133}}} \newcommand{\mMuldDD}{\ensuremath{\mathbf{Mul122}}} \newcommand{\mMuldDT}{\ensuremath{\mathbf{Mul123}}} \newcommand{\mMulAddDdD}{\ensuremath{\mathbf{MulAdd212}}} \newcommand{\mMulAddDD}{\ensuremath{\mathbf{MulAdd22}}} \newcommand{\mUlp}{\ensuremath{\mathrm{ulp}}} \newcommand{\nan}{\ensuremath{\mathrm{NaN}}} \newcommand{\sgn}{\ensuremath{\mathrm{sgn}}} \renewcommand{\succ}{\ensuremath{\mathrm{succ}}} \newcommand{\pred}{\ensuremath{\mathrm{pred}}} \newcommand{\xor}{\ensuremath{\mbox{ }\mathrm{XOR}\mbox{ }}} \newcommand{\Ord}{\ensuremath{\mathcal{O}}} %\newcommand{\deltapprox}{\delta_{\mathrm{approx}}} %\newcommand{\deltaround}{\delta_{\mathrm{round}}} % Environnement pour disposer de propriété ``à la leslie lamport'' \newcounter{propexp} % reset propexp à chaque chapitre \newenvironment{prop} {\begin{trivlist}\refstepcounter{propexp}\item[\hbox to 0pt{\spring {\bf $<$\arabic{propexp}$>$}}]} {\ifvmode\smallskip\fi$\bullet$\end{trivlist}} % Définition de l'environnement proof \def\spring{\hskip 0pt minus 1fil} \def\@yproof[#1]{\@proof{ #1}} \def\@proof#1{\begin{trivlist}\item[\hbox to 0pt{\spring $\diamond$}] \emph{Proof#1. }} \newenvironment{preuve} {\@proof{}}{\hfill\null\hfill$\square$\end{trivlist}} % Definition des options pour le packages listings \lstset{numbers=left, numberstyle=\tiny, stepnumber=1, numbersep=5pt, lineskip=-1pt, extendedchars=true, basicstyle=\footnotesize, breaklines, showstringspaces=false, frame=single, language={[ANSI]C}, firstnumber=last, escapeinside={(*@}{@*)} } \title{CR-LIBM\\A library of correctly rounded elementary functions in double-precision} \author{\mbox{Catherine Daramy-Loirat}, \mbox{David Defour}, \mbox{Florent~de~Dinechin},\\ \mbox{Matthieu Gallet}, \mbox{Nicolas Gast}, \mbox{Christoph Quirin Lauter}, \mbox{Jean-Michel Muller}} %% \abstract{ %% CRLibm is a mathematical library with correct rounding in %% double-precision in the four IEEE-754 rounding modes. This report %% explains the code and proves the correct rounding property. %% } %% \RRIresume{% %% CRLibm est une bibliothèque mathématique offrant l'arrondi correct %% en double précision selon les quatre modes d'arrondi. Ce rapport %% détaille les algorithmes utilisés et prouve fonction par fonction la %% propriété d'arrondi correct. %% }% %% \RRIkeywords{elementary functions, correct rounding, IEEE-754, double precision} %% \RRImotscles{fonctions élémentaires, arrondi correct, IEEE-754, double précision} %% \RRItheme{2} %% \RRIprojet{Arénaire} %% \RRIinria{\RRnote{% %% This text is also available as a research report of the %% Laboratoire de l'Informatique du Parallélisme {\tt %% http://www.ens-lyon.fr/LIP}. %% }}% \begin{document} \maketitle \section*{Important warning} This report describes and proves version 1.0beta5 of the \texttt{crlibm} library. It may therefore not correspond to the latest version. An up-to-date version will always be distributed along with the code. \vfill \section*{Many thanks to...} \begin{itemize} \item Vincent Lef\`evre, from \textsc{Inria}-Lorraine, without whom this project would't have started, and who has since then lended a helpful hand in more than 17 occasions; \item The Ar\'enaire project at ENS-Lyon, especially Marc Daumas, Sylvie Boldo, Guillaume Melquiond, Nathalie Revol and Arnaud Tisserand; \item Guillaume Melquiond for Gappa and its first-class hotline; \item The MPFR developers, and especially the \textsc{Inria} \textsc{Spaces} project; \item The Intel Nizhniy-Novgorod Lab, especially Andrey Naraikin, Sergei Maidanov and Evgeny Gvozdev; \item The contributors of bits and pieces, Phil Defert and Eric McIntosh from CERN, Patrick Pelissier from \textsc{Inria}; \item All the people who have reported bugs, hoping that they continue until they have to stop: Evgeny Gvozdev from Intel with special thanks, Christoph Lauter from TUM\"unchen (before he joined the project), Eric McIntosh from CERN, Patrick Pelissier and Paul Zimmermann from \textsc{Inria} Lorraine; \item William Kahan at UCBerkeley, Peter Markstein at HP, Neil Toda at Sun, Shane Story at Intel, and many others for interesting and sometimes heated discussions; \item Serge Torres for LIPForge. \end{itemize} This work was partly funded by the \textsc{Inria}, the ENS-Lyon and the Universit\'e de Perpignan. \tableofcontents \addtocounter{chapter}{-1} \chapter{Getting started with crlibm} \input{0_getting-started.tex} \chapter{Introduction: Goals and methods \label{chap:intro}} \input{0_intro.tex} \chapter{Common notations, theorems and procedures \label{chap:common}} \input{1_common.tex} \chapter{The natural logarithm \label{chap:log}} \input{log.tex} \chapter{The logarithm in base 2 \label{chap:log2}} \input{log2.tex} \chapter{The logarithm in base 10 \label{chap:log10}} \input{log10.tex} \chapter{The exponential \label{chap:exp}} \input{exp.tex} \chapter{The \texttt{expm1} function\label{chap:expm1}} \input{expm1.tex} \chapter{The \texttt{log1p} function\label{chap:log1p}} \input{log1p.tex} \chapter{The trigonometric functions \label{chap:trigo}} \input{trigo.tex} \chapter{The arcsine \label{chap:asin}} \input{asin.tex} \chapter{The arccosine \label{chap:acos}} \input{acos.tex} \chapter{The arctangent \label{chap:atan}} \input{atan.tex} \chapter{The trig-of-$\pi x$ functions \label{chap:trigpi}} \input{trigpi.tex} \chapter{The hyperbolic sine and cosine \label{chap:csh}} \input{csh.tex} \chapter{The power function \label{chap:pow}} \input{pow.tex} \appendix \bibliographystyle{plain} \bibliography{elem-fun} \end{document} interval-3.2.0/src/crlibm/docs/latex/csh.tex0000644000000000000000000007250013316017127017076 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA This chapter was initially contributed by Matthieu Gallet under the supervision of F. de~Dinechin. The accurate phase was rewritten by Ch. Q. Lauter and F. de~Dinechin. \section{Overview} Like the algorithms for others elementary functions, we will compute our hyperbolic cosine and sine in one or two steps. The first one, which is called 'fast step' is always executed and provides a precision of about 63 bits. This is a sufficient precision in most cases, but sometimes more precision is needed, and then we enter the second step using the SCS library. \subsection{Definition interval and exceptional cases} The hyperbolic cosine and the hyperbolic sine are defined for all real numbers, and then for all floating point numbers. These functions are divergent toward $+\infty$ and $-\infty$, so for $|x| > 710.47586007$, $\cosh(x)$ and $\sinh(x)$ should return $+\infty$ or the greatest representable number (depending ot the choosen rounding mode). \begin{itemize} \item If $x = NaN$ , then $\sin(x)$ and $\cosh(x)$ should return $NaN$ \item If $x = +\infty$ , then $\cosh(x)$ and $\sinh(x)$ should return $+\infty$. \item If $x = -\infty$ , then $\cosh(x)$ should return $+\infty$. \item If $x = -\infty$ , then $\sinh(x)$ should return $-\infty$. \end{itemize} This is true in all rounding modes. Concerning subnormals, $\cosh(x) \geq 1$, so $\cosh(x)$ can't return subnormal numbers, even for subnormal inputs. For small inputs ($|x| \leq 2^{-26}$), we have $\sinh(x) = x$ with 80 bits of precision, so we can return a result without any computation on subnormals. \subsection{Relation between $\cosh(x)$, $\sinh(x)$ and $e^x$} The hyperbolic sine and cosine are defined by $$\sinh(x) = \frac{e^x - e^{-x}}{2}$$ and $$\cosh(x) = \frac{e^x + e^{-x}}{2}$$ respectively. For large arguments, we will be able to neglect the smaller term. \begin{itemize} \item $e^{-x}<2^{-65}e^x$ as soon as $x>23$ (this is the target precision of the first step) \item $e^{-x}<2^{-115}e^x$ as soon as $x>40$ (this is the target precision of the second step) \end{itemize} Note that this has been used in the search for worst cases, too: knowing that correct rounding of \texttt{exp} requires at most $2^{-113}$ accuracy for $x>2^{-30}$, and the division by 2 being exact, we deduce that the worst cases for $\sinh$ and $\cosh$ will be those of the exponential for all the input values greater than 40. However, due to the division by 2, the domain of $\sinh$ and $\cosh$ is slightly larger than that of exp, so there is a little additional search to do (precisely between 709.78 and 710.75). For the same reason, this additional search gives worst cases for both $\sinh$ and $\cosh$. \subsection{Worst cases for correct rounding} The search for the worst-case accuracy required for correct rounding the hyperbolic sine and cosine and their inverses is completed. The $\cosh$ function require a relative accuracy of $2^{-142}$ in the worst case, while $\sinh$ requires $2^{-126}$. However, for $x>2^{-12}$, both functions require only $2^{-111}$. \section{Quick phase} \subsection{Overview of the algorithm} The algorithm consists of two argument reduction using classical formulae of hyperbolic trigonometry, followed by a polynomial evaluation using a Taylor polynom of degree $6$ (for $\cosh$) and $7$ (for $\sinh$). These formulaes are: \begin{itemize} \item $\sinh(x + y) = \sinh(x) \cosh(y) + \sinh(y) \cosh(x)$ \item $\cosh(x + y) = \cosh(x) \cosh(y) + \sinh(x) \sinh(y)$ \item $\cosh(k\ln(2)) = 2^{k-1} + 2^{-k-1}$ \item $\sinh(k\ln(2)) = 2^{k-1} - 2^{-k-1}$ \end{itemize} After having treated special cases ($NaN$, $+\infty$, $-\infty$), we do a first range reduction to reduce the argument between $\frac{-ln(2)}{2}$ and $\frac{ln(2)}{2}$. So, we write $x = k\ln(2) + y$, where k is given by rounding to the nearest integer $x \frac{1}{ln(2)}$. Now, $\frac{-ln(2)}{2} \leq y \leq \frac{ln(2)}{2}$, but it is even too large to have a sufficient precision during polynomial evaluation with small polynoms, and we do a second range reduction, by writing $y = a + b$, where $a = index . 2^{-8}$ (index is an integer) and $|b| \leq 2^{-9}$. Mathematically, we have: $$\sinh(x) = (2^{k-1} + 2^{-k-1})\sinh(y) + (2^{k-1} - 2^{-k-1}) \cosh(y)$$ and $$\cosh(x) = (2^{k-1} + 2^{-k-1})\cosh(y) + (2^{k-1} - 2^{-k-1}) \sinh(y)$$ The second range reduction allows to compute $\sinh(y)$ and $\cosh(y)$ as $\sinh(y) = \sinh(a) \cosh(b) + \sinh(b) \cosh(a)$ and $\cosh(y) = \cosh(a) \cosh(b) + \sinh(a) \sinh(b)$. In the C code, we have $ch\_hi + ch\_lo \approx \cosh(y)$ and $sh\_hi + sh\_lo \approx \sinh(y)$. A quick computation shows that $-89 \leq index \leq 89$, and we can pre-compute so few values of $\sinh(a)$ and $\cosh(a)$ and store them in a table as double-doubles. The constants $2^{k-1}$ and $2^{-k-1}$ are constructed by working directly on their binary representation. $\cosh(b)$ and $\sinh(b)$ are computed with Taylor polynoms. It's well-known that $$\cosh(b) = \sum_{n \geq 0}{\frac{x^{2n}}{(2n)!}}$$ and $$\sinh(b) = \sum_{n \geq 0}{\frac{x^{2n+1}}{(2n+1)!}}$$ For our needs, a degree $6$ polynom for cosh and a degree $7$ polynom for sinh give enough accuracy. We write $\cosh(b) = 1 + tcb$ and $\sinh(b) = b(1 + tsb)$, where $$tcb = b^{2} (\frac{1}{2} + b^{2}(\frac{1}{24} + b^{2} \frac{1}{720}))$$ $$tsb = b^{2} (\frac{1}{6} + b^{2} (\frac{1}{120} + b^{2} \frac{1}{5040}))$$ We use the Horner scheme for the evaluation of the polynoms, with all the coefficients being coded on double-precision numbers. If the input is very small (i.e. $|b| \leq 2^{-40}$), $tsb$ and $tcb$ are not calculated but directly set to $0$, to avoid any problem with subnormal numbers. At this stage, we have computed all the needed sub-terms before the final reconstruction, which is done in two steps, corresponding to the two-step range-reduction. The reconstruction is computed in double-double arithmetic. In the first reconstruction, some sub-terms can be ignored without any loss of precision, due to their very small relative values. For this step, it exists a particular case, when $index = 0$, since it is the only case where $|\sinh(a)| < 2^{-9}$ ($\sinh(a) = 0$). Now we have the definitive values of $\cosh(y)$ and $\sinh(y)$. In the second reconstruction, we begin by computing all needed products before adding their results (i.e. $2^{k-1}\cosh(y)$, $2^{k-1}\sinh(y)$,...). Computations are also done using double double arithmetics, with the Add22 function. \subsection{Error analysis} Many of the previous computations can introduce some error. \begin{itemize} \item{First range reduction} We have to consider two different cases: \begin{itemize} \item{$|x| \leq \frac{ln(2)}{2}$} We have $k = 0$, and there is no reduction, and no term of error. \item{$|x| > \frac{ln(2)}{2}$} We have $k \neq 0$, and we must compute the term of error introduced by the range reduction. Since $k$ is an integer, we can assume that there is no error on it. $ln(2)$ is a constant which is stored in the function in double-double, and we have $ln(2) = ln2_{hi} + ln2_{lo} + \maxabserr{repr\_ln2}$, where $|\maxabserr{repr ln2}| \leq 1.94e-31$. The total absolute error of this reduction is $\maxabserr{range\_reduc} = 3.437e-27$, so the maximum relative error is $\maxrelerr{range\_reduc} = 9.9e-27$ (we have $|x| \geq 0.36$), and that represents about $86.38$ bits of precision. \end{itemize} \item{Second range reduction} This range reduction is exact (we only cut y in two parts, with no multiplication nor division), so no new term of error is introduced. \item{Error in tabulation} Since $\cosh(a)$ and $\sinh(a)$ are stored as double-doubles, and since they are transcendental numbers (when $a \neq 0$), some error is done on their approximation. A simple Maple procedure can compute this error, which is about $\maxabserr{ca} = 6.08e-33$ for cosh and $\maxabserr{sa} = 1.47e-33$ for sinh. That is large overkill compared to precision on other values. \item{Error in polynomial approximations} We use the $errlist\_quickphase$ and $compute\_horner\_rounding\_error$ Maple procedures to compute thes errors on $tcb$ and $tsb$, which are $\maxabserr{rounding\_cosh} = 6.35e-22$ and $\maxabserr{rounding\_sinh} = 1.94e-22$. Then there is the approximation error. The sum of theses errors gives $\maxabserr{tcb} = 6.35e-22$ and $\maxabserr{tsb} = 1.11e-21$. \item{First reconstruction} This reconstruction is done by adding all the pre-calculated terms ($tcb$, $tsb$, $ca = \cosh(a)$, $sa = \sinh(a)$), in an order which try to minimize the total error.$\maxabserr{sh} = 2.10e-25$. Maple scripts are used to compute the error, since there are many terms. There are 2 different cases: \begin{itemize} \item{$a = 0$} $ch_{hi}+ch_{lo} = \widehat{\cosh(\widehat{y})} + \abserr{cosh0}$, where $|\abserr{cosh0}| \leq \maxabserr{cosh0} = 6.35e-22$, and $\sinh(y) = \widehat{\sinh(\widehat{y})} + \abserr{sinh0}$, where $|\abserr{sinh0}| \leq \maxabserr{sinh0} = 5.4e-20$. \item{$a \neq 0$} $ch_{hi}+ch_{lo} = \widehat{\cosh(\widehat{y})} + \abserr{cosh1}$, where $|\abserr{cosh1}| \leq \maxabserr{cosh1} = 2.39e-20$, and $\sinh(y) = \widehat{\sinh(\widehat{y})} + \abserr{sinh1}$, where $|\abserr{sinh1}| \leq \maxabserr{sinh1} = 1.09e-22$. \end{itemize} \item{Second reconstruction} This reconstruction is based on multiplying the obtained results before adding them. The products are exact since each product has a factor which a power of 2. We have to leave absolute errors for relative errors, since the range of values returned by $\cosh$ is too large. We will distinguish three different cases: \begin{itemize} \item{$|k| \leq 35$} All terms must be computed. We have $ch_{hi} + ch_{lo} = \widehat{\cosh(\widehat{x})}(1+\relerr{ch})$, where $|\relerr{ch}| \leq \maxrelerr{ch} = 7.66e-19$ \item{$k > 35$} In this case, the terms corresponding to $e^{-x}$ are neglected, with an error smaller than $2^{-68}$. We have $ch_{hi} + ch_{lo} = \widehat{\cosh(\widehat{x})}(1+\relerr{ch})$, where $|\relerr{ch}| \leq \maxrelerr{ch} = 7.69e-19$ \item{$k < -35$} This case is symmetric to the previous one, we just have to remplace k by -k. \end{itemize} \end{itemize} \subsection{Details of computer program} The procedures \texttt{cosh\_quick} and \texttt{sinh\_quick} contain the computation respectively shared by the functions \texttt{cosh\_rn}, \texttt{cosh\_ru}, \texttt{cosh\_rd} and \texttt{cosh\_rz} in one hand, and by the functions \texttt{sinh\_rn}, \texttt{sinh\_ru}, \texttt{sinh\_rd} and \texttt{sinh\_rz} in the other hand. The eight functions \texttt{cosh\_rX} and \texttt{sinh\_rX} call \texttt{cosh\_quick} or \texttt{sinh\_quick} with an integer which represent the choosen rounding mode. We will begin to prove the cosh function, and then we will prove the sinh function. Since both functions share a lot a code, only the different part between cosh and sinh will be proven for the sinh. \subsubsection{Exceptional cases and argument reduction} This part is shown for \texttt{cosh\_rn}, but it is quite identical for the three other functions. \begin{lstlisting}[caption={Exceptional cases},firstnumber=1] double cosh_rn(double x){ db_number y; y.d = x; y.i[HI] = y.i[HI] & 0x7FFFFFFF; /* to get the absolute value of the input */ if (y.d > max_input_ch.d) { /* out of range */ y.i[LO] = 0; y.i[HI] = 0x7FF00000; return (y.d); } if ((y.i[HI] & 0x7FF00000) >= (0x7FF00000)) { /*particular cases : QNaN, SNaN, +- oo*/ return (y.d); } return(cosh_quick(x, RN)); } \end{lstlisting} \begin{tabular}{ll} Lines 3 & Initialize y\\ Line 4 & Get the absolute value of y by removing the first bit.\\ Line 5 & Test if $\cosh(|x|) = \cosh(x)$ is representable as a double.\\ Line 6 & If this test is true, we must return $\infty$.\\ Line 8 & Test if $|x|$ is a special case, like NaN or $\infty$\\ Line 9 & If this test is true, we must return $|x|$ \\ Line 11 & $x$ is a correct input, we can return cosh\_quick. \\ \end{tabular} \subsubsection{Procedure cosh\_quick} \begin{lstlisting}[caption={Procedure \texttt{cosh\_quick} - variables},firstnumber=1] double cosh_quick(double x, int rounding_mode){ /*some variable declarations */ int k; db_number y; double res_hi, res_lo; double ch_hi, ch_lo, sh_hi, sh_lo;/* cosh(x) = (ch_hi + ch_lo)*(cosh(k*ln(2)) + (sh_hi + sh_lo)*(sinh(k*ln(2))) */ db_number table_index_float; int table_index; double temp_hi, temp_lo, temp;/* some temporary variables */ double b_hi, b_lo,b_ca_hi, b_ca_lo, b_sa_hi, b_sa_lo; double ca_hi, ca_lo, sa_hi, sa_lo; /*will be the tabulated values */ double tcb_hi, tsb_hi; /*results of polynomial approximations*/ double square_y_hi; double ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo; double sh_2_pk_hi, sh_2_pk_lo, sh_2_mk_hi, sh_2_mk_lo; db_number two_p_plus_k, two_p_minus_k; /* 2^(k-1) + 2^(-k-1) */ db_number absyh, absyl, u53, u; \end{lstlisting} Here there are all the variables which will be used in the code. \subsubsection{First range reduction} \begin{lstlisting}[caption={Procedure \texttt{cosh\_quick} - first range reduction},firstnumber=19] /* Now we can do the first range reduction*/ DOUBLE2INT(k, x * inv_ln_2.d) if (k != 0){ /* b_hi+b_lo = x - (ln2_hi + ln2_lo) * k */ temp_hi = x - ln2_hi.d * k; temp_lo = -ln2_lo.d * k; Add12Cond(b_hi, b_lo, temp_hi, temp_lo); } else { b_hi = x; b_lo = 0.; } \end{lstlisting} \begin{tabular}{ll} Line 20 & Put in k the closest integer of x * inv\_ln\_2. \\ & We use the property of DOUBLE2INT that convert a floating-point number in rouding to nearest mode. \\ & By its definition, $k$ satisfies the following properties:\\ & $\lfloor x \times inv\_ln2 \rfloor \leq k \leq \lceil x \times inv\_ln2\rceil$ \\ & $|k| \leq \frac{x}{2} \times inv\_ln2$ \\ & since $|x| \leq 710.475...$, we have $|k| \leq 1025$, so $k$ is coded on at most 11 bits. \\ Line 21 & First case : $k \neq 0$ \\ & We have by contruction : $ln2_{hi} + ln2_{lo} = \ln(2) + \abserr{repr\_ln2}$, where $|\abserr{repr\_ln2}| \leq \maxabserr{repr\_ln2} = 1.95e-31$.\\ & the last 11 bits of $ln_{hi}$ are set to zero by its construction \\ Line 22 & the $ln2_{hi} k$ product is exact since $k$ is coded on at most 11 bits and the last 11 bits of $ln2_{hi}$ are zeros \\ & we have to use the properties verified by $k$: $x inv\_ln2 - 1 \leq k \leq x inv\_ln2 + 1$\\ & if $x \geq 0$ \\ & we have $ k \geq 1$ and then $x \geq \frac{\ln(2)}{2}$, so $(x inv\_ln2 + 1)ln2_{hi} \leq 2 x$\\ & since $|k| \leq \frac{x}{2} \times inv\_ln2$, we have $\frac{x}{2} \leq (x inv\_ln2 - 1)ln2_{hi}$\\ & and then we have $\frac{x}{2} \leq k ln2_{hi} \leq 2 x$\\ & we can apply the Sterbenz theorem to prove that the result of this line is exact\\ & if $x \leq 0$\\ & we can use the same reasoning and then apply the Sterbenz theorem\\ & and this line of code is always exact. \\ Line 23 & this product is not exact, we can loose at most 11 bits of precision\\ & there is an error of $\abserr{round}$ which satisfies $|\abserr{round}|\leq \maxabserr{round} = 3.15e-30$ on $ln2_{lo}$ \\ & so a bound to the maximal absolute error is $k_{max} \maxabserr{round}$\\ Line 24 & We do an Add12 to have well-aligned double doubles in $b_{hi}$ and $b_{lo}$\\ & The conditionnal version is used since temp\_hi can be zero if $x$ is very close to $k ln(2)$.\\ & The total absolute error is bounded by $\maxabserr{b} = 3.43e-27$ \\ Line 27 & We have $k = 0$. We needn't to do any reduction, so $b_{hi} + b_{lo} = x$ exactly.\\ \end{tabular} At this stage, we have $b_{hi} + b_{lo} = \widehat{y} + \abserr{b}$, where $|\abserr{b}| \leq \maxabserr{b} = 3.43e-24$. Now we will write $y = a + b$, where $a = 2^{-8} index$. \subsubsection{Second range reduction} \begin{lstlisting}[caption={Procedure \texttt{cosh\_quick} - second range reduction},firstnumber=29] /*we'll construct 2 constants for the last reconstruction */ two_p_plus_k.i[LO] = 0; two_p_plus_k.i[HI] = (k-1+1023) << 20; two_p_minus_k.i[LO] = 0; two_p_minus_k.i[HI] = (-k-1+1023) << 20; /* at this stage, we've done the first range reduction : we have b_hi + b_lo between -ln(2)/2 and ln(2)/2 */ /* now we can do the second range reduction */ /* we'll get the 8 leading bits of b_hi */ table_index_float.d = b_hi + two_43_44.d; /*this add do the float equivalent of a rotation to the right, since -0.5 <= b_hi <= 0.5*/ table_index = LO(table_index_float.d);/* -89 <= table_index <= 89 */ table_index_float.d -= two_43_44.d; table_index += bias; /* to have only positive values */ b_hi -= table_index_float.d;/* to remove the 8 leading bits*/ /* since b_hi was between -2^-1 and 2^1, we now have b_hi between -2^-9 and 2^-9 */ \end{lstlisting} \begin{tabular}{ll} Line 30-33 & Put in \texttt{two\_p\_plus\_k} and \texttt{two\_p\_minus\_k} the exact values of $2^{k-1}$ and $2^{-k-1}$.\\ Line 38-44 & The goal of the second range reduction is to write $y$ as $y = index 2^{-8} + b$ \\ & We have $|y| \leq \frac{ln(2)}{2} \leq \frac{1}{2}$ \\ & so $2^{44} \leq 2^{44} + 2^{43} + y \leq 2^{44} + 2^{43} + 2^{42}$ \\ & since the mantissa counts 53 bits, only the part above $2^{-8}$ si kept in table\_index\_float\\ & It is easy to show that we have $-89 \leq table\_index \leq 89$ \\ & so we can add $bias = 89$ to $table\_index$ to have only positive values. \\ & then we remove this bits of $y$ to obtain the final $b = b_{hi} + b_{lo}$ \\ & all these operations are exact, so the final absolute error doesn't increase \\ \end{tabular} \subsubsection{Polynomial evaluation - First reconstruction} \begin{lstlisting}[caption={Procedure \texttt{cosh\_quick} - polynomial evaluation - first reconstruction},firstnumber=45] y.d = b_hi; /* first, y² */ square_b_hi = b_hi * b_hi; /* effective computation of the polynomial approximation */ if (((y.i[HI])&(0x7FFFFFFF)) < (two_minus_30.i[HI])) { tcb_hi = 0; tsb_hi = 0; } else { /* second, cosh(b) = b² * (1/2 + b² * (1/24 + b² * 1/720)) */ tcb_hi = (square_b_hi)* (c2.d + square_b_hi * (c4.d + square_b_hi * c6.d)); tsb_hi = square_b_hi * (s3.d + square_b_hi * (s5.d + square_b_hi * s7.d)); } if( table_index != bias) { /* we get the tabulated the tabulated values */ ca_hi = cosh_sinh_table[table_index][0].d; ca_lo = cosh_sinh_table[table_index][1].d; sa_hi = cosh_sinh_table[table_index][2].d; sa_lo = cosh_sinh_table[table_index][3].d; /* first reconstruction of the cosh (corresponding to the second range reduction) */ Mul12(&b_sa_hi,&b_sa_lo, sa_hi, b_hi); temp = ((((((ca_lo + (b_hi * sa_lo)) + b_lo * sa_hi) + b_sa_lo) + (b_sa_hi * tsb_hi)) + ca_hi * tcb_hi) + b_sa_hi); Add12Cond(ch_hi, ch_lo, ca_hi, temp); /* first reconstruction for the sinh (corresponding to the second range reduction) */ } else { Add12Cond(ch_hi, ch_lo, (double) 1, tcb_hi); } \end{lstlisting} \begin{tabular}{ll} Line 45 & Put in $y$ the value of $b_{hi}$, so we can use its hexadecimal aspect \\ Line 47 & Put $b^2$ in $square\_b_{hi}$. We have $square\_b_{hi} = \widehat{b} + \abserr{square\_b}$, where $|\abserr{square\_b}| \leq \maxabserr{square\_b} = 4.23e-22$ \\ Line 50 & Match $b_{hi}$ and then $b$ with $2^{-40}$\\ Line 51-52 & If $|b| \leq 2^{-40}$, we will have $|tcb|,[tsb| \leq \maxabserr{square\_b}$, so we can directly set $tcb$ and $tsb$ to zero: \\ & converning the mathematical values, we have $|\widehat{tcb}|, |\widehat{tsb}| \leq 2^{-24}$. \\ & We can avoid by this way any problem with subnormal numbers. \\ Line 55-56 & Polynomial evaluation of $\cosh(x)-1$ and $\frac{\sinh(x)}{x}-1$, following the Hörner scheme. \\ & A maple procedure is used to compute the error on this computations\\ & There are 2 reasons for the total error :\\ & the effective computations, since all operations are done with 53 bits of precision.\\ & the mathematical approximation, since we use polynoms \\ & finally, we have $tcb = \widehat{\cosh(\widehat{b}-1)} + \abserr{tcb}$, where $|\abserr{tcb}| \leq \maxabserr{tcb} = 6.35e-22$, \\ & and $tsb = \widehat{(\frac{\sinh(\widehat{b})}{\widehat{b}}-1)} + \abserr{tsb}$, where $|\abserr{tsb}| \leq \maxabserr{tsb} = 1.11e-21$ \\ Line 60 & If $y$ is very close to $0$, we have the 8 bits of the second range reduction which are null \\ Line 62-65 & We get tabulated values for $\cosh(a)$ and $\sinh(a)$. They are tabulated as double doubles: \\ & we have $ca_{hi} + ca_{lo} = \widehat{\cosh(\widehat{a})} + \abserr{ca}$, where $|\abserr{ca}| \leq \maxabserr{ca} = 6.08e-33$, \\ & and $sa_{hi} + sa_{lo} = \widehat{\sinh(\widehat{a})} + \abserr{sa}$, where $|\abserr{sa}| \leq \maxabserr{sa} = 1.47e-33$, \\ Line 68 & $b\_sa_{hi} + b\_sa_{lo} = sa_{hi} b_{hi}$. This product is exact. \\ Line 69-70 & it is the reconstruction : $\cosh(y) = \cosh(a)(1+tcb) + \sinh(a)b(1+tsb)$ \\ & A maple procedure is used to compute the error done in this reconstruction. \\ & We have $ch_{hi}+ch_{lo} = \widehat{\cosh(\widehat{y})} + \abserr{cosh1}$, where $|\abserr{cosh1}| \leq \maxabserr{cosh1} = 2.39e-20$\\ Line 75 & If $y$ is very close to $0$, we have $a = 0$ and $\cosh(y) = \cosh(b) = 1 + tcb$. \\ & This addition is exact, so no error is introduced. \\ & We have $ch_{hi}+ch_{lo} = \widehat{\cosh(\widehat{y})} + \abserr{cosh0}$, where $|\abserr{cosh0}| \leq \maxabserr{cosh0} = 6.35e-22$\\ \end{tabular} \subsubsection{Second reconstruction} \begin{lstlisting}[caption={Procedure \texttt{cosh\_quick} - reconstruction},firstnumber=77] if(k != 0) { if( table_index != bias) { /* first reconstruction for the sinh (corresponding to the second range reduction) */ Mul12(&b_ca_hi , &b_ca_lo, ca_hi, b_hi); temp = (((((sa_lo + (b_lo * ca_hi)) + (b_hi * ca_lo)) + b_ca_lo) + (sa_hi*tcb_hi)) + (b_ca_hi * tsb_hi)); Add12(temp_hi, temp_lo, b_ca_hi, temp); Add22Cond(&sh_hi, &sh_lo, sa_hi, (double) 0, temp_hi, temp_lo); } else { Add12Cond(sh_hi, sh_lo, b_hi, tsb_hi * b_hi + b_lo); } if((k < 35) && (k > -35) ) { ch_2_pk_hi = ch_hi * two_p_plus_k.d; ch_2_pk_lo = ch_lo * two_p_plus_k.d; ch_2_mk_hi = ch_hi * two_p_minus_k.d; ch_2_mk_lo = ch_lo * two_p_minus_k.d; sh_2_pk_hi = sh_hi * two_p_plus_k.d; sh_2_pk_lo = sh_lo * two_p_plus_k.d; sh_2_mk_hi = -1 * sh_hi * two_p_minus_k.d; sh_2_mk_lo = -1 * sh_lo * two_p_minus_k.d; Add22Cond(&res_hi, &res_lo, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo); Add22Cond(&ch_2_mk_hi, &ch_2_mk_lo , sh_2_pk_hi, sh_2_pk_lo, res_hi, res_lo); Add22Cond(&res_hi, &res_lo, ch_2_pk_hi, ch_2_pk_lo, ch_2_mk_hi, ch_2_mk_lo); } else if (k >= 35) { ch_2_pk_hi = ch_hi * two_p_plus_k.d; ch_2_pk_lo = ch_lo * two_p_plus_k.d; sh_2_pk_hi = sh_hi * two_p_plus_k.d; sh_2_pk_lo = sh_lo * two_p_plus_k.d; Add22Cond(&res_hi, &res_lo, ch_2_pk_hi, ch_2_pk_lo, sh_2_pk_hi, sh_2_pk_lo); } else /* if (k <= -35) */ { ch_2_mk_hi = ch_hi * two_p_minus_k.d; ch_2_mk_lo = ch_lo * two_p_minus_k.d; sh_2_mk_hi = -1 * sh_hi * two_p_minus_k.d; sh_2_mk_lo = -1 * sh_lo * two_p_minus_k.d; Add22Cond(&res_hi, &res_lo, ch_2_mk_hi, ch_2_mk_lo, sh_2_mk_hi, sh_2_mk_lo); } } else { res_hi = ch_hi; res_lo = ch_lo; } \end{lstlisting} \begin{tabular}{ll} Line 77 & Test if $k = 0$ or not \\ Line 78-87 & We have $k \neq 0$, so we must compute $\sinh(y)$ \\ & This computation is done like the computation of $\cosh(h)$ \\ & We can use an Add12 (instead of Add12Cond) since $b_{hi} ca_{hi} \geq temp$ \\ & A maple script gives $\sinh(y) = \widehat{\sinh(\widehat{y})} + \abserr{sinh1}$, where $|\abserr{sinh1}| \leq \maxabserr{sinh1} = 1.09e-22$ \\ & and $|\abserr{sinh1}| \leq \maxabserr{sinh0} = 5.4e-20$ (when $\sinh(a) = 0$) \\ Line 89 & We have $k\neq 0$, and $|k| \leq 35$ \\ Line 91-98 & we multiply $\sinh(y)$ and $\cosh(y)$ by powers of 2, so these products are exact \\ Line 100-102 & A maple script is used to compute the error: \\ & We have $ch_{hi} + ch_{lo} = \widehat{\cosh(\widehat{x})}(1+\relerr{ch})$, where $|\relerr{ch}| \leq \maxrelerr{ch} = 7.66e-19$ \\ Line 104 & $k \geq 35$ \\ Line 106-109 & we multiply $\sinh(y)$ and $\cosh(y)$ by powers of 2, so these products are exact \\ & Some terms are not computed, since they are too little \\ Line 110 & A maple script is used to compute the error: \\ & We have $ch_{hi} + ch_{lo} = \widehat{\cosh(\widehat{x})}(1+\relerr{ch})$, where $|\relerr{ch}| \leq \maxrelerr{ch} = 7.69e-19$ \\ Line 112 & $k \leq -35$ \\ Line 114-118 & this case is symmetric to the previous one. \\ & We also have $ch_{hi} + ch_{lo} = \widehat{\cosh(\widehat{x})}(1+\relerr{ch})$, where $|\relerr{ch}| \leq \maxrelerr{ch} = 7.69e-19$ \\ Line 121 & we now have $k = 0$ \\ & Since we have $1 \leq \cosh(x)$, we have $\maxrelerr{ch} \leq max(\maxabserr{cosh0},\maxabserr{cosh1}) = 2.39e-20$ \\ \end{tabular} At this, stage, we have $ch_{hi} + ch_{lo} = \widehat{\cosh(\widehat{x})}(1+\relerr{ch})$, where $|\relerr{ch}| \leq \maxrelerr{ch} = 7.69e-19 = 2^{-60.17}$ . \subsection{Rounding} \subsubsection{Rounding to the nearest} The code for rounding is strictly identical to that of Theorem~\ref{th:roundingRN1}. The condition to this theorem that $\mathtt{res\_hi}\ge 2^{-1022+53}$ is ensured by the image domain of the $\cosh$, since $\cosh(x) \geq 1$. The rounding constant \subsection{Directed rounding} Here again, the code is strictly identical to that of Theorem~\ref{th:roundingDirected}, and the conditions to this theorem are ensured by the image domain of the cosh. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Accurate phase} It is reminded that correct rounding requires an intermediate accuracy of $2^{-142}$ for $\cosh$ and $2^{-126}$ for $\sinh$. The triple-double exponential function in \texttt{crlibm} is sufficiently accurate for computing the $\cosh$, using the equation $$\cosh(x) = \frac{e^x + e^{-x}}{2}\quad.$$ For $\sinh$, we use the \texttt{expm1} triple-double implementation: This is more accurate around $0$, as the following equation shows: $$\sinh(x) = \frac{e^x - e^{-x}}{2}\quad = \frac{(e^x-1) - (e^{-x}-1)}{2}\quad .$$ As already noted, the $e^{-x}$ term is optimised out for large arguments. Indeed, for $|x|>40$ we have $e^{-x}<2^{-115}e^x$, therefore the relative error due to neglecting $e^{-x}$ is much smaller than the worst case accuracy required to decide rounding, which is smaller than $2^{-111}$ for both functions in this range. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Analysis of cosh performance} \label{section:cosh_results} The input numbers for the performance tests given here are random positive double-precision numbers with a normal distribution on the exponents. More precisely, we take random 63-bit integers and cast them into double-precision numbers. In average, the second step is taken in 0.13\% of the calls. \subsection{Speed} Table \ref{tbl:cosh_abstime} (produced by the \texttt{crlibm\_testperf} executable) gives absolute timings for a variety of processors and operating systems. \begin{table}[!htb] \begin{center} \renewcommand{\arraystretch}{1.2} \begin{tabular}{|l|r|r|r|} \hline \multicolumn{4}{|c|}{Pentium III / Linux 2.6 / gcc 4.0} \\ \hline \hline & min time & avg time & max time \\ \hline default \texttt{libm} & 242 & 272 & 304 \\ \hline \texttt{crlibm} & 212 & 344 & 2639 \\ \hline \hline \end{tabular} \end{center} \caption{Absolute timings for the hyperbolic cosine \label{tbl:cosh_abstime}} \end{table} Contributions to this table for new processors/OS/compiler combinations are welcome. %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/elem-fun.bib0000644000000000000000000013125113316017127017764 0ustar 00000000000000@COMMENT { This file is part of crlibm, the correctly rounded mathematical library, which has been developed by the Arénaire project at École normale supérieure de Lyon. Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, and Jean-Michel Muller This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA } @BOOK{Baker75, author = {A. Baker}, year = 1975, title = {Transcendental Number Theory}, publisher = {Cambridge University Press} } @Article{Ng1992, author = "K. C. Ng", title = "Argument Reduction for Huge Arguments: Good to the Last Bit", journal = "SunPro", day = "13", month = jul, year = "1992", bibdate = "Thu Sep 1 10:16:08 1994", bibsource = "ftp://garbo.uwasa.fi/pc/doc-soft/fpbibl18.zip", note = "Work in progress." } @TechReport{AMDoptim2001, author = {AMD}, title = {{AMD} Athlon Processor {x86} Code Optimization Guide}, institution = {Advanced Micro Devices,inc}, year = 2001 } @article{Car59, author = {Carr, J. W. }, journal = {Communications of the ACM}, number = 5, pages = {10-16}, title = {Error analysis in floating point arithmetic}, volume = 2, year = 1959, url = {http://delivery.acm.org/10.1145/370000/368329/p10-carr.pdf} } @InCollection{Gal86, author = {S. Gal}, title = {Computing elementary functions: A new approach for achieving high accuracy and good performance}, booktitle = {Accurate Scientific Computations, LNCS 235}, pages = {1-16}, publisher = {Springer Verlag}, year = 1986 } @ARTICLE{KarOfm62, author = {Karatsuba, A. and Ofman, Y.}, JOURNAL = {Doklady Akademii Nauk SSSR}, TITLE = {Multiplication of multidigit numbers on automata}, NUMBER = {2}, PAGES = {293-294}, VOLUME = {145}, YEAR = {1962}, CRINDEX = {Traduit} } @ARTICLE{Brent78, AUTHOR = {Richard P. Brent}, JOURNAL = {ACM Transactions on Mathematical Software}, NUMBER = 1, PAGES = {57-70}, TITLE = {A {Fortran} multiple-precision arithmetic package}, VOLUME = 4, YEAR = 1978 } @Article{Bernstein86, AUTHOR = {R. Bernstein}, TITLE = {Multiplication by Integer Constants}, JOURNAL = {Software -- Practice and Experience}, VOLUME = {16}, NUMBER = {7}, PAGES = {641--652}, MONTH = jul, YEAR = {1986} } @ARTICLE{DM94, AUTHOR = {Das Sarma, D. and Matula, D. W.}, JOURNAL = {IEEE Transactions on Computers}, MONTH = Aug, NUMBER = {8}, PAGES = {932-940}, TITLE = {Measuring the Accuracy of {ROM} Reciprocal Tables}, VOLUME = {43}, YEAR = {1994}, KEYWORDS = {division} } @ARTICLE{Bailey95, author = {David H. Bailey}, JOURNAL = {ACM Transactions on Mathematical Software}, NUMBER = {4}, PAGES = {379-387}, TITLE = {A {Fortran}-90 based multiprecision system}, VOLUME = {21}, YEAR = {1995}, CRINDEX = {Fichier}, url = {http://science.nas.nasa.gov/Pubs/TechReports/RNRreports/dbailey/RNR-94-013/RNR-94-013.ps} } @Misc{GMPweb, title = {{GMP}, the {GNU} Multi-Precision Library}, key = {GMP}, howpublished = {{\tt http://swox.com/gmp/}} } @Misc{MPFRweb, title = {{MPFR}}, key = {MPFR}, howpublished = {{\tt http://www.mpfr.org/}} } @Misc{IBMlibultimweb, title = {{IBM} {Accurate} {Portable} {Math.} {Library}}, key = {LibUltim}, howpublished = {{\tt http://oss.software.ibm.com/mathlib/}} } @Misc{FDLIBMweb, title = {Sun {Freely Distributable LIBM}}, howpublished = {{\tt http://www.netlib.org/fdlibm/}} } @Misc{IntelOpenSource, title = {Open Source from {Intel}}, howpublished = {{\tt http://www.intel.com/software/products/opensource/}} } @inproceedings{Daumas98, author = {Marc Daumas}, title = {Expansions: lightweight multiple precison arithmetic}, booktitle = {Architecture and Arithmetic Support for Multimedia}, address = {Dagstuhl, Germany}, year = {1998}, url = {ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/RR/RR98/RR98-39.ps.Z} } @ARTICLE{DauFin99a, AUTHOR = {Marc Daumas and Claire Finot}, NUMBER = {6}, VOLUME = {5}, PAGES = {323-338}, JOURNAL = {Journal of Universal Computer Science}, TITLE = {Division of floating point expansions with an application to the computation of a determinant}, YEAR = {1999}, CRINDEX = {Fichier}, LOCATION = {http://www.iicm.edu/jucs_5_6/division_of_floating_point/paper.pdf} } @INPROCEEDINGS{DauMor2K, AUTHOR = {Marc Daumas and Claire Moreau-Finot}, ADDRESS = {Dagstuhl, Germany}, BOOKTITLE = {Real Numbers and Computers}, PAGES = {61-74}, TITLE = {Exponential: implementation trade-offs for hundred bit precision}, CRINDEX = {Livre, Fichier}, YEAR = {2000} } @TECHREPORT{DefDinMul01, author = {D. Defour and F. de~Dinechin and J.M. Muller}, month = {July}, year = 2001, title = {Correctly Rounded Exponential Function in Double Precision Arithmetic}, number = {RR2001-26}, note = {Available at ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/RR/RR2001/RR2001-26.ps.Z}, institution = {LIP, \'Ecole Normale Sup\'erieure de Lyon}, } @TECHREPORT{Defour02, author = {D. Defour}, month = oct, year = 2002, title = {Cache-Optimised Methods for the Evaluation of Elementary Functions}, number = {RR2002-38}, note = {Available at ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/RR/RR2002/RR2002-38.ps.Z}, institution = {LIP, \'Ecole Normale Sup\'erieure de Lyon}, } @ARTICLE{Dek71, AUTHOR = {Theodorus J. Dekker}, JOURNAL = {Numerische Mathematik}, NUMBER = {3}, PAGES = {224-242}, TITLE = {A floating point technique for extending the available precision}, VOLUME = {18}, YEAR = {1971}, CRINDEX = {Classeur} } @INPROCEEDINGS{Far81, author = {P.~M. Farmwald}, editor = {K.~S. Trivedi and D.~E. Atkins}, year = 1981, title = {High Bandwidth Evaluation of Elementary Functions}, booktitle = {Proceedings of the 5th IEEE Symposium on Computer Arithmetic}, publisher = {IEEE Computer Society Press, Los Alamitos, CA}, key = {Far81} } @ARTICLE{Gol91, author = {D. Goldberg}, month = Mar, year = 1991, title = {What every computer scientist should know about floating-point arithmetic}, journal = {ACM Computing Surveys}, volume = 23, number = 1, pages = {5-47}, keywords = {floating-point arithmetic} } @techreport{Markstein2001, author = {R.-C. Li and P. Markstein and J. P. Okada and J. W. Thomas}, title = {The Libm library and floating-point arithmetic for {HP-UX} on {I}tanium}, institution = {{H}ewlett-{P}ackard company}, year = {2001}, month = {april} } @ARTICLE{HarKubStoTan99, author = {J. Harrison and T. Kubaska and S. Story and P.T.P. Tang}, year = 1999, title = {The Computation of Transcendental Functions on the {IA}-64 Architecture}, journal = {Intel Technology Journal}, volume = {Q4} } @INPROCEEDINGS{Hassler95, AUTHOR = {Hassler, H. and Takagi, N.}, ADDRESS = {Bath, UK}, BOOKTITLE = {12th IEEE Symposium on Computer Arithmetic}, EDITOR = {S. Knowles and W.H. McAllister}, PAGES = {10--16}, PUBLISHER = {IEEE Computer Society Press}, TITLE = {Function Evaluation by Table Look-up and Addition}, YEAR = {1995} } @BOOK{Hwang79, AUTHOR = {K. Hwang}, PUBLISHER = {Wiley, New York}, TITLE = {Computer Arithmetic Principles, Architecture and Design}, YEAR = {1979} } @BOOK{Knu73, author = {D. Knuth}, year = 1973, title = {The Art of Computer Programming}, volume = 2, publisher = {Addison Wesley, Reading, MA} } @BOOK{Kor93, AUTHOR = {I. Koren}, PUBLISHER = {Prentice-Hall}, TITLE = {Computer arithmetic algorithms}, YEAR = {1993}, KEYWORDS = {accuracy control,addition,cordic,division,elementary functions,exponential,floating-point arithmetic,logarithm,multiplication,number systems,redundant number systems,residue number systems,shift-and-add algorithms,square root,survey on computer arithmetic,trigonometric functions} } @INPROCEEDINGS{Arnold89, author = {Arnold, M.G. and Bailey, T.A. and Cowles, J.R. and Cupal, J.J.}, title = {Redundant Logarithmic Number Systems}, month = sep, year = 1989, booktitle = {Proceedings of the 9th IEEE Symposium on Computer Arithmetic}, editor = {Avizienis, Ercegovac and Swartzlander}, pages = {144-151}, publisher = {IEEE Computer Society Press}, address = {Santa Monica} } @INPROCEEDINGS{Lewis89, author = {Lewis, D.M. and Yu, L.K.}, title = {Algorithm Design for a 30 bit Integrated Logarithmic Processor}, month = sep, year = 1989, booktitle = {Proceedings of the 9th IEEE Symposium on Computer Arithmetic}, editor = {Avizienis, Ercegovac and Swartzlander}, pages = {192-199}, publisher = {IEEE Computer Society Press}, address = {Santa Monica} } @PHDTHESIS{Lef2000, author = {V.~Lefèvre}, year = 2000, title = {Moyens arithm\'etiques pour un calcul fiable}, school = {\'Ecole Normale Sup\'erieure de Lyon, Lyon, France} } @INPROCEEDINGS{LefMul2000, author = {V. Lefèvre and J.M. Muller}, month = aug, year = 2000, title = {On-the-Fly Range Reduction}, booktitle = {{SPIE's} International Symposium on Optical Science and Technology}, address = {San Diego} } @Article{LMT98, AUTHOR = {V. Lef\`evre and J.M. Muller and A. Tisserand}, JOURNAL = {IEEE Transactions on Computers}, MONTH = nov, NUMBER = {11}, PAGES = {1235--1243}, TITLE = {Towards Correctly Rounded Transcendentals}, VOLUME = {47}, YEAR = {1998}, KEYWORDS = {table maker's dilemma,elementary functions,rounding,floating-point arithmetic} } @Article{Lewis94, AUTHOR = {Lewis, D.M.}, JOURNAL = {IEEE Transactions on Computers}, MONTH = aug, NUMBER = {8}, PAGES = {974-982}, TITLE = {Interleaved Memory Function Interpolators with Application to an Accurate {LNS} Arithmetic Unit}, VOLUME = {43}, YEAR = {1994} } @TechReport{Lefevre99b, AUTHOR = {V. Lef\`evre}, TITLE = {Multiplication by an Integer Constant}, ADDRESS = {Lyon, France}, INSTITUTION = {Laboratoire d'Informatique du Parall\'elisme}, TYPE = {{LIP} research report}, NUMBER = {RR1999-06 (\texttt{ftp://ftp.ens-lyon.fr/pub/LIP­/Rapports/­RR/­RR1999/­RR1999-06.ps.Z})}, YEAR = {1999}, KEYWORDS = {multiplication,addition chains} } @BOOK{Map91, author = {B.~W. Char and K.~O. Geddes and G.~H. Gonnet and B.~L. Leong and M.~B. Monagan and S.~M. Watt}, year = 1991, title = {Maple V Library Reference Manual}, publisher = {Springer Verlag}, address = {Berlin, Germany}, key = {Map91}, issn_isbn = {3-540-97592-6} } @INPROCEEDINGS{Mehendale95, AUTHOR = {Mahesh Mehendale and S. D.Sherlekar and G. Venkatesh }, TITLE = {Synthesis of multiplier-less {FIR} filters with minimum number of additions}, BOOKTITLE = {IEEE/ACM International Conference on Computer-Aided Design}, PAGES = {668-671}, ADDRESS = {San Jose, CA USA}, MONTH = nov, YEAR = {1995} } @INPROCEEDINGS{Mehendale96, AUTHOR = {Mahesh Mehendale and G. Venkatesh and S.D.Sherleka}, TITLE = {Optimized code generation of multiplication-free linear transforms}, BOOKTITLE = {ACM IEEE Design Automation Conference }, PAGES = {41}, ADDRESS = {Las Vegas, NV USA}, MONTH = nov, YEAR = {1996} } @INPROCEEDINGS{Potkonjak94, AUTHOR = {M. Potkonjak and M.B. Srivastava and A. Chandrakasan}, TITLE = {Efficient substitution of multiple constant multiplications by shifts and additions using iterative pairwise matching}, BOOKTITLE = {ACM IEEE Design Automation Conference }, PAGES = {189-194}, ADDRESS = {San Diego, CA USA}, MONTH = jun, YEAR = {1994} } @INPROCEEDINGS{Pri91, author = {D.~M. Priest}, editor = {P. Kornerup and D.~W. Matula}, month = {June}, year = 1991, title = {Algorithms for arbitrary precision floating point arithmetic}, booktitle = {Proceedings of the 10th IEEE Symposium on Computer Arithmetic (Arith-10)}, pages = {132-144}, publisher = {IEEE Computer Society Press, Los Alamitos, CA}, address = {Grenoble, France}, keywords = {accuracy control,floating-point arithmetic}, location = {} } @INPROCEEDINGS{SS97, AUTHOR = {M.J. Schulte and J.E. Stine}, BOOKTITLE = {Proceedings of the 13th IEEE Symposium on Computer Arithmetic}, LOCATION = {Asilomar, CA}, EDITOR = {T. Lang and J.M. Muller and N. Takagi}, KEY = {SS97}, PUBLISHER = {IEEE Computer Society Press}, TITLE = {Symmetric Bipartite Tables for Accurate Function Approximation}, PAGES = {175-183}, YEAR = {1997} } @Article{SS99sbtm, AUTHOR = {M.J. Schulte and J.E. Stine}, JOURNAL = {IEEE Transactions on Computers}, MONTH = aug, NUMBER = {8}, PAGES = {842-847}, TITLE = {Approximating Elementary Functions with Symmetric Bipartite Tables}, VOLUME = {48}, YEAR = {1999} } @ARTICLE{SS99stam, author = { J.E. Stine and M.J. Schulte}, year = 1999, title = {The Symmetric Table Addition Method for Accurate Function Approximation}, journal = {Journal of VLSI Signal Processing}, number = 2, volume = 21, pages = {167-177} } @INPROCEEDINGS{She97, AUTHOR = {Jonathan R. Shewchuk}, BOOKTITLE = {Discrete and Computational Geometry}, PAGES = {305-363}, TITLE = {Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates}, VOLUME = {18}, YEAR = {1997}, CRINDEX = {Fichier}, LOCATION = {http://link.springer.de/link/service/journals/00454/papers97/18n3p305.pdf}, LOCATION.ALT = {http://www.cs.cmu.edu/afs/cs/project/quake/public/papers/robust-arithmetic.ps} } @BOOK{Ste74, author = {P.~H. Sterbenz}, year = 1974, title = {Floating point computation}, publisher = {Prentice-Hall}, address = {Englewood Cliffs, NJ}, keywords = {floating-point arithmetic} } @INPROCEEDINGS{StoTan99, author = {Shane Story and Ping Tak Peter Tang}, month = {April}, year = 1999, title = {New Algorithms for Improved Transcendental Functions on {IA}-64}, booktitle = {Proceedings of the 14th {IEEE} Symposium on Computer Arithmetic, Adelaide, Australia}, pages = {4---11}, publisher = {IEEE Computer Society Press} } @ARTICLE{Tang89, author = {P.~T.~P.~Tang}, month = jun, year = 1989, title = {Table-Driven Implementation of the Exponential Function in {IEEE} Floating-Point Arithmetic}, journal = {ACM Transactions on Mathematical Software}, volume = 15, number = 2, pages = {144--157}, key = {Tan89}, keywords = {Elementary functions, exponential} } @ARTICLE{Dunham90, author = {Dunham, C. B.}, month = oct, year = 1990, title = {Feasability of "perfect" function evaluation}, journal = {{SIGNUM} Newsletter}, volume = 25, number = 4, pages = {25-26} } @INPROCEEDINGS{Tan91, author = {P.~T.~P. Tang}, editor = {P. Kornerup and D.~W. Matula}, month = {June}, year = 1991, title = {Table lookup algorithms for elementary functions and their error analysis}, booktitle = {Proceedings of the 10th IEEE Symposium on Computer Arithmetic}, pages = {232-236}, publisher = {IEEE Computer Society Press, Los Alamitos, CA}, address = {Grenoble, France}, keywords = {accuracy control,elementary functions,table lookup algorithms}, location = {Grenoble, France} } @ARTICLE{Tan92, author = {Tang, P.T.P.}, month = jun, year = 1992, title = {Table-Driven Implementation of the Exponential Function in {IEEE} Floating-Point Arithmetic}, journal = {{ACM} Transactions on Mathematical Software}, volume = 18, number = 2, pages = {211--222}, key = {Tan92} } @book{ErcegovacLang94, author={Ercegovac, M. D. and Lang, T.}, title={Division and Square Root: Digit-Recurrence Algorithms and Implementations}, publisher={Kluwer Academic Publishers, Boston}, year= 1994 } @ARTICLE{WG94, author = {Wong, W. F. and Goto, E.}, month = mar, year = 1994, title = {Fast Hardware-Based Algorithms for Elementary Function Computations Using Rectangular Multipliers}, journal = {IEEE Transactions on Computers}, volume = 43, number = 3, pages = {278--294}, key = {WG94} } @ARTICLE{WG95, AUTHOR = {Wong, W.F. and Goto, E.}, JOURNAL = {IEEE Transactions on Computers}, MONTH = mar, NUMBER = {3}, PAGES = {453--457}, TITLE = {Fast Evaluation of the Elementary Functions in Single Precision}, VOLUME = {44}, YEAR = {1995} } @ARTICLE{Ziv91, author = {A.~Ziv}, month = sep, year = 1991, title = {Fast evaluation of elementary mathematical functions with correctly rounded last bit}, journal = {ACM Transactions on Mathematical Software}, volume = 17, number = 3, pages = {410--423} } @Article{HsiLauDel2000, author = "Shen-Fu Hsiao and Chun-Yi Lau and Jean-Marc Delosme", month = jun, year = "2000", title = "Redundant Constant-Factor Implementation of Multi-Dimensional {CORDIC} and Its Application to Complex {SVD}", journal = "Journal of VLSI Signal Processing Systems", volume = "25", number = "2", pages = "155--166", } @Book{Parhami2000, author = {Parhami, B.}, title = {Computer Arithmetic, Algorithms and Hardware Designs}, year = 2000, publisher = {Oxford University Press} } @Article{Coleman2000, AUTHOR = {Coleman, J. N. and Chester, E. I.}, JOURNAL = {IEEE Transactions on Computers}, TITLE = {Arithmetic on the European Logarithmic Microprocessor}, MONTH = jul, YEAR = {2000}, VOLUME = {49}, NUMBER = {7}, PAGES = {702--715} } @InProceedings{Pineiro2001, author = {Pi\~neiro, J. A. and Bruguera, J. D. and Muller, J.-M.}, title = {Faithful Powering Computation Using Table Look-Up and a Fused Accumulation Tree}, booktitle = {15th {IEEE} Symposium on Computer Arithmetic}, editor = {Neil Burgess and Luigi Ciminiera}, year = 2001, address = {Vail, Colorado}, month = Jun, pages = {40-47} } @InProceedings{CaoWeiCheng2001, author = {J. Cao and Wei, B.W.Y. and J. Cheng}, title = {High-Performance Architectures for Elementary Function Generation}, booktitle = {15th {IEEE} Symposium on Computer Arithmetic}, editor = {Neil Burgess and Luigi Ciminiera}, year = 2001, address = {Vail, Colorado}, month = Jun } @InProceedings{Pineiro2001b, author = {Pi\~neiro, J.A. and Bruguera, J.D. and Muller, J.-M.}, title = {{FPGA} Implementation of a Faithful Polynomial Approximation for Powering Function Computation}, booktitle = {EuroMicro DSD}, year = 2001, address = {Warszawa, Poland} } @InProceedings{Bailey2001, author = {Hida, Yozo and Li, Xiaoye S. and Bailey, David H.}, title = {Algorithms for Quad-Double Precision Floating-Point Arithmetic}, booktitle = {15th {IEEE} Symposium on Computer Arithmetic}, editor = {Neil Burgess and Luigi Ciminiera}, year = 2001, address = {Vail, Colorado}, month = Jun, pages = {155-162} } @inproceedings{Lee2002, author = {Lee, B. and Burgess, N.}, title = {Parameterisable Floating-Point Operators on {FPGA}s}, booktitle = {36th Asilomar Conference on Signals, Systems, and Computers}, pages = {1064-1068}, address = {Pacific Grove, California}, year = 2002 } @InProceedings{Pineiro2001b, author = {Pi\~neiro, J. A. and Bruguera, J. D. and Muller, J.-M.}, title = {{FPGA} Implementation of a Faithful Polynomial Approximation for Powering Function Computation}, booktitle = {EuroMicro DSD}, year = 2001, address = {Warszawa, Poland} } @InProceedings{Liddicoat2001, author = {Liddicoat, A. A. and Flynn, M. J. }, title = {High-Performance Floating Point Divide}, booktitle = {Euromicro Symposium on Digital System Design}, year = 2001, address = {Warsaw, Poland}, month = Sep, pages = {354-361} } @PhdThesis{liddicoat-thesis, author = {Liddicoat, A.A.}, title = {High-performance arithmetic for division and the elementary functions}, school = {Stanford University}, year = 2002 } @Misc{Briggs2002, author = {Briggs, K.}, year = 2002, title = {Doubledouble floating point arithmetic}, url = {{\tt http://members.lycos.co.uk/keithmbriggs/doubledouble.html}} } @InProceedings{MencerBoullisLukStyles2001, author = {O. Mencer and N. Boullis and W. Luk and H. Styles}, title = {Parametrized Function Evaluation on FPGAs}, booktitle = {Field-Programmable Logic and Applications}, year = 2001, address = {Belfast}, month = Sep } @InProceedings{Matousek2002, author = {R. Matou\v sek and M. Tich\' y and Z. Pohl and J. Kadlec and C. Softley and N. Coleman}, title = {Logarithmic Number System and Floating-Point Arithmetics on {FPGA}}, booktitle = {Field-Programmable Logic and Applications}, year = 2002, address = {Montpellier}, month = Sep, pages = {627-636} } @InProceedings{Arnold2002, author = {M. Arnold}, title = {21st Century Slide Rules with Logarithmic Arithmetic: High-Speed, Low-Cost, Low-Power Alternative to Fixed Point Arithmetic}, booktitle = {Online Symposium for Electronics Engineers (\texttt{http://www.osee.net})}, year = 2002, month = Feb } @InProceedings{Lee2003, author = {B. Lee and N. Burgess}, title = {A Dual-Path Logarithmic Number System Addition/Subtraction Scheme for {FPGA}}, booktitle = {Field-Programmable Logic and Applications}, year = 2003, address = {Lisbon}, month = Sep } @Article{Taylor88, AUTHOR = {Taylor, F. J. and Gill, R. and Joseph, J. and Radke, J.}, JOURNAL = {IEEE Transactions on Computers}, TITLE = {A 20 Bit Logarithmic Number System Processor}, YEAR = {1988}, MONTH = feb, VOLUME = {37}, NUMBER = {2}, PAGE = {190-199} } @Article{Lewis90, AUTHOR = {Lewis, D. M.}, JOURNAL = {IEEE Transactions on Computers}, TITLE = {An Architecture for Addition and Subtraction of Long Word Length Numbers in the Logarithmic Number System}, YEAR = {1990}, MONTH = nov, VOLUME = {39}, NUMBER = {11}, PAGE = {1325-1336} } @Book{Flynn2001, author = {Flynn, M. J. and Oberman, S. F.}, title = {Advanced Computer Arithmetic Design}, year = 2001, publisher = {Wiley-Interscience} } @Article{Lefevre2001, AUTHOR = {Defour, D. and Muller, J.M.}, JOURNAL = {R\'eseaux et syst\`emes r\'epartis, calculateurs parall\`eles}, TITLE = {\'Evaluation des fonctions \'el\'ementaires}, YEAR = {2001}, VOLUME = {13}, NUMBER = {4-5}, PAGE = {449-464} } @book{Markstein2000, author = {P. Markstein}, title = {{IA-64} and Elementary Functions : Speed and Precision}, publisher = {Prentice Hall}, year = {2000}, series = {Hewlett-Packard Professional Books}, note = {ISBN: 0130183482} } @Book{CorneaHarrisonTang2002, author = {M. Cornea and J. Harrison and Tang, P.T.P}, title = {Scientific Computing on Itanium-based Systems}, publisher = {Intel Press}, year = 2002 } @Misc{IEEE754, author = {ANSI/IEEE}, title = {Standard 754-1985 for Binary Floating-Point Arithmetic}, year = 1985 } @BOOK{KKLRW93, AUTHOR = {Klatte, R. and Kulisch, U. and Lawo, C. and Rauch, M. and Wiethoff, A.}, PUBLISHER = {Springer Verlag}, TITLE = {{C-XSC a C++ class library for extended scientific computing}}, YEAR = {1993} } @BOOK{Moore66, AUTHOR = {Moore, R.E.}, PUBLISHER = {Prentice Hall}, TITLE = {Interval analysis}, YEAR = {1966} } @book{ErcegovacLang2003, author={Ercegovac, M. D. and Lang, T.}, title={Digital Arithmetic}, publisher={Morgan Kaufmann}, year= 2003 } @Article{Vassiliadis2000, author = {S. Vassiliadis and M. Zhang and Delgado-Frias, J. G. }, title = {Elementary Function Generators for Neural-Network Emulators}, journal = {{IEEE} transactions on neural networks}, year = 2000, volume = 11, number = 6, pages = {1438-1449}, month = {nov} } @InProceedings{LeeLuk2003, author = {Lee, D-U and W. Luk and J. Villasenor and P. Cheung}, title = {Hierarchical Segmentation Schemes for Function Evaluation}, booktitle = {{IEEE} Conference on Field-Programmable Technology}, year = 2003, address = {Tokyo}, month = {dec} } @book{Muller89, AUTHOR = {Muller, Jean-Michel}, TITLE = {Arithm\'etique des ordinateurs, operateurs et fonctions \'el\'ementaires}, PUBLISHER = {Masson}, YEAR = 1989 } @BOOK{Muller97, AUTHOR = {Muller, J.-M.}, PUBLISHER = {Birkhauser}, ADDRESS = {Boston}, TITLE = {Elementary Functions, Algorithms and Implementation}, YEAR = {1997}, ISSN_ISBN = {ISBN 0-8176-3990-X} } @ARTICLE{Mul99, author = {Muller, J.-M. }, year = 1999, title = {A Few Results on Table-Based Methods}, journal = {Reliable Computing}, volume = 5, number = 3, pages = {279-288} } @ARTICLE{DefHanLefMulRevZim2004, AUTHOR = {Defour, D. and Hanrot, G. and Lef\`evre, V. and Muller, J.-M. and Revol, N. and Zimmermann, P.}, JOURNAL = {Numerical algorithms}, VOLUME = 37, NUMBER = {1-4}, PAGES = {367-375}, TITLE = {Proposal for a Standardization of Mathematical function Implementations in Floating-Point Arithmetic}, MONTH = jan, YEAR = 2004 } @inproceedings{Boldo2001, author = {Boldo, S. and Daumas, M.}, title = {A mechanically validated technique for extending the available precision}, PUBLISHER = {IEEE Computer Society Press}, booktitle = {35th Asilomar Conference on Signals, Systems, and Computers}, address = {Pacific Grove, California}, url = {http://www.ens-lyon.fr/~daumas/SoftArith/BolDau01b.pdf}, year = 2001 } @InProceedings{LefMulTis1997a, AUTHOR = {V. Lef\`evre and Muller, J.-M. and A. Tisserand}, ADDRESS = {Asilomar, USA}, BOOKTITLE = {Proceedings of the 13th IEEE Symposium on Computer Arithmetic}, PUBLISHER = {IEEE Computer Society Press, Los Alamitos, CA}, TITLE = {Towards Correctly Rounded Transcendentals}, YEAR = {1997}, KEYWORDS = {table maker's dilemma,elementary functions,rounding,floating-point arithmetic} } @TechReport{Lef1997a, AUTHOR = {V. Lef\`evre}, TITLE = {An Algorithm that Computes a Lower Bound on the Distance Between a Segment and $\mathbb{Z}^2$}, ADDRESS = {Lyon, France}, INSTITUTION = {Laboratoire de l'Informatique du Parallélisme}, TYPE = rr, NUMBER = {RR1997-18}, YEAR = {1997}, KEYWORDS = {elementary functions,floating-point arithmetic,rounding}, ABSTRACT-URL = {http://www.ens-lyon.fr/LIP/research_reports.us.html}, URL = {ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/RR/RR1997/RR1997-18.ps.Z} } @InProceedings{ELMT98, author = {M.D. Ercegovac and T. Lang and Muller, J.-M. and A. Tisserand}, title = {Reciprocation, square root, inverse square root, and some elementary functions using small multipliers}, booktitle = {International Symposium on Optical Science, Engineering and Instrumentation}, year = 1998, editor = {SPIE}, month = jun, note = {San Diego, U.S.A} } @TechReport{LefMulTis1998a, AUTHOR = {V. Lef\`evre and Muller, J.-M. and A. Tisserand}, TITLE = {The Table Maker's Dilemma}, ADDRESS = {Lyon, France}, INSTITUTION = {Laboratoire de l'Informatique du Parallélisme}, TYPE = rr, NUMBER = {RR1998-12}, YEAR = {1998}, KEYWORDS = {table maker's dilemma,elementary functions,rounding,floating-point arithmetic}, ABSTRACT-URL = {http://www.ens-lyon.fr/LIP/research_reports.us.html}, URL = {ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/RR/RR1998/RR1998-12.ps.Z} } @Article{ELMT2000, author = {M.D. Ercegovac and T. Lang and Muller, J.-M. and A. Tisserand}, title = {Reciprocation, square root, inverse square root, and some elementary functions using small multipliers}, JOURNAL = {{IEEE} Transactions on Computers}, year = 2000, MONTH = jul, NUMBER = {7}, PAGES = {628--637}, VOLUME = {49} } @Article{LefMulTis1998b, AUTHOR = {V. Lef\`evre and Muller, J.-M. and A. Tisserand}, JOURNAL = {{IEEE} Transactions on Computers}, MONTH = nov, NUMBER = {11}, PAGES = {1235--1243}, TITLE = {Towards Correctly Rounded Transcendentals}, VOLUME = {47}, YEAR = {1998}, KEYWORDS = {table maker's dilemma,elementary functions,rounding,floating-point arithmetic} } @Article{MST98, author = { Muller, J.-M. and A. Scherbyna and A. Tisserand}, title = {Semi-Logarithmic Number Systems}, journal = {IEEE Transactions on Computers}, year = 1998, volume = 47, number = 2, pages = {145--151}, month = {feb}, annote = {ISSN 0018-9340} } @Book{RALIP99, author = {{Laboratoire d'Informatique du Parallélisme}}, title = {Rapport d'activité 1999}, publisher = {ENS Lyon}, year = {1999}, URL = {http://www.ens-lyon.fr/LIP/Rapport99-WEB/} } @ARTICLE{BajKlaMul94, AUTHOR = {Jean-Claude Bajard and Sylvanus Kla and Jean-Michel Muller}, JOURNAL = {IEEE Transactions on Computers}, NUMBER = {8}, PAGES = {955-963}, TITLE = {{BKM}: a new hardware algorithm for complex elementary functions}, VOLUME = {43}, YEAR = {1994}, CRINDEX = {Non référencé} } @InProceedings{TMP99b, author = {A. Tisserand and P. Marchal and C. Piguet}, title = {An On-Line Arithmetic based FPGA for Low-Power Custom Computing}, booktitle = {9th International Workshop on Field Programmable Logic and Applications (FPL99)}, pages = {264--273}, year = 1999, number = 1673, series = {LNCS}, address = {Denver, Colorado}, month = {sep} } @Article{DTHL99, author = {M. Dimmler and A. Tisserand and U. Holmberg and R. Longchamp}, title = {On-Line Arithmetic for Real-Time Control of Microsystems}, journal = {IEEE/ASME Transactions on Mechatronics}, year = 1999, volume = 4, number = 2, pages = {213--217}, month = {jun}, annote = {ISSN 1083-4435} } @InCollection{Lef1999a, AUTHOR = {V. Lef\`evre}, TITLE = {An Algorithm that Computes a Lower Bound on the Distance Between a Segment and $\mathbb{Z}^2$}, BOOKTITLE = {Developments in Reliable Computing}, YEAR = {1999}, PUBLISHER = {Kluwer}, ADDRESS = {Dordrecht, Netherlands}, PAGES = {203--212}, KEYWORDS = {elementary functions,floating-point arithmetic,rounding} } @TechReport{Lef1999b, AUTHOR = {V. Lef\`evre}, TITLE = {Multiplication by an Integer Constant}, ADDRESS = {Lyon, France}, INSTITUTION = {Laboratoire de l'Informatique du Parallélisme}, TYPE = rr, NUMBER = {RR1999-06}, YEAR = {1999}, KEYWORDS = {multiplication,addition chains}, ABSTRACT-URL = {http://www.ens-lyon.fr/LIP/research_reports.us.html}, URL = {ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/RR/RR1999/RR1999-06.ps.Z} } @InProceedings{LefMul1999a, AUTHOR = {V. Lef\`evre and Muller, J.-M.}, TITLE = {Table Methods for the Elementary Functions}, BOOKTITLE = {Proceedings of the SPIE --- The International Society for Optical Engineering}, EDITOR = {F.T. Luk}, ADDRESS = {Denver, Colorado}, PAGES = {43--49}, VOLUME = {3807}, YEAR = {1999} } @PhDThesis{Lef2000a, AUTHOR = {V. Lef\`evre}, TITLE = {Moyens arithmétiques pour un calcul fiable}, SCHOOL = {École Normale Supérieure de Lyon}, ADDRESS = {Lyon, France}, YEAR = {2000}, MONTH = jan, URL = {ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/PhD/PhD2000/PhD2000-02.ps.Z} } @PhdThesis{Defour-thesis, author = {Defour, David}, title = {Fonctions \'el\'ementaires: algorithmes et impl\'ementations efficaces pour l'arrondi correct en double pr\'ecision}, school = {\'Ecole Normale Sup\'erieure de Lyon}, year = 2003, ADDRESS = {Lyon, France}, month = sep, URL = {ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/PhD/PhD2003/PhD2003-01.ps.gz} } @techreport{Lauter2003lip, author = {C. Lauter}, title = {A correctly rounded implementation of the exponential function on the {Intel} {Itanium} architecture}, institution = {{LIP}, \'Ecole Normale Sup\'erieure de Lyon}, year = 2003, number = {2003-54}, month = nov, note = {Available at ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/RR/RR2003/RR2003-54.ps.gz} } @TECHREPORT{Lauter2003inria, author = {C. Lauter}, title = {A correctly rounded implementation of the exponential function on the {Intel} {Itanium} architecture}, institution= {{INRIA}}, NUMBER = {RR-5024}, MONTH = nov, YEAR = {2003}, note = {Available at http://www.inria.fr/rrrt/rr-5024.html} } @InProceedings{BIT:spie03, author = { Beuchat, J.-L. and L. Imbert and A. Tisserand}, title = {Comparison of Modular Multipliers on {FPGA}s}, BOOKTITLE = {Proceedings of the SPIE --- The International Society for Optical Engineering}, year = {2003} } @InProceedings{BM:sympaaa2003, author = {Jean-Luc Beuchat and Jean-Michel Muller}, title = {Multiplication-addition modulaire: algorithmes it\'eratifs et implantations sur {FPGA}}, booktitle = {Actes de RenPar'15, CFSE'3 et SympAAA'2003}, editor = {M. Auguin and F. Baude and D. Lavenier and M. Riveill}, year = {2003}, pages = {235--242}, month = oct } @Article{BT:tsisympa8, author = {Jean-Luc Beuchat and Arnaud Tisserand}, title = {Evaluation polynomiale en-ligne de fonctions \'el\'ementaires sur {FPGA}}, journal = {Technique et science informatiques}, year = {\aparaitre} } @InProceedings{Beuchat:asap03, author = {Jean-Luc Beuchat}, title = {Modular Multiplication for {FPGA} Implementation of the {IDEA} Block Cipher}, booktitle = {Proceedings of the 14th IEEE International Conference on Application-Specific Systems, Architectures, and Processors}, pages = {412--422}, year = {2003}, editor = {E. Deprettere and S. Bhattacharyya and J. Cavallaro and A. Darte and L. Thiele}, publisher = {IEEE Computer Society} } @InProceedings{Beuchat:fpl2003, author = {Jean-Luc Beuchat}, title = {{FPGA} Implementations of the {RC6} Block Cipher}, booktitle = {Field-Programmable Logic and Applications}, pages = {101--110}, year = {2003}, editor = {P. Y. K. Cheung and G. A. Constantinides and J. T. de Sousa}, number = {2778}, series = {Lecture Notes in Computer Science}, publisher = {Springer} } @InProceedings{Beuchat:raw03, author = {Jean-Luc Beuchat}, title = {Some Modular Adders and Multipliers for Field Programmable Gate Arrays}, booktitle = {Proceedings of the 17th International Parallel \& Distributed Processing Symposium}, year = {2003}, publisher = {IEEE Computer Society} } @InProceedings{BouTis03-arith16, author = {N. Boullis and A. Tisserand}, title = {Some Optimizations of Hardware Multiplication by Constant Matrices}, booktitle = {ARITH 16}, pages = {20--27}, year = 2003 } @INPROCEEDINGS{BouTis02sympa, AUTHOR = {Boullis, N. and Tisserand, A.}, ADDRESS = {Hamamet, Tunisie}, BOOKTITLE = {8\`eme SYMPosium en Architectures nouvelles de machines}, MONTH = apr, PAGES = {283--290}, TITLE = {G\'en\'eration automatique d'architectures de calcul pour des op\'erations lin\'eaires~: application \`a l'{IDCT} sur {FPGA}}, YEAR = {2002} } @misc{LefMul2004, author = {Lef\`evre, V. and Muller, J.-M}, title = {Worst Cases for Correct Rounding of the Elementary Functions in Double Precision}, institution = {LIP/ENS-Lyon}, year = 2004, howpublished = {http://perso.ens-lyon.fr/jean-michel.muller/Intro-to-TMD.htm} } @InProceedings{DefDinMul2001, author = {D. Defour and F. de~Dinechin and J.M. Muller}, title = {Correctly Rounded Exponential Function in Double Precision Arithmetic}, booktitle = {Advanced Signal Processing Algorithms, Architectures, and Implementations X (SPIE'2000)}, editor = {}, year = 2001, volume = {}, address = {San Diego, California}, month = Aug, note = {Also available as LIP research report 2001-26} } @InProceedings{DefDin2002, author = {Defour, D. and de~Dinechin, F.}, title = {Software carry-save for fast multiple-precision algorithms}, booktitle = {35th International Congress of Mathematical Software}, year = 2002, address = {Beijing, China}, note = {Updated version of LIP research report 2002-08} } @InProceedings{DinDef2003, author = {de Dinechin, F. and Defour, D.}, title = {Software Carry-Save: A case study for instruction-level parallelism}, booktitle = {Seventh International Conference on Parallel Computing Technologies}, year = 2003, month = Sep, address = {Nizhny Novgorod, Russia} } @techreport{DarDefDinMul03, author = {C. Daramy and D. Defour and F. de~Dinechin and J.M. Muller}, title = {{CR-LIBM}: The evaluation of the exponential}, institution = {LIP, \'Ecole Normale Sup\'erieure de Lyon}, year = 2003, number = {RR2003-37}, month = jul, note = {Available at ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/RR/RR2003/RR2003-37.ps.gz} } @misc{SCSweb, title = {{SCS}, {S}oftware {C}arry-{S}ave multiprecision library}, url = {http://www.ens-lyon.fr/LIP/Arenaire/News/SCSLib/} } @techreport{DinDefLau2004LIP, author = {de~Dinechin, F. and D. Defour and C. Lauter}, title = {Fast correct rounding of elementary functions in double precision using double-extended arithmetic}, institution = {LIP, \'Ecole Normale Sup\'erieure de Lyon}, year = 2004, number = {2004-10}, month = mar, note = {Available at http://www.ens-lyon.fr/LIP/Pub/Rapports/RR/RR2004/RR2004-10.pdf} } @techreport{DinGast2004LIP, author = { de~Dinechin, F. and Gast, N.}, title = {Towards the post-ultimate \texttt{libm}}, institution = {LIP, \'Ecole Normale Sup\'erieure de Lyon}, year = 2004, number = {2004-47}, month = nov, note={Submitted to Arith' 17}, anote = {available at \url{http://www.ens-lyon.fr/LIP/Pub/Rapports/RR/RR2004/RR2004-47.pdf}} } @InProceedings{DinErshGast2005, author = {de~Dinechin, F. and Ershov, A. and Gast, N.}, title = {Towards the post-ultimate libm}, booktitle = {17th Symposium on Computer Arithmetic}, year = 2005, nolocation = {Cape Cod, Massachussets}, PUBLISHER = {IEEE Computer Society Press}, month = jun, pages = {288-295}, url = {http://perso.ens-lyon.fr/florent.de.dinechin/recherche/publis/2005-Arith.pdf} } @TechReport{Lauter2005LIP:tripledouble, author = {Lauter, Ch. Q.}, title = {Basic building blocks for a triple-double intermediate format}, institution = {LIP}, year = {2005}, month = sep, number = {RR2005-38}, location = {http://www.ens-lyon.fr/LIP/Pub/Rapports/RR/RR2005/RR2005-38.pdf} } @inproceedings{BroMelPio03, author = {H. Br{\"o}nnimann and G. Melquiond and S. Pion}, title = {The {B}oost interval arithmetic library}, booktitle = {Proceedings of the 5th Conference on Real Numbers and Computers}, pages = {65--80}, location = {Lyon, France}, year = {2003}, url = {http://perso.ens-lyon.fr/guillaume.melquiond/doc/03-rnc5-article.ps.gz} } @inproceedings{DauMelMun05, author = {M. Daumas and G. Melquiond and C. Mu{\~n}oz}, title = {Guaranteed proofs using interval arithmetic}, booktitle = {Proceedings of the 17th IEEE Symposium on Computer Arithmetic}, Noeditor = {Paolo Montuschi and Eric Schwarz}, pages = {188--195}, address = {Cape Cod, Massachusetts, USA}, year = {2005}, url = {http://perso.ens-lyon.fr/guillaume.melquiond/doc/05-arith17-article.pdf} } @inproceedings{MelPio05, author = {G. Melquiond and S. Pion}, title = {Formal certification of arithmetic filters for geometric predicates}, booktitle = {Proceedings of the 15th IMACS World Congress on Computational and Applied Mathematics}, location = {Paris, France}, year = {2005}, url = {http://perso.ens-lyon.fr/guillaume.melquiond/doc/05-imacs17_2-article.ps.gz} } @misc{Melqu05, title = {Gappa - G\'en\'eration automatique de preuves de propri\'et\'es arithm\'etiques}, author = {G. Melquiond}, howpublished = {Available at \url{http://lipforge.ens-lyon.fr/www/gappa/}} } @PhdThesis{Finot-thesis, author = {Finot-Moreau, Claire}, title = {Preuves et algorithmes utilisant l'arithm\'etique flottante normalis\'ee IEEE}, school = {\'Ecole Normale Sup\'erieure de Lyon}, year = 2001, ADDRESS = {Lyon, France}, month = jul, URL = {ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/PhD/PhD2001/PhD2001-03.ps.Z} } @techreport{Muller05INRIA, author = {Muller, Jean-Michel}, title = {On the definition of ulp$(x)$}, institution = {INRIA}, year = 2005, number = {RR 5504}, month = feb, note = {Available at ftp://ftp.inria.fr/INRIA/publication/publi-pdf/RR/RR-5504.pdf} } @Misc{crlibmweb, title = {{CR-Libm}, A library of correctly rounded elementary functions in double-precision}, howpublished = {\url{http://lipforge.ens-lyon.fr/www/crlibm/}} } @InProceedings{DinLauMel2005, author = {de~Dinechin, F. and Lauter, Ch. Q. and Melquiond, G.}, title = {Assisted verification of elementary functions using {Gappa}}, booktitle = {ACM{ } Symposium on Applied Computing}, note = {Extended version available as LIP research report RR2005-43, \url{http://www.ens-lyon.fr/LIP/Pub/Rapports/RR/RR2005/RR2005-43.pdf}}, year = 2006 } @PhdThesis{Stehle-thesis, author = {Damien Stehl\'e}, title = {Algorithmique de la réduction de réseaux et application à la recherche de pires cas pour l'arrondi de fonctions mathématiques}, school = {LORIA}, year = 2006, URL = {http://perso.ens-lyon.fr/damien.stehle/these.html} } @techreport{LauterLefevre2007, author = {Ch. Lauter and V. Lef{\`e}vre}, institution = {Laboratoire de l'Informatique du Parall{\'e}lisme}, number = {RR-2007-36}, title = {An efficient rounding boundary test for pow(x,y) in double precision}, type = {Technical Report}, year = {2007}, url = {http://prunel.ccsd.cnrs.fr/ensl-00169409/}, note = {To appear in IEEE Transactions on Computers} } @techreport{KorLauLefLouvMul2008, author = {P. Kornerup and Ch. Lauter and V. Lef{\`e}vre and N. Louvet and J.-M. Muller}, title = {Computing Correctly Rounded Integer Powers in Floating-Point Arithmetic}, number = {RR 2008-15}, institution = {SDU, Odense, Denmark et LIP, CNRS/ENS Lyon/INRIA/Université de Lyon, Lyon, France}, year = {2008}, month = may, note = {To appear in ACM Transactions on Mathematical Software} } interval-3.2.0/src/crlibm/docs/latex/exp.tex0000644000000000000000000015641413316017127017124 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA This chapter is contributed by Ch. Q. Lauter. \section{Overview of the algorithm} The exponential function allows for additive argument reduction with multiplicative reconstruction: $e^{a + b} = e^a \cdot e^b$. In particular, the following equation is useful in developing an argument reduction: $$e^x = e^{E \cdot \ln\left(2\right) + z} = \left(e^{\ln\left( 2 \right)}\right)^E \cdot e^z = 2^E \cdot e^z$$ Here, $E$ can be considered to be a signed integer, $E \in \Z$ and $z$ to be a reduced argument such that $\left \vert z \right \vert < \ln\left(2\right)$. One remarks that the use of such an argument reduction implies a multiplication with a transcendental constant, $\ln\left( 2 \right)$. This means that the reduced argument will not be exact. The corresponding error bound will be given in section \ref{sec:expargred}. A reduced argument obtained by the reduction shown above is generally still to great for polynomial approximation. By use of tabulation methods, the following argument reduction can be employed and yields to smaller reduced arguments. \begin{eqnarray*} k & = & \left \lfloor x \cdot \frac{2^l}{\ln\left(2 \right)} \right \rceil \\ \hat{r} & = & x - k \cdot \frac{\ln\left( 2 \right)}{2^l} \\ k & = & 2^l \cdot M + 2^{w_1} \cdot i_2 + i_1 \end{eqnarray*} where $\hat{r}$ is the reduced argument, $k, M \in \N$ are intermediate integers, and $w_1, w_2 \in \N$, $l = w_1 + w_2$, are the widths of the indices to the two tables. The corresponding reconstruction phase is $$e^x = 2^M \cdot 2^{\frac{i_2}{2^{w_1}}} \cdot 2^{\frac{i_1}{2^l}} \cdot e^{\hat{r}} = 2^M \cdot t_1 \cdot t_2 \cdot e^{\hat{r}}$$ with the table values $t_1 = 2^{\frac{i_2}{2^{w_1}}}$ and $t_2 = 2^{\frac{i_1}{2^l}}$. The argument reduction ensures that $\left \vert \hat{r} \right \vert \leq \frac{\ln\left( 2 \right)}{2^l} < 2^{-l}$. This magnitude is small enough for allowing for polynomial approximation. In the case of the given algorithm, we use $l = 12$ and $w_1 = w_2 = 6$. The subtraction $\hat{r} = x - k \cdot \round \left(\frac{\ln\left( 2 \right)}{2^l}\right)$ can be implemented exactly but leads to catastrophic cancellation that amplifies the absolute error of the potentially exact multiplication of $k$ by the approximated $\frac{\ln\left( 2 \right)}{2^l}$. Is is nevertheless not of such an issue, as will be shown in section \ref{sec:expaccuracy}. % ATTENTION: CHANGER EVTL LA MARQUE \section{Special case handling}\label{sec:expspecial} The exponential function $e^x$, which is monotone increasing, produces results that are representable in a floating point format for arguments $$x \in \left[ \mbox{\small \it underflowBound}; \mbox{\small \it overflowBound} \right]$$ Herein the following values are observed for double precision: $$\mbox{\small \it underflowBound} = \round \left( \ln\left(2^{-1075} \right) \right) \approx -745.13$$ and $$\mbox{\small \it overflowBound} = \round \left( \ln\left(2^{1024} \cdot \left( 1 - 2^{-53} \right) \right) \right) \approx 709.78$$ Its double precision result is gradually underflowed in the argument domain $$x \in \left[\mbox{\small \it underflowBound}; \mbox{\small \it denormBound} \right]$$ where $$\mbox{\small \it denormBound} = \round\left( \ln\left( 2^{-1022} \right) \right) \approx -708.40$$ for double precision. No special case can therefore occur for arguments $x$ such that $$\left \vert x \right \vert \leq \min \left( \left \vert \mbox{\small \it underflowBound} \right \vert, \left \vert \mbox{\small \it overflowBound} \right \vert, \left \vert \mbox{\small \it denormBound} \right \vert \right) \approx 708.40$$ This provides us a very efficient filter for the greatest part of the definition domain. Since also some arguments are filtered out that actually do not represent a special case, additional tests are made in the body of the main special handling sequence launched by the filter. Particular cases like $x=\pm \infty$, $x = \nan$ are handled as follows: \begin{itemize} \item The result for $x = \nan$ is $\nan$. \item The result for $x = + \infty$ is $+ \infty$. \item The result for $x = - \infty$ is $0$, even in round-upwards mode. \end{itemize} If the result is clearly underflowed, $0$ is returned with the inexact flag set for round-to-nearest and round-downwards, $0^+$ is returned for round-upwards. The ordering of double precision numbers is compatible with the integer ordering of the signed 64 bit integers the floating point numbers can be read in memory as. Further the ordering on numbers is equal to the lexicographic ordering of its digits. So if the higher order word of $\left \vert x \right \vert$ is less than the higher order word of $\mbox{\small \it overUnderDenormBound} = \min \left( \left \vert \mbox{\small \it underflowBound} \right \vert, \left \vert \mbox{\small \it overflowBound} \right \vert, \left \vert \mbox{\small \it denormBound} \right \vert \right)$, no underflow, gradual underflow or overflow can occur. In the other cases, special handling in the reconstruction step may be necessary. A flag \texttt{mightBeDenorm} is set for possible subnormals. Cases where intermediate results are not representable because of overflow but where the final result is representable can be overcome by replacing the corresponding floating point multiplication by an integer manipulation. This will be shown below. Since $e^{x} = 1 + x + \Ord\left( x^2 \right)$ for small $\left \vert x \right \vert$, underflowed arguments $x$ ($\left \vert x \right \vert \leq 2^{-1022}$) can be handled as follows: \begin{itemize} \item In round-to-nearest mode, $1$ can be returned since $\round \left( 1 + x \right) = 1$ for $\left \vert x \right \vert \leq 2^{-54}$. \item In round-upwards mode, $1$ must be returned for $x = 0$. For $x < 0$, $1$ can be returned, too, because $\roundup \left( 1 - \left \vert x \right \vert \right) = 1$. If $x > 0$, $1^+$ must be returned. \item Round-downwards mode is analogous to round-upwards mode, but the signs are inverted. \item Round-towards-zero mode is equivalent to round-downwards mode since $e^x > 0 \mbox{~~} \forall x \in \R$. \end{itemize} The following sequence realizes the special case handling for round-to-nearest. The sequences for the other rounding modes are straightforward and will not be shown here. The constants\\ \texttt{OVRUDRFLWSMPLBOUND}, \texttt{OVRFLWBOUND} and \texttt{DENORMBOUND} are computed by the corresponding Maple script that realizes the equations given above. \begin{lstlisting}[caption={Handling special cases},firstnumber=1] /* Special cases tests */ xIntHi = xdb.i[HI]; mightBeDenorm = 0; /* Test if argument is a denormal or zero */ if ((xIntHi & 0x7ff00000) == 0) { /* We are in the RN case, return 1.0 in all cases */ return 1.0; } /* Test if argument is greater than approx. 709 in magnitude */ if ((xIntHi & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) { /* If we are here, the result might be overflowed, underflowed, inf, or NaN */ /* Test if +/- Inf or NaN */ if ((xIntHi & 0x7fffffff) >= 0x7ff00000) { /* Either NaN or Inf in this case since exponent is maximal */ /* Test if NaN: mantissa is not 0 */ if (((xIntHi & 0x000fffff) | xdb.i[LO]) != 0) { /* x = NaN, return NaN */ return x + x; } else { /* +/- Inf */ /* Test sign */ if ((xIntHi & 0x80000000)==0) /* x = +Inf, return +Inf */ return x; else /* x = -Inf, return 0 */ return 0; } /* End which in NaN, Inf */ } /* End NaN or Inf ? */ /* If we are here, we might be overflowed, denormalized or underflowed in the result but there is no special case (NaN, Inf) left */ /* Test if actually overflowed */ if (x > OVRFLWBOUND) { /* We are actually overflowed in the result */ return LARGEST * LARGEST; } /* Test if surely underflowed */ if (x <= UNDERFLWBOUND) { /* We are actually sure to be underflowed and not denormalized any more So we return 0 and raise the inexact flag */ return SMALLEST * SMALLEST; } /* Test if possibly denormalized */ if (x <= DENORMBOUND) { /* We know now that we are not sure to be normalized in the result We just set an internal flag for a further test */ mightBeDenorm = 1; } } /* End might be a special case */ \end{lstlisting} \section{Argument reduction}\label{sec:expargred} Mathematically, the argument reduction used for quick and accurate phase is the same. The reduced argument is nevertheless different for the both phases because the reduction is inexact. It is therefore implemented in two or three phases: First, $k$ corresponding to $\left \lfloor x \cdot \frac{2^{12}}{\ln\left(2 \right)} \right \rceil$ is computed in both integer and floating point (double) representation. Herein $\frac{2^{12}}{\ln\left(2 \right)}$ is represented in double precision and the multiplication by $x$ is performed in double precision, too. Then the nearest integer $k$ to the number obtained is computed. This computational problem is principally subject to the Table Maker's Dilemma: $x \cdot \frac{2^{12}}{\ln\left(2 \right)}$ is transcendental for all $x \not = \ln\left(2 \right)$ and the to-nearest-integer operation is equivalent to a rounding to the nearest. It is not possible to guarantee that the computed $k$ is really the integer nearest to $x \cdot \frac{2^{12}}{\ln\left(2 \right)}$. Nevertheless, this is not a problem. The following argument reduction steps, as $\hat{r} = x - k \cdot \frac{\ln\left(2\right)}{2^{12}}$, and the reconstruction are mathematically correct for any $k$. So computing the wrong $k$ only leads to a slight enlargement of the interval of the reduced argument $\hat{r}$, as one can see with the following argument: The function's argument's value $x$ is bounded in magnitude by $2^{10}$. So, $x \cdot \frac{2^{12}}{\ln\left(2 \right)}$ is bounded in magnitude by $2^{22}$. Since the accuracy of the value $xMultLog2InvMult2L = \round \left( x \cdot \round \left( \frac{2^{12}}{\ln\left(2 \right)} \right) \right)$ with respect to the exact value $x \cdot \frac{2^{12}}{\ln\left(2 \right)}$ is at least $51$ bits, an error is made not earlier than at the $19$th bit following the integer-fractional point. Thus $$\left \vert \frac{k - x \cdot \frac{2^{12}}{\ln\left(2 \right)}}{x \cdot \frac{2^{12}}{\ln\left(2 \right)}} \right \vert \leq \frac{1}{2} + 2^{-19}$$ Therefore $\hat{r}^\prime$ is actually bounded by $\left \vert \hat{r}^\prime \right \vert \leq \frac{\ln\left( 2 \right)}{2^{12}} \cdot \left( \frac{1}{2} + 2^{-19} \right)$ instead of $\left \vert \hat{r} \right \vert \leq \frac{\ln\left( 2 \right)}{2^{12}} \cdot \frac{1}{2}$. This difference can be taken into account in the error computation, and we may safely assume that its effects will be negligible. Note further that $k$ is computed exactly ($k = 0$) for $\left \vert x \right \vert \leq 2^{-14}$ because no Table Maker's Dilemma can no longer occur. This first step is performed by the following code sequence: \begin{lstlisting}[caption={Argument reduction - first step},firstnumber=1] xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; k = shiftedXMultdb.i[LO]; \end{lstlisting} Here, \texttt{k} and \texttt{kd} represent $k$ in integer and floating point (double) format. The technique for computing $\left \lfloor z \right \rceil$ out of $z$ is explained in section \ref{sec:double2int}, page \pageref{sec:double2int}. In the second step of the argument reduction, an arithmetical approximation to $\hat{r} = x - k \cdot \frac{\ln\left( 2 \right)}{2^{12}}$, $r_\hi + r_\mi = \hat{r} + \delta_{\mbox{\tiny argred}}$, is computed using a double-double approximation to $\frac{\ln\left( 2 \right)}{2^{12}}$ and double-double precision for computations. We will consider its absolute error $\delta_{\mbox{\tiny argredquick}} = r_\hi + r_\mi - \hat{r}$ and the resulting relative error on the exponential function $\epsilon_{\mbox{\tiny argredquick}} = \frac{e^{\hat{r} + \delta} - e^{\hat{r}}}{e^{\hat{r}}}$ below. This argument reduction step is implemented as follows: \begin{lstlisting}[caption={Argument reduction - second step},firstnumber=1] Mul12(&s1,&s2,msLog2Div2Lh,kd); s3 = kd * msLog2Div2Lm; s4 = s2 + s3; s5 = x + s1; Add12Cond(rh,rm,s5,s4); \end{lstlisting} Here, \texttt{msLog2Div2Lh} and \texttt{msLog2Div2Lm} are a double-double representing $-\frac{\ln\left( 2 \right)}{2^{12}}$ with an relative error $\left \vert \epsilon_{\mbox{\tiny logconstquick}} \right \vert = \left \vert \frac{msLog2Div2L_\hi + msLog2Div2L_\mi + 2^{-12} \cdot \ln\left( 2 \right)}{-2^{-12} \cdot \ln\left( 2 \right)} \right \vert \leq 2^{-109}$. Further, $\left \vert msLog2Div2L_\mi \right \vert \leq 2^{-54} \cdot \left \vert msLog2Div2L_\hi \right \vert$. Let us now show first a bound on the absolute round-off error of the given sequence. We know that the multiplication $s_1 + s_2 = kd \cdot msLog2Div2h$ and the final addition $r_\hi + r_\mi = s_5 + s_4$ are exact. Further, the addition $s_5 = x \oplus s_1$ is exact as per Sterbenz' lemma. In fact, since $$\left \vert x - \left \lfloor x \cdot \frac{2^{12}}{\ln\left(2\right)} \right \rceil \cdot \frac{\ln\left(2\right)}{2^{12}} \right \vert \leq 2^{-12}$$ and $$s_1 = - \left \lfloor x \cdot \frac{2^{12}}{\ln\left(2\right)} \right \rceil \cdot \frac{\ln\left(2\right)}{2^{12}} \cdot \left( 1 + \epsilon^\prime \right)$$ with $\left \vert \epsilon^\prime \right \vert \leq 2^{-50}$, it is trivial to see that $$\frac{1}{2} \cdot \left \vert s_1 \right \vert \leq \left \vert x \right \vert \leq 2 \cdot \left \vert s_1 \right \vert$$ In addition, $s_1$ and $x$ are clearly of opposed sign. So, noting $$s_3 = k \cdot msLog2Div2L_\mi \cdot \left( 1 + \epsilon_1 \right)$$ and $$s_4 = \left( s_2 + s_3 \right) \cdot \left( 1 + \epsilon_2 \right)$$ with $\left \vert \epsilon_1 \right \vert \leq 2^{-53}$ and $\left \vert \epsilon_2 \right \vert \leq 2^{-53}$, we get $$r_\hi + r_\mi = x + k \cdot \left( msLog2Div2L_\hi + msLog2Div2L_\mi \right) + \delta^\prime$$ with $$\left \vert \delta^\prime \right \vert \leq \left \vert \epsilon_1 \right \vert \cdot \left \vert k \cdot msLog2Div2L_\mi \right \vert + \left \vert \epsilon_2 \right \vert \cdot \left \vert s_2 + s_3 \right \vert$$ We have $$\left \vert s_2 \right \vert \leq 2^{-53} \cdot \left \vert s_1 \right \vert \leq 2^{-53} \cdot \left \vert \round \left( k \cdot msLog2Div2L_\hi \right) \right \vert \leq 2^{-52} \cdot \left \vert k \cdot msLog2Div2L_\hi \right \vert$$ and further $$\left \vert s_3 \right \vert \leq \left \vert k \cdot msLog2Div2L_\mi \left( 1 + \epsilon_1 \right) \right \vert \leq \left \vert k \cdot msLog2Div2L_\mi \right \vert + \left \vert \epsilon_1 \right \vert \cdot \left \vert k \cdot msLog2Div2L_\mi \right \vert$$ So one can easily check that $$\left \vert \delta^\prime \right \vert \leq 2^{-104} \cdot \left \vert k \cdot msLog2Div2Lh \right \vert$$ In consequence using the fact that $\left \vert msLog2Div2L_\hi \right \vert = \left \vert \round \left( \frac{\ln\left( 2 \right)}{2^{12}} \right) \right \vert \leq 2 \cdot \left \vert \frac{\ln\left( 2 \right)}{2^{12}} \right \vert$ and the bound for $k$, one obtains $$\left \vert \delta^\prime \right \vert \leq \left \vert \left( x \cdot \frac{2^{12}}{\ln\left( 2 \right)} + \frac{1}{2} + 2^{-19} \right) \cdot \frac{\ln\left( 2 \right)}{2^{12}} \right \vert$$ Since $\left \vert x \right \vert \leq 746$ after filtering out the special cases, we obtain $\left \vert \delta^\prime \right \vert \leq 2^{-103} \cdot 2^{10} = 2^{-93}$. To this round-off error adds the approximation error comitted by rounding $\frac{\ln\left( 2 \right)}{2^{12}}$ to a double-double. We can note $$r_\hi + r_\mi = x - k \cdot \frac{\ln\left( 2 \right)}{2^{12}} \cdot \left( 1 + \epsilon_{\mbox{\tiny logconstquick}} \right) + \delta^\prime$$ This gives us $$r_\hi + r_\mi = \hat{r} + \delta$$ with $\left \vert \delta \right \vert \leq \left \vert k \cdot \frac{\ln\left( 2 \right)}{2^{12}} \cdot \epsilon_{\mbox{\tiny logconstquick}} \right \vert + \left \vert \delta^\prime \right \vert$. One can easily check that one obtains thus finally $\left \vert \delta \right \vert \leq 2^{-92}$. This absolute error $\delta$ in the reduced argument $\hat{r}$ translates to a relative error $\epsilon_{\mbox{\tiny argredquick}}$ in the function $e^{\hat{r}}$ as follows: \begin{eqnarray*} e^r & = & e^{\hat{r} + \delta} \\ & = & e^{\hat{r}} \cdot e^{\delta} \\ & = & e^{\hat{r}} \cdot \sum\limits_{i=0}^{\infty} \frac{1}{i!} \cdot \delta^i \\ & = & e^{\hat{r}} \cdot \left( 1 + \sum\limits_{i=1}^{\infty} \frac{1}{i!} \cdot \delta^i \right) \\ & = & e^{\hat{r}} \cdot \left( 1 + \epsilon_{\mbox{\tiny argredquick}} \right) \end{eqnarray*} with $\epsilon_{\mbox{\tiny argredquick}} = \sum\limits_{i=1}^{\infty} \frac{1}{i!} \cdot \delta^i = \delta \cdot \sum\limits_{i=0}^{\infty} \frac{1}{\left(i + 1 \right)!} \cdot \delta^i$. Since $\left \vert \delta \right \vert < \frac{1}{2}$, we get $$\forall i \geq 0 \mbox{ . } \left \vert \frac{1}{\left( i + 1 \right)!} \cdot \delta^i \right \vert \leq \left( \frac{1}{2} \right)^i$$ In consequence, $\sum\limits_{i=0}^{\infty} \frac{1}{\left(i + 1 \right)!} \cdot \delta^i \leq \sum\limits_{i=0}^{\infty} \left( \frac{1}{2} \right)^i = 2$. Thus we get $\left \vert \epsilon_{\mbox{\tiny argredquick}} \right \vert \leq 2 \cdot \left \vert \delta \right \vert \leq 2^{-91}$. Still in the second step of the argument reduction, the values $M$, $i_1$ and $i_2$ are computed exactly in integer computation as follows: \begin{lstlisting}[caption={Argument reduction - second step (cont'd)},firstnumber=1] M = k >> L; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> LHALF; \end{lstlisting} Here \texttt{L} is equal to $12$ and \texttt{LHALF} is equal to $6$. The values \texttt{INDEXMASK1} and \texttt{INDEXMASK2} are masks to the lowest 6 bits and respectively to bits 6 through 15 of an 32 bit word. If ever the accurate phase must be launched, a third argument reduction phase is performed. It computes a triple-double $r_\hi + r_\mi + r_\lo = \hat{r} + \delta$ such that the resulting relative error on the exponential function $\epsilon_{\mbox{\tiny argredaccurate}} = \frac{e^{\hat{r} + \delta} - e^{\hat{r}}}{e^{\hat{r}}}$ is bounded by $\left \vert \epsilon_{\mbox{\tiny argredaccurate}} \right \vert \leq 2^{-140}$ as will be shown below. This step uses a triple-double approximation to $\frac{\ln\left( 2 \right)}{2^{12}}$ with a relative error $$\left \vert \epsilon_{\mbox{\tiny logconstaccurate}} \right \vert = \left \vert \frac{msLog2Div2L_\hi + msLog2Div2L_\mi + msLog2Div2L_\lo + 2^{-12} \cdot \ln\left( 2 \right)}{-2^{-12} \cdot \ln\left( 2 \right)} \right \vert \leq 2^{-163}$$ It is implemented as follows: \begin{lstlisting}[caption={Argument reduction - third step},firstnumber=1] Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); \end{lstlisting} The values for $k$, $M$, $i_1$ and $i_2$ that have been exactly computed already at the second argument reduction step can of course be reused. All operation but the first \texttt{Mul133} operator are exact: the last two by their general properties, the addition $t_1 = x \oplus msLog2Div2LMultK_\hi$ as per Sterbenz' lemma analogously as in the second argument reduction step. So one can note $$r_\hi + r_\mi + r_\lo = x - k \cdot \left( msLog2Div2L_\hi + msLog2Div2L_\mi + msLog2Div2L_\lo \right) \cdot \left( 1 + \epsilon_1 \right)$$ where $\epsilon_1$ is the relative error bound of the \texttt{Mul133} operator, for instance $\left \vert \epsilon_1 \right \vert \leq 2^{-153}$. Integrating also the rounding error in the constant, we get $$r_\hi + r_\mi + r_\lo = x - k \cdot \frac{\ln\left( 2 \right)}{2^{12}} + \delta$$ with $\left \vert \delta \right \vert \leq \left \vert k \cdot \frac{\ln\left( 2 \right)}{2^{12}} \right \vert \cdot \left( 2^{-163} + 2^{-153} \right) \leq 2^{-152} \cdot \left \vert k \cdot \frac{\ln\left( 2 \right)}{2^{12}} \right \vert \leq 2^{-141}$. One checks the previous upper bounds by using analogous arguments as the ones given for the second argument reduction step. Once again, this absolute error $\delta$ translates to a relative error $\epsilon_{\mbox{\tiny argredaccurate}} = \frac{e^{\hat{r} + \delta} - e^{\hat{r}}}{e^{\hat{r}}}$ in a similar way as mentioned above. We get $$\left \vert \epsilon_{\mbox{\tiny argredaccurate}} \right \vert \leq 2^{-140}$$ which is the bound to prove. Let us still remark that argument reduction is exact for arguments $x$ such that $\left \vert x \right \vert \leq \frac{\ln\left( 2 \right)}{2^{13}} < 2^{-13}$. In fact, in this case, $k = 0$ which implies that all multiplications of $k$ by the constants for $\frac{\ln\left( 2 \right)}{2^{12}}$ are exact. According to their uses either in quick or accurate phase, the table values $t_1 = e^{\frac{i_1}{2^{12}}}$ and $t_2 = e^{\frac{i_1}{2^{12}}}$ for $i_1, i_2 \in \left \lbrace 0 \dots 63 \right \rbrace$ are read as a double-double or as a triple-double. By construction, the double-double values have a relative error $\epsilon_{\mbox{\tiny tablequick}} = \frac{tbl_{i\hi} + tbl_{i\mi} - t_i}{t_i}$ bounded by $\left \vert \epsilon_{\mbox{\tiny tablequick}} \right \vert \leq 2^{-106}$. The triple-double values with $\epsilon_{\mbox{\tiny tableaccurate}} = \frac{tbl_{i\hi} + tbl_{i\mi} + tbl_{i\lo} - t_i}{t_i}$ verify $\left \vert \epsilon_{\mbox{\tiny tableaccurate}} \right \vert \leq 2^{-159}$. For $i_1 = 0$ and $i_2 = 0$ both errors are equal to $0$, so both argument reduction and reconstruction steps are exact for argument $x$ that verify $\left \vert x \right \vert \leq 2^{-13}$. \section{Polynomial approximation and reconstruction}\label{sec:exppolynomial} In both quick and accurate phase, the reduced argument $r_\hi + r_\mi$ respectively $r_\hi + r_\mi + r_\lo$ corresponding to their mathematical equivalent $\hat{r}$ are bounded by $\left \vert \hat{r} \right \vert \leq \frac{\ln\left( 2 \right)}{2^{12}} \cdot \left( 2^{-1} + 2^{-19} \right) + \delta < 2^{-13}$. After simplification by $e^{r_\hi + r_\mi + r_\lo} = e^{r_\hi} \cdot e^{r_\mi} \cdot e^{r_\lo}$, $e^{r_\hi} - 1$ is approximated by a polynomial of degree 4 or 7. The functions $e^{r_\mi} - 1$ and potentially $e^{r_\lo} - 1$ are both approximated linearly by $r_\mi$ or, respectively, $r_\lo$. Concerning the approximation errors for $e^{r_\mi}$ and $e^{r_\lo}$, one can note that $\left \vert r_\mi \right \vert \leq 2^{-52} \cdot 2^{-13} \leq 2^{-65}$ and $\left \vert r_\lo \right \vert \leq 2^{-105} \cdot 2^{-13} \leq 2^{-118}$. In consequence $\epsilon_{\mbox{\tiny approxargmiddle}} = \frac{r_\mi - \left( e^{r_\mi} - 1 \right)}{\left( e^{r_\mi} - 1 \right)}$ and $\epsilon_{\mbox{\tiny approxarglower}} = \frac{r_\lo - \left( e^{r_\lo} - 1 \right)}{\left( e^{r_\lo} - 1 \right)}$ are bounded by $\left \vert \epsilon_{\mbox{\tiny approxargmiddle}} \right \vert \leq 2^{-66}$ and $\left \vert \epsilon_{\mbox{\tiny approxarglower}} \right \vert \leq 2^{-119}$. \subsection{Quick phase polynomial approximation and reconstruction} In quick phase $e^{r_\hi} - 1$ is approximated by a polynomial $p\left( r_\hi \right)$ of the following form $$p\left( r_\hi \right) = r_\hi + \frac{1}{2} \cdot r_\hi^2 + c_3 \cdot r_\hi^3 + c_4 \cdot r_\hi^4$$ The coefficients $c_3$ and $c_4$ are stored in double precision, $\frac{1}{2}$ is exactly representable. For $r_\hi$ bounded as indicated above, the relative approximation error $\epsilon_{\mbox{\tiny approxarghighquick}} = \frac{p\left( r_\hi \right) - e^{r_\hi} + 1}{e^{r_\hi} - 1}$ is bounded by $\left \vert \epsilon_{\mbox{\tiny approxarghighquick}} \right \vert \leq 2^{-62}$. The polynomial $p\left(r_\hi \right) - r_\hi = \frac{1}{2} \cdot r_\hi^2 + c_3 \cdot r_\hi^3 + c_4 \cdot r_\hi^4$ is evaluated in double precision using the following scheme: \begin{enumerate} \item In the beginning, an approximation to $r_\hi^2$, $rhSquare$, is computed. Concurrently, $c_3$ is multiplied by $r_\hi$ yielding to $rhC3 = c_3 \cdot r_\hi \cdot \left( 1 + \epsilon \right)$. \item At the first step, the squared argument $rhSquare$ is multiplied by $\frac{1}{2}$ yielding to the approximation $rhSquareHalf$. At the same time, it is multiplied by $rhC3$ which results in $monomialCube$ approximating now $c_3 \cdot r_\hi^3$. Still in the same moment, it is squared once again yielding to $rhFour$ which approximates thus $r_\hi^4$. \item At the next dependency top, $rhFour$ is multiplied by $c_4$. This results in $monomialFour$ -- a value corresponding to $c_4 \cdot r_\hi^4$. \item In the next moment, $monomialCube$ and $monomialFour$ are added together. This gives a value approximating $c_3 \cdot r_\hi^3 + c_4 \cdot r_\hi^4$. \item Finally, $rhSquareHalf$ is added to the value obtained at the previous step yielding to an arithmetical approximation of $\frac{1}{2} \cdot r_\hi + c_3 \cdot r_\hi^3 + c_4 \cdot r_\hi^4$, stored in $highPolyWithSquare$. \end{enumerate} This scheme does not completely exploit the possible parallelism for purpose of not deteriorating too much the final accuracy. It is implemented as follows: \begin{lstlisting}[caption={Quick phase polynomial evaluation - high order terms},firstnumber=1] rhSquare = rh * rh; rhC3 = c3 * rh; rhSquareHalf = 0.5 * rhSquare; monomialCube = rhC3 * rhSquare; rhFour = rhSquare * rhSquare; monomialFour = c4 * rhFour; highPoly = monomialCube + monomialFour; highPolyWithSquare = rhSquareHalf + highPoly; \end{lstlisting} The following steps must still add the linear term $r_\hi$ of the polynomial ($p\left( r_\hi \right) = r_\hi + highPolyWithSquare$) and reconstruct the exponential as $$e^{x} = 2^M \cdot \left( tbl_{1\hi} + tbl_{1\mi} \right) \cdot \left( tbl_{2\hi} + tbl_{2\mi} \right) \cdot \left( 1 + r_\hi + highPolyWithSquare \right) \cdot \left( 1 + r_\mi \right) + \delta$$ In order to allow for increasing speed by approximating different terms, they are implemented as this: \begin{enumerate} \item The two table values $tbl_{1\hi} + tbl_{1\mi}$ and $tbl_{2\hi} + tbl_{2\mi}$ are multiplied using a double-double multiplication operator yielding to $tables_\hi + tables_\lo = \left( tbl_{1\hi} + tbl_{1\mi} \right) \cdot \left( tbl_{2\hi} + tbl_{2\mi} \right) \cdot \left( 1 + \epsilon \right)$. \item The term \\ $\left( 1 + r_\hi + highPolyWithSquare \right) \cdot \left( 1 + r_\mi \right) =$ \\ $1 + r_\hi + highPolyWithSquare + r_\mi + r_\hi \cdot r_\mi + highPolyWithSquare \cdot r_\mi$ \\ is approximated by neglecting the quadratic terms. First $r_\hi$ and $highPolyWithSquare$ are added together in double precision. Their sum is then added to $r_\hi$ in double precision, too. This yields to the intermediate value $t_9$. The addition with $1$ is not explicited. \item The multiplication $\left( tables_\hi + tables_\lo \right) \cdot \left( 1 + t_9 \right)$ is approximated by $tables_\hi + tables_\lo + tables_\hi \cdot t_9$. The multiplication $tables_\hi \cdot t_9$ is performed in double precision. It produces $t_{10}$. \item The addition $tables_\hi + tables_\lo + t_{10}$ is carried out in double-double precision. Its result $polyTbl_\hi + polyTbl_\mi$ approximates finally $$polyTbl_\hi + polyTbl_\mi = \left( tbl_{1\hi} + tbl_{1\mi} \right) \cdot \left( tbl_{2\hi} + tbl_{2\mi} \right) \cdot \left( 1 + p\left( r_\hi \right) \right) \cdot \left( 1 + r_\mi \right) \cdot \left( 1 + \epsilon \right)$$ for some relative error $\epsilon$. \end{enumerate} The steps explained above are implemented in the code as follows: \begin{lstlisting}[caption={Quick phase reconstruction},firstnumber=1] Mul22(&tablesh,&tablesl,tbl1h,tbl1m,tbl2h,tbl2m); t8 = rm + highPolyWithSquare; t9 = rh + t8; t10 = tablesh * t9; Add12(t11,t12,tablesh,t10); t13 = t12 + tablesl; Add12(polyTblh,polyTblm,t11,t13); \end{lstlisting} The final result for the exponential is $e^x \approx 2^M \cdot \left( polyTbl_\hi + polyTbl_\mi \right)$. On this value, a rounding test would have to be performed. Since gradual underflow is excluded by special case handling, the multiplication by $2^M$ is exact. In consequence, it is possible to do the rounding test on $polyTbl_\hi + polyTbl_\mi$ and to multiply then by $2^M$. This is the way chosen in the given implementation. See section \ref{sec:expfinalround}, page \pageref{sec:expfinalround}, for further details. \subsection{Accurate phase polynomial approximation and reconstruction} In accurate phase, $e^{r_\hi} - 1$ is approximated by a polynomial $p\left( r_\hi \right)$ of degree $7$. It has the following form: $$p\left( r_\hi \right) = r_\hi + \frac{1}{2} \cdot r_\hi^2 + r_\hi^3 \cdot \left( \left( c_{3\hi} + c_{3\lo} \right) + r_\hi \cdot \left( \left( c_{4\hi} + c_{4\lo} \right) + r_\hi \cdot \left( c_5 + r_\hi \cdot \left( c_6 + r_\hi \cdot c_7 \right) \right) \right) \right)$$ Coefficients $c_{3\hi} + c_{3\lo}$ and $c_{4\hi} + c_{4\lo}$ are stored as double-double numbers, coefficients $c_5$ through $c_7$ are stored in double precision. For $r_\hi$ bounded by $\left \vert r_\hi \right \vert \leq 2^{-13}$, the relative approximation error $\epsilon_{\mbox{\tiny approxarghighaccu}} = \frac{p\left( r_\hi \right) - e^{r_\hi} + 1}{e^{r_\hi} - 1}$ is bounded by $\left \vert \epsilon_{\mbox{\tiny approxarghighaccu}} \right \vert \leq 2^{-113}$. For $r_\hi$ such that $\left \vert r_\hi \right \vert \leq 2^{-30}$, $\epsilon_{\mbox{\tiny approxarghighaccu}}$ is bounded by $\left \vert \epsilon_{\mbox{\tiny approxarghighaccu}} \right \vert \leq 2^{-160}$. The polynomial $p\left( r_\hi \right)$ is evaluated as follows: \begin{enumerate} \item The high order terms of $p\left( r_\hi \right)$, $c_5 + r_\hi \cdot \left( c_6 + r_\hi \cdot c_7 \right)$ are evaluated in double precision using Horner's scheme. The result of this evaluation is stored in $highPoly \approx c_5 + r_\hi \cdot \left( c_6 + r_\hi \cdot c_7 \right)$. \item The multiplication $r_\hi \cdot highPoly$ is implemented using an exact operator and yields to a double-double $t_{1\hi} + t_{1\lo}$. The following steps leading to $t_{4\hi} + t_{4\lo} \approx \left( c_{3\hi} + c_{3\lo} \right) + r_\hi \cdot \left( \left( c_{4\hi} + c_{4\lo} \right) + \left( t_{1\hi} + t_{1\lo} \right) \right)$ are implemented using double-double computations and Horner's scheme. \item The sum of the low order terms $r_\hi + \frac{1}{2} \cdot r_\hi^2$, stored in a non-overlapped triple-double $lowPoly_\hi + lowPoly_\mi + lowPoly_\lo$, is computed exactly as follows: first $r_\hi$ is squared exactly using an exact multiplication operator producing $rhSquare_\hi + rhSquare_\lo = r_\hi \cdot r_\hi$. Since for arguments $x$ to the exponential function such that $\left \vert x \right \vert \leq 2^{-55}$ rounding is trivial in all rounding modes, we can suppose that $\left \vert x \right > 2^{-55}$. In consequence, since $x$ is a double precision number, the reduced argument $r_\hi$ is either equal to $0$ or greater in magnitude than $2^{-58}$. So both $rhSquare_\hi$ and $rhSquare_\lo$ are either exactly $0$ or greater in magnitude than $\left( 2^{-58} \right)^2 \cdot 2^{-53} = 2^{-169}$. They are thus never subnormal. Therefore the pairwise multiplication of $rhSquare_\hi + rhSquare_\lo$ by $\frac{1}{2}$ yielding to $rhSquareHalf_\hi + rhSquareHalf_\lo = \frac{1}{2} \cdot r_\hi^2$ is exact. Since $r_\hi$ is such that $\left \vert r_\hi \right \vert \leq 2^{-13}$, $r_\hi + rhSquareHalf_\hi + rhSquareHalf_\lo$ can be considered as a partially overlapped triple-double number. The overlap bound is such that $\left \vert rhSquareHalf_\hi \right \vert \leq 2^{-12} \cdot \left \vert r_\hi \right \vert$ and $\left \vert rhSquareHalf_\lo \right \vert \leq 2^{-53} \cdot \left \vert rhSquareHalf_\hi \right \vert$. Thus it is possible to use the \Renormalize~ sequence \cite{Lauter2005LIP:tripledouble} to obtain a non-overlapped triple-double $lowPoly_\hi + lowPoly_\mi + lowPoly_\lo$ which is exactly equal to $r_\hi + \frac{1}{2} \cdot r_\hi^2$ because the renormalization operator is exact and all preceeding operations have been, too. \item An triple-double approximation to $r_\hi^3$, stored in $rhCube_\hi + rhCube_\mi + rhCube_\lo$ is computed by multiplying $r_\hi$ by the exact $rhSquare_\hi + rhSquare_\lo$ computed in the previous step. For this operation the \MulDT~ sequence is used. \item The approximation of the high order terms of the polynomial, $t_{4\hi} + t_{4\lo}$ is then multiplied by $rhCube_\hi + rhCube_\mi + rhCube_\lo$ using a triple-double multiplication operator. The result of this operation is added to $lowPoly_\hi + lowPoly_\mi + lowPoly_\lo$ in order to obtain a potentially overlapped triple-double $p_\hi + p_\mi + p_\lo$ approximating $p\left( r_\hi \right)$. \end{enumerate} All this steps are implemented by the following code: \begin{lstlisting}[caption={Accurate phase polynomial approximation},firstnumber=1] highPoly = accPolyC5 + rh * (accPolyC6 + rh * accPolyC7); Mul12(&t1h,&t1l,rh,highPoly); Add22(&t2h,&t2l,accPolyC4h,accPolyC4l,t1h,t1l); Mul22(&t3h,&t3l,rh,0,t2h,t2l); Add22(&t4h,&t4l,accPolyC3h,accPolyC3l,t3h,t3l); Mul12(&rhSquareh,&rhSquarel,rh,rh); Mul23(&rhCubeh,&rhCubem,&rhCubel,rh,0,rhSquareh,rhSquarel); rhSquareHalfh = 0.5 * rhSquareh; rhSquareHalfl = 0.5 * rhSquarel; Renormalize3(&lowPolyh,&lowPolym,&lowPolyl,rh,rhSquareHalfh,rhSquareHalfl); Mul233(&highPolyMulth,&highPolyMultm,&highPolyMultl,t4h,t4l,rhCubeh,rhCubem,rhCubel); Add33(&ph,&pm,&pl,lowPolyh,lowPolym,lowPolyl,highPolyMulth,highPolyMultm,highPolyMultl); \end{lstlisting} For reconstructing $e^x$ out of the polynomial approximation of $e^{r_\hi}-1$, $e^{r_\mi}-1$, $e^{r_\lo}-1$ and the table values $tbl_{1\hi} + tbl_{1\mi} + tbl_{1\lo}$ and $tbl_{2\hi} + tbl_{2\mi} + tbl_{2\lo}$ the following term must be approximated: $$e^x \approx 2^M \cdot \left( tbl_{1\hi} + tbl_{1\mi} + tbl_{1\lo} \right) \cdot \left( tbl_{2\hi} + tbl_{2\mi} + tbl_{2\lo} \right) \cdot \left( 1 + \left( p_\hi + p_\mi + p_\lo \right) \right) \cdot \left( 1 + r_\mi \right) \cdot \left( 1 + r_\lo \right)$$ First, the following approximation is possible $$\left( 1 + \left( p_\hi + p_\mi + p_\lo \right) \right) \cdot \left( 1 + r_\mi \right) \cdot \left( 1 + r_\lo \right) \approx 1 + \left( p_\hi + p_\mi + p_\lo + r_\mi + r_\lo + \left( r_\mi + r_\lo \right) \cdot \left( p_\hi + p_\mi \right) \right)$$ First an arithmetical approximation $fullPoly_\hi + fullPoly_\mi + fullPoly_\lo$ to $p_\hi + p_\mi + p_\lo + r_\mi + r_\lo + \left( r_\mi + r_\lo \right) \cdot \left( p_\hi + p_\mi \right)$ is computed as follows: \begin{enumerate} \item By means of an exact, unconditional addition, $p_\hi$ and $p_\mi$, which may be potentially overlapped because of being the higher significant parts of an overlapped triple-double, are renormalized. \item They are then multiplied by the non-overlapping $r_\mi + r_\lo$ using a double-double multiplication operator. The result of this product is added to $r_\mi + r_\lo$ in double-double precision. \item The result of this addition, $q_\hi + q_\lo$, approximates thus $r_\mi + r_\lo + \left( r_\mi + r_\lo \right) \cdot \left( p_\hi + p_\mi \right)$. \item The triple-double addition operator \AddDTT~ allows then for adding $p_\hi + p_\mi + p_\lo$ to $q_\hi + q_\lo$ resulting in $fullPoly_\hi + fullPoly_\mi + fullPoly_\lo$. \end{enumerate} Then $1$ is added to $fullPoly_\hi + fullPoly_\mi + fullPoly_\lo$ by the following code sequence: \begin{lstlisting}[caption={Addition with $1$},firstnumber=1] Add12(polyAddOneh,t5,1,fullPolyh); Add12Cond(polyAddOnem,t6,t5,fullPolym); polyAddOnel = t6 + fullPolyl; \end{lstlisting} Since the \Add~ operator is exact, the round-off error of this adding of $1$ is equal to the round-off error in the last addition $polyAddOne_\lo = t_6 \oplus fullPoly_\lo$. In absolute value, it is always less than $2^{-53} \cdot \left \vert t_6 + fullPoly_\lo \right \vert$. Since $\left \vert r_\hi \right \vert \leq 2^{-12}$, one checks that $\frac{1}{2} < polyAddOne_\hi < 2$. So the relative error of this addition with $1$, $\epsilon_{\mbox{\tiny addOne}}$ is in magnitude less than $2^{-52} \cdot \left \vert t_6 + fullPoly_\lo \right \vert$. This is particularly important when considering high critical precision worst cases, see section \ref{sec:expaccuracy}, page \pageref{sec:expaccuracy}. The result of the polynomial approximation, $$polyWithOne_\hi + polyWithOne_\mi + polyWithOne_\lo \approx e^{r_\hi} \cdot e^{r_\mi} \cdot e^{r_\lo}$$ is then multiplied in two steps first by $tbl_{1\hi} + tbl_{1\mi} + tbl_{2\lo}$ and then by $tbl_{2\hi} + tbl_{2\mi} + tbl_{2\lo}$ using each time the triple-double multiplication operator \MulTT. Remark that these multiplications are exact for arguments $\left \vert x \right \vert \leq 2^{-14}$ because in this case, $k=0$, $i_1 = 0$ and $i_2 = 0$ which implies that $tbl_{1\hi} = 1$, $tbl_{2\hi} = 1$ and $tbl_{i\mi} = 0$ and $tbl_{i\lo} = 0$. In fact machine multiplications by $1$ are always exact. The final product of this multiplications may be overlapped and is therefore renormalized using the \Renormalize~ sequence. This yields to the non-overlapped triple-double $polyTbl_\hi + polyTbl_\mi + polyTbl_\lo$ approximating $\frac{e^x}{2^M}$. All these steps are implemented by the following code sequence: \begin{lstlisting}[caption={Accurate phase reconstruction},firstnumber=1] Add12(phnorm,pmnorm,ph,pm); Mul22(&rmlMultPh,&rmlMultPl,rm,rl,phnorm,pmnorm); Add22(&qh,&ql,rm,rl,rmlMultPh,rmlMultPl); Add233Cond(&fullPolyh,&fullPolym,&fullPolyl,qh,ql,ph,pm,pl); Add12(polyAddOneh,t5,1,fullPolyh); Add12Cond(polyAddOnem,t6,t5,fullPolym); polyAddOnel = t6 + fullPolyl; Mul33(&polyWithTbl1h,&polyWithTbl1m,&polyWithTbl1l,tbl1h,tbl1m,tbl1l,polyAddOneh,polyAddOnem,polyAddOnel); Mul33(&polyWithTablesh,&polyWithTablesm,&polyWithTablesl, tbl2h,tbl2m,tbl2l, polyWithTbl1h,polyWithTbl1m,polyWithTbl1l); Renormalize3(polyTblh,polyTblm,polyTbll,polyWithTablesh,polyWithTablesm,polyWithTablesl); \end{lstlisting} The multiplication of $polyTbl_\hi + polyTbl_\mi + polyTbl_\lo$ by $2^M$ and the final rounding will be discussed in the next section. \section{Final rounding}\label{sec:expfinalround} For both quick and accurate phase, final rounding is simple when the result cannot be underflowed. In this case, the final multiplication of $t_1 \cdot t_2 \cdot e^r$ by $2^M$ only affects the exponent of $t_1 \cdot t_2 \cdot e^r$. So the rounding test and the final rounding (in quick and accurate phase) can be done on $t_1 \cdot t_2 \cdot e^r$ before this value is multiplied by $2^M$. This rounding is a standard \crlibm~ rounding of respectively a double-double or a triple-double. Since $M$ might be as great as $M = 1024$ (whilst $t_1 \cdot t_2 \cdot e^r < 1$ in this case, because overflow in the final result has been filtered out), $2^M$ may not be representable. Nevertheless it is possible not to representate $2^M$ explicitely in a variable and to replace the operation by the following sequence. We suppose that $polyTbl_\hi = \round \left( t_1 \cdot t_2 \cdot e^r + \delta \right)$. \begin{lstlisting}[caption={Final multiplication by $2^M$},firstnumber=1] polyTblhdb.d = polyTblh; polyTblhdb.i[HI] += M << 20; return polyTblhdb.d; \end{lstlisting} If the result might be gradually underflowed but is not completely underflowed (i.e. not equal to $0$ or $0^+$ depending on the rounding mode), the quick phase is not used and the accurate phase is launched in any case. This does not sensibly affect performance. The triple-double result of the accurate phase, \texttt{polyTblh}, \texttt{polyTblm} and \texttt{polyTbll}, where $polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \approx t_1 \cdot t_2 \cdot e^r$, is multiplied by $2^M$ and rounded to double precision as follows: \begin{itemize} \item $polyTbl_\hi$ is multiplied by $2^M$ in two steps: $2^M$ is not representable in double precision but $2^{-1000}$ and $2^{M+1000}$ are. This multiplication generates a subnormal $t_4$, which prevents us from replacing it by an integer sequence manipulating the exponent of the numbers involved. We have $t_4 = \round \left( 2^M \cdot polyTbl_\hi\right) = 2^M polyTbl_\hi + \delta$ with $\left \vert \delta \right \vert \leq \frac{1}{2} \cdot \mUlp\left( \mbox{\small \it denorm} \right) = 2^{-1075}$. \item The obtained value $t_4$ is remultiplied by $2^{-M}$, once again in $2$ steps. This multiplication produces a normal number and is therefore exact: $t_6 = 2^{-M} \cdot \round\left( 2^M \cdot polyTbl_\hi \right) = polyTbl_\hi + 2^{-M} \cdot \delta$. \item Since $\left \vert M \right \vert \leq 1075$ and $\left \vert polyTbl_\hi \right \vert \leq 2$, one checks that $$\frac{1}{2} \cdot polyTbl_\hi \leq t_6 \leq 2 \cdot polyTbl_\hi$$ is verified. So the arithmetical substraction $t_7 = polyTbl_\hi \ominus t_6$ is exact by Sterbenz' lemma and one obtains: $$t_7 = 2^{-M} \cdot \left( 2^M \cdot polyTbl_\hi - \round \left( 2^M \cdot polyTbl_\hi \right) \right)$$ We obtain therefore $$t_4 + 2^M \cdot \left( t_7 + polyTbl_\mi + polyTbl_\lo \right) = 2^M \cdot \left( polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \right)$$ Further, since the triple-double number $polyTbl_\hi + polyTbl_\mi + polyTbl_\lo$ is non-overlapping, we know that $$t_4 \in \left \lbrace r^-, r, r^+\right \rbrace$$ with $r = \round \left( polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \right)$. In addition, since the precision of a denormal is maximally $52$ bits and that of a normal (like $polyTbl_\hi$) is $53$ bits, $t_7$ is either $0$ or greater in magnitude than $polyTbl_\mi + polyTbl_\lo$. If this were not the case, the triple-double would overlap. Thus $2^M \cdot \left( t_7 + polyTbl_\mi + polyTbl_\lo \right)$ corresponds to the part of the high accuracy mantissa that is rounded off when rounding to the subnormal and if $t_7$ is not zero, it contains at least the first bit that is rounded off. \end{itemize} The arithmetical steps mentioned are performed by the following code sequence: \begin{lstlisting}[caption={Underflowed final multiplication and rounding},firstnumber=1] /* Final rounding and multiplication with 2^M We first multiply the highest significant byte by 2^M in two steps and adjust it then depending on the lower significant parts. We cannot multiply directly by 2^M since M is less than -1022. We first multiply by 2^(-1000) and then by 2^(M+1000). */ t3 = polyTblh * twoPowerM1000; /* Form now twoPowerM with adjusted M */ twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M + 2023) << 20; /* Multiply with the rest of M, the result will be denormalized */ t4 = t3 * twoPowerMdb.d; /* For x86, force the compiler to pass through memory for having the right rounding */ t4db.d = t4; /* Do not #if-ify this line, we need the copy */ #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) t4db2.i[HI] = t4db.i[HI]; t4db2.i[LO] = t4db.i[LO]; t4 = t4db2.d; #endif /* Remultiply by 2^(-M) for manipulating the rounding error and the lower significant parts */ M *= -1; twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M + 23) << 20; t5 = t4 * twoPowerMdb.d; t6 = t5 * twoPower1000; t7 = polyTblh - t6; \end{lstlisting} One remarks that on $x86$ platforms, it is necessary to write $t_4$ to memory and to reread it from there in order to to overcome the inexistence of pseudosubnormals in the underlying $80$ bit register format. Depending on the rounding mode, $t_4$ is then adjusted to the correct rounding of \\$2^M \cdot \left( polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \right)$ as follows: \begin{itemize} \item In round-to-nearest mode, the rounding decision when rounding to a subnormal is made at a constant value $\frac{1}{2} \cdot \mUlp\left( \mbox{\small \it denorm}\right) = 2^{-1075}$. Rounding is simple for round-to-nearest when the mantissa does not contain a one following the last mantissa bit of the rounded result. In this case, the rounding downwards and thus equivalent to a truncation. Truncation to different lengths is associative. Omitting $polyTbl_\mi + polyTbl_\lo$ is a truncation. The rounding of $2^M \cdot polyTbl_\hi$ to a subnormal is correct as per the use of a IEEE 754 operation. So $t_4$ already is equal to $\round\left( polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \right)$. If the first bit following the last mantissa bit of the rounded result is a one, two cases must be considered: if the TMD's case is such that the next following mantissa one is contained in the bits of $polyTbl_\hi$ that are rounded of, the rounding $\round \left( 2^M \cdot polyTbl_\hi \right)$ is equivalent to the rounding $\round \left( 2^M \cdot \left( polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \right) \right)$ because both roundings are upwards. So in this case, too, $t_4$ already contains the correct result. In contrast, if the the TMD's case is such that the next following mantissa one (after the first one following the rounded mantissa) is only contained in $polyTbl_\mi + polyTbl_\lo$, the rounding direction of $\round \left( 2^M \cdot polyTbl_\hi \right)$ and $\round \left( 2^M \cdot \left( polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \right) \right)$ may be different. As $t_7$ is the (scaled) correction of the roundoff of $\round \left( 2^M \cdot polyTbl_\hi \right)$ and greater in magnitude than $polyTbl_\mi + polyTbl_\lo$, its sign determines the rounding direction of the rounding $t_4 = \round \left( 2^M \cdot polyTbl_\hi \right)$. The sign of $polyTbl_\mi = \round \left( polyTbl_\hi + polyTbl_\lo \right)$ determines then that of the direction of \\$\round \left( 2^M \cdot \left( polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \right) \right)$ and such whether $t_4$ must be adjusted by $\pm 1 \mUlp$. The algorithm is thus the following: $2^M \cdot t_7$ is compared to $\frac{1}{2} \cdot \mUlp\left( \mbox{\small \it denorm}\right)$ by comparing $t_7$ to $2^{-1075-M}$. This determines whether the rounding is easy and $t_4$ can be returned or whether an adjustment must be made. If the latter is the case, the signs of $t_7$ and $polyTbl_\hi$ are examined and $t_4$ is adjusted. Since $e^x > 0 \mbox{~~} \forall x \in \R$, the adjustment of $t_4$ by $\pm \mUlp$ can be simplified. The code sequence below implements this: \begin{lstlisting}[caption={Rounding adjustment in round-to-nearest},firstnumber=1] /* The rounding decision is made at 1/2 ulp of a denormal, i.e. at 2^(-1075) We construct this number and by comparing with it we get to know whether we are in a difficult rounding case or not. If not we just return the known result. Otherwise we continue with further tests. */ twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M - 52) << 20; if (ABS(t7) != twoPowerMdb.d) return t4; /* If we are here, we are in a difficult rounding case */ /* We have to adjust the result iff the sign of the error on rounding 2^M * polyTblh (which must be an ulp of a denormal) and polyTblm +arith polyTbll is the same which means that the error made was greater than an ulp of an denormal. */ polyTblm = polyTblm + polyTbll; if (t7 > 0.0) { if (polyTblm > 0.0) { t4db.l++; return t4db.d; } else return t4; } else { if (polyTblm < 0.0) { t4db.l--; return t4db.d; } else return t4; } \end{lstlisting} \item In round-upwards mode, the rounding~~ $\roundup \left( polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \right)$ is determined by $\round\left( polyTbl_\hi \right)$ and the rounding rest $2^M \cdot \left( t_7 + polyTbl_\mi + polyTbl_\lo \right)$. If $t_7$ not equal to $0$, it is greater in magnitude than $polyTbl_\mi + polyTbl_\lo$. Thus the rounding direction of the to-nearest rounding $\round\left( polyTbl_\hi \right)$ is downwards if $t_7 + polyTbl_\mi + polyTbl_\lo$ is positive. In this case, an adjustment of $+ 1 \mUlp$ must be made on $t_4$. If $t_7$ is equal to $0$, the rounding $\round\left( polyTbl_\hi \right)$ was errorless and $t_4 = 2^M \cdot polyTbl_\hi$. So we get $$\roundup\left( 2^M \cdot \left( polyTbl_\hi + polyTbl_\mi + polyTbl_\lo \right) \right) = \roundup\left( t_4 + 2^M \cdot \left( polyTbl_\mi + polyTbl_\lo \right) \right)$$ Clearly, $2^M \cdot \left( polyTbl_\mi + polyTbl_\lo \right)$ is less than $\mUlp\left( t_4 \right)$ because $polyTbl_\hi + polyTbl_\mi + polyTbl_\lo$ is non-overlapping. One can show that $$\roundup\left( x + \mu \right) = \roundup\left( x + \nu \right)$$ if $x \in \F$ and $\sgn\left( \mu \right) = \sgn\left( \nu \right)$, $\left \vert \mu \right \vert, \left \vert \nu \right \vert < \mUlp\left( x \right)$ and $\mu, \nu \in \R$ \cite{Lauter2005LIP:tripledouble}. Since the algebraic images of double arguments have been filtered out, it is thus possible to find $\mu \in \R$ such that with $\nu = 2^M \cdot \left( polyTbl_\mi + polyTbl_\lo \right)$ respectively $\nu = \mUlp\left(t_4\right) + 2^M \cdot \left( polyTbl_\mi + polyTbl_\lo \right)$ the following can be verified: $$\roundup \left( t_4 + 2^M \cdot \left( polyTbl_\mi + polyTbl_\lo \right) \right) = \left \lbrace \begin{array}{ll} t_4 & \mbox{ if } polyTbl_\mi + polyTbl_\lo < 0 \\ t_4^+ & \mbox{ otherwise} \end{array} \right.$$ So it suffices to add $t_7$ and $polyTbl_\mi = \round\left( polyTbl_\mi + polyTbl\lo \right)$ together and to check for the sign of this sum. The rounding error of this operation may not affect the sign of its result. If the sign is positive, $+1 \mUlp$ is added to $t_4$. The following code sequence realizes this: \begin{lstlisting}[caption={Rounding adjustment in round-upwards},firstnumber=1] /* The rounding can be decided using the sign of the arithmetical sum of the round-to-nearest-error (i.e. t7) and the lower part(s) of the final result. We add first the lower parts and add the result to the error in t7. We have to keep in mind that everything is scaled by 2^(-M). t8 can never be exactly 0 since we filter out the cases where the image of the function is algebraic and the implementation is exacter than the TMD worst case. */ polyTblm = polyTblm + polyTbll; t8 = t7 + polyTblm; /* Since we are rounding upwards, the round-to-nearest-rounding result in t4 is equal to the final result if the rounding error (i.e. the error plus the lower parts) is negative, i.e. if the rounding-to-nearest was upwards. */ if (t8 < 0.0) return t4; /* If we are here, we must adjust the final result by +1ulp Relying on the fact that the exponential is always positive, we can simplify this adjustment */ t4db.l++; return t4db.d; \end{lstlisting} \item Round-downwards mode is analogous to round-upwards mode with signs inverted. \item Round-towards-zero is equivalent to rounding downwards. \end{itemize} \section{Accuracy bounds}\label{sec:expaccuracy} In this section we give an overview on the error bound computation. The actual error bound proof is implemented using the Gappa tool. An implementation of the exponential function in double precision can be considered to be correctly rounding if the accuracy of the accurate phase is at least $113$ bits for arguments $x$ such that $\left \vert x \right \vert \geq 2^{-30}$ and at least $158$ bits for $2^{-54} \leq \left \vert x \right \vert < 2^{-30}$ -- provided that the rounding test after the quick phase is correct \cite{DinDefLau2004LIP}. In order to give a first error estimate, one can consider \begin{eqnarray*} \mbox{\tt exp(x)} & = & 2^M \cdot tbl_1 \cdot tbl_2 \cdot \left( 1 + p\left( r_\hi \right) \right) \cdot \left( 1 + r_\mi \right) \cdot \left( 1 + r_\lo \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny arith}} \right) \\ & = & 2^M \cdot t_1 \cdot \left( 1 + \epsilon_{\mbox{\tiny tbl1}} \right) \cdot t_2 \left( 1 + \epsilon_{\mbox{\tiny tbl1}} \right) \cdot \\ & & \cdot \left( 1 + \left( e^{r_\hi} - 1 \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny approxhigh}} \right) \right) \cdot \\ & & \cdot \left( 1 + \left( e^{r_\mi} - 1 \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny approxmiddle}} \right) \right) \cdot \\ & & \cdot \left( 1 + \left( e^{r_\lo} - 1 \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny approxlower}} \right) \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny arith}} \right) \\ & = & 2^M \cdot t_1 \cdot t_2 \cdot e^{r_\hi + r_\mi + r_\lo} \cdot \\ & & \cdot \left( 1 + \epsilon_{\mbox{\tiny tbl1}} \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny tbl2}} \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny approxhigh}}^\prime \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny approxmiddle}}^\prime \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny approxlower}}^\prime \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny arith}} \right) \\ & = & 2^M \cdot t_1 \cdot t_2 \cdot e^{\hat{r}} \cdot \\ & & \cdot \left( 1 + \epsilon_{\mbox{\tiny tbl1}} \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny tbl2}} \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny approxhigh}}^\prime \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny approxmiddle}}^\prime \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny approxlower}}^\prime \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny arith}} \right) \cdot \left( 1 + \epsilon_{\mbox{\tiny argred}} \right) \\ & = & e^x \cdot \left( 1 + \epsilon \right) \end{eqnarray*} where $\epsilon_{\mbox{\tiny approxhigh}}^\prime = \epsilon_{\mbox{\tiny approxhigh}} - \frac{\epsilon_{\mbox{\tiny approxhigh}}}{e^{r_\hi}}$, $\epsilon_{\mbox{\tiny approxmiddle}}^\prime = \epsilon_{\mbox{\tiny approxmiddle}} - \frac{\epsilon_{\mbox{\tiny approxmiddle}}}{e^{r_\mi}}$ and $\epsilon_{\mbox{\tiny approxlower}}^\prime = \epsilon_{\mbox{\tiny approxlower}} - \frac{\epsilon_{\mbox{\tiny approxlower}}}{e^{r_\lo}}$. The Gappa proof files integrate all these errors and allow for evaluating the relative arithmetical round-off error $\epsilon_{\mbox{\tiny arith}}$. %TODO: inserer les valeurs obtenues en Gappa pour les deux phases \section{Timings}\label{sec:exptiming} For evaluating the timings of the triple-double based implementation of the exponential function $e^x$, in comparison with other correctly rounded functions. ``{\tt crlibm} portable using {\tt scslib}'' still stands for a logarithm implementation in {\tt crlibm} before the work on triple-double. The values are given in arbitrary units and obtained on a IBM Power 5 processor with gcc 3.3.3 on a Linux Kernel 2.6.5. The timings on other systems are comparable. \begin{center} \begin{tabular}{|l|r|r|} \hline Library & avg time & max time \\ \hline \hline \texttt{MPFR} & 2128 & 4908 \\ \hline \texttt{crlibm} portable using \texttt{scslib} & 44 & 1976 \\ \hline \texttt{crlibm} portable using triple-double & 39 & 258 \\ \hline default \texttt{libm} (IBM's {\tt libultim}) & 34 & 221062 \\ \hline \end{tabular} \end{center} On average, our triple-double based implementation wins about $12\%$ speed-up in comparison with the SCS based implementation. It is however slightly less performant than Ziv's library. Concerning worst case timing, the results are more striking and confirm the general results concering triple-double: the use of triple-double arithmetic instead of the SCS format allows for a speed-up of a factor of about $7.65$. In comparison with IBM's {\tt libultim} a performance gain of a factor $857$ is achieved. The timing difference between average and worst-case is decreased to a factor of about $6.6$. %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/expm1.tex0000644000000000000000000000007113316017127017345 0ustar 00000000000000 Todo. In between, see files expm1-td.\{h,c,mpl,gappa\}. interval-3.2.0/src/crlibm/docs/latex/fig_exp/reconstruction.fig0000644000000000000000000005667113316017127023003 0ustar 00000000000000#FIG 3.2 Portrait Center Metric A4 24.00 Single -2 1200 2 0 32 #ffffff 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 12558 69 747 542 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 12558 69 747 542 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 10393 2362 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 10393 2362 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 14173 7086 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 14173 7086 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 17952 8503 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 17952 8503 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 14173 1417 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 14173 1417 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 14173 -5669 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 14173 -5669 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 17952 2834 944 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 17952 2834 944 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 17952 0 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 17952 0 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 21732 -2834 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 21732 -2834 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 19370 -1417 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 19370 -1417 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 22204 9921 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 22204 9921 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 25511 -1417 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 25511 -1417 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 21732 -9921 944 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 21732 -9921 944 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 25511 -7086 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 25511 -7086 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 26456 -4724 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 26456 -4724 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 27401 -944 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 27401 -944 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 31181 472 944 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 31181 472 944 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 34960 -4724 944 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 34960 -4724 944 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 38740 -944 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 38740 -944 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 38740 -7559 944 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 38740 -7559 944 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 42519 -3307 472 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 42519 -3307 472 472 0 0 0 0 1 1 0 3 32 32 0 0 20 31.496 1 0.0000 46299 -5669 944 472 0 0 0 0 1 1 0 3 0 -1 0 0 -1 31.496 1 0.0000 46299 -5669 944 472 0 0 0 0 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 10059 2028 10727 2696 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 10059 2696 10727 2028 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 9448 944 10393 944 10393 1889 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 9448 3779 10393 3779 10393 2834 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 11338 1417 13228 1417 13228 2362 11338 2362 11338 1417 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 11338 1417 13228 1417 13228 2362 11338 2362 11338 1417 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 13839 6752 14507 7420 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 13839 7420 14507 6752 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 13228 1889 13228 2362 14173 2362 14173 6614 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 13228 8031 14173 8031 14173 7559 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 10866 2362 11338 2362 11338 1889 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 15118 6141 17007 6141 17007 7086 15118 7086 15118 6141 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 15118 6141 17007 6141 17007 7086 15118 7086 15118 6141 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 14645 7086 15118 7086 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 17618 8169 18286 8838 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 17618 8838 18286 8169 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 17007 7086 17952 7086 17952 8031 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 17007 9921 17952 9921 17952 8976 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 19370 7559 21259 7559 21259 8503 19370 8503 19370 7559 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 19370 7559 21259 7559 21259 8503 19370 8503 19370 7559 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 13839 1083 14507 1751 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 13839 1751 14507 1083 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 14173 1889 14173 2362 13228 2362 13228 1889 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 13306 69 13306 0 14173 0 14173 944 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 15118 472 17007 472 17007 1417 15118 1417 15118 472 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 15118 472 17007 472 17007 1417 15118 1417 15118 472 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 14645 1417 15118 1417 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 13839 -6003 14507 -5335 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 13839 -5335 14507 -6003 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 13228 -7086 14173 -7086 14173 -6141 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 13228 -4251 14173 -4251 14173 -5196 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 18897 -6614 20787 -6614 20787 -5669 18897 -5669 18897 -6614 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 18897 -6614 20787 -6614 20787 -5669 18897 -5669 18897 -6614 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 14645 -5669 18897 -5669 18897 -6141 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 17007 4251 17284 4251 17284 3168 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 17007 1417 17284 1417 17284 2500 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 18897 472 20787 472 20787 1417 18897 1417 18897 472 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 18897 472 20787 472 20787 1417 18897 1417 18897 472 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 18897 3307 20787 3307 20787 4251 18897 4251 18897 3307 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 18897 3307 20787 3307 20787 4251 18897 4251 18897 3307 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 18897 1417 18620 1417 18620 2500 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 18897 4251 18620 4251 18620 3168 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 17952 -472 17952 472 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 17480 0 18425 0 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 17007 -1889 17007 -1417 17952 -1417 17952 -472 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 17007 1417 17952 1417 17952 472 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 17007 -4724 17007 -4251 19370 -4251 19370 -1889 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 18425 0 19370 0 19370 -944 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 21732 -3307 21732 -2362 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 21259 -2834 22204 -2834 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 20787 -6141 20787 -5669 21732 -5669 21732 -3307 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 19842 -1417 21732 -1417 21732 -2362 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 19036 -1751 19704 -1083 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 19036 -1083 19704 -1751 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 22677 -3779 24566 -3779 24566 -2834 22677 -2834 22677 -3779 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 22677 -3779 24566 -3779 24566 -2834 22677 -2834 22677 -3779 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 22204 -2834 22677 -2834 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 21870 9587 22538 10255 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 21870 10255 22538 9587 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 23149 8976 25039 8976 25039 9921 23149 9921 23149 8976 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 23149 8976 25039 8976 25039 9921 23149 9921 23149 8976 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 21259 8503 22204 8503 22204 9448 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 21259 11338 22204 11338 22204 10393 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 22677 9921 23149 9921 23149 9448 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 25511 -1889 25511 -944 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 25039 -1417 25984 -1417 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 24566 -2834 25511 -2834 25511 -1889 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 20787 1417 25511 1417 25511 -944 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 20787 -11338 21064 -11338 21064 -10255 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 20787 -8976 20787 -8503 21064 -8503 21064 -9587 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 22677 -12283 24566 -12283 24566 -11338 22677 -11338 22677 -12283 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 22677 -12283 24566 -12283 24566 -11338 22677 -11338 22677 -12283 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 22677 -9448 24566 -9448 24566 -8503 22677 -8503 22677 -9448 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 22677 -9448 24566 -9448 24566 -8503 22677 -8503 22677 -9448 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 22677 -11338 22400 -11338 22400 -10255 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 22677 -8976 22677 -8503 22400 -8503 22400 -9587 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 25511 -7559 25511 -6614 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 25039 -7086 25984 -7086 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 24566 -8976 24566 -8503 25511 -8503 25511 -6614 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 24566 -6141 24566 -5669 25511 -5669 25511 -7559 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 26456 -5196 26456 -4251 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 25984 -4724 26929 -4724 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 25984 -7086 26456 -7086 26456 -5196 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 26456 -4251 26456 -1417 25984 -1417 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 27401 -1417 27401 -472 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 26929 -944 27874 -944 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 25039 9921 27401 9921 27401 -472 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 26929 -4724 27401 -4724 27401 -1417 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 28346 -1889 30236 -1889 30236 -944 28346 -944 28346 -1889 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 28346 -1889 30236 -1889 30236 -944 28346 -944 28346 -1889 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 27874 -944 27874 -911 28346 -911 28346 -1417 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 30236 -1417 30236 -944 30512 -944 30512 138 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 20787 4251 30512 4251 30512 806 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 32125 -1889 34015 -1889 34015 -944 32125 -944 32125 -1889 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 32125 -1889 34015 -1889 34015 -944 32125 -944 32125 -1889 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 32125 944 34015 944 34015 1889 32125 1889 32125 944 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 32125 944 34015 944 34015 1889 32125 1889 32125 944 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 32125 -944 31849 -944 31849 138 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 32125 1417 32125 1889 31849 1889 31849 806 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 35905 -7086 37795 -7086 37795 -6141 35905 -6141 35905 -7086 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 35905 -7086 37795 -7086 37795 -6141 35905 -6141 35905 -7086 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 35905 -4251 37795 -4251 37795 -3307 35905 -3307 35905 -4251 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 35905 -4251 37795 -4251 37795 -3307 35905 -3307 35905 -4251 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 35905 -6614 35905 -6141 35628 -6141 35628 -5058 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 35905 -3307 35628 -3307 35628 -4390 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 34015 -1417 34015 -944 34292 -944 34292 -4390 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 24566 -11338 34292 -11338 34292 -5058 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 38740 -1417 38740 -472 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 38267 -944 39212 -944 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 34015 1417 34015 1889 38740 1889 38740 -472 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 37795 -3307 38740 -3307 38740 -1417 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 39685 -1889 41574 -1889 41574 -944 39685 -944 39685 -1889 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 39685 -1889 41574 -1889 41574 -944 39685 -944 39685 -1889 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 39212 -944 39685 -944 39685 -1417 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 39685 -9921 41574 -9921 41574 -8976 39685 -8976 39685 -9921 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 39685 -9921 41574 -9921 41574 -8976 39685 -8976 39685 -9921 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 39685 -7086 41574 -7086 41574 -6141 39685 -6141 39685 -7086 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 39685 -7086 41574 -7086 41574 -6141 39685 -6141 39685 -7086 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 39685 -8976 39408 -8976 39408 -7893 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 39685 -6614 39685 -6141 39408 -6141 39408 -7224 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 41574 -6614 41580 -6120 42520 -6122 42519 -3779 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 37795 -8976 38072 -8976 38072 -7893 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 37795 -6614 37795 -6141 38072 -6141 38072 -7224 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 42519 -3779 42519 -2834 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 42047 -3307 42992 -3307 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 41574 -1417 41574 -944 42519 -944 42519 -2834 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 43464 -4251 45354 -4251 45354 -3307 43464 -3307 43464 -4251 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 43464 -4251 45354 -4251 45354 -3307 43464 -3307 43464 -4251 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 42992 -3307 43464 -3307 43464 -3779 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 47244 -8031 49133 -8031 49133 -7086 47244 -7086 47244 -8031 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 47244 -8031 49133 -8031 49133 -7086 47244 -7086 47244 -8031 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 47244 -7559 47244 -7086 46967 -7086 46967 -6003 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 47244 -4251 46967 -4251 46967 -5335 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 3 41574 -8976 45631 -8976 45631 -6003 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 4 45354 -3779 45354 -3307 45631 -3307 45631 -5335 2 1 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 2 19370 8503 18425 8503 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 11340 -7110 13230 -7110 13230 -6165 11340 -6165 11340 -7110 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 47244 -5196 49133 -5196 49133 -4251 47244 -4251 47244 -5196 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 47244 -5196 49133 -5196 49133 -4251 47244 -4251 47244 -5196 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 15120 -1440 17010 -1440 17010 -495 15120 -495 15120 -1440 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 11340 -4275 13230 -4275 13230 -3330 11340 -3330 11340 -4275 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 15120 -4275 17010 -4275 17010 -3330 15120 -3330 15120 -4275 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 15120 1395 17010 1395 17010 2340 15120 2340 15120 1395 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 11340 2340 13230 2340 13230 3285 11340 3285 11340 2340 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 15120 4230 17010 4230 17010 5175 15120 5175 15120 4230 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 7560 945 9450 945 9450 1890 7560 1890 7560 945 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 7560 3780 9450 3780 9450 4725 7560 4725 7560 3780 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 11340 8010 13230 8010 13230 8955 11340 8955 11340 8010 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 15120 7065 17010 7065 17010 8010 15120 8010 15120 7065 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 15120 9900 17010 9900 17010 10845 15120 10845 15120 9900 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 19372 11340 21240 11340 21240 12262 19372 12262 19372 11340 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 19372 8505 21240 8505 21240 9429 19372 9429 19372 8505 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 23130 9900 25020 9900 25020 10845 23130 10845 23130 9900 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 18900 4230 20790 4230 20790 5175 18900 5175 18900 4230 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 18900 1395 20790 1395 20790 2340 18900 2340 18900 1395 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 18900 -5670 20790 -5670 20790 -4725 18900 -4725 18900 -5670 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 22680 -5670 24570 -5670 24570 -4725 22680 -4725 22680 -5670 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 22680 -2835 24570 -2835 24570 -1890 22680 -1890 22680 -2835 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 18900 -8505 20790 -8505 20790 -7560 18900 -7560 18900 -8505 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 22680 -8505 24570 -8505 24570 -7560 22680 -7560 22680 -8505 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 22680 -11340 24570 -11340 24570 -10395 22680 -10395 22680 -11340 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 18900 -11340 20790 -11340 20790 -10395 18900 -10395 18900 -11340 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 28350 -945 30240 -945 30240 0 28350 0 28350 -945 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 32130 -945 34020 -945 34020 0 32130 0 32130 -945 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 32130 1890 34020 1890 34020 2835 32130 2835 32130 1890 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 35910 -3330 37800 -3330 37800 -2385 35910 -2385 35910 -3330 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 39690 -945 41580 -945 41580 0 39690 0 39690 -945 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 39690 -6165 41580 -6165 41580 -5220 39690 -5220 39690 -6165 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 39690 -9000 41580 -9000 41580 -8055 39690 -8055 39690 -9000 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 35910 -6165 37800 -6165 37800 -5220 35910 -5220 35910 -6165 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 35910 -9000 37800 -9000 37800 -8055 35910 -8055 35910 -9000 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 43470 -3330 45360 -3330 45360 -2385 43470 -2385 43470 -3330 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 47250 -4275 49140 -4275 49140 -3330 47250 -3330 47250 -4275 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 47250 -7110 49140 -7110 49140 -6165 47250 -6165 47250 -7110 2 3 0 3 32 32 0 -1 20 31.496 0 0 0 0 0 5 39909 8709 41798 8709 41798 9654 39909 9654 39909 8709 2 3 0 3 0 0 0 0 -1 31.496 0 0 0 0 0 5 39909 8709 41798 8709 41798 9654 39909 9654 39909 8709 2 2 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 39915 9630 41805 9630 41805 10575 39915 10575 39915 9630 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 7560 0 9450 0 9450 945 7560 945 7560 0 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 7560 2835 9450 2835 9450 3780 7560 3780 7560 2835 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 15120 -2385 17010 -2385 17010 -1440 15120 -1440 15120 -2385 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 11340 7065 13230 7065 13230 8010 11340 8010 11340 7065 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 11340 -5220 13230 -5220 13230 -4275 11340 -4275 11340 -5220 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 18900 -12285 20790 -12285 20790 -11340 18900 -11340 18900 -12285 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 18900 -9450 20790 -9450 20790 -8505 18900 -8505 18900 -9450 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 11340 -8055 13230 -8055 13230 -7110 11340 -7110 11340 -8055 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 15120 -5220 17010 -5220 17010 -4275 15120 -4275 15120 -5220 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 15120 3285 17010 3285 17010 4230 15120 4230 15120 3285 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 15120 8955 17010 8955 17010 9900 15120 9900 15120 8955 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 19350 10395 21240 10395 21240 11340 19350 11340 19350 10395 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 35910 -9945 37800 -9945 37800 -9000 35910 -9000 35910 -9945 2 2 0 3 0 3 50 -1 20 0.000 0 0 -1 0 0 5 22680 -6615 24570 -6615 24570 -5670 22680 -5670 22680 -6615 4 1 0 0 0 12 23 0.0000 4 270 630 12558 173 1/2\001 4 1 0 0 0 2 28 0.0000 4 375 990 8503 3307 rp_hi\001 4 1 0 0 0 2 28 0.0000 4 375 990 8503 472 rp_hi\001 4 1 0 0 0 2 28 0.0000 4 285 510 12283 1889 R1\001 4 1 0 0 0 2 28 0.0000 4 375 990 12283 7559 rp_hi\001 4 1 0 0 0 2 28 0.0000 4 375 1170 16062 6614 crp_hi\001 4 1 0 0 0 2 28 0.0000 4 330 645 16062 9448 P_r\001 4 1 0 0 0 2 28 0.0000 4 285 510 20314 8031 R2\001 4 1 0 0 0 2 28 0.0000 4 285 510 16062 944 R1\001 4 1 0 0 0 2 28 0.0000 4 330 960 12283 -7559 ex_hi\001 4 1 0 0 0 2 28 0.0000 4 375 960 12283 -4724 rp_lo\001 4 1 0 0 0 2 28 0.0000 4 285 510 19842 -6141 R4\001 4 1 0 0 0 2 28 0.0000 4 330 960 16062 3779 ex_hi\001 4 1 0 0 0 12 20 0.0000 4 180 990 17952 2834 Dekker\001 4 1 0 0 0 2 28 0.0000 4 330 1050 19842 944 R5_lo\001 4 1 0 0 0 2 28 0.0000 4 330 1080 19842 3779 R5_hi\001 4 1 0 0 0 2 28 0.0000 4 375 990 16062 -1889 rp_hi\001 4 1 0 0 0 2 28 0.0000 4 330 930 16062 -4724 ex_lo\001 4 1 0 0 0 2 28 0.0000 4 285 510 23622 -3307 R6\001 4 1 0 0 0 2 28 0.0000 4 330 960 20314 10866 ex_hi\001 4 1 0 0 0 2 28 0.0000 4 285 510 24094 9448 R7\001 4 1 0 0 0 2 28 0.0000 4 375 990 19842 -11811 rp_hi\001 4 1 0 0 0 2 28 0.0000 4 330 960 19842 -8976 ex_hi\001 4 1 0 0 0 12 20 0.0000 4 180 990 21732 -9921 Dekker\001 4 1 0 0 0 2 28 0.0000 4 330 1050 23622 -11811 R3_lo\001 4 1 0 0 0 2 28 0.0000 4 330 1050 23622 -8976 R3_lo\001 4 1 0 0 0 2 28 0.0000 4 330 930 23622 -6141 ex_lo\001 4 1 0 0 0 2 28 0.0000 4 285 510 29291 -1417 R7\001 4 1 0 0 0 12 20 0.0000 4 180 1320 31181 472 Fast2Sum\001 4 1 0 0 0 2 28 0.0000 4 285 510 33070 -1417 R9\001 4 1 0 0 0 2 28 0.0000 4 285 510 33070 1417 R8\001 4 1 0 0 0 12 20 0.0000 4 180 1320 34960 -4724 Fast2Sum\001 4 1 0 0 0 2 28 0.0000 4 285 720 36850 -6614 R10\001 4 1 0 0 0 2 28 0.0000 4 360 720 36850 -3779 tmp\001 4 1 0 0 0 2 28 0.0000 4 285 510 40629 -1417 R8\001 4 1 0 0 0 2 28 0.0000 4 330 960 36850 -9448 ex_hi\001 4 1 0 0 0 12 20 0.0000 4 180 1320 38740 -7559 Fast2Sum\001 4 1 0 0 0 2 28 0.0000 4 285 720 40629 -9448 R11\001 4 1 0 0 0 2 28 0.0000 4 360 720 40629 -6614 tmp\001 4 1 0 0 0 2 28 0.0000 4 285 510 44409 -3779 R8\001 4 1 0 0 0 12 20 0.0000 4 180 1320 46299 -5669 Fast2Sum\001 4 1 0 0 0 2 28 0.0000 4 285 720 48188 -7559 R11\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 23490 10305 $2^{-30}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 11745 -6570 $2^{-1}$\001 4 1 0 0 0 2 28 0.0000 4 285 510 48188 -4724 R8\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 11655 -3690 $2^{-63}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 15480 -3690 $2^{-55}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 15570 -900 $2^{-9}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 11790 2925 $2^{-9}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 15525 1935 $2^{-19}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 15570 4815 $2^{-1}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 7965 1440 $2^{-9}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 7965 4320 $2^{-9}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 11745 8595 $2^{-9}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 15525 10440 $2^{-2}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 15525 7560 $2^{-27}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 19755 11880 $2^{-1}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 19710 9045 $2^{-29}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 19260 1935 $2^{-20}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 19260 4815 $2^{-74}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 19215 -5130 $2^{-64}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 22995 -5130 $2^{-55}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 23040 -2295 $2^{-62}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 19260 -10800 $2^{-9}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 23085 -10800 $2^{-10}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 19305 -7965 $2^{-1}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 23040 -7965 $2^{-64}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 28665 -405 $2^{-29}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 32445 -405 $2^{-19}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 32490 2430 $2^{-73}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 40045 -5618 $2^{-53}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 36315 -8415 $2^{-1}$\001 4 0 0 0 -1 0 20 0.0000 2 270 945 40185 -8460 $2^{0}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 36360 -5580 $2^{-9}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 36270 -2790 $2^{-63}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 40050 -405 $2^{-62}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 43785 -2745 $2^{-53}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1170 47565 -3690 $2^{-53}$\001 4 0 0 0 -1 0 20 0.0000 2 270 1035 47610 -6570 $2^{-1}$\001 4 1 0 0 0 2 28 0.0000 4 285 300 40860 9315 A\001 4 1 0 0 0 2 28 0.0000 4 300 1965 43020 9315 Variable A\001 4 1 0 0 -1 0 20 0.0000 2 240 765 40860 10215 $max$\001 4 0 0 0 -1 0 20 0.0000 2 270 1620 42120 10260 $|A| \\leq max$\001 interval-3.2.0/src/crlibm/docs/latex/fig_exp/reconstruction.pstex0000644000000000000000000007071013316017127023367 0ustar 00000000000000%!PS-Adobe-2.0 EPSF-2.0 %%Title: /home/ddefour/ens/Personnel/these/fig_chap4/reconstruction.fig %%Creator: fig2dev Version 3.2 Patchlevel 4 %%CreationDate: Tue Jun 24 14:20:21 2003 %%For: ddefour@pecheresse (David Defour) %%BoundingBox: 0 0 630 373 %%Magnification: 0.2400 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def /col32 {0.996 0.996 0.996 srgb} bind def end save newpath 0 373 moveto 0 0 lineto 630 0 lineto 630 373 lineto closepath clip newpath -113.8 185.9 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /reencdict 12 dict def /ReEncode { reencdict begin /newcodesandnames exch def /newfontname exch def /basefontname exch def /basefontdict basefontname findfont def /newfont basefontdict maxlength dict def basefontdict { exch dup /FID ne { dup /Encoding eq { exch dup length array copy newfont 3 1 roll put } { exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall newfont /FontName newfontname put newcodesandnames aload pop 128 1 255 { newfont /Encoding get exch /.notdef put } for newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat newfontname newfont definefont pop end } def /isovec [ 8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde 8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis 8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron 8#220 /dotlessi 8#230 /oe 8#231 /OE 8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling 8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis 8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot 8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus 8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph 8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine 8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf 8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute 8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring 8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute 8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute 8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve 8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply 8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex 8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave 8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring 8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute 8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute 8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve 8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide 8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex 8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def /Courier /Courier-iso isovec ReEncode /Times-Bold /Times-Bold-iso isovec ReEncode /Times-Roman /Times-Roman-iso isovec ReEncode /DrawEllipse { /endangle exch def /startangle exch def /yrad exch def /xrad exch def /y exch def /x exch def /savematrix mtrx currentmatrix def x y tr xrad yrad sc 0 0 1 startangle endangle arc closepath savematrix setmatrix } def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.01512 0.01512 sc % % Fig objects follow % % % here starts figure with depth 50 % Polyline 30.000 slw n 11340 -7110 m 13230 -7110 l 13230 -6165 l 11340 -6165 l cp gs col0 s gr % Polyline n 15120 -1440 m 17010 -1440 l 17010 -495 l 15120 -495 l cp gs col0 s gr % Polyline n 11340 -4275 m 13230 -4275 l 13230 -3330 l 11340 -3330 l cp gs col0 s gr % Polyline n 15120 -4275 m 17010 -4275 l 17010 -3330 l 15120 -3330 l cp gs col0 s gr % Polyline n 15120 1395 m 17010 1395 l 17010 2340 l 15120 2340 l cp gs col0 s gr % Polyline n 11340 2340 m 13230 2340 l 13230 3285 l 11340 3285 l cp gs col0 s gr % Polyline n 15120 4230 m 17010 4230 l 17010 5175 l 15120 5175 l cp gs col0 s gr % Polyline n 7560 945 m 9450 945 l 9450 1890 l 7560 1890 l cp gs col0 s gr % Polyline n 7560 3780 m 9450 3780 l 9450 4725 l 7560 4725 l cp gs col0 s gr % Polyline n 11340 8010 m 13230 8010 l 13230 8955 l 11340 8955 l cp gs col0 s gr % Polyline n 15120 7065 m 17010 7065 l 17010 8010 l 15120 8010 l cp gs col0 s gr % Polyline n 15120 9900 m 17010 9900 l 17010 10845 l 15120 10845 l cp gs col0 s gr % Polyline n 19372 11340 m 21240 11340 l 21240 12262 l 19372 12262 l cp gs col0 s gr % Polyline n 19372 8505 m 21240 8505 l 21240 9429 l 19372 9429 l cp gs col0 s gr % Polyline n 23130 9900 m 25020 9900 l 25020 10845 l 23130 10845 l cp gs col0 s gr % Polyline n 18900 4230 m 20790 4230 l 20790 5175 l 18900 5175 l cp gs col0 s gr % Polyline n 18900 1395 m 20790 1395 l 20790 2340 l 18900 2340 l cp gs col0 s gr % Polyline n 18900 -5670 m 20790 -5670 l 20790 -4725 l 18900 -4725 l cp gs col0 s gr % Polyline n 22680 -5670 m 24570 -5670 l 24570 -4725 l 22680 -4725 l cp gs col0 s gr % Polyline n 22680 -2835 m 24570 -2835 l 24570 -1890 l 22680 -1890 l cp gs col0 s gr % Polyline n 18900 -8505 m 20790 -8505 l 20790 -7560 l 18900 -7560 l cp gs col0 s gr % Polyline n 22680 -8505 m 24570 -8505 l 24570 -7560 l 22680 -7560 l cp gs col0 s gr % Polyline n 22680 -11340 m 24570 -11340 l 24570 -10395 l 22680 -10395 l cp gs col0 s gr % Polyline n 18900 -11340 m 20790 -11340 l 20790 -10395 l 18900 -10395 l cp gs col0 s gr % Polyline n 28350 -945 m 30240 -945 l 30240 0 l 28350 0 l cp gs col0 s gr % Polyline n 32130 -945 m 34020 -945 l 34020 0 l 32130 0 l cp gs col0 s gr % Polyline n 32130 1890 m 34020 1890 l 34020 2835 l 32130 2835 l cp gs col0 s gr % Polyline n 35910 -3330 m 37800 -3330 l 37800 -2385 l 35910 -2385 l cp gs col0 s gr % Polyline n 39690 -945 m 41580 -945 l 41580 0 l 39690 0 l cp gs col0 s gr % Polyline n 39690 -6165 m 41580 -6165 l 41580 -5220 l 39690 -5220 l cp gs col0 s gr % Polyline n 39690 -9000 m 41580 -9000 l 41580 -8055 l 39690 -8055 l cp gs col0 s gr % Polyline n 35910 -6165 m 37800 -6165 l 37800 -5220 l 35910 -5220 l cp gs col0 s gr % Polyline n 35910 -9000 m 37800 -9000 l 37800 -8055 l 35910 -8055 l cp gs col0 s gr % Polyline n 43470 -3330 m 45360 -3330 l 45360 -2385 l 43470 -2385 l cp gs col0 s gr % Polyline n 47250 -4275 m 49140 -4275 l 49140 -3330 l 47250 -3330 l cp gs col0 s gr % Polyline n 47250 -7110 m 49140 -7110 l 49140 -6165 l 47250 -6165 l cp gs col0 s gr % Polyline n 39915 9630 m 41805 9630 l 41805 10575 l 39915 10575 l cp gs col0 s gr % Polyline n 7560 0 m 9450 0 l 9450 945 l 7560 945 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 7560 2835 m 9450 2835 l 9450 3780 l 7560 3780 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 15120 -2385 m 17010 -2385 l 17010 -1440 l 15120 -1440 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 11340 7065 m 13230 7065 l 13230 8010 l 11340 8010 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 11340 -5220 m 13230 -5220 l 13230 -4275 l 11340 -4275 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 18900 -12285 m 20790 -12285 l 20790 -11340 l 18900 -11340 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 18900 -9450 m 20790 -9450 l 20790 -8505 l 18900 -8505 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 11340 -8055 m 13230 -8055 l 13230 -7110 l 11340 -7110 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 15120 -5220 m 17010 -5220 l 17010 -4275 l 15120 -4275 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 15120 3285 m 17010 3285 l 17010 4230 l 15120 4230 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 15120 8955 m 17010 8955 l 17010 9900 l 15120 9900 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 19350 10395 m 21240 10395 l 21240 11340 l 19350 11340 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 35910 -9945 m 37800 -9945 l 37800 -9000 l 35910 -9000 l cp gs col3 1.00 shd ef gr gs col0 s gr % Polyline n 22680 -6615 m 24570 -6615 l 24570 -5670 l 22680 -5670 l cp gs col3 1.00 shd ef gr gs col0 s gr % here ends figure; % % here starts figure with depth 0 % Ellipse 30.000 slw n 12558 69 747 542 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 12558 69 747 542 0 360 DrawEllipse gs col0 s gr % Ellipse n 10393 2362 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 10393 2362 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 14173 7086 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 14173 7086 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 17952 8503 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 17952 8503 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 14173 1417 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 14173 1417 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 14173 -5669 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 14173 -5669 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 17952 2834 944 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 17952 2834 944 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 17952 0 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 17952 0 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 21732 -2834 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 21732 -2834 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 19370 -1417 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 19370 -1417 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 22204 9921 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 22204 9921 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 25511 -1417 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 25511 -1417 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 21732 -9921 944 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 21732 -9921 944 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 25511 -7086 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 25511 -7086 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 26456 -4724 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 26456 -4724 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 27401 -944 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 27401 -944 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 31181 472 944 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 31181 472 944 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 34960 -4724 944 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 34960 -4724 944 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 38740 -944 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 38740 -944 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 38740 -7559 944 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 38740 -7559 944 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 42519 -3307 472 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 42519 -3307 472 472 0 360 DrawEllipse gs col0 s gr % Ellipse n 46299 -5669 944 472 0 360 DrawEllipse gs col32 1.00 shd ef gr gs col32 s gr % Ellipse n 46299 -5669 944 472 0 360 DrawEllipse gs col0 s gr % Polyline n 10059 2028 m 10727 2696 l gs col0 s gr % Polyline n 10059 2696 m 10727 2028 l gs col0 s gr % Polyline n 9448 944 m 10393 944 l 10393 1889 l gs col0 s gr % Polyline n 9448 3779 m 10393 3779 l 10393 2834 l gs col0 s gr % Polyline n 11338 1417 m 13228 1417 l 13228 2362 l 11338 2362 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 11338 1417 m 13228 1417 l 13228 2362 l 11338 2362 l cp gs col0 s gr % Polyline n 13839 6752 m 14507 7420 l gs col0 s gr % Polyline n 13839 7420 m 14507 6752 l gs col0 s gr % Polyline n 13228 1889 m 13228 2362 l 14173 2362 l 14173 6614 l gs col0 s gr % Polyline n 13228 8031 m 14173 8031 l 14173 7559 l gs col0 s gr % Polyline n 10866 2362 m 11338 2362 l 11338 1889 l gs col0 s gr % Polyline n 15118 6141 m 17007 6141 l 17007 7086 l 15118 7086 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 15118 6141 m 17007 6141 l 17007 7086 l 15118 7086 l cp gs col0 s gr % Polyline n 14645 7086 m 15118 7086 l gs col0 s gr % Polyline n 17618 8169 m 18286 8838 l gs col0 s gr % Polyline n 17618 8838 m 18286 8169 l gs col0 s gr % Polyline n 17007 7086 m 17952 7086 l 17952 8031 l gs col0 s gr % Polyline n 17007 9921 m 17952 9921 l 17952 8976 l gs col0 s gr % Polyline n 19370 7559 m 21259 7559 l 21259 8503 l 19370 8503 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 19370 7559 m 21259 7559 l 21259 8503 l 19370 8503 l cp gs col0 s gr % Polyline n 13839 1083 m 14507 1751 l gs col0 s gr % Polyline n 13839 1751 m 14507 1083 l gs col0 s gr % Polyline n 14173 1889 m 14173 2362 l 13228 2362 l 13228 1889 l gs col0 s gr % Polyline n 13306 69 m 13306 0 l 14173 0 l 14173 944 l gs col0 s gr % Polyline n 15118 472 m 17007 472 l 17007 1417 l 15118 1417 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 15118 472 m 17007 472 l 17007 1417 l 15118 1417 l cp gs col0 s gr % Polyline n 14645 1417 m 15118 1417 l gs col0 s gr % Polyline n 13839 -6003 m 14507 -5335 l gs col0 s gr % Polyline n 13839 -5335 m 14507 -6003 l gs col0 s gr % Polyline n 13228 -7086 m 14173 -7086 l 14173 -6141 l gs col0 s gr % Polyline n 13228 -4251 m 14173 -4251 l 14173 -5196 l gs col0 s gr % Polyline n 18897 -6614 m 20787 -6614 l 20787 -5669 l 18897 -5669 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 18897 -6614 m 20787 -6614 l 20787 -5669 l 18897 -5669 l cp gs col0 s gr % Polyline n 14645 -5669 m 18897 -5669 l 18897 -6141 l gs col0 s gr % Polyline n 17007 4251 m 17284 4251 l 17284 3168 l gs col0 s gr % Polyline n 17007 1417 m 17284 1417 l 17284 2500 l gs col0 s gr % Polyline n 18897 472 m 20787 472 l 20787 1417 l 18897 1417 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 18897 472 m 20787 472 l 20787 1417 l 18897 1417 l cp gs col0 s gr % Polyline n 18897 3307 m 20787 3307 l 20787 4251 l 18897 4251 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 18897 3307 m 20787 3307 l 20787 4251 l 18897 4251 l cp gs col0 s gr % Polyline n 18897 1417 m 18620 1417 l 18620 2500 l gs col0 s gr % Polyline n 18897 4251 m 18620 4251 l 18620 3168 l gs col0 s gr % Polyline n 17952 -472 m 17952 472 l gs col0 s gr % Polyline n 17480 0 m 18425 0 l gs col0 s gr % Polyline n 17007 -1889 m 17007 -1417 l 17952 -1417 l 17952 -472 l gs col0 s gr % Polyline n 17007 1417 m 17952 1417 l 17952 472 l gs col0 s gr % Polyline n 17007 -4724 m 17007 -4251 l 19370 -4251 l 19370 -1889 l gs col0 s gr % Polyline n 18425 0 m 19370 0 l 19370 -944 l gs col0 s gr % Polyline n 21732 -3307 m 21732 -2362 l gs col0 s gr % Polyline n 21259 -2834 m 22204 -2834 l gs col0 s gr % Polyline n 20787 -6141 m 20787 -5669 l 21732 -5669 l 21732 -3307 l gs col0 s gr % Polyline n 19842 -1417 m 21732 -1417 l 21732 -2362 l gs col0 s gr % Polyline n 19036 -1751 m 19704 -1083 l gs col0 s gr % Polyline n 19036 -1083 m 19704 -1751 l gs col0 s gr % Polyline n 22677 -3779 m 24566 -3779 l 24566 -2834 l 22677 -2834 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 22677 -3779 m 24566 -3779 l 24566 -2834 l 22677 -2834 l cp gs col0 s gr % Polyline n 22204 -2834 m 22677 -2834 l gs col0 s gr % Polyline n 21870 9587 m 22538 10255 l gs col0 s gr % Polyline n 21870 10255 m 22538 9587 l gs col0 s gr % Polyline n 23149 8976 m 25039 8976 l 25039 9921 l 23149 9921 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 23149 8976 m 25039 8976 l 25039 9921 l 23149 9921 l cp gs col0 s gr % Polyline n 21259 8503 m 22204 8503 l 22204 9448 l gs col0 s gr % Polyline n 21259 11338 m 22204 11338 l 22204 10393 l gs col0 s gr % Polyline n 22677 9921 m 23149 9921 l 23149 9448 l gs col0 s gr % Polyline n 25511 -1889 m 25511 -944 l gs col0 s gr % Polyline n 25039 -1417 m 25984 -1417 l gs col0 s gr % Polyline n 24566 -2834 m 25511 -2834 l 25511 -1889 l gs col0 s gr % Polyline n 20787 1417 m 25511 1417 l 25511 -944 l gs col0 s gr % Polyline n 20787 -11338 m 21064 -11338 l 21064 -10255 l gs col0 s gr % Polyline n 20787 -8976 m 20787 -8503 l 21064 -8503 l 21064 -9587 l gs col0 s gr % Polyline n 22677 -12283 m 24566 -12283 l 24566 -11338 l 22677 -11338 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 22677 -12283 m 24566 -12283 l 24566 -11338 l 22677 -11338 l cp gs col0 s gr % Polyline n 22677 -9448 m 24566 -9448 l 24566 -8503 l 22677 -8503 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 22677 -9448 m 24566 -9448 l 24566 -8503 l 22677 -8503 l cp gs col0 s gr % Polyline n 22677 -11338 m 22400 -11338 l 22400 -10255 l gs col0 s gr % Polyline n 22677 -8976 m 22677 -8503 l 22400 -8503 l 22400 -9587 l gs col0 s gr % Polyline n 25511 -7559 m 25511 -6614 l gs col0 s gr % Polyline n 25039 -7086 m 25984 -7086 l gs col0 s gr % Polyline n 24566 -8976 m 24566 -8503 l 25511 -8503 l 25511 -6614 l gs col0 s gr % Polyline n 24566 -6141 m 24566 -5669 l 25511 -5669 l 25511 -7559 l gs col0 s gr % Polyline n 26456 -5196 m 26456 -4251 l gs col0 s gr % Polyline n 25984 -4724 m 26929 -4724 l gs col0 s gr % Polyline n 25984 -7086 m 26456 -7086 l 26456 -5196 l gs col0 s gr % Polyline n 26456 -4251 m 26456 -1417 l 25984 -1417 l gs col0 s gr % Polyline n 27401 -1417 m 27401 -472 l gs col0 s gr % Polyline n 26929 -944 m 27874 -944 l gs col0 s gr % Polyline n 25039 9921 m 27401 9921 l 27401 -472 l gs col0 s gr % Polyline n 26929 -4724 m 27401 -4724 l 27401 -1417 l gs col0 s gr % Polyline n 28346 -1889 m 30236 -1889 l 30236 -944 l 28346 -944 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 28346 -1889 m 30236 -1889 l 30236 -944 l 28346 -944 l cp gs col0 s gr % Polyline n 27874 -944 m 27874 -911 l 28346 -911 l 28346 -1417 l gs col0 s gr % Polyline n 30236 -1417 m 30236 -944 l 30512 -944 l 30512 138 l gs col0 s gr % Polyline n 20787 4251 m 30512 4251 l 30512 806 l gs col0 s gr % Polyline n 32125 -1889 m 34015 -1889 l 34015 -944 l 32125 -944 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 32125 -1889 m 34015 -1889 l 34015 -944 l 32125 -944 l cp gs col0 s gr % Polyline n 32125 944 m 34015 944 l 34015 1889 l 32125 1889 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 32125 944 m 34015 944 l 34015 1889 l 32125 1889 l cp gs col0 s gr % Polyline n 32125 -944 m 31849 -944 l 31849 138 l gs col0 s gr % Polyline n 32125 1417 m 32125 1889 l 31849 1889 l 31849 806 l gs col0 s gr % Polyline n 35905 -7086 m 37795 -7086 l 37795 -6141 l 35905 -6141 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 35905 -7086 m 37795 -7086 l 37795 -6141 l 35905 -6141 l cp gs col0 s gr % Polyline n 35905 -4251 m 37795 -4251 l 37795 -3307 l 35905 -3307 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 35905 -4251 m 37795 -4251 l 37795 -3307 l 35905 -3307 l cp gs col0 s gr % Polyline n 35905 -6614 m 35905 -6141 l 35628 -6141 l 35628 -5058 l gs col0 s gr % Polyline n 35905 -3307 m 35628 -3307 l 35628 -4390 l gs col0 s gr % Polyline n 34015 -1417 m 34015 -944 l 34292 -944 l 34292 -4390 l gs col0 s gr % Polyline n 24566 -11338 m 34292 -11338 l 34292 -5058 l gs col0 s gr % Polyline n 38740 -1417 m 38740 -472 l gs col0 s gr % Polyline n 38267 -944 m 39212 -944 l gs col0 s gr % Polyline n 34015 1417 m 34015 1889 l 38740 1889 l 38740 -472 l gs col0 s gr % Polyline n 37795 -3307 m 38740 -3307 l 38740 -1417 l gs col0 s gr % Polyline n 39685 -1889 m 41574 -1889 l 41574 -944 l 39685 -944 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 39685 -1889 m 41574 -1889 l 41574 -944 l 39685 -944 l cp gs col0 s gr % Polyline n 39212 -944 m 39685 -944 l 39685 -1417 l gs col0 s gr % Polyline n 39685 -9921 m 41574 -9921 l 41574 -8976 l 39685 -8976 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 39685 -9921 m 41574 -9921 l 41574 -8976 l 39685 -8976 l cp gs col0 s gr % Polyline n 39685 -7086 m 41574 -7086 l 41574 -6141 l 39685 -6141 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 39685 -7086 m 41574 -7086 l 41574 -6141 l 39685 -6141 l cp gs col0 s gr % Polyline n 39685 -8976 m 39408 -8976 l 39408 -7893 l gs col0 s gr % Polyline n 39685 -6614 m 39685 -6141 l 39408 -6141 l 39408 -7224 l gs col0 s gr % Polyline n 41574 -6614 m 41580 -6120 l 42520 -6122 l 42519 -3779 l gs col0 s gr % Polyline n 37795 -8976 m 38072 -8976 l 38072 -7893 l gs col0 s gr % Polyline n 37795 -6614 m 37795 -6141 l 38072 -6141 l 38072 -7224 l gs col0 s gr % Polyline n 42519 -3779 m 42519 -2834 l gs col0 s gr % Polyline n 42047 -3307 m 42992 -3307 l gs col0 s gr % Polyline n 41574 -1417 m 41574 -944 l 42519 -944 l 42519 -2834 l gs col0 s gr % Polyline n 43464 -4251 m 45354 -4251 l 45354 -3307 l 43464 -3307 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 43464 -4251 m 45354 -4251 l 45354 -3307 l 43464 -3307 l cp gs col0 s gr % Polyline n 42992 -3307 m 43464 -3307 l 43464 -3779 l gs col0 s gr % Polyline n 47244 -8031 m 49133 -8031 l 49133 -7086 l 47244 -7086 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 47244 -8031 m 49133 -8031 l 49133 -7086 l 47244 -7086 l cp gs col0 s gr % Polyline n 47244 -7559 m 47244 -7086 l 46967 -7086 l 46967 -6003 l gs col0 s gr % Polyline n 47244 -4251 m 46967 -4251 l 46967 -5335 l gs col0 s gr % Polyline n 41574 -8976 m 45631 -8976 l 45631 -6003 l gs col0 s gr % Polyline n 45354 -3779 m 45354 -3307 l 45631 -3307 l 45631 -5335 l gs col0 s gr % Polyline n 19370 8503 m 18425 8503 l gs col0 s gr % Polyline n 47244 -5196 m 49133 -5196 l 49133 -4251 l 47244 -4251 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 47244 -5196 m 49133 -5196 l 49133 -4251 l 47244 -4251 l cp gs col0 s gr % Polyline n 39909 8709 m 41798 8709 l 41798 9654 l 39909 9654 l cp gs col32 1.00 shd ef gr gs col32 s gr % Polyline n 39909 8709 m 41798 8709 l 41798 9654 l 39909 9654 l cp gs col0 s gr /Courier-iso ff 345.00 scf sf 12558 173 m gs 1 -1 sc (1/2) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 8503 3307 m gs 1 -1 sc (rp_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 8503 472 m gs 1 -1 sc (rp_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 12283 1889 m gs 1 -1 sc (R1) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 12283 7559 m gs 1 -1 sc (rp_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 16062 6614 m gs 1 -1 sc (crp_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 16062 9448 m gs 1 -1 sc (P_r) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 20314 8031 m gs 1 -1 sc (R2) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 16062 944 m gs 1 -1 sc (R1) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 12283 -7559 m gs 1 -1 sc (ex_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 12283 -4724 m gs 1 -1 sc (rp_lo) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 19842 -6141 m gs 1 -1 sc (R4) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 16062 3779 m gs 1 -1 sc (ex_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Courier-iso ff 300.00 scf sf 17952 2834 m gs 1 -1 sc (Dekker) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 19842 944 m gs 1 -1 sc (R5_lo) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 19842 3779 m gs 1 -1 sc (R5_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 16062 -1889 m gs 1 -1 sc (rp_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 16062 -4724 m gs 1 -1 sc (ex_lo) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 23622 -3307 m gs 1 -1 sc (R6) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 20314 10866 m gs 1 -1 sc (ex_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 24094 9448 m gs 1 -1 sc (R7) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 19842 -11811 m gs 1 -1 sc (rp_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 19842 -8976 m gs 1 -1 sc (ex_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Courier-iso ff 300.00 scf sf 21732 -9921 m gs 1 -1 sc (Dekker) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 23622 -11811 m gs 1 -1 sc (R3_lo) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 23622 -8976 m gs 1 -1 sc (R3_lo) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 23622 -6141 m gs 1 -1 sc (ex_lo) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 29291 -1417 m gs 1 -1 sc (R7) dup sw pop 2 div neg 0 rm col0 sh gr /Courier-iso ff 300.00 scf sf 31181 472 m gs 1 -1 sc (Fast2Sum) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 33070 -1417 m gs 1 -1 sc (R9) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 33070 1417 m gs 1 -1 sc (R8) dup sw pop 2 div neg 0 rm col0 sh gr /Courier-iso ff 300.00 scf sf 34960 -4724 m gs 1 -1 sc (Fast2Sum) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 36850 -6614 m gs 1 -1 sc (R10) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 36850 -3779 m gs 1 -1 sc (tmp) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 40629 -1417 m gs 1 -1 sc (R8) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 36850 -9448 m gs 1 -1 sc (ex_hi) dup sw pop 2 div neg 0 rm col0 sh gr /Courier-iso ff 300.00 scf sf 38740 -7559 m gs 1 -1 sc (Fast2Sum) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 40629 -9448 m gs 1 -1 sc (R11) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 40629 -6614 m gs 1 -1 sc (tmp) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 44409 -3779 m gs 1 -1 sc (R8) dup sw pop 2 div neg 0 rm col0 sh gr /Courier-iso ff 300.00 scf sf 46299 -5669 m gs 1 -1 sc (Fast2Sum) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 48188 -7559 m gs 1 -1 sc (R11) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 48188 -4724 m gs 1 -1 sc (R8) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 40860 9315 m gs 1 -1 sc (A) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Bold-iso ff 420.00 scf sf 43020 9315 m gs 1 -1 sc (Variable A) dup sw pop 2 div neg 0 rm col0 sh gr % here ends figure; $F2psEnd rs showpage interval-3.2.0/src/crlibm/docs/latex/fig_exp/reconstruction.pstex_t0000644000000000000000000001275413316017127023716 0ustar 00000000000000\begin{picture}(0,0)% \includegraphics{fig_exp/reconstruction.pstex}% \end{picture}% \setlength{\unitlength}{994sp}% % \begingroup\makeatletter\ifx\SetFigFont\undefined% \gdef\SetFigFont#1#2#3#4#5{% \reset@font\fontsize{#1}{#2pt}% \fontfamily{#3}\fontseries{#4}\fontshape{#5}% \selectfont}% \fi\endgroup% \begin{picture}(41646,24613)(7528,-11456) \put(23491,-9466){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-30}$}% }}}} \put(11746,7409){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-1}$}% }}}} \put(11656,4529){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-63}$}% }}}} \put(15481,4529){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-55}$}% }}}} \put(15571,1739){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-9}$}% }}}} \put(11791,-2086){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-9}$}% }}}} \put(15526,-1096){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-19}$}% }}}} \put(15571,-3976){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-1}$}% }}}} \put(7966,-601){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-9}$}% }}}} \put(7966,-3481){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-9}$}% }}}} \put(11746,-7756){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-9}$}% }}}} \put(15526,-9601){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-2}$}% }}}} \put(15526,-6721){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-27}$}% }}}} \put(19756,-11041){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-1}$}% }}}} \put(19711,-8206){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-29}$}% }}}} \put(19261,-1096){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-20}$}% }}}} \put(19261,-3976){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-74}$}% }}}} \put(19216,5969){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-64}$}% }}}} \put(22996,5969){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-55}$}% }}}} \put(23041,3134){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-62}$}% }}}} \put(19261,11639){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-9}$}% }}}} \put(23086,11639){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-10}$}% }}}} \put(19306,8804){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-1}$}% }}}} \put(23041,8804){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-64}$}% }}}} \put(28666,1244){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-29}$}% }}}} \put(32446,1244){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-19}$}% }}}} \put(32491,-1591){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-73}$}% }}}} \put(40046,6457){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-53}$}% }}}} \put(36316,9254){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-1}$}% }}}} \put(40186,9299){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{0}$}% }}}} \put(36361,6419){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-9}$}% }}}} \put(36271,3629){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-63}$}% }}}} \put(40051,1244){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-62}$}% }}}} \put(43786,3584){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-53}$}% }}}} \put(47566,4529){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-53}$}% }}}} \put(47611,7409){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$2^{-1}$}% }}}} \put(40861,-9376){\makebox(0,0)[b]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$max$}% }}}} \put(42121,-9421){\makebox(0,0)[lb]{\smash{{\SetFigFont{5}{6.0}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$|A| \leq max$}% }}}} \end{picture}% interval-3.2.0/src/crlibm/docs/latex/fig_exp/rnd_to_nearest.fig0000644000000000000000000001136013316017127022712 0ustar 00000000000000#FIG 3.2 Landscape Center Metric A4 41.00 Single -2 1200 2 6 15975 1125 18000 1350 4 0 0 50 -1 0 20 0.0000 4 195 210 15975 1350 X\001 4 0 0 50 -1 0 20 0.0000 4 30 180 16875 1350 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 210 17775 1350 X\001 4 0 0 50 -1 0 20 0.0000 4 195 210 17550 1350 X\001 -6 6 1313 2580 8228 3210 4 1 0 50 -1 0 20 0.0000 2 270 6915 4770 2790 $R8 > 0 \\mbox{~~~et~~~} R11\\_err=\\frac{1}{2}ulp(R12)$\001 4 1 0 50 -1 0 20 0.0000 0 255 675 4770 3150 cas a)\001 -6 6 9900 1350 13725 2025 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 9900 1440 9900 1665 13725 1665 13725 1440 4 0 0 50 -1 0 20 0.0000 4 195 465 11475 1890 R11\001 -6 6 10538 2580 17543 3210 4 1 0 50 -1 0 20 0.0000 2 270 7005 14040 2790 $R8 < 0 \\mbox{~~~et~~~} R11\\_err=-\\frac{1}{2}ulp(R12)$\001 4 1 0 50 -1 0 20 0.0000 0 255 675 14040 3150 cas b)\001 -6 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 9900 -135 9900 90 18000 90 18000 -135 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 675 990 675 1215 2025 1215 2025 990 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 2250 990 2250 1215 4500 1215 4500 990 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 675 1440 675 1665 4500 1665 4500 1440 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 4950 1215 4950 1440 8775 1440 8775 1215 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 11437 982 11437 1207 13725 1215 13725 990 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 9900 990 9900 1215 11340 1215 11340 990 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 14175 1215 14175 1440 18000 1440 18000 1215 4 0 0 50 -1 0 20 0.0000 4 30 180 12375 1125 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 135 14175 1350 0\001 4 0 0 50 -1 0 20 0.0000 4 195 135 14400 1350 0\001 4 0 0 50 -1 0 20 0.0000 4 195 135 15300 1350 0\001 4 0 0 50 -1 0 20 0.0000 4 195 210 9900 0 X\001 4 0 0 50 -1 0 20 0.0000 4 30 180 10575 0 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 135 11475 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 11700 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 11925 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 12150 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 12375 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 12600 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 12825 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 13050 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 13275 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 13500 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 15075 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 14850 0 1\001 4 0 0 50 -1 0 20 0.0000 4 30 180 14175 0 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 210 15975 0 X\001 4 0 0 50 -1 0 20 0.0000 4 30 180 16875 0 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 210 17775 0 X\001 4 0 0 50 -1 0 20 0.0000 4 195 210 17550 0 X\001 4 0 0 50 -1 0 20 0.0000 4 195 210 15750 0 X\001 4 0 0 50 -1 0 20 0.0000 4 30 180 12375 1125 ...\001 4 0 0 50 -1 0 20 0.0000 4 30 180 12375 1125 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 225 15525 1350 -1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 15525 0 0\001 4 0 0 50 -1 0 20 0.0000 4 195 135 15300 0 1\001 4 0 0 50 -1 0 20 0.0000 4 195 210 675 1125 X\001 4 0 0 50 -1 0 20 0.0000 4 195 210 900 1125 X\001 4 0 0 50 -1 0 20 0.0000 4 195 210 1800 1125 X\001 4 0 0 50 -1 0 20 0.0000 4 195 135 2250 1125 1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 2475 1125 0\001 4 0 0 50 -1 0 20 0.0000 4 195 135 4275 1125 0\001 4 0 0 50 -1 0 20 0.0000 4 195 135 4050 1125 0\001 4 0 0 50 -1 0 20 0.0000 4 195 135 2700 1125 0\001 4 0 0 50 -1 0 20 0.0000 4 30 180 3150 1125 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 135 4950 1350 0\001 4 0 0 50 -1 0 20 0.0000 4 195 135 5175 1350 0\001 4 0 0 50 -1 0 20 0.0000 4 30 180 5625 1350 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 135 6075 1350 0\001 4 0 0 50 -1 0 20 0.0000 4 195 135 6300 1350 1\001 4 0 0 50 -1 0 20 0.0000 4 195 210 6525 1350 X\001 4 0 0 50 -1 0 20 0.0000 4 195 210 6750 1350 X\001 4 0 0 50 -1 0 20 0.0000 4 30 180 7650 1350 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 210 8550 1350 X\001 4 0 0 50 -1 0 20 0.0000 4 195 210 8325 1350 X\001 4 0 0 50 -1 0 20 0.0000 4 195 465 1125 1440 R12\001 4 0 0 50 -1 0 20 0.0000 4 255 930 2925 1440 R11_err\001 4 0 0 50 -1 0 20 0.0000 4 195 465 2250 1890 R11\001 4 0 0 50 -1 0 20 0.0000 4 195 330 6525 1890 R8\001 4 0 0 50 -1 0 20 0.0000 4 30 180 14850 1350 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 135 11925 1125 0\001 4 0 0 50 -1 0 20 0.0000 4 195 225 11475 1125 -1\001 4 0 0 50 -1 0 20 0.0000 4 195 135 13500 1125 0\001 4 0 0 50 -1 0 20 0.0000 4 195 135 13275 1125 0\001 4 0 0 50 -1 0 20 0.0000 4 255 930 12150 1440 R11_err\001 4 0 0 50 -1 0 20 0.0000 4 195 465 10350 1440 R12\001 4 0 0 50 -1 0 20 0.0000 4 195 210 10125 1125 X\001 4 0 0 50 -1 0 20 0.0000 4 195 210 9900 1125 X\001 4 0 0 50 -1 0 20 0.0000 4 30 180 10575 1132 ...\001 4 0 0 50 -1 0 20 0.0000 4 195 285 11025 1125 +1\001 4 0 0 50 -1 0 20 0.0000 4 195 210 10125 0 X\001 4 0 0 50 -1 0 20 0.0000 4 195 1095 13275 450 R11 + R8\001 4 0 0 50 -1 0 20 0.0000 4 195 210 11025 0 X\001 4 0 0 50 -1 0 20 0.0000 4 195 330 15750 1890 R8\001 interval-3.2.0/src/crlibm/docs/latex/fig_exp/rnd_to_nearest.pstex0000644000000000000000000002622713316017127023320 0ustar 00000000000000%!PS-Adobe-2.0 EPSF-2.0 %%Title: rnd_to_nearest.fig %%Creator: fig2dev Version 3.2 Patchlevel 4 %%CreationDate: Mon Jun 30 21:34:50 2003 %%For: ddefour@pecheresse (David Defour) %%BoundingBox: 0 0 449 89 %%Magnification: 0.4100 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 89 moveto 0 0 lineto 449 0 lineto 449 89 lineto closepath clip newpath -17.1 83.3 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /reencdict 12 dict def /ReEncode { reencdict begin /newcodesandnames exch def /newfontname exch def /basefontname exch def /basefontdict basefontname findfont def /newfont basefontdict maxlength dict def basefontdict { exch dup /FID ne { dup /Encoding eq { exch dup length array copy newfont 3 1 roll put } { exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall newfont /FontName newfontname put newcodesandnames aload pop 128 1 255 { newfont /Encoding get exch /.notdef put } for newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat newfontname newfont definefont pop end } def /isovec [ 8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde 8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis 8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron 8#220 /dotlessi 8#230 /oe 8#231 /OE 8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling 8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis 8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot 8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus 8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph 8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine 8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf 8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute 8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring 8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute 8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute 8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve 8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply 8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex 8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave 8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring 8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute 8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute 8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve 8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide 8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex 8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def /Times-Roman /Times-Roman-iso isovec ReEncode /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.02583 0.02583 sc % % Fig objects follow % % % here starts figure with depth 50 /Times-Roman-iso ff 300.00 scf sf 15975 1350 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 16875 1350 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 17775 1350 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 17550 1350 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 4770 3150 m gs 1 -1 sc (cas a\)) dup sw pop 2 div neg 0 rm col0 sh gr % Polyline 7.500 slw n 9900 1440 m 9900 1665 l 13725 1665 l 13725 1440 l gs col0 s gr /Times-Roman-iso ff 300.00 scf sf 11475 1890 m gs 1 -1 sc (R11) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 14040 3150 m gs 1 -1 sc (cas b\)) dup sw pop 2 div neg 0 rm col0 sh gr % Polyline n 9900 -135 m 9900 90 l 18000 90 l 18000 -135 l gs col0 s gr % Polyline n 675 990 m 675 1215 l 2025 1215 l 2025 990 l gs col0 s gr % Polyline n 2250 990 m 2250 1215 l 4500 1215 l 4500 990 l gs col0 s gr % Polyline n 675 1440 m 675 1665 l 4500 1665 l 4500 1440 l gs col0 s gr % Polyline n 4950 1215 m 4950 1440 l 8775 1440 l 8775 1215 l gs col0 s gr % Polyline n 11437 982 m 11437 1207 l 13725 1215 l 13725 990 l gs col0 s gr % Polyline n 9900 990 m 9900 1215 l 11340 1215 l 11340 990 l gs col0 s gr % Polyline n 14175 1215 m 14175 1440 l 18000 1440 l 18000 1215 l gs col0 s gr /Times-Roman-iso ff 300.00 scf sf 12375 1125 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 14175 1350 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 14400 1350 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 15300 1350 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 9900 0 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 10575 0 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 11475 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 11700 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 11925 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 12150 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 12375 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 12600 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 12825 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 13050 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 13275 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 13500 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 15075 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 14850 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 14175 0 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 15975 0 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 16875 0 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 17775 0 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 17550 0 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 15750 0 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 12375 1125 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 12375 1125 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 15525 1350 m gs 1 -1 sc (-1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 15525 0 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 15300 0 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 675 1125 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 900 1125 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 1800 1125 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 2250 1125 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 2475 1125 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 4275 1125 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 4050 1125 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 2700 1125 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 3150 1125 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 4950 1350 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 5175 1350 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 5625 1350 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 6075 1350 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 6300 1350 m gs 1 -1 sc (1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 6525 1350 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 6750 1350 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 7650 1350 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 8550 1350 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 8325 1350 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 1125 1440 m gs 1 -1 sc (R12) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 2925 1440 m gs 1 -1 sc (R11_err) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 2250 1890 m gs 1 -1 sc (R11) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 6525 1890 m gs 1 -1 sc (R8) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 14850 1350 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 11925 1125 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 11475 1125 m gs 1 -1 sc (-1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 13500 1125 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 13275 1125 m gs 1 -1 sc (0) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 12150 1440 m gs 1 -1 sc (R11_err) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 10350 1440 m gs 1 -1 sc (R12) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 10125 1125 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 9900 1125 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 10575 1132 m gs 1 -1 sc (...) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 11025 1125 m gs 1 -1 sc (+1) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 10125 0 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 13275 450 m gs 1 -1 sc (R11 + R8) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 11025 0 m gs 1 -1 sc (X) col0 sh gr /Times-Roman-iso ff 300.00 scf sf 15750 1890 m gs 1 -1 sc (R8) col0 sh gr % here ends figure; $F2psEnd rs showpage interval-3.2.0/src/crlibm/docs/latex/fig_exp/rnd_to_nearest.pstex_t0000644000000000000000000000133213316017127023631 0ustar 00000000000000\begin{picture}(0,0)% \includegraphics{fig_exp/rnd_to_nearest.pstex}% \end{picture}% \setlength{\unitlength}{1699sp}% % \begingroup\makeatletter\ifx\SetFigFont\undefined% \gdef\SetFigFont#1#2#3#4#5{% \reset@font\fontsize{#1}{#2pt}% \fontfamily{#3}\fontseries{#4}\fontshape{#5}% \selectfont}% \fi\endgroup% \begin{picture}(17349,3421)(664,-2387) \put(4771,-1951){\makebox(0,0)[b]{\smash{{\SetFigFont{8}{9.6}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$R8 > 0 \mbox{~~~et~~~} R11\_err=\frac{1}{2}ulp(R12)$}% }}}} \put(14041,-1951){\makebox(0,0)[b]{\smash{{\SetFigFont{8}{9.6}{\familydefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$R8 < 0 \mbox{~~~et~~~} R11\_err=-\frac{1}{2}ulp(R12)$}% }}}} \end{picture}% interval-3.2.0/src/crlibm/docs/latex/fig_scs/exponent_representation.eps0000644000000000000000000003310713316017127024707 0ustar 00000000000000%!PS-Adobe-2.0 EPSF-2.0 %%Title: exponent_representation2.eps %%Creator: fig2dev Version 3.2 Patchlevel 3d %%CreationDate: Tue Apr 2 18:10:36 2002 %%For: ddefour@reena (David Defour) %%BoundingBox: 0 0 712 300 %%Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 300 moveto 0 0 lineto 712 0 lineto 712 300 lineto closepath clip newpath 426.6 384.1 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /reencdict 12 dict def /ReEncode { reencdict begin /newcodesandnames exch def /newfontname exch def /basefontname exch def /basefontdict basefontname findfont def /newfont basefontdict maxlength dict def basefontdict { exch dup /FID ne { dup /Encoding eq { exch dup length array copy newfont 3 1 roll put } { exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall newfont /FontName newfontname put newcodesandnames aload pop 128 1 255 { newfont /Encoding get exch /.notdef put } for newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat newfontname newfont definefont pop end } def /isovec [ 8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde 8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis 8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron 8#220 /dotlessi 8#230 /oe 8#231 /OE 8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling 8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis 8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot 8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus 8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph 8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine 8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf 8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute 8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring 8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute 8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute 8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve 8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply 8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex 8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave 8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring 8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute 8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute 8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve 8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide 8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex 8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def /Times-Roman /Times-Roman-iso isovec ReEncode /Helvetica /Helvetica-iso isovec ReEncode /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0.06299 0.06299 sc % % Fig objects follow % /Times-Roman-iso ff 270.00 scf sf -2925 3825 m gs 1 -1 sc (2) col0 sh gr /Times-Roman-iso ff 210.00 scf sf -2475 3660 m gs 1 -1 sc (r) col0 sh gr /Times-Roman-iso ff 225.00 scf sf -2835 3600 m gs 1 -1 sc (2.m) col0 sh gr /Times-Roman-iso ff 270.00 scf sf -4275 3825 m gs 1 -1 sc (2) col0 sh gr /Times-Roman-iso ff 210.00 scf sf -3825 3660 m gs 1 -1 sc (r) col0 sh gr /Times-Roman-iso ff 225.00 scf sf -4185 3600 m gs 1 -1 sc (3.m) col0 sh gr /Times-Roman-iso ff 225.00 scf sf -1350 3600 m gs 1 -1 sc (m) col0 sh gr /Times-Roman-iso ff 210.00 scf sf -1125 3660 m gs 1 -1 sc (r) col0 sh gr /Times-Roman-iso ff 225.00 scf sf 1222 3592 m gs 1 -1 sc (-m) col0 sh gr /Times-Roman-iso ff 210.00 scf sf 1522 3652 m gs 1 -1 sc (r) col0 sh gr /Times-Roman-iso ff 225.00 scf sf 2572 3592 m gs 1 -1 sc (-2.m) col0 sh gr /Times-Roman-iso ff 210.00 scf sf 3037 3652 m gs 1 -1 sc (r) col0 sh gr /Helvetica-iso ff 300.00 scf sf -2925 1800 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -1575 1800 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -2025 1800 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -675 1800 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf 675 1800 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf 1800 1800 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf 225 1800 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -2475 1800 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -900 1800 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -3375 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -3150 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -2700 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -2250 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -1800 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -1350 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -450 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -1125 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -225 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 0 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 450 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 900 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 1125 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 1575 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 1350 1800 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 0 1800 m gs 1 -1 sc (,) col0 sh gr % Polyline 7.500 slw n -4620 1350 m -4725 1350 -4725 1920 105 arcto 4 {pop} repeat -4725 2025 2145 2025 105 arcto 4 {pop} repeat 2250 2025 2250 1455 105 arcto 4 {pop} repeat 2250 1350 -4620 1350 105 arcto 4 {pop} repeat cp gs col0 s gr /Helvetica-iso ff 300.00 scf sf -4500 1800 m gs 1 -1 sc (X = ) col0 sh gr % Polyline n -3945 4500 m -4050 4500 -4050 4845 105 arcto 4 {pop} repeat -4050 4950 -2805 4950 105 arcto 4 {pop} repeat -2700 4950 -2700 4605 105 arcto 4 {pop} repeat -2700 4500 -3945 4500 105 arcto 4 {pop} repeat cp gs col0 s gr % Polyline n -2550 4500 m -2655 4500 -2655 4845 105 arcto 4 {pop} repeat -2655 4950 -1455 4950 105 arcto 4 {pop} repeat -1350 4950 -1350 4605 105 arcto 4 {pop} repeat -1350 4500 -2550 4500 105 arcto 4 {pop} repeat cp gs col0 s gr % Polyline n -1200 4500 m -1305 4500 -1305 4845 105 arcto 4 {pop} repeat -1305 4950 -105 4950 105 arcto 4 {pop} repeat 0 4950 0 4605 105 arcto 4 {pop} repeat 0 4500 -1200 4500 105 arcto 4 {pop} repeat cp gs col0 s gr % Polyline n 150 4500 m 45 4500 45 4845 105 arcto 4 {pop} repeat 45 4950 1245 4950 105 arcto 4 {pop} repeat 1350 4950 1350 4605 105 arcto 4 {pop} repeat 1350 4500 150 4500 105 arcto 4 {pop} repeat cp gs col0 s gr % Polyline n 1500 4500 m 1395 4500 1395 4845 105 arcto 4 {pop} repeat 1395 4950 2595 4950 105 arcto 4 {pop} repeat 2700 4950 2700 4605 105 arcto 4 {pop} repeat 2700 4500 1500 4500 105 arcto 4 {pop} repeat cp gs col0 s gr /Helvetica-iso ff 300.00 scf sf -2895 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -1545 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -1995 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -645 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf 705 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf 1830 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf 255 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -2445 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -870 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -3345 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -3120 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -2670 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -2220 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -1770 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -1320 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -420 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -1095 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf -195 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 30 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 480 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 930 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 1155 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 1605 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 1380 4830 m gs 1 -1 sc (1) col0 sh gr /Helvetica-iso ff 300.00 scf sf 2055 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf 2280 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf 2505 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -4020 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -3795 4830 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 300.00 scf sf -3570 4830 m gs 1 -1 sc (0) col0 sh gr % Polyline 15.000 slw n -5520 4275 m -5625 4275 -5625 5970 105 arcto 4 {pop} repeat -5625 6075 3045 6075 105 arcto 4 {pop} repeat 3150 6075 3150 4380 105 arcto 4 {pop} repeat 3150 4275 -5520 4275 105 arcto 4 {pop} repeat cp gs col0 s gr /Helvetica-iso ff 300.00 scf sf -5355 4800 m gs 1 -1 sc (R.digits =) col0 sh gr /Helvetica-iso ff 240.00 scf sf -1350 5850 m gs 1 -1 sc (Software Carry Save Structure \(SCSS\)) col0 sh gr /Helvetica-iso ff 300.00 scf sf -5340 5745 m gs 1 -1 sc (R.sign = 1 ) col0 sh gr /Helvetica-iso ff 300.00 scf sf -5355 5295 m gs 1 -1 sc (R.index = 3 ) col0 sh gr % Polyline n -5175 3150 m 2925 3150 l gs col0 s gr % Polyline n 0 2925 m 0 3375 l gs col0 s gr % Polyline n 1350 2925 m 1350 3375 l gs col0 s gr % Polyline n 2700 2925 m 2700 3375 l gs col0 s gr % Polyline n -1350 2925 m -1350 3375 l gs col0 s gr % Polyline n -2700 2925 m -2700 3375 l gs col0 s gr % Polyline [90] 0 sd n 2925 3150 m 4500 3150 l gs col0 s gr [] 0 sd % Polyline [90] 0 sd n -6750 3150 m -5175 3150 l gs col0 s gr [] 0 sd % Polyline n -4050 2925 m -4050 3375 l gs col0 s gr % Polyline n -2700 2925 m -2700 3375 l gs col0 s gr % Polyline 7.500 slw [15 45] 45 sd n -2700 1350 m -2700 4950 l gs col0 s gr [] 0 sd % Polyline [15 45] 45 sd n -1350 1350 m -1350 4950 l gs col0 s gr [] 0 sd % Polyline [15 45] 45 sd n 0 1350 m 0 4950 l gs col0 s gr [] 0 sd % Polyline [15 45] 45 sd n 1350 1350 m 1350 4950 l gs col0 s gr [] 0 sd % Polyline [15 45] 45 sd n -4050 1350 m -4050 4950 l gs col0 s gr [] 0 sd /Times-Roman-iso ff 270.00 scf sf 2475 3825 m gs 1 -1 sc (2) col0 sh gr /Times-Roman-iso ff 270.00 scf sf -225 3825 m gs 1 -1 sc (2) col0 sh gr /Times-Roman-iso ff 270.00 scf sf 1125 3825 m gs 1 -1 sc (2) col0 sh gr /Times-Roman-iso ff 270.00 scf sf -1575 3825 m gs 1 -1 sc (2) col0 sh gr /Helvetica-iso ff 270.00 scf sf -3435 2925 m gs 1 -1 sc (3) col0 sh gr /Helvetica-iso ff 270.00 scf sf -2085 2925 m gs 1 -1 sc (2) col0 sh gr /Helvetica-iso ff 270.00 scf sf -765 2925 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 270.00 scf sf 570 2925 m gs 1 -1 sc (-1) col0 sh gr /Helvetica-iso ff 270.00 scf sf 1890 2925 m gs 1 -1 sc (-2) col0 sh gr /Times-Roman-iso ff 225.00 scf sf -75 3653 m gs 1 -1 sc (0) col0 sh gr /Helvetica-iso ff 270.00 scf sf -5415 2910 m gs 1 -1 sc (Index =) col0 sh gr /Helvetica-iso ff 270.00 scf sf -5430 3825 m gs 1 -1 sc (Value =) col0 sh gr $F2psEnd rs interval-3.2.0/src/crlibm/docs/latex/fig_scs/exponent_representation.pdf0000644000000000000000000001101413316017127024662 0ustar 00000000000000%PDF-1.3 %쏢 6 0 obj <> stream xXn7W(ir%F9Z#bYQ0Zdٚ)> Zb+*?0}?wn$l vns1"Nx!C)7ElNd[8IIn0m瑴,MVMEXK:+(&/ 1@31vJ.Fc1lWbY; ˲5hc €6I,5FhLrj隤g5D+"jҧ:?D}!*>ˇu\S4W!KRbJ29@$1LTv3CR)k*ro'BzS>r= rt5MNA''gd?cTGH09:M+l4"w6[n/آ&\ ?\no~1Rk . zL׮V?>Bl.}?wyټ{ue./ b\\ĘAqV2\TU/ha, B'오Q"|rkȾ Q Vˌ_ň,U^UZhZ Z4v-F_Ex԰ti~청YZIM{ ܶuiEK|uOֲ]RsZǮŠE)@> ZT䱩G9>Th"m-hRU-$РYH1 (@[Uh8TSm>(irpU5-v ;endstream endobj 7 0 obj 1385 endobj 12 0 obj <> endobj 13 0 obj <> endobj 5 0 obj <> /Contents 6 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 5 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 4 0 obj <> endobj 8 0 obj <> endobj 9 0 obj <> endobj 14 0 obj <> endobj 10 0 obj <> endobj 11 0 obj <> endobj 15 0 obj <> endobj 2 0 obj <>endobj xref 0 16 0000000000 65535 f 0000001771 00000 n 0000004170 00000 n 0000001712 00000 n 0000001819 00000 n 0000001561 00000 n 0000000015 00000 n 0000001470 00000 n 0000001888 00000 n 0000001949 00000 n 0000003028 00000 n 0000003088 00000 n 0000001490 00000 n 0000001520 00000 n 0000002970 00000 n 0000004112 00000 n trailer << /Size 16 /Root 1 0 R /Info 2 0 R >> startxref 4222 %%EOF interval-3.2.0/src/crlibm/docs/latex/fig_scs/multiplication.eps0000644000000000000000000006363313316017127022771 0ustar 00000000000000%!PS-Adobe-3.0 %%Pages: (atend) %%BoundingBox: 0 0 373 234 %%HiResBoundingBox: 0.000000 0.000000 372.082007 233.460010 %......................................... %%Creator: GNU Ghostscript 707 (pswrite) %%CreationDate: 2004/04/07 15:40:39 %%DocumentData: Clean7Bit %%LanguageLevel: 2 %%EndComments %%BeginProlog % This copyright applies to everything between here and the %%EndProlog: % Copyright (C) 2003 artofcode LLC, Benicia, CA. All rights reserved. %%BeginResource: procset GS_pswrite_2_0_1001 /GS_pswrite_2_0_1001 80 dict dup begin /PageSize 2 array def/setpagesize{ PageSize aload pop 3 index eq exch 4 index eq and{ pop pop pop}{ PageSize dup 1 5 -1 roll put 0 4 -1 roll put dup null eq {false} {dup where} ifelse{ exch get exec} { pop/setpagedevice where { pop 1 dict dup /PageSize PageSize put setpagedevice} { /setpage where{ pop PageSize aload pop pageparams 3 {exch pop} repeat setpage}if}ifelse}ifelse}ifelse} bind def /!{bind def}bind def/#{load def}!/N/counttomark # /rG{3{3 -1 roll 255 div}repeat setrgbcolor}!/G{255 div setgray}!/K{0 G}! /r6{dup 3 -1 roll rG}!/r5{dup 3 1 roll rG}!/r3{dup rG}! /w/setlinewidth #/J/setlinecap # /j/setlinejoin #/M/setmiterlimit #/d/setdash #/i/setflat # /m/moveto #/l/lineto #/c/rcurveto # /p{N 2 idiv{N -2 roll rlineto}repeat}! /P{N 0 gt{N -2 roll moveto p}if}! /h{p closepath}!/H{P closepath}! /lx{0 rlineto}!/ly{0 exch rlineto}!/v{0 0 6 2 roll c}!/y{2 copy c}! /re{4 -2 roll m exch dup lx exch ly neg lx h}! /^{3 index neg 3 index neg}! /f{P fill}!/f*{P eofill}!/s{H stroke}!/S{P stroke}! /q/gsave #/Q/grestore #/rf{re fill}! /Y{P clip newpath}!/Y*{P eoclip newpath}!/rY{re Y}! /|={pop exch 4 1 roll 3 array astore cvx exch 1 index def exec}! /|{exch string readstring |=}! /+{dup type/nametype eq{2 index 7 add -3 bitshift 2 index mul}if}! /@/currentfile #/${+ @ |}! /B{{2 copy string{readstring pop}aload pop 4 array astore cvx 3 1 roll}repeat pop pop true}! /Ix{[1 0 0 1 11 -2 roll exch neg exch neg]exch}! /,{true exch Ix imagemask}!/If{false exch Ix imagemask}!/I{exch Ix image}! /Ic{exch Ix false 3 colorimage}! /F{/Columns counttomark 3 add -2 roll/Rows exch/K -1/BlackIs1 true>> /CCITTFaxDecode filter}!/FX{<LV-6=/W1KIbcNP~> , 3238 1822 50 67 /2A $C ,@^]Qs8W,uC_a_a7U1gtpYWIK\)6(]^Mi"Yhf%D$hnK''hnK'(IJ\GRhZ!8a^$kE7~> , 3323 1850 62 69 /6T $C 0GKEKD(GKUh-Flo]"1qoF`aaglKMMYe^Cn7l_SGKInJEqrfsjlHF80)^:.9mVd7[UmZ[ODh'_qg \kcPZFIot=kr2sDd^m/^V0.2F>GV+5[f~> , 3380 1822 2A , 2784 1794 6P , 2841 1765 2A , 2388 1737 6P , 2444 1709 2A , 2047 1652 2A , 2501 1737 6T , 1991 1680 6P , 2104 1680 6T , 2169 1652 26 67 /2E $C .E2>es8W-!s8W-!s89Y\s3/915WE`O^AI[~> , 2062.92 1651.96 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 2062.92 1651.96 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 2898 1794 6T , 3182.25 2162.18 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.46 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 2785.42 2162.18 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.45 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 2954 1763 49 69 /6X $C ,6?_R_@@-!*BJ:.%e,&5-L!IemF(mtmB?Ols/fANX , 1254.76 1765.34 0 -113.38 S 1198.07 1708.65 113.38 0 S 2558 1709 50 67 /2I $C 2@A?VnfY,aqgRDhgV^L/fPoZ%@D`SmL>dmsfPoV)%GQZIDqi%[iEuWRs)kp=^=ldqBl#)(KWJ1S , 2841 1537 6X , 2388 1510 6P , 2444 1480 6X , 1991.74 2162.18 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.46 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 2047 1423 6X , 1594 1397 6P , 1651 1367 6X , 2898 1567 6T , 2954 1539 2A , 2501 1510 6T , 2558 1480 6X , 2784 1567 6P , 2161 1425 2I , 1707 1397 6T , 1772 1369 2E , 2062.92 1538.58 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 2062.92 1538.58 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 2062.92 1425.2 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.48 14.48 14.48 c 8 0 14.49 -6.48 14.49 -14.48 c f* 2062.92 1425.2 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.48 14.48 14.48 c 8 0 14.49 -6.48 14.49 -14.48 c h S 2388.58 2162.18 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.45 0 p 31.31 0 56.7 25.38 56.7 56.69 c 0 0 p 0 31.31 -25.39 56.69 -56.7 56.69 c h S 3323 2049 2A , 3266 2077 6P , 2926 2047 6X , 2869 2077 6P , 1991 1454 6P , 461.08 1198.43 0 -113.38 S 404.39 1141.74 113.38 0 S 2388 1283 6P , 2444 1255 2I , 1991 1227 6P , 2047 1198 2I , 1594 1170 6P , 1651 1142 2I , 2104 1454 6T , 1254 1085 2I , 2501 1283 6T , 2558 1255 2A , 2104 1227 6T , 2161 1196 6X , 1707 1170 6T , 1764 1142 2I , 1310 1113 6T , 1375 1085 2E , 2062.92 1311.81 m 0 -8 -6.49 -14.48 -14.49 -14.48 c -8 0 -14.48 6.48 -14.48 14.48 c 0 8.01 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.48 14.49 -14.49 c f* 2062.92 1311.81 m 0 -8 -6.49 -14.48 -14.49 -14.48 c -8 0 -14.48 6.48 -14.48 14.48 c 0 8.01 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.48 14.49 -14.49 c h S 2062.92 1198.43 m 0 -8 -6.49 -14.48 -14.49 -14.48 c -8 0 -14.48 6.48 -14.48 14.48 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 2062.92 1198.43 m 0 -8 -6.49 -14.48 -14.49 -14.48 c -8 0 -14.48 6.48 -14.48 14.48 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 2529 2049 2I , 2473 2077 6P , 2140 2049 2E , 801.23 1425.2 113.38 0 S 2076 2077 6P , 2055 972 2E , 1594 943 6P , 1659 915 2E , 1197 887 6P , 1262 858 2E , 800 830 6P , 865 802 2E , 914 830 6T , 978 802 2E , 1310 887 6T , 1367 858 2I , 1707 943 6T , 1764 913 6X , 2104 1000 6T , 2161 972 2A , 2062.92 971.67 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 2062.92 971.67 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 1666.08 914.98 m 0 -8 -6.48 -14.49 -14.48 -14.49 c -8.01 0 -14.49 6.49 -14.49 14.49 c 0 8 6.48 14.49 14.49 14.49 c 8 0 14.48 -6.49 14.48 -14.49 c f* 1666.08 914.98 m 0 -8 -6.48 -14.49 -14.48 -14.49 c -8.01 0 -14.49 6.49 -14.49 14.49 c 0 8 6.48 14.49 14.49 14.49 c 8 0 14.48 -6.49 14.48 -14.49 c h S 1269.25 858.29 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.49 6.49 -14.49 14.49 c 0 8 6.49 14.49 14.49 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 1269.25 858.29 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.49 6.49 -14.49 14.49 c 0 8 6.49 14.49 14.49 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 28.3455 w 1594.91 2218.87 -141.73 -141.73 S 1453.18 2218.87 141.73 -141.73 S 3323 2219 2A , 1197 1113 6P , 255 G 404.39 404.76 m -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 -31.31 25.38 -56.69 56.69 -56.69 c 680.3 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 31.31 -25.38 56.69 -56.69 56.69 c f* 4.72425 w K 404.39 404.76 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 680.3 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 3266 2247 6T , 2926 2217 6X , 2869 2247 6T , 255 G 404.39 404.76 m -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 -31.31 25.38 -56.69 56.69 -56.69 c 680.3 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 31.31 -25.38 56.69 -56.69 56.69 c f* K 404.39 404.76 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 680.3 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 2529 2219 2I , 2473 2247 6T , 2140 2219 2E , 885 318 65 72 /7B $C +@1f-%I4-:+Qtd[SN7n)*^l_NG&5J;2fJ$%3!<5X0Os8W-!hgbOlgEOLapAU>l CMpShd^HS$9+3D)"KYV(:t.1mKa]C4#Cl~> , 950 291 2E , 1282 374 7B , 1339 348 2I , 1679 431 7B , 1736 403 6X , 2076 488 7B , 2132 461 2A , 857.92 1481.89 0 -113.38 S 2076 2247 6T , 1991 1000 6P , 885 36 56 69 /2M $C 2?]ZPaASo&hfeDAp?gVKmG#,;gUDUc[r:$1DYpn\hm[LZpMSg%DV_qmh7I , 942 8 2I , 1282 36 2M , 1339 6 6X , 1679 36 2M , 1736 8 2A , 488 36 2M , 553 8 2E , 801.23 121.3 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.46 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 1198.07 121.3 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.45 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 1594.91 121.3 -0.01 0 P -31.3 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.39 -56.69 56.7 -56.69 c 283.45 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S [ 37.794 ] 0 d 1991.74 121.3 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.46 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 2388.58 121.3 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.45 0 p 31.31 0 56.7 25.38 56.7 56.69 c 0 0 p 0 31.31 -25.39 56.69 -56.7 56.69 c h S 2785.42 121.3 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.45 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 3182.25 121.3 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.46 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S [ ] 0 d 404.39 121.3 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.46 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 64.25 914.98 0 -113.38 S 7.56 858.29 113.38 0 S 1269.25 1085.05 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.49 6.49 -14.49 14.49 c 0 8 6.49 14.49 14.49 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 1269.25 1085.05 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.49 6.49 -14.49 14.49 c 0 8 6.49 14.49 14.49 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 1269.25 971.67 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.49 6.49 -14.49 14.49 c 0 8 6.49 14.49 14.49 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 1269.25 971.67 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.49 6.49 -14.49 14.49 c 0 8 6.49 14.49 14.49 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 1254.76 1085.05 0 -113.38 S 1666.08 1141.74 m 0 -8 -6.48 -14.49 -14.48 -14.49 c -8.01 0 -14.49 6.49 -14.49 14.49 c 0 8 6.48 14.49 14.49 14.49 c 8 0 14.48 -6.49 14.48 -14.49 c f* 1666.08 1141.74 m 0 -8 -6.48 -14.49 -14.48 -14.49 c -8.01 0 -14.49 6.49 -14.49 14.49 c 0 8 6.48 14.49 14.49 14.49 c 8 0 14.48 -6.49 14.48 -14.49 c h S 1666.08 1028.36 m 0 -8 -6.48 -14.49 -14.48 -14.49 c -8.01 0 -14.49 6.49 -14.49 14.49 c 0 8 6.48 14.49 14.49 14.49 c 8 0 14.48 -6.49 14.48 -14.49 c f* 1666.08 1028.36 m 0 -8 -6.48 -14.49 -14.48 -14.49 c -8.01 0 -14.49 6.49 -14.49 14.49 c 0 8 6.48 14.49 14.49 14.49 c 8 0 14.48 -6.49 14.48 -14.49 c h S 1651.6 1141.74 0 -113.38 S 2062.92 1198.43 m 0 -8 -6.49 -14.48 -14.49 -14.48 c -8 0 -14.48 6.48 -14.48 14.48 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 2062.92 1198.43 m 0 -8 -6.49 -14.48 -14.49 -14.48 c -8 0 -14.48 6.48 -14.48 14.48 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 2062.92 1085.05 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 2062.92 1085.05 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 2048.43 1198.43 0 -113.38 S 1666.08 1368.51 m 0 -8.01 -6.48 -14.49 -14.48 -14.49 c -8.01 0 -14.49 6.48 -14.49 14.49 c 0 8 6.48 14.48 14.49 14.48 c 8 0 14.48 -6.48 14.48 -14.48 c f* 1666.08 1368.51 m 0 -8.01 -6.48 -14.49 -14.48 -14.49 c -8.01 0 -14.49 6.48 -14.49 14.49 c 0 8 6.48 14.48 14.49 14.48 c 8 0 14.48 -6.48 14.48 -14.48 c h S 1666.08 1255.12 m 0 -8 -6.48 -14.48 -14.48 -14.48 c -8.01 0 -14.49 6.48 -14.49 14.48 c 0 8 6.48 14.49 14.49 14.49 c 8 0 14.48 -6.49 14.48 -14.49 c f* 1666.08 1255.12 m 0 -8 -6.48 -14.48 -14.48 -14.48 c -8.01 0 -14.49 6.48 -14.49 14.48 c 0 8 6.48 14.49 14.49 14.49 c 8 0 14.48 -6.49 14.48 -14.49 c h S 1651.6 1368.51 0 -113.39 S 2062.92 1425.2 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.48 14.48 14.48 c 8 0 14.49 -6.48 14.49 -14.48 c f* 2062.92 1425.2 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.48 14.48 14.48 c 8 0 14.49 -6.48 14.49 -14.48 c h S 2062.92 1311.81 m 0 -8 -6.49 -14.48 -14.49 -14.48 c -8 0 -14.48 6.48 -14.48 14.48 c 0 8.01 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.48 14.49 -14.49 c f* 2062.92 1311.81 m 0 -8 -6.49 -14.48 -14.49 -14.48 c -8 0 -14.48 6.48 -14.48 14.48 c 0 8.01 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.48 14.49 -14.49 c h S 2048.43 1425.2 0 -113.39 S 2062.92 1651.96 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 2062.92 1651.96 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 2062.92 1538.58 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 2062.92 1538.58 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.48 6.49 -14.48 14.49 c 0 8 6.48 14.49 14.48 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 2048.43 1651.96 0 -113.38 S 872.41 801.6 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.49 6.49 -14.49 14.49 c 0 8 6.49 14.49 14.49 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c f* 872.41 801.6 m 0 -8 -6.49 -14.49 -14.49 -14.49 c -8 0 -14.49 6.49 -14.49 14.49 c 0 8 6.49 14.49 14.49 14.49 c 8 0 14.49 -6.49 14.49 -14.49 c h S 2388.58 2332.25 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.45 0 p 31.31 0 56.7 25.38 56.7 56.69 c 0 0 p 0 31.31 -25.39 56.69 -56.7 56.69 c h S 2785.42 2332.25 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.45 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 3182.25 2332.25 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.46 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 1991.74 2332.25 0 0 P -31.31 0 -56.69 -25.38 -56.69 -56.69 c 0 0 p 0 -31.31 25.38 -56.69 56.69 -56.69 c 283.46 0 p 31.31 0 56.69 25.38 56.69 56.69 c 0 0 p 0 31.31 -25.38 56.69 -56.69 56.69 c h S 28.3455 w 1311.45 1992.11 2409.37 0 S Q q 0 2340 0 -2340 3750 0 ^ H 2025.13 565.38 47.24 0 0.63 62.36 -23.94 -47.24 -23.3 47.24 Y* K 2048.43 971.67 0 -396.84 f* 4.72425 w 2048.43 971.67 0 -396.84 S Q q 0 0 3750 0 0 2340 ^ Y K 2025.76 627.74 23.3 -47.24 23.94 47.24 -47.24 0 f* 4.72425 w 2025.76 627.74 23.3 -47.24 23.94 47.24 -47.24 0 H S Q q 0 2340 0 -2340 3750 0 ^ H 1628.29 508.69 47.24 0 0.63 62.36 -23.93 -47.24 -23.31 47.24 Y* K 1651.6 914.98 0 -396.84 f* 4.72425 w 1651.6 914.98 0 -396.84 S Q q 0 0 3750 0 0 2340 ^ Y K 1628.92 571.05 23.31 -47.24 23.93 47.24 -47.24 0 f* 4.72425 w 1628.92 571.05 23.31 -47.24 23.93 47.24 -47.24 0 H S Q q 0 2340 0 -2340 3750 0 ^ H 1231.45 452 47.25 0 0.62 62.36 -23.93 -47.24 -23.31 47.24 Y* K 1254.76 858.29 0 -396.84 f* 4.72425 w 1254.76 858.29 0 -396.84 S Q q 0 0 3750 0 0 2340 ^ Y K 1232.08 514.36 23.31 -47.24 23.93 47.24 -47.24 0 f* 4.72425 w 1232.08 514.36 23.31 -47.24 23.93 47.24 -47.24 0 H S Q q 0 2340 0 -2340 3750 0 ^ H 834.62 395.31 47.24 0 0.63 62.36 -23.94 -47.24 -23.31 47.24 Y* K 857.92 801.6 0 -396.84 f* 4.72425 w 857.92 801.6 0 -396.84 S Q q 0 0 3750 0 0 2340 ^ Y K 835.25 457.67 23.31 -47.24 23.94 47.24 -47.24 0 f* 4.72425 w 835.25 457.67 23.31 -47.24 23.94 47.24 -47.24 0 H S 28.3455 w 291.01 234.69 2551.1 0 S [ 9.4485 28.3455 ] 28.3455 d 4.72425 w 744.54 404.76 0 -340.15 S 1141.38 518.14 0 -453.53 S 1538.21 574.83 0 -510.22 S 1935.05 631.52 0 -566.91 S 347.7 348.07 0 -283.46 S cleartomark end end pagesave restore showpage %%PageTrailer %%Trailer %%Pages: 1 %%EOF interval-3.2.0/src/crlibm/docs/latex/fig_scs/multiplication.pdf0000644000000000000000000001405613316017127022746 0ustar 00000000000000%PDF-1.3 %쏢 6 0 obj <> stream x]ˎ$WQP uؑ9@3Zd AN܃QYUR AqG|8X^O~gOqY02M6\uXy ېc<t~=Ő<+GSP)Ms{"ȶ =rDJ.`74B~=waVxҔGOiX8_N_N1u#wi qXSH:B@hʗF8ú炼bLN~AXJ3@.Rz@.LR304CeG.LI89ѴB8KDT1I3AiGʮ]Z=QjQ"z@)M$LX']B6ȅȴJ(94SEWk}Q=Aj1!j07(O Rд [^u@PXR()ʲ$W\"r(cP*[ĺ| ڃ"v|5:g гz'Ij$[sf{e  s˓sfC83qV-cb#d4ve)3HByMuRI3jc,o&ǚI= 4Rr[$k0YXM_VRj98*g|nǧm "_%_0%"#,J !G\ 838T6bC Lr|A; iS}V[)z բ40[x= ᘅia.wÒ7ewŀ4*CcINȯC)qk ;wrB{T[%=.(l0.lҮDZGwEEy )c#}cL|Tժq"d#._TɩQ+ǿ>~FvsE:[y= nD5W &cG\9_qXM,snUe7 QSI&s;MTߨӹ~Aڥڸ]1DV+ d=rqȼ4,xP*[z~J NʴChZm'|V6>~FJQeX'f{ʎ \c4u0pXTNȴbj=FJ*0m3_TeM:meC dv=r1$΍C9KG_8+8"Bʖ1t}(^ ,] db"MB(>f1=BɧOQX95=QN9I!nIL?Vvxͤlj),%mez6/KhFpOƎn.[M2?,''}U)L?Rϧ___Oӆ{_vj%+ ie[z͟O RJ픗ןN/%iJo˹<\zKOv/MW}/I5-Xß@Fc #THkP/S( `Kdj[aVk "zY8'd@CZY!d_e5u4+VmEa+uz%-Xr&iV,R *QJ#e)$1@%8az[25 ,(lPxv`t*{b@3lTޟUd",3lR'ck{]c0X}I]|*Ot&B>Ց@Oa;TtQF*abU,VKr2)-gz_>hꝓ:eũGlb ]LħO󓲕DqҾ }7v,Dw!uD5~{aQZXR{R"P5:wzyS#ϼH*jًD!c&os[];בҖidܬgR~|B62PƖ"S;}CJ5Mv`ιmDιIhM2CdPA |Rj-^T1> `=W~sK:[;T6J6ZuM5 kuQ9Erܑ QFxܪ$ ᶶֽ tD-Q)2ekpBmksOdnをg{hA9j;e9$[w0`.aF_}\ݽO}~bAC7ߜkݮ}TDz9W%y,,BdOb *ہp"6yu2GUlɞJbTBg}x 4ZfTBs£]xt7e|RlF[<ȫn _Ƅ[y!?k9{,^TKd0lQ fsӢMp?#}4s1M.;rmZlŏvb9W" {-B.Agm3o3[0Y 6AÊmS0_a!v#Agm3oytO?X!NEGJa'smƵ *w Rk(eزpdp.)#l'ƠGD %z>0[ ^>ܣ>>J%Q}[Ѱ=&HRr6B\jhsmh>d2C<反@E9of}nQPvNCڭJ;˼MtSmDܞ$# x=c釷NԹ6ޛڻS3'v2@FlH뽍Y'`%~?9>L0NLj Svl5Tt fS-D=9 QmihKv]Z%'U9nWMdlx=ct%Qiq¿W>v>f|zEme~SmGP`v~9mvh7\,[鵧:9t^V2m۶@~=SYNe*uC jJynyPvGʶØ?E?Ex^,)eI1?ĝ8SMR"=pRvp7hU+!04a=RNzZ%](vExr ;z]S}]x# 04a=RNzZ-Jâ;2ޠJbؕ| wPK2mwKCNZVp+h_l(UDK-ı@Jӯiigʾvԟ.BG):!scT$H(-8srcd3q 翳c'Pbv 3/4^M:{[;߁{B#˽&[L(e&d!sCr,kuK٢{8ܱ EJou4]81 6qsE l,Is[ERL;Yqu;T[oݗ^4h~olg![옘im[r"A)6r4[ T.cWi4g12Zm3/_2ܽ ߉t߱]c]b:Ŗ5Rve#'gnp-/`"] wY)ob{ S ڮ/v~9߿7Wendstream endobj 7 0 obj 5198 endobj 10 0 obj <> endobj 11 0 obj <> endobj 5 0 obj <> /Contents 6 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 5 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 4 0 obj <> endobj 9 0 obj <> endobj 8 0 obj <> endobj 2 0 obj <>endobj xref 0 12 0000000000 65535 f 0000005573 00000 n 0000005820 00000 n 0000005514 00000 n 0000005621 00000 n 0000005363 00000 n 0000000015 00000 n 0000005283 00000 n 0000005761 00000 n 0000005690 00000 n 0000005303 00000 n 0000005333 00000 n trailer << /Size 12 /Root 1 0 R /Info 2 0 R >> startxref 5872 %%EOF interval-3.2.0/src/crlibm/docs/latex/log.tex0000644000000000000000000017210313316017127017102 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA There are two versions of the logarithm. \begin{itemize} \item The first relies on 80-bit double-extended arithmetic, and is well suited to IA32 and IA64 architectures which have hardware support for such arithmetic. It computes the quick step in double-extended arithmetic, and the accurate step in double-double-extended arithmetic. \item The second relies only on double-precision arithmetic, and is portable. It uses double-double for the quick step, and triple-double for the accurate step. \end{itemize} Both implementations use the same algorithm, which is detailed in \ref{sec:logoutline}. Sections \ref{sec:logdeproof} and \ref{sec:logtdproof} detail the proof of both implementations, and \ref{sec:logperf} give some performance results. \section{General outline of the algorithm\label{sec:logoutline}} The algorithm used is mainly due to Wong and Goto\cite{WG94} and has been discussed further in \cite{Muller97}. In the case we are given here, both quick and accurate phase use principally the same algorithm however optimized for different accuracies. The function's argument $x \in \F$ is first checked for special cases, such as $x\leq0$, $+\infty$, $\nan$ etc. These checks are mainly implemented using integer arithmetics and will be further explained in section \ref{subsec:reduction}. Then, the argument is reduced using integer arithmetics as follows: $$x = 2^{E^\prime} \cdot m$$ where $E^\prime$ is the exponent of $x$ and $m$ a double corresponding to the mantissa of $x$. This decomposition is done such that in any case, i.e. even if $x$ is subnormal, $1 \leq m < 2$. In the subnormal case, the exponent of $x$ is adjusted accordingly. This first argument reduction corresponds to the equality $$\log\left( x \right) = E^\prime \cdot \log\left(2\right) + \log\left(m \right)$$ Using this term directly would lead to catastrophic cancellation in the case where $E^\prime = -1$ and $m \approx 2$. To overcome this difficulty, a second adjustment is done as follows: \begin{center} \begin{tabular}{cc} \begin{minipage}{50mm} $$E = \left \lbrace \begin{array}{lcl} E^\prime & \mbox{ if } & m \leq \sqrt{2} \\ E^\prime +1 & \mbox{ if } & m > \sqrt{2} \end{array} \right.$$ \end{minipage} & \begin{minipage}{50mm} $$y = \left \lbrace \begin{array}{lcl} m & \mbox{ if } & m \leq \sqrt{2} \\ \frac{m}{2} & \mbox{ if } & m > \sqrt{2} \end{array} \right.$$ \end{minipage} \end{tabular} \end{center} The decision whether $m \leq \sqrt{2}$ or not is performed using integer arithmetics on the high order bits of the mantissa $m$. The test is therefore not completely exact which is no disadvantage since, in any case, the bound $\sqrt{2}$ is somewhat arbitrary.\par All the previous reduction steps can be implemented exactly as they consist mainly in decompositions of a floating point number, multiplications by powers of $2$ and integer additions on the corresponding exponent value. All this leads to the following equation $$\log\left( x \right) = E \cdot \log\left( 2 \right) + \log\left( y \right)$$ where $$-\frac{1}{2} \cdot \log\left( 2 \right) \leq \log\left( y \right) \leq \frac{1}{2} \cdot \log\left( 2 \right)$$ The magnitude of $y$ is thus still too great for allowing for a direct polynomial approximation of $\log\left(y\right)$. Therefore, a second argument reduction step is performed using a table of $128$ entries as follows: using the high order bits of $y$ as an index $i$, a tabulated value $r_i$ is looked up which approximated very well $\frac{1}{y}$. Setting $z = y \cdot r_i - 1$, one obtains $$\log\left( y \right) = \log\left( 1 + z \right) - \log\left( r_i \right)$$ Since $y = \frac{1}{r_i} + \delta$ the magnitude of $z$ is finally small enough (typically $\left \vert z \right \vert < 2^{-8}$) for approximating $\log\left(1+z\right)$ by a Remez polynomial $p\left(z\right)$. The values for $\log\left(r_i\right)$ are of course also tabulated. It is important to notice that the reduction step $$z = y \cdot r_i - 1$$ can be implemented exactly which eases the correctness proof of the algorithm. This property will be proven in section \ref{subsec:reduction}. The reduced argument $z$ will be represented as a double-double number $z_\hi + z_\lo$ that will be fed into the polynomial approximation algorithms of both quick and accurate phase. Each of these phases will take into account the lower significant value $z_\lo$ for more or less higher monomial degrees. Both phases will finally reconstruct the function's value as follows: $$\log\left( x \right) \approx E \cdot \log\left( 2 \right) + p\left( z \right) - \log\left( r_i \right)$$ using a double (respectively a triple for the accurate phase) double value for each $\log\left( 2 \right)$ and $-\log\left( r_i \right)$. The computations necessary for performing this reconstruction are carried out in double-double arithmetics for the quick phase and triple-double for the accurate phase. The quick phase uses a modified Remez polynomial of degree $7$ of the form $$p\left( z \right) = z - \frac{1}{2} \cdot z^2 + z^3 \cdot \left( c_3 + z \cdot \left( c_4 + z \cdot \left( c_5 + z \cdot \left( c_6 + z \cdot c_7 \right) \right) \right) \right)$$ with $c_i \in \F$. This polynomial is evaluated as indicated by the parenthesis in the following term: $$p\left( z_\hi + z_\lo \right) \approx \left( \left(z_\hi + z_\lo \right) - \frac{1}{2} \cdot z_\hi^2\right) + \left( \left( - z_\hi \cdot z_\lo \right) + \left(z_\hi^2 \cdot z_\hi \right) \cdot \left( c_3 + z_\hi \cdot \left( c_4 + z_\hi \cdot \left( c_5 + z_\hi \cdot \left( c_6 + z_\hi \cdot c_7 \right) \right) \right) \right) \right)$$ The mathematical relative approximation error of the polynomial $p\left( z \right)$ defined as $$\epsilon_{\mbox{\tiny meth}} = \frac{p\left( z \right) - \log\left( 1 + z \right)}{\log\left(1 + z \right)}$$ is bounded by $$\left \vert \epsilon_{\mbox{\tiny meth}} \right \vert \leq 2^{-62.99}$$ This methodical error is joined by the arithmetical error induced by the evaluation of $p\left( z \right)$ and by the rounding of the constants $\log\left( 2 \right)$ and $\log\left( r_i \right)$. As will be shown in section \ref{subsec:quickphase}, the overall error of the quick phase defined as $$\epsilon_{\mbox{\tiny quick}} = \frac{\left(log_\hi + log_\lo\right) - \log\left(x\right)}{\log\left(x\right)}$$ is bounded by $$\left \vert \epsilon_{\mbox{\tiny quick}} \right \vert \leq 5 \cdot 2^{-65} \leq 2^{-62.6}$$ ~ \par After the computation of the quick phase double-double value $\left( log_\hi + log_\lo \right)$ a rounding test is performed using the rounding constants according to \ref{th:roundingRN1}. If the rounding cannot be decided, the accurate phase is launched. \par The accurate phase performs all its computations on the same reduced argument $z = z_\hi + z_\lo$ which will be shown to be exact. An approximation polynomial of degree $14$ is used. It is once again a modified Remez polynomial and has the following form: $$p\left( z \right) = z + \frac{1}{2} \cdot z + z^3 \cdot q\left( z \right)$$ where $$q\left( z \right) = c^\prime_3 + z \cdot \left( c^\prime_4 + z \cdot \left( c^\prime_5 + z \cdot \left( c^\prime_6 + z \cdot \left( c^\prime_7 + z \cdot \left( c^\prime_8 + z \cdot \left( c^\prime_9 + z \cdot r\left( z \right) \right) \right) \right) \right) \right) \right)$$ with $c^\prime_i = c_{i\hi} + c_{i\lo} \in \F + \F$ and $$r\left( z \right) = c_{10} + z \cdot \left( c_{11} + z \cdot \left( c_{12} + z \cdot \left( c_{13} + z \cdot c_{14} \right) \right) \right)$$ with $c_i \in \F$. The mathematical relative error $$\epsilon_{\mbox{\tiny meth}} = \frac{p\left( z \right) - \log\left( 1 + z \right)}{\log\left( 1 + z \right)}$$ is bounded by $$\left \vert \epsilon_{\mbox{\tiny meth}} \right \vert \leq 2^{-125}$$ The polynomial is evaluated using double precision for $r\left( z \right)$, double-double arithmetic for $q\left( z \right)$ and a triple-double representation for $p\left( z \right)$ and the final reconstruction. The overall error $$\epsilon_{\mbox{\tiny accurate}} = \frac{\left( log_\hi + log_\mi + log_\lo \right) - \log\left( x \right)}{\log\left( x \right)}$$ is bounded by $$\left \vert \epsilon_{\mbox{\tiny accurate}} \right \vert \leq 5735 \cdot 2^{-132} \leq 2^{-119.5}$$ as will be shown in section \ref{subsec:accuratephase}. Here $\left( log_\hi + log_\mi + log_\lo \right)$ are obtained by reconstructing the logarithm as indicated by the parenthesis in the following term: $$log_\hi + log_\mi + log_\lo = \left(E \cdot \left( log2_\hi + log2_\mi + log2_\lo \right) \right) + \left( \left( p_\hi + p_\mi + p_\lo \right) + \left(logi_\hi + logi_\mi + logi_\lo \right) \right)$$ where $log2_\hi + log2_\mi + log2_\lo \approx \log\left( 2 \right)$ and $logi_\hi + logi_\mi + logi_\lo \approx -\log\left(r_i \right)$. Since the critical accuracy of the double precision $\log$ function is $118$ bits according to \cite{DinDefLau2004LIP}, rounding $\log_\hi + log_\mi + log_\lo \approx \log\left( x \right)$ to double precision is equivalent to rounding the infinite precision value $\log\left( x \right)$ to double precision. Using the final rounding sequences presented in \cite{Lauter2005LIP:tripledouble}, which are supposed to be correct, the double precision value returned by the function is the correctly rounded double precision value of $\log\left( x \right)$. \section{Proof of correctness of the triple-double implementation \label{sec:logtdproof}} Proving that an implementation of an elementary function is correctly rounded means mainly proving two bounds on the relative error $\epsilon_{\mbox{\tiny quick}}$ and $\epsilon_{\mbox{\tiny accurate}}$, using the appropriate lemma for proving the correctness of the rounding test and conluding by means of the theorem stating the critical accuracy of the function considered. The computation of the error bounds will be done mainly using the Gappa tool\cite{Melqu05} but some parts of the proof are still based on paper or Maple computations. These parts will be shown in sections \ref{subsec:reduction}, \ref{subsec:quickphase} and \ref{subsec:accuratephase} and mainly comprise the following: \begin{itemize} \item the demonstration that all special cases are handled correctly, \item a proof that $z_\hi + z_\lo = r_i \cdot y - 1$ exactly, \item the bounds for the mathematical approximation errors for the polynoms, \item a proof of the exactness of some multiplications in the code, \item the proof for the accuracy of all basic addition and multiplication code sequences on double-double and triple-double numbers, \item the correctness proof of the final rounding sequences for rounding triple-double numbers to double precision and \item the mathematical equality of the term rewriting hints in the Gappa code. \end{itemize} The proofs for the accuracy of the basic operation bricks and the correctness proof of the final rounding sequences are somewhat lengthy and are not given here; they can be found in \cite{Lauter2005LIP:tripledouble}. \subsection{Exactness of the argument reduction\label{subsec:reduction}} In this section, we will show that all special cases are handled correctly and that the reduced argument consisting in $E$ and $z_\hi + z_\lo$ is exact, which means that we have the mathematically exact equation $$\log\left( x \right) = E \cdot \log\left( 2 \right) + \log\left( 1 + \left( z_\hi + z_\lo \right) \right) - \log\left( r_i \right)$$ This part of the algorithm is performed by the following code sequences which we will analyse line by line: \begin{lstlisting}[caption={Handling of special cases and table access},firstnumber=1] E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= ((db_number) ((double) two52)).d; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Do argument reduction */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; ed = (double) E; ri = argredtable[index].ri; logih = argredtable[index].logih; logim = argredtable[index].logim; \end{lstlisting} Analysis of the code: {\renewcommand{\labelenumi}{} \begin{enumerate} \item line 1 and 2: Initialization of integer $E$ and {\tt db\_number} {\tt xdb} which is now equal to $x$. \item line 5: As the integer ordering and the ordering on floating point numbers are compatible, $x < +2^{-1022}$, i.e. negative, negative infinite, equal to zero or a subnormal. \item line 6: {\tt xdb.i[HI] \& 0x7fffffff} is the high order word of $x$ without the sign bit. If the test is true, $\left \vert x \right \vert = 0$. As the logarithm of $0$ is not defined but as the limit $-\infty$ is known, returning $-1.0 / 0.0$ is correct. \item line 9: Since the integer ordering and the ordering on floating point numbers are compatible, {\tt xdb.i[HI] < 0} implies $x < 0$. The logarithm is not defined for negative numbers, so the result must be $\nan$. $0.0 / 0.0$ leads to a $\nan$; one uses $\left(x - x\right) / 0.0$ in order to overcome the static tests of the compiler. \item line 13 and 14: if this code lines are reached, $x$ is a subnormal. Since $E$ equals $0$ at this point, setting it to $-52$ and multipliying {\tt xdb} by $2^{-52}$ means bringing {\tt xdb} to the normal number range and rescaling the internal representation $x = 2^E \cdot m = 2^E \cdot${\tt xdb} in consequence. \item line 17: As the integer ordering and the ordering on floating point numbers are compatible and as {\tt 0x7fefffff ffffffff} is the greatest normal, the test being true implies that $x$ is equal to $+\infty$ or $\nan$. In the case of $x=+\infty$, $+\infty$ must be returned which is done. In the other case, $\nan$ must be returned which is still assured by $x + x$. \item line 23: At this point of the code, the most significant bit of the high order word of {\tt xdb} must be $0$ as the case where $x < 0$ is already filtered out. So {\tt xdb.i[HI] > > 20} is equal to the biased exponent of {\tt xdb} because a double number consists in $1$ sign bit, $11$ exponent bits and the word bit length is supposed to be $32$. Subtracting $1023$ yields to the unbiased exponent which is written to $E$. \item line 24 and 25: Since a double number consists in $1$ sign bit and $11$ exponent bits, the operation {\tt xdb.i[HI] \& 0x000fffff} masks out the mantissa bits in the higher order word of {\tt xdb}. Rewriting {\tt xdb.i[HI] = index | 0x3ff00000} means setting the exponent of {\tt xdb} to $0$ because {\tt 0x3ff}$ - 1023 = 0$. \item line 26: Before execution of this line of code, {\tt index} contains the high order bits of the normalized mantissa of $x$ stored as a double in {\tt xdb.d} and verifying thus $1 \leq m < 2$. The second argument reduction step will slice this intervall in $128$ intervalls for each of which we dispose of a table entry. For reasons of possible cancellation in the reconstruction step on the operation $p\left( z \right) - \log\left( r_i \right)$, we want the small intervalls to be centered around $1$. That means e.g. for the intervall around $1$ and a table indexed by $7$ bits that mantissas (as doubles) with the high order word {\tt 0x3fefffff} through {\tt 0x3ff00fff} must be mapped to $0$. The decision is therefore made at the $7+1$th bit of the mantissa part of the double depending on whether this bit is $0$ -- in which case the value falls in the lower intervall -- or $1$ -- in which case the value goes to the next higher intervall. So adding $1$ to the $\left(20 - 7 - 1\right)$ rightmost bit ($L = 7$) increases the index value by $1$ iff this bit is $1$. So after execution of the line, {\tt index} contains the number of the intervall for the second argument reduction step centered in $1$. \item line 29 through 31: The second adjustment to be made on $E^\prime$ and $m$ is the decision whether $m > \sqrt{2}$ as indicated in section \ref{sec:logoutline}. The high order word of $\sqrt{2}$ rounded to a double is {\tt 0x3ff6a09e}. As one can simply verify, the value for {\tt index} calculated for this value is $53$. As the integer ordering and the ordering of floating point numbers are compatible and as the computations for computing {\tt index} are monotone, {\tt index} being greater or equal than $53$ implies that the (normalized) mantissa of $x$ is greater than $\sqrt{2} + \delta$ with a neglectable error $\delta$. As {\tt MAXINDEX} is equal to $53$, the test will be true iff the adjustment on $E^\prime$ leading to $E$ and $m$ yielding $y$ is to be made. It is trivial to see that the code in the {\tt if}'s body implements the adjustment correctly. \item lines 33 and 34: the final value of the reduced argument $y$ -- still stored in {\tt xdb.d} -- is copied to a {\tt double} variable (or register) named {\tt y}. The final index value is masked out by means of an {\tt INDEXMASK} which is equal to $127 = 2^7-1$. \item lines 36: The integer value of the exponent $E$ stored in {\tt E} is cast to a {\tt double ed}. \item lines 38 through 41: The table is indexed by {\tt index} and values {\tt ri}$=r_i$ and {\tt logih}$=logi_\hi$ and {\tt logim}$=logi_\mi$ are read. Since the latter form a double-double precision value, we know that $logi_\hi + logi_\mi = \log\left( r_i \right) \cdot \left( 1 + \epsilon \right)$ with $\left \vert \epsilon \right \vert \leq 2^{-106}$. The value {\tt ri} is stored as a single precision variable and a Maple procedure assures that for each value $y$ the following inegality is verified: $$\left \vert z \right \vert = \left \vert y \cdot r_i - 1 \right \vert \leq 2^{-8}$$ \end{enumerate} } Let us show now that the following line calculate $z_\hi$ and $z_\lo$ such that for each $y$ and corresponding $r_i$, we obtain exactly $$z_\hi + z_\lo = y \cdot r_i - 1$$ \begin{lstlisting}[caption={Argument reduction},firstnumber=42] Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); \end{lstlisting} We know that we can suppose that the multiplication and addition sequences \Mul~ and \Add~ used at lines 42 and 44 are exact. Thus, it suffices to show that $$yri_\hi - 1.0 = yri_\hi \ominus 1.0$$ because in that case, we can note $$z_\hi + z_\lo = th + yri_\lo = yri_\hi \ominus 1.0 + yri_\lo = y \cdot r_i - 1.0$$ We will show this property using Sterbenz' lemma. It suffices thus to prove that $$\frac{1}{2} \leq yri_\hi \leq 2$$ We know that \begin{eqnarray*} yri_\hi & = & \circ\left( y \cdot r_i \right) \\ & \leq & \circ \left( 1 + 2^{-8} \right) \\ & = & 1 + 2^{-8} \\ & < & 2 \end{eqnarray*} since the rounding function $\circ$ is monotonic and the accuracy of the format is greater than $9$ bits. The other way round, we get \begin{eqnarray*} yri_\hi & = & \circ \left( y \cdot r_i \right) \\ & \geq & \circ \left( 1 - 2^{-8} \right) \\ & = & 1 - 2^{-8} \\ & > & \frac{1}{2} \end{eqnarray*} for the same reasons. Thus $z_\hi + z_\lo = y \cdot r_i$ exactly. Since the previous phases of the argument reduction were all exact, the reduced argument verifies $x = 2^{E} \cdot y$ exactly. Still in this section, let us show that neither the reduced argument of the logarithm function nor its result may be a sub-normal double number. The first property has already been assured by special case handling as shown above. The latter can be proven as follows: the $\log\left( x \right)$ function has one zero for $x = 1$ and only one. As it is monotone, for $x = 1 \pm 1 \mUlp = 1 \pm 2^{-52}$ we will obtain $\log\left( 1 \pm 2^{-52} \right) = 0 \pm 2^{-52} + \delta$ with $\left \vert \delta \right \vert \leq 2^{-103}$. As $0 \pm 2^{-1022}$ is the least normal, the result of the logarithm function will always be a normal. Further, in both double-double and triple-double representations for the final intermediate result for the function, as its critical accuracy is $118$, the least significant double in the representation will still be a normal as $52 + 106 = 158 < 1022$. \subsection{Accuracy proof of the quick phase\label{subsec:quickphase}} As already mentionned, the accuracy proof of the quick phase is mainly based on the Gappa tool. To prove the desired accuracy bound defined as $$\epsilon_{\mbox{\tiny quick}} = \frac{\left(log_\hi + log_\lo\right) - \log\left(x\right)}{\log\left(x\right)}$$ and given by $$\left \vert \epsilon_{\mbox{\tiny quick}} \right \vert \leq 5 \cdot 2^{-65} \leq 2^{-62.6}$$ three different Gappa proof files are necessary depending on the following cases: \begin{itemize} \item for $E \geq 1$ and all indexes to the table $0 \leq i \leq 127$, a general proof file named {\tt log-td.gappa} is used \item for $E = 0$ and all indexes to the table except $0$, i.e. $1 \leq i \leq 127$, a proof file named {\tt log-td-E0.gappa} comes to hand and \item for $E = 0$ and the table index $i = 0$, a proof file called {\tt log-td-E0-logir0.gappa} is employed. This latter file uses relative error computations in opposition to the other two cases where absolute error estimates suffice. This is necessary because in this case and in this one only, the logarithm function has a zero in the intervall considered. \end{itemize} In each of the three proof files, we will ask the Gappa tool to verify the accuracy bound expressed in its syntax as follows: \begin{lstlisting}[caption={Accuracy bound to prove},firstnumber=109] -> ((logh + logm) - Log) / Log in [-5b-65,5b-65] \end{lstlisting} Still in any proof file, some hypothesis are made on the correctness of one multiplication sequence and the accuracy of the constants and resting operations carried out in double-double arithmetic. These hypothesis are the following: \begin{itemize} \item The operations in the following code sequence are exact since the constants are stored with enough trailing zeros: \begin{lstlisting}[caption={Multiplication by $E$},firstnumber=50] Add12(log2edh, log2edl, log2h * ed, log2m * ed); \end{lstlisting} This means that $log2ed_\hi + log2ed_\lo = E \cdot \left( log2_\hi + log2_\lo \right)$ exactly. \item The operations in the following code sequence are exact since multiplications with a power of $2$ are exact as long as the result is not underflowed: \begin{lstlisting}[caption={Multiplication by $-0.5$},firstnumber=60] zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; \end{lstlisting} i.e. $zhSquareHalf_\hi + zhSquareHalf_\lo = -0.5 \cdot \left( zhSquare_\hi + zhSquare_\lo \right)$. \item The following hypothesis on the accuracy bounds, expressed here in Gappa syntax, are verified: \begin{lstlisting}[caption={Gappa hypothesis},firstnumber=100] (T2hl - T2) / T2 in [-1b-103,1b-103] /\ (Phl - PE) / PE in [-1b-103,1b-103] /\ (LogTabPolyhl - LogTabPoly) / LogTabPoly in [-1b-103,1b-103] /\ (Loghm - LogE) / LogE in [-1b-103,1b-103] /\ (Log2hm - Log2) / Log2 in [-1b-84,1b-84] /\ (Logihm - Logir) / Logir in [-1b-106,1b-106] /\ Z in [_zmin,_zmax] /\ (P - Log1pZ) / Log1pZ in [-_epsilonApproxQuick,_epsilonApproxQuick] /\ ((logh + logm) - Loghm) / Loghm in [-1b-106,1b-106] \end{lstlisting} Here, {\tt \_zmin}, {\tt \_zmax} and {\tt \_epsilonApproxQuick} are replaced by Maple calculated values, typically $-zmin = zmax = 2^{-8}$ and $epsilonApproxQuick = 2^{-62.99}$. \end{itemize} Let us now show each of this hypothesises. \begin{enumerate} \item The operations yielding {\tt log2edh} and {\tt log2edl} are all exact because the \Add~ sequence is supposed to be exact in any case and because the constants {\tt log2h} and {\tt log2m} are calculated by the following Maple code and have in consequence at least 11 trailing zeros and {\tt ed} $=E$ is less than $1024$ in magnitude since $1024$ is the maximum exponent value for double precision. \begin{lstlisting}[caption={Maple code for computing {\tt log2h} and {\tt log2m}},firstnumber=21,label={list:maplelog2}] log2acc := log(2): log2h := round(log2acc * 2**(floor(-log[2](abs(log2acc))) + (53 - 11))) / 2**(floor(-log[2](abs(log2acc))) + (53 - 11)): log2m := round((log2acc - log2h) * 2**(floor(-log[2](abs((log2acc - log2h)))) + (53 - 11))) / 2**(floor(-log[2](abs((log2acc - log2h)))) + (53 - 11)): \end{lstlisting} \item To show that $zhSquareHalf_\hi + zhSquareHalf_\lo = -0.5 \cdot \left( zhSquare_\hi + zhSquare_\lo \right)$ we just have to show that both values $zhSquare_\hi$ and $zhSquare_\lo$ are either equal to $0$ or greater than $2$ times the smallest normal. Let us first give the definitions of both values: \begin{eqnarray*} zhSquare_\hi & = & \circ \left( z_\hi \cdot z_\hi \right) \\ zhSquare_\lo & = & z_\hi \cdot z_\hi - zhSquare_\hi \end{eqnarray*} where $z_\hi = \circ \left( z \right)$. Let us suppose that $z \not = 0$. Otherwise all values are equal to $0$ and we can conclude. Let us first show that $\left \vert zhSquare_\hi \right \vert$ is greater than $2^{54}$ times the smallest normal. Let us therefore suppose that this is not the case, i.e. $\left \vert zhSquare_\hi \right \vert < 2^{-948}$. Since the rounding function is monotonic, this implies that $\left \vert z_\hi \right \vert \leq 2^{-424}$. For the same reason, we can note that $\left \vert z \right \vert \leq 2^{-424}$. As we have $z = y \cdot r_i - 1$, clearly neither $y$ nor $r_i$ can be exactly $1$. If this were the case for both, we would obtain $z=0$ which we excluded; if there were one of them only that was exactly $1$, the other being a floating point number in the intervall $\left[ 0.5; 1.5 \right]$, the resulting inegality $\left \vert z \right \vert \geq 2^{-53}$ which would be contradictory. Otherwise, since we know that $1 - 2^{-8} \leq y \cdot r_i \leq 1 + 2^{-8}$ and since the precision of all formats used is greater than $9$, the hypothesis that $1 - 2^{-424} \leq y \cdot r_i \leq 1 + 2^{-424}$ and $y \cdot r_i \not = 0$ would imply that the infinite precision mantissa of $y \cdot r_i$ contains a $1$ weighted with $2^0$ and a $1$ weighted with less than $2^{-424}$. So its length would be greater than $423$ bits. As it is the product of two floating point numbers which have $52$ and $23$ significant bits, there cannot be a $1$ weighted with less than $76$ if there is a $1$ weighted with $2^0$ which is the case. Contradiction. So $-0.5 \cdot zhSquare_\hi$ is not underflowed. Additionally, with a similar argument, since {\tt zh} is a double precision number, $zhSquare_\lo$ is either $0$ or greater in magnitude than $2^{-53} \cdot \left \vert zhSquare_\hi \right \vert$ which is $2^{52}$ times greater in magnitude than the smallest normal. So $zhSquare_\lo$ is either $0$ or $2$ times greater in magnitude than the smallest normal. So, the floating point multiplication of $zhSquare_\hi$ and $zhSquare_\lo$ with $-0.5$ can be considered to be exact. \item {\tt (T2hl - T2) / T2 in [-1b-103,1b-103]} which means that $$\left \vert \frac{T2hl - T2}{T2} \right \vert \leq 2^{-103}$$ is verified as $T2hl$ and $T2$ are defined as follows: $$T2hl = t2_\hi + t2_\lo \gets \mAddDD \left( z_\hi, z_\lo, zhSquareHalf_\hi, zhSquareHalf_\lo \right)$$ $$T2 = \left( z_\hi + z_\lo \right) + \left( zhSquareHalf_\hi + zhSquareHalf_\lo \right)$$ The given bound is thus just the accuracy bound of the \AddDD~ sequence for which a proof can be found in \cite{Lauter2005LIP:tripledouble}. \item {\tt (Phl - PE) / PE in [-1b-103,1b-103]} is verified for the same reason; let us just recall the definitions $$Phl = p_\hi + p_\lo \gets \mAddDD \left( t2_\hi, t2_\lo, t1_\hi, t1_\lo \right)$$ $$PE = \left( t2_\hi + t2_\lo\right) + \left( t1_\hi + t1_\lo \right)$$ \item {\tt (LogTabPolyhl - LogTabPoly) / LogTabPoly in [-1b-103,1b-103]} falls still into the same case with $$LogTabPolyhl = logTabPoly_\hi + logTabPoly_\lo \gets \mAddDD \left( logi_\hi, logi_\mi, p_\hi, p_\lo \right)$$ $$LogTabPoly = \left( logi_\hi, + logi_\mi \right) + \left( p_\hi + p_\lo \right)$$ \item And finally, {\tt (Loghm - LogE) / LogE in [-1b-103,1b-103]} which is also just the accuracy bound of the \AddDD~ sequence for $$Loghm = log_\hi + log_\mi \gets \mAddDD \left( log2ed_\hi, log2ed_\lo, logTabPoly_\hi, logTabPoly_\lo \right)$$ $$LogE = \left( log2ed_\hi + log2ed_\lo \right) + \left( logTabPoly_\hi + logTabPoly_\lo \right)$$ \item {\tt (Log2hm - Log2) / Log2 in [-1b-84,1b-84]} is verified since $log2_\hi$ and $log2_\mi$ are computed as already indicated in listing \ref{list:maplelog2}. This means that at least $11$ trailing zeros are stored in each in the doubles in this (pseudo-)double-double number, so it is exact to $2^{-106-2 \cdot 11} = 2^{-84}$. \item {\tt (Logihm - Logir) / Logir in [-1b-106,1b-106]} which means $$\left \vert \frac{\left( logi_\hi + logi_\mi \right) - \log\left( r_i \right)}{\log\left( r_i \right)} \right \vert \leq 2^{-106}$$ is verified by construction as $logi_\hi$ and $logi_\mi$ are computed by the following Maple code: \begin{lstlisting}[caption={Maple code for computing $logi_\hi$ and $logi_\mi$},firstnumber=35] (logih[i], logim[i], logil[i]) := hi_mi_lo(evalf(-log(r[i]))): \end{lstlisting} where {\tt hi\_mi\_lo} is the procedure for rounding an arbitrary precision number to a triple-double number the higher significant numbers of which form a double-double number. \item The hypothesis {\tt Z in [\_zmin,\_zmax]} simply recalls the bounds for $z$ as calculated by Maple. \item The same can be said on the hypothesis \\ {\tt (P - Log1pZ) / Log1pZ in [-\_epsilonApproxQuick,\_epsilonApproxQuick]} \\ which gives the mathematical approximation error of the polynomial. This bound is computed by Maple using the following instructions: \begin{lstlisting}[caption={Maple code for computing the relative error of the polynomial},firstnumber=129] epsilonApproxQuick := numapprox[infnorm]( 1-polyQuick/log(1+x), x=zminmin..zmaxmax) \end{lstlisting} \item Finally, Gappa's hypothesis {\tt ((logh + logm) - Loghm) / Loghm in [-1b-106,1b-106]} simply restates the fact that a double-double precision number is exact to at least $2^{-106}$ in terms of its relative error. \end{enumerate} The Gappa tool itself is not capable of proving the final accuracy bound it is asked for a complex algorithm as the one given here. Its user must provide hints to help it to rewrite the interval arithmetics terms it encounters in the program. These hints are generally given in the form {\tt $\alpha$ -> $\beta$} where $\beta$ is an expression we want the tool to rewrite the expression $\alpha$ by. Generally speaking, the idea behind each hint is one of the following: \begin{itemize} \item For computing intervall bounds on differences like $\alpha = a - A$ where both $a$ and $A$ are sums of terms like $a = c + C$ and $B = d + D$, it is often useful to rewrite $\alpha$ by $\beta = \left(c - d \right) + \left( C - D \right)$. \item An intervall bound can often be easier found for a term $A$ representing an exact mathematical value that for $a$ which is its arithmetical equivalent. So it is useful to rewrite $a$ by $A \cdot \left( 1 + \frac{a - A}{A} \right)$ when an intervall for $\frac{a - A}{A}$ is known. \item Fractional left hand sides like $\frac{a}{b}$ where both expressions $a$ and $b$ are functions in a common argument $x$ that can be written like $a = a\left( x \right) = x^n \cdot a^\prime\left( x \right)$ and $b = b\left( x \right) = x^m \cdot b^\prime\left( x \right)$ should usually be rewritten as follows: $$\frac{a\left(x\right)}{b\left( x \right)} = \frac{x^n \cdot a^\prime\left( x \right)}{x^m \cdot b^\prime\left( x \right)} = x^{n - m} \cdot \frac{a^\prime\left( x \right)}{b^\prime\left( x \right)}$$ In particular, this kind of hint is needed when an intervall for the denominator of a fractional left-hand-side comprises $0$. \item Fractional left-hand-sides of the form $\frac{a - A}{A}$ with an unknown $A$ can easily be written like $$\frac{a - A}{A} = \frac{a - B}{B} + \frac{B - A}{A} + \frac{a - B}{B} \cdot \frac{B - A}{A}$$ We can show this equivalence like this \begin{eqnarray*} \frac{a - A}{A} & = & \frac{a - B + B - A}{A} \\ & = & \frac{a - B}{A} + \frac{B - A}{A} \\ & = & \frac{a - B}{B} \cdot \frac{B}{A} + \frac{B - A}{A} \\ & = & \frac{a - B}{B} \cdot \left( 1 + \frac{B - A}{A} \right) + \frac{B - A}{A} \\ & = & \frac{a - B}{B} + \frac{B - A}{A} + \frac{a - B}{B} \cdot \frac{B - A}{A} \end{eqnarray*} This is particularly useful when a bound on the relative error of some term $a$ with regard to $B$ should be extended to the next approximation level. \end{itemize} Clearly, the left-hand-side $A$ and right-hand-side $B$ of an hint must be mathematically equivalent to provide a correct result. The Gappa tool checks for this equivalence and sometimes is able to prove it. If not, it emits a warning indicating that the formal proof it is generating for the accuracy bound computations is valid only under the hypothesis that both sides of the rewriting hint are mathematically equivalent. Further, it prints out the difference $A - B$ of both sides $A$ and $B$ which it has already reduced using the equivalences given in the Gappa code. It is relatively simple to verify that all this differences are equal to $0$ modulo the definitions given in the Gappa code by means of Maple-scripts. This work can even been done automatically. Thus, we refrain from giving a paper proof of each hint in the Gappa files used for proving the logarithm function but just give the exhaustive list of the hints in files {\tt log-td.gappa} and {\tt log-td-E0-logir0.gappa}: \begin{lstlisting}[caption={Gappa term rewriting hints in file {\tt log-td.gappa}},firstnumber=115] T2hl - T2 -> ((T2hl - T2) / T2) * T2; T2hl -> (T2hl - T2) + T2; Phl - PE -> ((Phl - PE) / PE) * PE; Phl -> (Phl - PE) + PE; LogTabPolyhl -> (LogTabPolyhl - LogTabPoly) + LogTabPoly; Loghm -> (Loghm - LogE) + LogE; Log2 -> Log2hm * (1 / (((Log2hm - Log2) / Log2) + 1)); Logir -> Logihm * (1 / (((Logihm - Logir) / Logir) + 1)); LogTabPolyhl - LogTabPoly -> ((LogTabPolyhl - LogTabPoly) / LogTabPoly) * LogTabPoly; HZZsimp -> (-0.5 * zh * zh) - (0.5 * zl * zl); T2hl - ZpHZZsimp -> (0.5 * zl * zl) + delta1; zhCube - ZZZ -> (Z * (zhSquareh - Z * Z)) - (zl * zhSquareh); polyUpper - ZZZPhigher -> ZZZ * (polyHorner - Phigher) + polyHorner * delta3 + delta2; ZpHZZ + ZZZPhigher -> ZpHZZsimp + ZZZPhigherPzhzl; Phl - P -> (T2hl - ZpHZZsimp) + (T1hl - ZZZPhigherPzhzl) + delta4; Log1pZ -> P * (1 / (((P - Log1pZ) / Log1pZ) + 1)); P - Log1pZ -> ((P - Log1pZ) / Log1pZ) * Log1pZ; Phl - Log1pZ -> (Phl - P) + delta6; LogTabPolyhl - Log1pZpTab -> (Logihm - Logir) + (Phl - Log1pZ) + delta7; Loghm - Log -> (Log2edhm - Log2E) + (LogTabPolyhl - Log1pZpTab) + delta5; (logh + logm) - Loghm -> (((logh + logm) - Loghm) / Loghm) * Loghm; (logh + logm) - Log -> ((logh + logm) - Loghm) + (Loghm - Log); \end{lstlisting} \begin{lstlisting}[caption={Gappa term rewriting hints in file {\tt log-td-E0-logir0.gappa}},firstnumber=81] T2hl - T2 -> ((T2hl - T2) / T2) * T2; T2hl -> (T2hl - T2) + T2; Phl - PE -> ((Phl - PE) / PE) * PE; Phl -> (Phl - PE) + PE; (ZhSquarehl - ZZ) / ZZ -> 2 * ((zh - Z) / Z) + ((zh - Z) / Z) * ((zh - Z) / Z); (zhSquareh - ZZ) / ZZ -> ((ZhSquarehl - ZZ) / ZZ) + ((zhSquareh - ZhSquarehl) / ZZ); (zhSquareh - ZhSquarehl) / ZZ -> ((zhSquareh - ZhSquarehl) / ZhSquarehl) * (ZhSquarehl / ZZ); ZhSquarehl / ZZ -> ((ZhSquarehl - ZZ) / ZZ) + 1; (ZhCube - ZZZ) / ZZZ -> (((zh * zhSquareh) - ZZZ) / ZZZ) + ((ZhCube - (zh * zhSquareh)) / ZZZ); ((zh * zhSquareh) - ZZZ) / ZZZ -> (1 + ((zh - Z) / Z)) * (1 + ((zhSquareh - ZZ) / ZZ)) - 1; ((ZhCube - (zh * zhSquareh)) / ZZZ) -> ((ZhCube - (zh * zhSquareh)) / (zh * zhSquareh)) * (((zh - Z) / Z) + 1) * (((zhSquareh - ZZ) / ZZ) + 1); polyHorner / Phigher -> ((polyHorner - Phigher) / Phigher) + 1; (polyUpper - ZZZPhigher) / ZZZPhigher -> ((polyHorner - Phigher) / Phigher) + ((ZhCube - ZZZ) / ZZZ) * (polyHorner / Phigher) + + ((polyUpper - (polyHorner * ZhCube)) / (polyHorner * ZhCube)) * (polyHorner / Phigher) + + ((ZhCube - ZZZ) / ZZZ) * ((polyUpper - (polyHorner * ZhCube)) / (polyHorner * ZhCube)) * (polyHorner / Phigher); ((ZhSquareHalfhl - (zh * zl)) - HZZ) / HZZ -> - ((zh - Z) / Z) * ((zh - Z) / Z); (ZhSquareHalfhl - HZZ) / HZZ -> (ZhSquarehl - ZZ) / ZZ; ((T2hl - (zh * zl)) - ZpHZZ) / ZpHZZ -> ((HZ * (((ZhSquareHalfhl - (zh * zl)) - HZZ) / HZZ)) + ((T2hl - T2) / T2) + (HZ * ((T2hl - T2) / T2)) + (HZ * ((ZhSquareHalfhl - HZZ) / HZZ) * ((T2hl - T2) / T2))) / (1 + HZ); (PE - P) / P -> (((1 + HZ) * (((T2hl - (zh * zl)) - ZpHZZ) / ZpHZZ)) + ((1 + ((zh - Z) / Z)) * (Z * ((zh - Z) / Z)) * ((Flzhzl - (zh * zl)) / (zh * zl))) + (ZZ * Phigher * ((polyUpper - ZZZPhigher) / ZZZPhigher))) / (1 + HZ + ZZ * Phigher); (Phl - P) / P -> ((PE - P) / P) + ((((PE - P) / P) + 1) * ((Phl - PE) / PE)); (Loghm - Log) / Log -> ((Loghm - P) / P) + ((P - Log) / Log) + ((Loghm - P) / P) * ((P - Log) / Log); (((logh + logm) - Log) / Log) -> (((logh + logm) - Loghm) / Loghm) + ((Loghm - Log) / Log) + (((logh + logm) - Loghm) / Loghm) * ((Loghm - Log) / Log); \end{lstlisting} For the reasons mentionned, we can consider the accuracy proof of the quick phase to be correct. \subsection{Accuracy proof of the accurate phase\label{subsec:accuratephase}} The accuracy proof of the accurate phase is also based mainly on the use of the Gappa tool. Nevertheless, since the tool is currently not directly supporting triple-double representations, some additional hand-proven accuracy bound results for the main addition and multiplication operators are needed. They can be found in \cite{Lauter2005LIP:tripledouble}. Since all these accuracy bounds are parameterized by the maximal overlap bound for the triple-double numbers along the computations, before being able to give a numerical value for these error bounds understood by the Gappa tool, it is necessary to do a maximal overlap bound analysis using the theorems given in \cite{Lauter2005LIP:tripledouble}.\par Eventually, since not an overlapped triple-double intermediate result is to be returned by the logarithm function but a double precision number that is the correct rounding according to the rounding mode chosen, the algorithm effectuates a renormalizing operation on the final result and rounds this non-overlapped result down to a double using an appropriate rounding sequence. All this renormalization and rounding sequences are exact and have been shown to be correct in \cite{Lauter2005LIP:tripledouble}. The same way, all properties shown in section \ref{subsec:reduction} concerning the special case handling and exactness argument reduction can be reused because the algorithm implemented in the accurate phase uses the same reduced argument and is substantially the same as for the quick phase. \par We will thus rely on all these properties and simply show the following accuracy bound $$\epsilon_{\mbox{\tiny accurate}} = \frac{\left( log_\hi + log_\mi + log_\lo \right) - \log\left( x \right)}{\log\left( x \right)}$$ is bounded by $$\left \vert \epsilon_{\mbox{\tiny accurate}} \right \vert \leq 5735 \cdot 2^{-132} \leq 2^{-119.5}$$ which will be expressed in Gappa syntax as follows: \begin{lstlisting}[caption={Accuracy bound to prove for the accurate phase},firstnumber=165] -> ((logh + logm + logl) - MLog) / MLog in [-5735b-132,5735b-132] \end{lstlisting} The Gappa proof files still make the hypothesis that two of the multiplications in the accurate phase code can be considered to be exact. This property must therefore be shown in a paper proof in the following. The first of these multiplications is the following sequence: \begin{lstlisting}[caption={Multiplication of triple-double $\circ\left( Z \cdot Z \right)$ by $-\frac{1}{2}$},firstnumber=99] zSquareHalfh = zSquareh * -0.5; zSquareHalfm = zSquarem * -0.5; zSquareHalfl = zSquarel * -0.5; \end{lstlisting} As it will be shown below, the relative error $\epsilon_{ZSquare}$ defined as $$\epsilon_{ZSquare} = \frac{\left( zSquare_\hi + zSquare_\mi + zSquare_\lo \right) - Z^2}{Z^2}$$ is bounded by $\left \vert \epsilon_{ZSquare} \right \vert \leq 2^{-149}$. Using the same argument as the one given in section \ref{subsec:quickphase}, one can show that $Z$ is either $0$ or greater in magnitude than at least $2^{-77}$. So the following is true $$Z^2 = 0 \lor \left \vert Z^2 \right \vert \geq 2^{-154}$$ If $Z^2=0$, $ZSquarehml = zSquare_\hi + zSquare_\mi + zSquare_\lo$ trivially is $0$, too, and the multiplication is with $-\frac{1}{2}$ is therefore exact. Since we can note $ZSquarehml = Z^2 \cdot \left( 1 + \epsilon_{ZSquare} \right)$, we know that in the other case, $$\left \vert ZSquarehml \right \vert \geq 2^{-155}$$ We can suppose that in the triple-double number $zSquare_\hi + zSquare_\mi + zSquare_\lo$, $zSquare_\mi$ and $zSquare_\lo$ are not overlapped at all (since $zSquare_\mi = \circ \left( zSquare_\mi + zSquare_\lo \right)$) and that $zSquare_\hi$ and $zSquare_\mi$ are not fully overlapped. So we can note $\left \vert zSquare_\mi \right \vert \leq 2^{-\beta_o} \cdot \left \vert zSquare_\hi \right \vert$ and $\left \vert zSquare_\lo \right \vert \leq 2^{-\beta_u} \cdot \left \vert zSquare_\mi \right \vert$ with $\beta_o \geq 1$ and $\beta_u \geq 53$. We will show this property below we are just supposing here. So we can verify the following \begin{eqnarray*} \left \vert ZSquarehml \right \vert & = & \left \vert zSquare_\hi + zSquare_\mi + zSquare_\lo \right \vert \\ & \leq & \left \vert zSquare_\hi \right \vert + \left \vert zSquare_\mi \right \vert + \left \vert zSquare_\lo \right \vert \\ & \leq & \left \vert zSquare_\hi \right \vert + 2^{-\beta_o} \cdot \left \vert zSquare_\hi \right \vert + 2^{-\beta_o} \cdot 2^{-\beta_u} \cdot \left \vert zSquare_\hi \right \vert \\ & \leq & 2 \cdot \left \vert zSquare_\hi \right \vert \end{eqnarray*} In consequence, we obtain $$\left \vert zSquare_\hi \right \vert \geq \frac{1}{2} \cdot \left \vert ZSquarehml \right \vert$$ and thus $$\left \vert zSquare_\hi \right \vert \geq 2^{-156}$$ under the hypothesis that it is not exactly zero. So $zSquareHalf_\hi = -\frac{1}{2} \cdot zSquare_\hi$ will never be underflowed. Let us now show first that the operations for computing $zSquareHalf_\mi$ and $zSquareHalf_\lo$ cannot both be inexact. We will use the fact that $\left \vert zSquare_\lo \right \vert \leq 2^{-53} \cdot \left \vert zSquare_\mi \right \vert$. Suppose first that $$zSquareHalf_\mi \gets - \frac{1}{2} \otimes zSquare_\mi$$ is inexact. So $\left \vert zSquare_\mi \right \vert < 2^{-1022}$ and in consequence $\left \vert zSquare_\lo \right \vert < 2^{-1022-53}$. Note that the inegality is strict. Since the least (in magnitude) representable denormalized double precision floating point number is $2^{-52} \cdot 2^{-1023}$, $zSquare_\lo = 0$ in this case. So $$zSquareHalf_\lo \gets - \frac{1}{2} \otimes zSquare_\lo$$ is exact because trivially, a multiplication with $0$ is exact. Suppose now that $$zSquareHalf_\lo \gets - \frac{1}{2} \otimes zSquare_\lo$$ is inexact. So $\left \vert zSquare_\lo \right \vert < 2^{-1022}$. Further, the least significant bit of the mantissa of $zSquare_\lo$ is $1$ because otherwise, a bit-shift in its mantissa by 1 would be an exact operation. Thus $\left \vert zSquare_\lo \right \vert \geq 2^{-52} \cdot 2^{-1023}$ and $\left \vert zSquare_\mi \right \vert \geq 2^{-1022}$. So $$zSquareHalf_\mi \gets - \frac{1}{2} \otimes zSquare_\mi$$ cannot be inexact because in this case we would have $\left \vert zSquare_\mi \right \vert < 2^{-1022}$. So, in any case, if ever $zSquareHalf_\mi + zSquareHalf_\lo$ are not exactly $-\frac{1}{2} \cdot \left( zSquare_\mi + zSquare_\lo \right)$, the error made will be $\frac{1}{2} \cdot d$ in magnitude, where $d = 0^+$ is the smallest representable denormalized non-zero double. So we can note down in this case $$zSquareHalf_\hi + zSquareHalf_\mi + zSquareHalf_\lo = - \frac{1}{2} \cdot \left( zSquare_\hi + zSquare_\mi + zSquare_\lo \right) + \delta$$ with $\left \vert \delta \right \vert \leq 2^{-1075}$. Since we know that $\left \vert - \frac{1}{2} \cdot \left( zSquare_\hi + zSquare_\mi + zSquare_\lo \right) \right \vert \geq 2^{-156}$, we can give the following bound $$\left \vert \frac{\delta}{-\frac{1}{2} \cdot \left( zSquare_\hi + zSquare_\mi + zSquare_\lo \right)} \right \vert \leq \frac{2^{-1075}}{2^{-156}} = 2^{-919}$$ So we get $$ZSquareHalfhml = - \frac{1}{2} \cdot ZSquarehml \cdot \left(1 + \epsilon\right)$$ with $\left \vert \epsilon \right \vert \leq 2^{-919}$ In contrast, since we know that $\left \vert Z \right \vert \leq 2^{-8}$ thus that $\left \vert Z^2 \right \vert \leq 2^{-16}$ but that $\left \vert Z^2 \right \vert \geq 2^{-154}$, we can assume that the infinite precision mantissa of $Z^2$ can always be written exactly with at most $154 - 16 = 138 < 149$ bits. As we can show that $\frac{1}{2} \cdot \left \vert ZSquarehml \right \vert \leq \left \vert zSquare_\hi \right \vert \leq 2 \cdot \left \vert ZSquarehml \right \vert$ we know that if ever one of $zSquare_\mi$ or $zSquare_\lo$ is such that the multiplication with $-\frac{1}{2}$ is not exact, the error made has already been accounted for in the error bound for $ZSquarehml$ with regard to $Z^2$. So the operation computing $ZSquareHalfhml$ out of $ZSquarehml$ can be considered to be exact. \par Let us now analyse the following sequence \begin{lstlisting}[caption={Multiplication of triple-double $Log2hml$ by $E$},firstnumber=126] log2edhover = log2h * ed; log2edmover = log2m * ed; log2edlover = log2l * ed; \end{lstlisting} Similar to the argumentation that has been given in section \ref{subsec:quickphase}, since $E=ed$ is bound in magnitude by $1024=2^{10}$ and since $log2_\hi$, $log2_\mi$ are stored with at least $11$ trailing bits at zero, the multiplications in these components are exact. The constant $log2_\lo$ is not stored with $11$ trailing bits at zero but it could be because we will be just supposing the bound $\left \vert \epsilon_{Log2hml} \right \vert \leq 2^{-3 \cdot 53 + 33} = 2^{-126}$ for $$\epsilon_{Log2hml} = \frac{log2_\hi + log2_\mi + log2_\lo - \log\left( 2 \right)}{\log\left( 2 \right)}$$ So the multiplication is not exact in itself but the final result is exacter than the bound we are using for it. Let us finally just recall the Maple code for computing the constants: \begin{lstlisting}[caption={Maple code for computing $Log2hml$},firstnumber=21] log2acc := log(2): log2h := round(log2acc * 2**(floor(-log[2](abs(log2acc))) + (53 - 11))) / 2**(floor(-log[2](abs(log2acc))) + (53 - 11)): log2m := round((log2acc - log2h) * 2**(floor(-log[2](abs((log2acc - log2h)))) + (53 - 11))) / 2**(floor(-log[2](abs((log2acc - log2h)))) + (53 - 11)): log2l := log2acc - (log2h + log2m): \end{lstlisting} So the multiplication can be considered to be exact as long the less accurate bound for $\epsilon_{Log2hml}$ is used. Let us know analyse the bounds that we can give for the maximal overlap of the components of the triple-double numbers in the logarithm implementation. For doing this, we will assign each triple-double number in the code an overlap bound as follows. Call the number in consideration e.g. $a_\hi + a_\mi + a_\lo$. So we will give the bounds expressed like this: \begin{eqnarray*} \left \vert a_\mi \right \vert & \leq & 2^{-\alpha_o} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-\alpha_u} \cdot \left \vert a_\mi \right \vert \end{eqnarray*} where $\alpha_o, \alpha_u \geq 2$. We will then propagate this information following the flow of control in the implementation and using the overlap bound theorems given in \cite{Lauter2005LIP:tripledouble}. Here, we understand by ``propagating'' checking a system of constraints of the bounds under the limitations provided by the theorems. As the control-flow-graph of our implementation is completely linear, this check is linear, too. The theorems mentionned can be summarized as follows: \begin{center} \begin{tabular}{|l|ll|ll|ll|} \hline Operation & 1st arg. & 2nd arg. & result high & result low \\ \hline \AddTT & $\alpha_o \geq 4$, $\alpha_u \geq 1$ & $\beta_o \geq 4$, $\beta_u \geq 1$ & $\gamma_o \geq \min\left( \alpha_o, \beta_o \right) - 5$ & $\gamma_u \geq 53$ \\ \hline \AddDTT & - & $\beta_o \geq 2$, $\beta_u \geq 1$ & $\gamma_o \geq \min\left( 45, \beta_o - 4, \beta_o + \beta_u - 2 \right)$ & $\gamma_u \geq 53$ \\ \hline \MulDT & - & - & $\gamma_o \geq 48$ & $\gamma_u \geq 53$ \\ \hline \MulDTT & - & $\beta_o \geq 2$, $\beta_u \geq 1$ & $\gamma_o \geq \min\left( 48, \beta_o - 4, \beta_o + \beta_u - 4 \right)$ & $\gamma_u \geq 53$ \\ \hline \end{tabular} \end{center} So let us analyse the following code: \begin{lstlisting}[caption={Triple-double computations},firstnumber=90,label={list:tripledouble}] Mul23(&zSquareh, &zSquarem, &zSquarel, zh, zl, zh, zl); Mul233(&zCubeh, &zCubem, &zCubel, zh, zl, zSquareh, zSquarem, zSquarel); Mul233(&higherPolyMultZh, &higherPolyMultZm, &higherPolyMultZl, t14h, t14l, zCubeh, zCubem, zCubel); zSquareHalfh = zSquareh * -0.5; zSquareHalfm = zSquarem * -0.5; zSquareHalfl = zSquarel * -0.5; Add33(&polyWithSquareh, &polyWithSquarem, &polyWithSquarel, zSquareHalfh, zSquareHalfm, zSquareHalfl, higherPolyMultZh, higherPolyMultZm, higherPolyMultZl); Add233(&polyh, &polym, &polyl, zh, zl, polyWithSquareh, polyWithSquarem, polyWithSquarel); Add33(&logyh, &logym, &logyl, logih, logim, logil, polyh, polym, polyl); log2edhover = log2h * ed; log2edmover = log2m * ed; log2edlover = log2l * ed; log2edh = log2edhover; log2edm = log2edmover; log2edl = log2edlover; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, logyh, logym, logyl); \end{lstlisting} This code will finally generate triple-double numbers respecting the following overlap bounds as will be shown below: \begin{center} \begin{tabular}{|l|l|l|l|} \hline Variable & Line(s) & $\alpha_o \geq$ & $\alpha_u \geq$ \\ \hline $ZSquarehml$ & 90 & $48$ & $53$ \\ \hline $ZCubehml$ & 91 & $44$ & $53$ \\ \hline $HigherPolyMultZhml$ & 92 & $40$ & $53$ \\ \hline $ZSquareHalfhml$ & 93-95 & $48$ & $53$ \\ \hline $PolyWithSquarehml$ & 96-98 & $35$ & $53$ \\ \hline $Polyhml$ & 99 & $31$ & $53$ \\ \hline $Logyhml$ & 100 & $26$ & $53$ \\ \hline $Log2edhml$ & 101-106 & $40$ & $40$ \\ \hline $Logoverhml$ & 107 & $21$ & $53$ \\ \hline \end{tabular} \end{center} So let us verify exemplarily some of these bounds: \begin{itemize} \item At line 90, $ZSquarehml$ is computed out of the double-double number $z_\hi + z_\lo$ by use of the \MulDT~ sequence. Since the inputs of this function are not triple-double, the overlap bound is just the bound provided by the sequence itself, i.e. $\alpha_o \geq 48$, $\alpha_u \geq 53$. \item $ZCubehml$ is the result of a \MulDTT~ sequence at line 91. Its overlap bound depends therefore on the one for $ZSquarehml$, which is the second argument of the function. Since we know the bound for this variable, we easily verify the one for $ZCubehml$ which is $\alpha_o \geq 44$ and $\alpha_u \geq 53$. \item $Log2edhml$ is the exact pairwise product of the triple-double constant $Log2hml$ and double $E$. Since $E$ may be as small as $0$ in magnitude and further, since the multiplication is pairwise, the overlap bound we dispose of for $Log2edhml$ is the same as for $Log2hml$ which is stored with at least $11$ bit trailing zeros. So an appropriate bound is $\alpha_o \geq 52 - 11 \geq 40$ and $\alpha_u \geq 40$. \end{itemize} All other bounds can be verified the same way using the theorems given in \cite{Lauter2005LIP:tripledouble} and indicated above. \par Since we have computed the overlap bounds for the different triple-double operands in the code, we can now calculate the accuracy bounds for the operations. Doing this is only possible with the knowledge of the overlap of the operations because all accuracy bound theorems given in \cite{Lauter2005LIP:tripledouble} are parameterized with this overlap expressions. Let us first give a list of the accuracy of the different basic operations which is not exhaustive with regard to its lack of listing almost all preconditions on the sequences required for theorems to hold. We refrain from explicitely verifying each of this preconditions in this document as this is only fastidious work but not of special interest. \begin{center} \begin{tabular}{|l|l|l|l|} \hline Operation & Overlap 1st arg. & Overlap 2nd arg. & Relative error $\epsilon$ \\ \hline \AddDD & - & - & $\left \vert \epsilon \right \vert \leq 2^{-103.5} \leq 2^{-103}$ \\ \hline \MulDD & - & - & $\left \vert \epsilon \right \vert \leq 2^{-102}$\\ \hline \AddTT & $\alpha_o \geq 4$, $\alpha_u \geq 1$ & $\beta_o \geq 4$, $\beta_u \geq 1$ & $\left \vert \epsilon \right \vert \leq 2^{-\min\left( \alpha_o + \alpha_u, \beta_o + \beta_u \right) -47} + 2^{-\min\left( \alpha_o, \beta_o \right) - 98}$ \\ \hline \AddDTT & - & $\beta_o \geq 2$, $\beta_u \geq 1$ & $\left \vert \epsilon \right \vert \leq 2^{-\beta_o - \beta_u - 52} + 2^{-\beta_o-104} + 2^{-153}$ \\ \hline \MulDT & - & - & $\left \vert \epsilon \right \vert \leq 2^{-149}$ \\ \hline \MulDTT & - & $\beta_o \geq 2$, $\beta_u \geq 1$ & $\left \vert \epsilon \right \vert \leq 2^{-97-\beta_o} + 2^{-97-\beta_o-\beta_u} + 2^{-150}$ \\ \hline \end{tabular} \end{center} Still analyzing the following double-double computations code and the code given at listing \ref{list:tripledouble}, one can now easily check the bounds for the relative error of the different operations listed in the table below. We define here the relative error of an operation $\ast$ and its arithmetical equivalent $\circledast$ as follows: $$\epsilon = \frac{\left(a \circledast b \right) - \left(a \ast b\right)}{\left(a \ast b \right)}$$ \begin{lstlisting}[caption={Double-double computations in accurate phase},firstnumber=73,label={list:doubledouble}] Mul12(&t1h, &t1l, zh, highPoly); Add22(&t2h, &t2l, accPolyC9h, accPolyC9l, t1h, t1l); Mul22(&t3h, &t3l, zh, zl, t2h, t2l); Add22(&t4h, &t4l, accPolyC8h, accPolyC8l, t3h, t3l); Mul22(&t5h, &t5l, zh, zl, t4h, t4l); Add22(&t6h, &t6l, accPolyC7h, accPolyC7l, t5h, t5l); Mul22(&t7h, &t7l, zh, zl, t6h, t6l); Add22(&t8h, &t8l, accPolyC6h, accPolyC6l, t7h, t7l); Mul22(&t9h, &t9l, zh, zl, t8h, t8l); Add22(&t10h, &t10l, accPolyC5h, accPolyC5l, t9h, t9l); Mul22(&t11h, &t11l, zh, zl, t10h, t10l); Add22(&t12h, &t12l, accPolyC4h, accPolyC4l, t11h, t11l); Mul22(&t13h, &t13l, zh, zl, t12h, t12l); Add22(&t14h, &t14l, accPolyC3h, accPolyC3l, t13h, t13l); \end{lstlisting} \begin{center} \begin{tabular}{|l|l|l|l|} \hline Result & Line(s) & Operation & Relative error $\epsilon$ \\ \hline $T1hl$ through $T14hl$ & 73 - 86 & \AddDD~ / \MulDD & $\left \vert \epsilon \right \vert \leq 2^{-103}$ / $\left \vert \epsilon \right \vert \leq 2^{-102}$ \\ \hline $ZSquarehml$ & 90 & \MulDT & $\left \vert \epsilon \right \vert \leq 2^{-149}$ \\ \hline $ZCubehml$ & 91 & \MulDTT & $\left \vert \epsilon \right \vert \leq 2^{-144}$ \\ \hline $HigherPolyMultZhml$ & 92 & \MulDTT & $\left \vert \epsilon \right \vert \leq 2^{-141}$ \\ \hline $PolyWithSquarehml$ & 96-98 & \AddTT & $\left \vert \epsilon \right \vert \leq 2^{-137}$ \\ \hline $Polyhml$ & 99 & \AddDTT & $\left \vert \epsilon \right \vert \leq 2^{-134}$ \\ \hline $Logyhml$ & 100 & \AddTT & $\left \vert \epsilon \right \vert \leq 2^{-128}$ \\ \hline $Logoverhml$ & 107 & \AddTT & $\left \vert \epsilon \right \vert \leq 2^{-123}$ \\ \hline \end{tabular} \end{center} Let us just explicitely check the bound for one of the operations for sake of an example. Let us take therefore the \AddTT~ sequence at lines 96-98 computing $PolyWithSquarehml$ out of $ZSquareHalfhml$ and $HigherPolyMultZhml$. We have already obtained to following overlap bounds: \begin{eqnarray*} \left \vert zSquareHalf_\mi \right \vert & \leq & 2^{-48} \cdot \left \vert zSquareHalf_\hi \right \vert \\ \left \vert zSquareHalf_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert zSquareHalf_\mi \right \vert \\ \left \vert higherPolyMultZ_\mi \right \vert & \leq & 2^{-40} \cdot \left \vert higherPolyMultZ_\hi \right \vert \\ \left \vert higherPolyMultZ_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert higherPolyMultZ_\mi \right \vert \end{eqnarray*} Feeding now this bounds into the theorem on the accuracy of \AddTT, we get $$\left \vert \epsilon \right \vert \leq 2^{-\min\left( 48 + 53, 40 + 53 \right) - 47} + 2^{-\min \left( 48, 40 \right) - 98} \leq 2^{-140} + 2^{-138} \leq 2^{-137}$$ All other error bounds can be verified in a similar way. They are finally expressed in Gappa syntax as follows: \begin{lstlisting}[caption={Relative error bounds in Gappa code},firstnumber=139] (T2hl - T2) / T2 in [-1b-103,1b-103] /\ (T3hl - T3) / T3 in [-1b-102,1b-102] /\ (T4hl - T4) / T4 in [-1b-103,1b-103] /\ (T5hl - T5) / T5 in [-1b-102,1b-102] /\ (T6hl - T6) / T6 in [-1b-103,1b-103] /\ (T7hl - T7) / T7 in [-1b-102,1b-102] /\ (T8hl - T8) / T8 in [-1b-103,1b-103] /\ (T9hl - T9) / T9 in [-1b-102,1b-102] /\ (T10hl - T10) / T10 in [-1b-103,1b-103] /\ (T11hl - T11) / T11 in [-1b-102,1b-102] /\ (T12hl - T12) / T12 in [-1b-103,1b-103] /\ (T13hl - T13) / T13 in [-1b-102,1b-102] /\ (T14hl - T14) / T14 in [-1b-103,1b-103] /\ (ZSquarehml - ZSquare) / ZSquare in [-1b-149,1b-149] /\ (ZCubehml - ZCube) / ZCube in [-1b-144,1b-144] /\ (HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ in [-1b-141,1b-141] /\ (PolyWithSquarehml - PolyWithSquare) / PolyWithSquare in [-1b-137,1b-137] /\ (Polyhml - Poly) / Poly in [-1b-134,1b-134] /\ (Logyhml - Logy) / Logy in [-1b-128,1b-128] /\ (Loghml - Logover) / Logover in [-1b-123,1b-123] /\ (Log2hml - MLog2) / MLog2 in [-1b-126,1b-126] /\ (Logihml - MLogi) / MLogi in [-1b-159,1b-159] /\ (MPoly - MLog1pZ) / MLog1pZ in [-_epsilonApproxAccurate,_epsilonApproxAccurate] /\ Z in [_zmin,_zmax] /\ ((logh + logm + logl) - Loghml) / Loghml in [-1b-159,1b-159] \end{lstlisting} Concerning the Gappa proofs for accurate phase, in a similar way as for the quick phase, three different proof files are used. They reflect once again the three main cases for the argument of the logarithm function: \begin{itemize} \item For cases where after argument reduction $\left \vert E \right \vert \geq 1$, the file {\tt log-td-accurate.gappa} is used. In this case, absolute error computations are sufficient for the final relative error bound to be calculable because $\left \vert \log\left( x \right) \right \vert \geq \frac{1}{2} \log\left( 2 \right)$ in this case. \item For the case where after argument reduction, $E = 0$ and $i \not = 0$, the file {\tt log-td-accurate-E0.gappa} is used. The same way here, we have a preponderant constant term so absolute error computations suffice. \item For the other case, where $E=0$ and $i=0$ the file {\tt log-td-accurate-E0-logir0.gappa} provides the accuracy bound proof. In contrast to the other cases, we obliged to relative error estimations since the beginning since the function $\log\left( x \right)$ has a zero in this intervall. \end{itemize} Once again, several term rewriting hints are needed in the Gappa proof files for enabling the Gappa tool to generate a proof for the accuracy bounds. In a similar way, the hints which cannot directly be checked for their mathematical correctness by the tool itself are verified by semi-automatic Maple scripts.\par By the existence of an accuracy proof for a final relative error of $\left \vert \epsilon_{\mbox{\tiny accurate}} \right \vert \leq 2^{-119.5}$ and by the use of the critical accuracy of the double precision natural logarithm function which is $118$ bits\cite{DinDefLau2004LIP}, we can consider the implementation to be correctly rounding under the hypothesis that the final rounding sequence used is exact and correct. Since we suppose this -- a correctness proof can be found in \cite{Lauter2005LIP:tripledouble} -- the correctly rounding property is verified. \section{Proof of correctness of the double-extended implementation \label{sec:logdeproof}} \section{Performance results\label{sec:logperf}} The given implementation of the natural logarithm function aims at being both portable and more performant than the previous implementations using the SCS libary for the accurate phase. This goal is acheived in terms of memory consumption (if the code sizes for {\tt scslib} are taken into account) and in terms of speed performance. The reason for this is mainly the possibility of reusing all values computed in the argument reduction phase and the tables for the accurate phase directly. \subsection{Memory requirements} \subsection{Timings} %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/log10.tex0000644000000000000000000002652513316017127017251 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA This chapter is contributed by Ch. Q. Lauter. \section{Main considerations, critical accuracy bounds}\label{subsec:criticalboundslog10} If one wants to guarantee that an implementation of the logarithm in base $10$, $\log_{10}\left( x \right)$, in double precision is correctly rounded, one has to ensure that the final intermediate approximation before rounding to double precision has a relative error of less than $2^{-122}$. An implementation of $\log_{10}\left(x\right)$ can also be derived from an implementation of the natural logarithm $\ln\left(x\right)$ using the formula: \begin{equation} \log_{10}\left( x \right) = \frac{1}{\ln\left( 10 \right)} \cdot \ln\left( x \right)\label{eq:log10} \end{equation} When doing so, one must ensure that the constant $\mathit{log10inv} = \frac{1}{\ln\left(10\right)}$ is stored with enough accuracy, that the approximation for $\ln\left( x \right)$ is exact enough and that the multiplication sequence does not introduce too great an error. As we will see in the next section \ref{subsec:outlinelog10}, this implies slight changes to the code for the natural logarithm with regard to what has been presented in Chapter \ref{chap:log}. With regard to final rounding, the elementary function $\log_{10}$ presents a particular issue that is somewhat singular amongst all considered elementary functions: There exist a large set of input double-precision numbers $x$ such that $\log_{10}(x)$ is a rational and is representable as a double-precision number. For such cases, a final directed rounding will be correct only if the approximation error is exactly $0$. Indeed, the rounding $\diamond\left( f\left( x \right) \right)$ of the exactly representably value $f\left(x\right) \in \F$ is trivially $\diamond\left( f\left( x \right) \right) = f\left( x \right)$ \cite{IEEE754}. In contrast, $\diamond\left( f\left( x \right) + \delta \right) \not = f\left( x \right) \in \F$ holds for all $\left \vert \delta \right \vert > 0$. As it is impossible to achieve an approximation error exactly equal to zero, it is preferable to filter out such cases and handle them separately. Other functions described so far had only one such argument ($x=1$ for $\log$, x=0 for the trigs). $\log_2$ has a set of such cases ($x = 2^k$, $k \in \Z$) which is equally trivial to handle in binary floating point. For $f = \log_{10}$, filtering much more difficult. In fact, $y = \log\left( x \right)$ is algebraic for exactly all $x = 10^k$, $k \in \Z$ \cite{Baker75}. Filtering means thus testing whether an input $x$ can be written $x = 10^k$ with an integer $k \in \Z$. This is equivalent to testing if $\log_{10}\left( x \right)$ an integer, i.e. $\log_{10}\left( x \right) \in \Z$. However, since $\log_{10}\left( x \right)$ can only be approximated, filtering this way is impossible. One possibility is the following approach. In floating point arithmetic, in order to be in a situation of difficult rounding, not only $\log_{10}\left( x \right)$ must be algebraic but also the corresponding $x = 10^k$, $k \in \Z$, must be representable in floating point. To start with eliminating cases, we can argue that this impossible for all $k < 0$. Indeed, since $2 \nmid 5$, there exist no $m \in \N$ and $e \in \Z$ for any $k \in \Z^-$ such that $10^k = 2^e \cdot m$ \cite{Muller97}. So we have reduced the range of cases to filter to all $x = 10^k$, $k \in \N \cup \left \lbrace 0\right \rbrace$. Further in double precision, the mantissa's length is $53$. So $10^k = 2^k \cdot 5^k = 2^e \cdot m$ is exactly representable in double precision only for values $k \in \N \cup \left \lbrace 0 \right \rbrace$ such that $5^k \leq 2^{53}$. This yields to $k \leq 53 \cdot \frac{\ln\left( 2 \right)}{\ln\left( 5 \right)} \approx 22.82$; hence $0 \leq k \leq 22$. In consequence, it would be possible to filter out the $23$ arguments $x = 10^k$ with $k \in \left \lbrace 0 \dots 22 \right \rbrace$. Nevertheless, this approach would be relatively costly. It is not the way that has been chosen for the implementation presented here. Our approach uses the critical worst case accuracy of the elementary function $\log_{10}\left( x \right)$. As already mentioned, it is $2^{-122}$. Under the condition that we can provide an approximation to the function that is exact to at least $2^{-123}$, we can decide the directed rounding using a modified final rounding sequence: We know that a $1$ after a long series of $0$s (respectively a $0$ after a long series of $1$s) must be present at least at the $122$th bit of the intermediate mantissa. If it is not, we can consider a potentially present $1$ after the $122$th bit to be an approximation error artefact. In fact this means neglecting $\delta$s relatively less than $2^{-122}$ when rounding $\diamond \left( f\left( x \right) + \delta \right)$ instead of $\diamond \left( f\left( x \right) \right)$. One shortcoming of this approach is that the accurate phase is launched for arguments where the quick phase's accuracy would suffice to return the correct result. As such arguments are extremely rare ($p = \frac{23}{2^{63}} \approx 2.5 \cdot 10^{-18}$~!), this is not of an issue. The modification of the final rounding sequence is relatively lightweight: merely one floating point multiplication, two integer masks and one integer comparison have to be added to handle the case. One remarks this approach is only possible because the critical worst case accuracy of the function is known by Lef{\`e}vre's works. Ziv's oignon peeling strategy without the filtering of the $23$ possible cases in input and without any accuracy limitation for intermediate computations yields to nontermination of the implementation of the function on such arguments $x = 10^k$. An earlier \crlibm\ implementation of the $\log_{10}\left(x\right)$ function based on the SCS format did not handle the problem and returned incorrectly rounded results for inputs $x = 10^k$ in the directed rounding modes. \section{General outline of the algorithm and accuracy estimates}\label{subsec:outlinelog10} % 1/2 page % % - Multiply by the right constant, this time using a triple double for the constant => Mul33 which is costly % - Tell about the need to gain some bits in the log for the worst case => renormalize at some point in the code % - Analyse the issue of integer powers of 10 => give explanation that there are only 17 cases % - Indicate the way the final rounding sequence for triple double can be modified => additional costs % - Mention that we launch the accurate phase even for results where the quick phase result suffices (10^n), % analyse the problem and mention that it is unique for log10 (in the usual list of elementary functions) % but that it is quasi impossible to get around it (tell that log10 in SCS did not correctly treat the problem) The quick phase of the implementation of the $\log_{10}\left( x \right)$ follows exactly the scheme depicted by equation (\ref{eq:log10}) above. Similarly to the logarithm in base $2$, the natural logarithm's intermediate double-double result is multiplied by a double-double precision approximation of $\mathit{log10inv}$. The rounding test is slightly modified in order to ensure safe rounding or launching the accurate phase. Concerning the accurate phase, some modifications in the natural logarithm's code are necessary because of the tighter accuracy bound needed for the worst case. The natural logarithms accurate phase polynomial approximation relative error has already been less than $2^{-125}$ which is exact enough for $\log_{10}\left( x \right)$. The fact that the complete triple-double implementation is exact to only $119$ bits, is mainly due to the inexactness of the operators used in reconstruction phase. In turn, this inexactness is caused by the relatively high overlap in the triple-double numbers handled. By adding two additional renormalisations the triple-double operators become exact enough. The constant $\mathit{log10inv}$ cannot be stored in double-double precision with an accuracy of $124$ bits. A triple-double approximation is therefore used. Its relative approximation error is smaller than $2^{-159}$. The final multiplication of the triple-double constant representing $\mathit{log10inv}$ and the triple-double natural logarithm result is performed by a \MulTT. The relative error of this operator on non-overlapping triple-doubles is not greater than $2^{-140}$. This last operation therefore offers a large accuracy overkill. TODO The combination of the previous errors should be verified in Gappa. \section{Timings}\label{subsec:timingslog10} We compare \crlibm's portable triple-double implementation for $\log_{10}\left( x \right)$ to other correctly rounded and not-correctly rounded implementations. ``\crlibm\ portable using \scslib'' is the timing for the earlier implementation in {\tt crlibm}, which has been superseded by the one depicted here since version 0.10$\beta$. This earlier implementation was completely based on the SCS format and did not contain a quick phase implemented in double precision arithmetic. The values are given in arbitrary units and obtained on a IBM Power 5 processor with gcc 3.3.3 on a Linux Kernel 2.6.5. \begin{table}[h] \begin{center} \begin{tabular}{|l|r|r|} \hline Library & avg time & max time \\ \hline \hline \multicolumn{3}{|c|}{Power5 / Linux-2.6 / gcc-3.3} \\ \hline \texttt{MPFR} & 9490 & 84478 \\ \hline \crlibm\ portable using \texttt{scslib} & 2624 & 2744 \\ \hline \crlibm\ portable using triple-double & 60 & 311 \\ \hline default \texttt{libm} (not correctly rounded) & 66 & 71 \\ \hline \hline \multicolumn{3}{|c|}{PentiumM / Linux-2.6 / gcc-4.0} \\ \hline \crlibm\ portable using triple-double & 304 & 1529 \\ \hline default \texttt{libm} (not correctly rounded) & 153 & 1904 \\ \hline \hline \end{tabular} \end{center} \caption{Log10 timings on Power5 and PentiumM architectures} \label{Log10timings} \end{table} On average, our triple-double based implementation is even $10\%$ faster than its incorrectly rounding counterpart on Power. On Pentium, we observe the usual factor 2 with respect to an implementation using double-extended arithmetic. Worst case timings are acceptable in both cases. %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/log1p.tex0000644000000000000000000000007113316017127017335 0ustar 00000000000000 Todo. In between, see files log1p-td.\{h,c,mpl,gappa\}. interval-3.2.0/src/crlibm/docs/latex/log2.tex0000644000000000000000000000007013316017127017155 0ustar 00000000000000 Todo. In between, see files log2-td.\{h,c,mpl,gappa\}. interval-3.2.0/src/crlibm/docs/latex/pow.tex0000644000000000000000000000737013316017127017131 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA This chapter is contributed by Ch. Q. Lauter and F. de Dinechin. \section{Work in progress} Here is the status of the current implementation of pow in CRLibm: \begin{itemize} \item Exact and mid-point cases are handled properly \cite{LauterLefevre2007}. This is especially important because an exact case would mean an infinite Ziv iteration. \item Worst cases are not known for the full input range. This is a deep theoretical issue. Recent research has focussed on $x^n$ for integer $n$. At the time of release, it has been proved computationally that that an intermediate precision of $2^{-118}$ is enough to round correctly $x^n$ for all integer $n$ between -180 and +1338. In addition, specific algorithms have been studied for the computation of $x^n$ \cite{KorLauLefLouvMul2008}. \item Due to lack of time, only round-to-nearest is implemented. Directed rounding requires additional work, in particular in subnormal handling and in exact case management. There are more exact cases in directed rounding modes, therefore the performance should also be inferior. \item The current implementation computes two Ziv iterations, to $2^{-61}$ then to $2^{-120}$. With current technology, there is little hope to find all the worst cases for the full range of the power function. Should an input require more than $2^{-120}$ happen (to our knowledge none has been exhibited so far), current implementation will not necessarily return the correctly rounded result. Options are: \begin{itemize} \item Ignore silently the problem (this is the current option). \item perform a second rounding test at the end of the accurate step. If the test fails (with a probability smaller that $2^{-120}$), \begin{itemize} \item an arbitrary precision computation could be launched, for example MPFR. This requires adding a dependency to MPFR only for this highly improbable case. \item launch a high, but not arbitrary precision third step (say, accurate to $2^{-3000}$. Variations of the SLZ algorithm \cite{Stehle-thesis} could provide, at an acceptable computational cost, a certificate that there is no worst case requiring a larger precision. This is the only fully satisfactory solution that seems at reach, but this idea remains to be explored. \item (in addition to the previous) a message on the standard error could be written, including the corresponding inputs, and inviting anyone who reads it to send us a mail. Considering the probability, we might wait several centuries before getting the first mail. \end{itemize} \end{itemize} \end{itemize} %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/sqrt.tex0000644000000000000000000004006213316017127017310 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Some of \crlibm's functions need high precision square roots. They are not intended to be used outside \crlibm. In particular, we do currently not guarantee the correct rounding of their results because this property is not needed for our purposes. Their implementation does not handle all possible special cases ($x < 0$, $\nan$, $\infty$ etc.) neither. We currently provide two C macros computing the square root of a double precision argument either in double-double precision with at least $100$ correct bits (in faithful rounding) or in triple-double precision with an accuracy of at least $146$ bits (in faithful rounding). The corresponding macros are called \SqrtD~ and \SqrtT. The implementation of these macros was guided by the following principles: \begin{itemize} \item no dependency on other \texttt{libm}s, so avoidance of bootstrapping a Newton iteration by a double precision square root implemented elsewhere, \item high efficiency, \item a small memory footprint, \item the possible use of hardware support on some platforms in the future. \end{itemize} \subsubsection{Overview of the algorithm} The algorithm uses a combination of polynomial approximation and Newton iteration. After handling some special cases, the argument $x = 2^{E^\prime} \cdot m^\prime$ is reduced into its exponent $E^\prime$ stored in integer and its fractional part $m^\prime$ stored as a double precision number. This argument reduction is obviously exact. The two values are then adjusted as follows: \vspace{-3mm} \begin{center} \begin{tabular}{cc} \begin{minipage}{60mm} $$E = \left \lbrace \begin{array}{ll} E^\prime & \mbox{ if } \exists n \in \N \mbox{ . } E^\prime = 2n\\ E^\prime +1 & \mbox{ otherwise} \end{array} \right.$$ \end{minipage} & \begin{minipage}{60mm} $$m = \left \lbrace \begin{array}{ll} m^\prime & \mbox{ if } \exists n \in \N \mbox{ . } E^\prime = 2n \\ \frac{m^\prime}{2} & \mbox{ otherwise } \end{array} \right.$$ \end{minipage} \end{tabular} \end{center} One easily checks that $\frac{1}{2} \leq m \leq 2$ and that $E$ is always even. Thus $$\sqrt{x} = \sqrt{2^E \cdot m} = 2^{\frac{E}{2}} \cdot \sqrt{m} = 2^{\frac{E}{2}} \cdot m \cdot \frac{1}{\sqrt{m}}$$ The algorithm therefore approximates $\hat{r} = \frac{1}{\sqrt{m}}$ and reconstructs the square root by multiplying by $m$ and exactly by $2^{\frac{E}{2}}$. The reciprocal square root $\hat{r}$ is approximated in two steps. First, a polynomial approximation yields to $r_0 = \hat{r} \cdot \left( 1 + \epsilon_1 \right)$, which is exact to about $8$ bits. In a second step, this approximation is refined by a Newton iteration that approximately doubles its accuracy at each step. So for a double-double result, $4$ iterations are needed and for a triple-double result $5$. The initial polynomial approximation is less exact than the one provided by Itanium's \texttt{} operation, which allows for using this hardware assistance in the future. \subsubsection{Special case handling} The square root of a double precision number can never be subnormal. In fact, if $\sqrt{x} \leq 2^{-1021}$, $x = \sqrt{x}^2 \leq 2^{-1042441}$, a value that is is not representable in double precision. Concerning subnormals in argument, it to be mentioned that still $E^\prime$ and $m^\prime$ can be found such that $x = 2^{E^\prime} \cdot m$ exactly and $1 \leq m^\prime \leq 2$. Only the extraction sequence must be modified: $x$ is first multiplied by $2^{52}$ where $E^\prime$ is set to $-52$. The double number $x$ is thus no longer a subnormal an integer handling can extract its mantissa easily. The extraction of the exponent takes into account the preceeding bias of $E^\prime$. The case $x = 0$ is filtered out before. Obviously $\sqrt{0} = 0$ is returned for this argument. The special cases $x < 0$, $x = \pm \infty$ and $x = \nan$ are not handled since they can be easily excluded by the code using the square root macros. Special case handling is implemented as follows: \begin{lstlisting}[caption={Special case handling},firstnumber=1] /* Special case x = 0 */ if (x == 0) { *resh = x; *resl = 0; } else { E = 0; /* Convert to integer format */ xdb.d = x; /* Handle subnormal case */ if (xdb.i[HI] < 0x00100000) { E = -52; xdb.d *= ((db_number) ((double) SQRTTWO52)).d; /* make x a normal number */ } /* Extract exponent E and mantissa m */ E += (xdb.i[HI]>>20)-1023; xdb.i[HI] = (xdb.i[HI] & 0x000fffff) | 0x3ff00000; m = xdb.d; /* Make exponent even */ if (E & 0x00000001) { E++; m *= 0.5; /* Suppose now 1/2 <= m <= 2 */ } /* Construct sqrt(2^E) = 2^(E/2) */ xdb.i[HI] = (E/2 + 1023) << 20; xdb.i[LO] = 0; \end{lstlisting} \subsubsection{Polynomial approximation} The reciprocal square root $\hat{r} = \frac{1}{\sqrt{m}}$ is approximated in the domain $m \in \left[ \frac{1}{2}; 2 \right]$ by a polynomial $p\left( m \right) = \sum\limits_{i=0}^4 c_i \cdot m^i$ of degree $4$. The polynomial's coefficients $c_0$ through $c_4$ are stored in double precision. The following values are used: \begin{eqnarray*} c_0 & = & 2.50385236695888790947606139525305479764938354492188 \\ c_1 & = & -3.29763389114324168005509818613063544034957885742188 \\ c_2 & = & 2.75726076139124520736345402838196605443954467773438 \\ c_3 & = & -1.15233725777933848632983426796272397041320800781250 \\ c_4 & = & 0.186900066679800969104974228685023263096809387207031 \end{eqnarray*} The relative approximation error $\epsilon_{\mbox{\tiny approx}} = \frac{p\left( m\right) - \hat{r}}{\hat{r}}$ is bounded by $\left \vert \epsilon_{\mbox{\tiny approx}} \right \vert \leq 2^{-8.32}$ for $m \in \left[ \frac{1}{2}; 2 \right]$. The polynomial is evaluated in double precision using Horner's scheme. There may be some cancellation in the different steps but the relative arithmetical error $\epsilon_{\mbox{\tiny arithpoly}}$ is always less in magnitude than $2^{-30}$. This will be shown in more detail below. The code implementing the polynomial approximation reads: \begin{lstlisting}[caption={Polynomial approximation},firstnumber=1] r0 = SQRTPOLYC0 + m * (SQRTPOLYC1 + m * (SQRTPOLYC2 + m * (SQRTPOLYC3 + m * SQRTPOLYC4))); \end{lstlisting} So 4 double precision multiplications and 4 additions are needed for computing the initial approximation. They can be replaced by 4 FMA instructions, if available. \subsubsection{Double and double-double Newton iteration} The polynomial approximation is then refined using the following iteration scheme: $$r_{i+1} = \frac{1}{2} \cdot r_i \cdot (3 - m \cdot r_i^2)$$ If the arithmetic operations were exact, one would obtain the following error estimate: \begin{eqnarray*} \epsilon_{i+1} & = & \frac{r_i - \hat{r}}{\hat{r}} \\ & = & \frac{\frac{1}{2} \cdot r_i \cdot \left(3 - m \cdot r_i^2\right) - \hat{r}}{\hat{r}} \\ & = & \frac{\frac{1}{2} \cdot \hat{r} \cdot \left( 1 + \epsilon_i \right) \cdot \left( 3 - m \cdot \hat{r}^2 \cdot \left( 1 + \epsilon_i \right)^2 \right) - \hat{r}}{\hat{r}} \\ & = & \frac{1}{2} \cdot \left( 1 + \epsilon_i \right) \cdot \left( 3 - m \cdot \frac{1}{m} \cdot \left( 1 + \epsilon_i\right)^2 \right) - 1 \\ & = & \frac{1}{2} \cdot \left( 1 + \epsilon_i \right) \cdot \left( 3 - 1 - 2 \cdot \epsilon_i - \epsilon_i^2 \right) - 1 \\ & = & \left( 1 + \epsilon_i \right) \cdot \left( 1 - \epsilon_i - \frac{1}{2} \cdot \epsilon_i^2 \right) - 1 \\ & = & 1 - \epsilon_i - \frac{1}{2} \cdot \epsilon_i^2 + \epsilon_i - \epsilon_i^2 - \frac{1}{2} \cdot \epsilon_i^3 - 1\\ & = & - \frac{3}{2} \cdot \epsilon_i^2 - \frac{1}{2} \cdot \epsilon_i^3 \end{eqnarray*} So the accuracy of the approximation of the reciprocal square root is doubled at each step. Since the initial accuracy is about $8$ bits, it is possible to iterate two times on pure double precision without any considerable loss of accuracy. After the two iterations about $31$ bits will be correct. The macro implements therefore: \begin{lstlisting}[caption={Newton iteration - double precision steps},firstnumber=1] r1 = 0.5 * r0 * (3 - m * (r0 * r0)); r2 = 0.5 * r1 * (3 - m * (r1 * r1)); \end{lstlisting} For these two iterations, 8 double precision multiplications and 2 additions are needed. The next iteration steps must be performed in double-double precision because the $53$ bit mantissa of a double cannot contain the about $60$ bit exact value $m \cdot r_2^2 \approx 1$ before cancellation in the substraction with $3$ and the multiplication by $r_2$. In order to exploit maximally the parallelism in the iteration equation, we rewrite it as \begin{eqnarray*} r_{3} & = & \frac{1}{2} \cdot r_2 \cdot \left( 3 - m \cdot r_2^2 \right) \\ & = & \left( r_2 + \frac{1}{2} \cdot r_2 \right) - \frac{1}{2} \cdot \left( m \cdot r_2 \right) \cdot \left( r_2 \cdot r_2 \right) \end{eqnarray*} Since multiplications by integer powers of $2$ are exact, it is possible to compute $r_2 + \frac{1}{2} \cdot r_2$ exactly as a double-double. Concurrently it is possible to compute $m \cdot r_2$ and $r_2 \cdot r_2$ exactly as double-doubles by means of an exact multiplication. The multiplication $\left( m \cdot r_2 \right) \cdot \left( r_2 \cdot r_2 \right)$ is then implemented as a double-double multiplication. The multiplication by $\frac{1}{2}$ of the value obtained is exact and can be performed pairwise on the double-double. A final double-double addition leads to $r_3 = \left( r_2 + \frac{1}{2} \cdot r_2 \right) - \frac{1}{2} \cdot \left( m \cdot r_2 \right) \cdot \left( r_2 \cdot r_2 \right)$. Here, massive cancellation is no longer possible since the values added are approximately $\frac{3}{2} \cdot r_2$ and $\frac{1}{2} \cdot r_2$. These steps are implemented as follows: \begin{lstlisting}[caption={Newton iteration - first double-double step},firstnumber=1] Mul12(&r2Sqh, &r2Sql, r2, r2); Add12(r2PHr2h, r2PHr2l, r2, 0.5 * r2); Mul12(&mMr2h, &mMr2l, m, r2); Mul22(&mMr2Ch, &mMr2Cl, mMr2h, mMr2l, r2Sqh, r2Sql); MHmMr2Ch = -0.5 * mMr2Ch; MHmMr2Cl = -0.5 * mMr2Cl; Add22(&r3h, &r3l, r2PHr2h, r2PHr2l, MHmMr2Ch, MHmMr2Cl); \end{lstlisting} The next iteration step provides enough accuracy for a double-double result. We rewrite the basic iteration equation once again as: \begin{eqnarray*} r_4 & = & \frac{1}{2} \cdot r_3 \cdot \left( 3 - m \cdot r_3^2 \right) \\ & = & r_3 \cdot \left( \frac{3}{2} - \frac{1}{2} \cdot m \cdot r_3^2 \right) \\ & = & r_3 \cdot \left( \frac{3}{2} - \frac{1}{2} \cdot \left( \left( m \cdot r_3^2 - 1 \right) + 1 \right) \right) \\ & = & r_3 \cdot \left( 1 - \frac{1}{2} \cdot \left( m \cdot r_3^2 - 1 \right) \right) \end{eqnarray*} Further, we know that $r_3$, stored as a double-double, verifies $r_3 = \hat{r} \cdot \left( 1 + \epsilon_3 \right)$ with $\left \vert \epsilon_3 \right \vert \leq 2^{-60}$. So we check that $$m \cdot r_3^2 = m \cdot \hat{r}^2 \cdot \left( 1 + \epsilon_3 \right)^2 = 1 + 2 \cdot \epsilon_3 + \epsilon_3^2$$ Clearly, $\left \vert 2 \cdot \epsilon_3 + \epsilon_3^2 \right \vert < \frac{1}{2} \mUlp\left( 1 \right)$. So when squaring $r_{3\hi} + r_{3\lo}$ in double-double precision and multiplying it in double-double precision by $m$ produces a double-double $mMr3Sq_\hi + mMr3Sq_\lo = m \cdot \left( r_{3\hi} + r_{3\lo} \right)^2 \cdot \left( 1 + \epsilon \right)$, $\left \vert \epsilon \right \vert \leq 2^{-100}$ such that $mMr3Sq_\hi = 1$ in all cases. So we can implement the iteration equation $$r_4 = r_3 \cdot \left( 1 - \frac{1}{2} \cdot \left( m \cdot r_3^2 - 1 \right) \right)$$ as follows: \begin{lstlisting}[caption={Newton iteration - second double-double step},firstnumber=1] Mul22(&r3Sqh, &r3Sql, r3h, r3l, r3h, r3l); Mul22(&mMr3Sqh, &mMr3Sql, m, 0, r3Sqh, r3Sql); Mul22(&r4h, &r4l, r3h, r3l, 1, -0.5 * mMr3Sql); \end{lstlisting} We since get $r_{4\hi} + r_{4\lo} = \hat{r} \cdot \left( 1 + \epsilon_4 \right)$ with $\left \vert \epsilon_4 \right \vert \leq 2^{-102}$, the accuracy being limited by the accuracy of the last double-double multiplication operator. This approximation is than multiplied by $m$ in double-double precision, leading to an approximation $srtm_\hi + srtm_\lo = \sqrt{m} \cdot \left( 1 + \epsilon \right)$ with $\left \vert \epsilon \right \vert \leq 2^{-100}$. Out of this value, the square root of the initial argument can be reconstructed by multiplying by $2^{\frac{E}{2}}$, which has already been stored in $xdb.d$. This multiplication is exact because it cannot produce a subnormal. These two steps are implemented as shown below: \begin{lstlisting}[caption={Multiplication $m \cdot \hat{r}$, reconstruction},firstnumber=1] Mul22(&srtmh,&srtml,m,0,r4h,r4l); /* Multiply componentwise by sqrt(2^E), which is an integer power of 2 that may not produce a subnormal */ *resh = xdb.d * srtmh; *resl = xdb.d * srtml; \end{lstlisting} \subsubsection{Triple-double Newton iteration} For producing a triple-double approximate to $\hat{r}$ with an accuracy of at least $147$ bits, one more Newton iteration is needed. We apply the same equation as in the last double-double step, which reads: $$r_5 = r_4 \cdot \left( 1 - \frac{1}{2} \cdot \left( m \cdot r_4^2 - 1 \right) \right)$$ Once again, the first component of the triple-double number holding an approximation to $m \cdot r_4^2$ is exactly equal to $1$. So by neglecting this component, we substract $1$ from it. Unfortunately, a renormalization step is needed after the multiplications for squaring $r_4$ and by $m$ because the values computed might be overlapped which would prevent us form substracting $1$ by neglecting a component. We implement thus: \begin{lstlisting}[caption={Newton iteration - triple-double step},firstnumber=1] Mul23(&r4Sqh, &r4Sqm, &r4Sql, r4h, r4l, r4h, r4l); Mul133(&mMr4Sqhover, &mMr4Sqmover, &mMr4Sqlover, m, r4Sqh, r4Sqm, r4Sql); Renormalize3(&mMr4Sqh, &mMr4Sqm, &mMr4Sql, mMr4Sqhover, mMr4Sqmover, mMr4Sqlover); HmMr4Sqm = -0.5 * mMr4Sqm; HmMr4Sql = -0.5 * mMr4Sql; Mul233(&r5h,&r5m,&r5l,r4h,r4l,1,HmMr4Sqm,HmMr4Sql); \end{lstlisting} This approximation $r_{5\hi} + r_{5\mi} + r_{5\lo} = \hat{r} \cdot \left( 1 + \epsilon_5 \right)$, where $\left \vert \epsilon_5 \right \vert \leq 2^{-147}$ is then multiplied by $m$ in order to obtain a triple-double approximation of $\sqrt{m}$. Once renormalized result is exactly multiplied by $2^{\frac{E}{2}}$ stored in $xdb.d$. We implement: \begin{lstlisting}[caption={Newton iteration - triple-double step},firstnumber=1] Mul133(&srtmhover, &srtmmover, &srtmlover,m,r5h,r5m,r5l); Renormalize3(&srtmh,&srtmm,&srtml,srtmhover,srtmmover,srtmlover); (*(resh)) = xdb.d * srtmh; (*(resm)) = xdb.d * srtmm; (*(resl)) = xdb.d * srtml; \end{lstlisting} \subsubsection{Accuracy bounds} TODO: see possibly available Gappa files meanwhile interval-3.2.0/src/crlibm/docs/latex/trigo.tex0000644000000000000000000017573013316017127017456 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA This chapter is contributed by F. de~Dinechin with assistance of C. Daramy-Loirat and D. Defour. \section*{Introduction} This chapter describes the implementations of sine, cosine and tangent, as they share much of their code. The proof sketch below is supported by the Maple script \texttt{maple/trigo.mpl} and the Gappa scripts \texttt{gappa/trigoSinCosCase3.gappa} and \texttt{gappa/trigoTanCase2.gappa} of the \crlibm\ distribution. These scripts implement the computations of error bounds and validity bounds for the various algorithmic paths described here. \section{Overview of the algorithms} \subsection{Exceptional cases} The three trigonometric functions return NaN for infinite and NaN arguments, and are defined otherwise. An argument based on continued fractions to find the worst cases for range reduction may also be used to show that the sine and cosine of a floating-point number outside of $[-1,1]$ is always larger than $2^{-150}$, and therefore never flushes to zero nor to subnormal (see \cite{Muller97} p. 151 and following). Therefore $\tan(x)=\sin(x)/\cos(x)$ also remains larger than $2^{-150}$. This has two important consequences: \begin{itemize} \item as the output a trigonometric function is never a subnormal except for inputs around zero (for which the value to return is trivial anyway), we can safely use the rounding tests from Section \ref{section:testrounding} p.~\pageref{section:testrounding}. \item as the cosine never flushes to zero, the tangent of a floating-point number is never an infinity, and does not even come close, so again we may safely use the rounding tests from Section \ref{section:testrounding}. \end{itemize} For very small arguments, \begin{itemize} \item $\sin(x) = x-x^3/6 + O(x^5) = x(1-x^2/6) + O(x^5)$ where $O(x^5)$ has the sign of $x$. Therefore $\sin(x)$ is rounded to $x$ or one of its floating-point neighbours as soon as $|x|<2^{-26}$. \item $\cos(x) = 1-x^2/2 + O(x^4)$ where $O(x^4)$ is positive. Therefore $\cos(x)$ is rounded to $1$ in RN and RU mode if $x<\sqrt{2^{-53}}$. In RD and RZ modes, we have $\cos(0)=1$ and $\cos(x)=1-2^{-53}$ for $|x|<2^{-26}$. \item $\tan(x) = x+x^3/3 + O(x^5) = x(1+x^2/3) + O(x^5)$ where $O(x^5)$ has the sign of $x$. Therefore $\tan(x)$ is rounded to $x$ or one of its neighbours for all the rounding modes if $|x|<2^{-27}$. \end{itemize} \subsection{Range reduction} Most implementations of the trigonometric functions have two steps of range reduction: \begin{itemize} \item first the input number $x$ is reduced to $y\in [-\frac{\pi}{4}, \frac{\pi}{4}]$, with reconstruction using periodicity and symmetry properties, \item then the reduced argument is further broken down as $y=a+z$, with reconstruction using the formula for $\sin(a+z)$ and $\cos(a+z)$, using tabulated values of $\sin(a)$ and $\cos(a)$ \end{itemize} We chose to implement range reduction in one step only, which computes an integer $k$ and a reduced argument y such that \begin{equation} x = k\frac{\pi}{256} + y\label{eq:trigoargred} \end{equation} where $k$ is an integer and $ |y| \leq {\pi}/{512}$. This step computes $y$ as a double-double: $y\approx y_h+y_l$. In the following we note $$a=k\pi/256.$$ Then we read off a table $$sa_h+sa_l \approx sin(a)$$ $$ca_h+ca_l \approx cos(a)$$ Only 64 quadruples $(sa_h,sa_l,ca_h,ca_l)$ are tabulated (amounting to $64\times 8 \times 4 = 2048$ bytes), the rest is obtained by periodicity and symmetry, implemented as masks and integer operations on the integer $k$. For instance, $a \mod 2\pi$ is implemented by $k \mod 512$, $\pi/2-a$ is implemented as $128-k$, etc. Then we use the reconstruction steps: \begin{equation} \sin(x) = \sin(a + y) = \cos(a) \sin(y) + \sin(a) \cos(y) \label{eq:sinapy} \end{equation} \begin{equation} \cos(x) = \cos(a + y) = \cos(a) \cos(y) - \sin(a) \sin(y) \label{eq:cosapy} \end{equation} \begin{equation} tan(x) = \frac{\sin(x)}{\cos(x)} \label{eq:tanapy} \end{equation} \subsection{Polynomial evaluation} To implement the previous equations, $\cos(y)$ and $\sin(y)$ are computed as unevaluated $1+t_c$ and $(y_h+y_l)(1+t_s)$ respectively, where $t_c$ and $t_s$ are doubles computed using a polynomial approximation of small degree: \begin{itemize} \item $t_s = y^2(s_3 + y^2(s_5 + y^2s_7)))$ with $s3$, $s5$ and $s7$ the Taylor coefficients. \item $t_c = y^2(c_2 + y^2(c_4 + y^2c_6))$ with $c2$, $c4$ and $c6$ the Taylor coefficients (or a more accurate minimax approximation). \end{itemize} \subsection{Reconstruction} \subsubsection{Sine} According to equation (\ref{eq:sinapy}), we have to compute: \begin{eqnarray*} \sin(a+y) &=& \sin(a) \cos(y) + \cos(a)\sin(y) \\ & \approx& (sa_h+sa_l)(1+t_c) + (ca_h+ca_l)(y_h+y_l)(1+t_s) \end{eqnarray*} Figure~\ref{fig:sine-reconstruction} shows the worst-case respective orders of magnitude of the terms of this sum. The terms completely to the right of the vertical bar will be neglected, and a bound on the error thus entailed is computed in the following. Note that the term $ca_hy_h$ has to be computed exactly by a Mul12. Finally the reconstruction consists of adding together the lower-order terms in increasing order of magnitude, and computing the double-double result by an Add12. \begin{figure}[htbp] \begin{center} \small \setlength{\unitlength}{3ex} \framebox{ \begin{picture}(22,9)(-3,-4.2) \put(9.5,4){\line(0,-1){8}} %\put(9,4){$\epsilon$} \put(4,3.2){$sa_h$} \put(0.05,3){\framebox(7.9,0.7){}} \put(12,3.2){$sa_l$} \put(8.05,3){\framebox(7.9,0.7){}} \put(6,2.2){$sa_ht_c$} \put(2.05,2){\framebox(7.9,0.7){}} \put(14,2.2){$sa_lt_c$} \put(10.05,2){\framebox(7.9,0.7){}} \put(4.5,1.2){$ca_hy_h$} \put(0.55,1){\framebox(7.9,0.7){}} \put(12.5,1.2){$ca_hy_h$} \put(8.55,1){\framebox(7.9,0.7){}} \put(11.5,0.2){$ca_hy_l $} \put(7.55,0){\framebox(7.9,0.7){}} \put(11.5,-0.8){$ca_ly_h $} \put(7.55,-1){\framebox(7.9,0.7){}} \put(6.5,-1.8){$ca_hy_ht_s$} \put(2.55,-2){\framebox(7.9,0.7){}} \put(13.5,-2.8){$ca_hy_lt_s $} \put(9.55,-3){\framebox(7.9,0.7){}} \put(13.5,-3.8){$ca_ly_ht_s $} \put(9.55,-4){\framebox(7.9,0.7){}} \end{picture} } \end{center} \caption{The sine reconstruction} \label{fig:sine-reconstruction} \end{figure} \subsubsection{Cosine} According to equation (\ref{eq:cosapy}), we have to compute in double-double precision: \begin{eqnarray*} \cos(a+y) &=& \cos(a) \cos(y) - \sin(a)\sin(y) \\ & \approx& (ca_h+ca_l)(1+t_c) - (sa_h+sa_l)(y_h+y_l)(1+t_s) \end{eqnarray*} This is similar to the case of the sine, and the respective orders of magnitude are given by Figure~\ref{fig:sine-reconstruction}. \begin{figure}[htbp] \begin{center} \small \setlength{\unitlength}{3ex} \framebox{ \begin{picture}(22,9)(-3,-4.2) \put(9.5,4){\line(0,-1){8}} % \put(9,4){$\epsilon$} \put(4,3.2){$ca_h$} \put(0.05,3){\framebox(7.9,0.7){}} \put(12,3.2){$ca_l$} \put(8.05,3){\framebox(7.9,0.7){}} \put(6,2.2){$ca_ht_c$} \put(2.05,2){\framebox(7.9,0.7){}} \put(14,2.2){$ca_lt_c$} \put(10.05,2){\framebox(7.9,0.7){}} \put(4.5,1.2){$-sa_hy_h$} \put(0.55,1){\framebox(7.9,0.7){}} \put(12.5,1.2){$-sa_hy_h$} \put(8.55,1){\framebox(7.9,0.7){}} \put(11.5,0.2){$-sa_hy_l $} \put(7.55,0){\framebox(7.9,0.7){}} \put(11.5,-0.8){$-sa_ly_h $} \put(7.55,-1){\framebox(7.9,0.7){}} \put(6.5,-1.8){$-sa_hy_ht_s$} \put(2.55,-2){\framebox(7.9,0.7){}} \put(13.5,-2.8){$-sa_hy_lt_s $} \put(9.55,-3){\framebox(7.9,0.7){}} \put(13.5,-3.8){$-sa_ly_ht_s $} \put(9.55,-4){\framebox(7.9,0.7){}} \end{picture} } \end{center}\centering \caption{The cosine reconstruction} \label{fig:cosine-reconstruction} \end{figure} \subsubsection{Tangent} The tangent is obtained by the division of the sine by the cosine, using the \texttt{Div22} procedure which is accurate to $2^{-104}$. \subsection{Precision of this scheme} As we have $|y|<2^{-7}$, this scheme computes these functions accurately to roughly $2^{53+13}$ bits, so these first steps are very accurate. \subsection{Organisation of the code} The code for range reduction is shared by the three trigonometric functions. It is detailed and proven in Section~\ref{trigo:argred}. Then there are four procedures (currently implemented as macros for efficiency), respectively called \texttt{DoSinZero}, \texttt{DoCosZero}, \texttt{DoSinNotZero} and \texttt{DoCosNotZero} which do the actual computation after range reduction as per Figures~\ref{fig:sine-reconstruction} and \ref{fig:cosine-reconstruction}. The tangent function is computed by dividing the sine by the cosine. These procedures are studied in section \ref{trigo:auxiliary}. Finally, each of the three trigonometric functions comes in four variants for the four rounding modes. These four variants differ in the beginning (special cases) and in the end (rounding), but share the bulk of the computation. The shared computation is called \verb!compute_trig_with_argred!. \section{Details of range reduction \label{trigo:argred}} \subsection{Which accuracy do we need for range reduction?} The additive reduction consists in adding or removing $N$ times a certain constant $C$ from the input argument. For trigonometric function this constant is usually equal to $\pi/2$ or $\pi/4$, in our case it is $\pi/128$. A naive range reduction based on machine precision for trigonometric function would be implemented as : \begin{equation} \begin{array}{rcl} k &=& \lfloor \frac{x}{C} \rfloor \\ x^* &=& x-kC. \\ \end{array} \label{chap6:eqn:rangereduction} \end{equation} Obviously, this subtraction cancels all the bits common to $x$ and $kC$: \begin{itemize} \item The absolute accuracy of $x^*$ with respect to the exact value of $x-kC$ depends only on the precision used to compute the subtraction and the product in $x-kC$ ($x$ is considered exact as it is the input to the function). \item However, the relative accuracy of $x^*$ with respect to the exact value of $x-kC$ also depends on this exact value. For a given precision of the operations used in computing $x-kC$, the closer $x$ to $kC$, the smaller the exact value of $x-kC$, and the worse the relative accuracy (or, in less formal terms, the more bits of the results are lost to cancellation). \end{itemize} As the theorems for correct rounding of Section~\ref{section:testrounding} p.~\pageref{section:testrounding} depend on the relative accuracy of the evaluation (and therefore on the relative accuracy of the reduced argument), we have to prove bounds on the relative accuracy of range reduction. Formulated in simpler terms, how many bits can be lost in the subtraction $x-kC$ ? This number is related to the knowledge of the closest input number $x$ to a multiple of $C$. There exists an algorithm due to Kahan/Douglas and based on continued fraction to compute this number and therefore the number of bit lost (see \cite{Muller97} p. 151 and following). We used a Maple version from \cite{Muller97} to determine than up to 62 bits may be cancelled during range reduction for a ieee double precision number. This Maple procedure is implemented as function \texttt{WorstCaseForAdditiveRangeReduction} in \texttt{maple/common-procedures.mpl}. One advantage of having $C=\pi/128$, however, is that this is only a concern when $x$ is close to a multiple of $\pi/2$ (that is, $k \mod 128=0$): in the other cases (i.e. in the general, most frequent case) the reconstruction will add some tabulated non-zero value, so the error to consider in the range reduction is the absolute error. Only in the cases when $k \mod 128=0$ do we need to have 62 extra bits to compute with. This is ensured by using a slower, more accurate range reduction. As a compensation, in this case when $k \mod 128=0$, there is no table to read and no reconstruction to perform: a simple polynomial approximation to the function suffices. \subsection{Details of the used scheme} We have 4 possible range reductions, depending on the magnitude of the input number (and the previous considerations): \begin{itemize} \item Cody and Waite with 2 constants (the fastest), \item Cody and Waite with 3 constants (almost as fast), \item Cody and Waite with 3 constants in double-double and $k$ a 64-bit int, and \item Payne and Hanek, implemented in SCS (the slowest). \end{itemize} Each of these range reductions except Payne and Hanek is valid for $x$ smaller than some bound. The computation of these bounds is detailed below. Section \ref{trigo:structargred} details the organization of this multi-level range reduction, and is followed by a detailed proof of each level. \subsection{Structure of the range reduction \label{trigo:structargred}} The complete code is detailed below. To provide a complete picture to the reader it actually also includes the reconstruction. \begin{lstlisting}[caption={Multilevel range reduction \label{lst:trig:argred}},firstnumber=1] struct rrinfo_s {double rh; double rl; double x; int absxhi; int function;} ; typedef struct rrinfo_s rrinfo; #define changesign function /* saves one int in the rrinfo structure */ static void ComputeTrigWithArgred(rrinfo *rri){ double sah,sal,cah,cal, yh, yl, yh2, ts,tc, kd; double kch_h,kch_l, kcm_h,kcm_l, th, tl,sh,sl,ch,cl; int k, quadrant, index; long long int kl; if (rri->absxhi < XMAX_CODY_WAITE_3) { /* Compute k, deduce the table index and the quadrant */ DOUBLE2INT(k, rri->x * INV_PIO256); kd = (double) k; quadrant = (k>>7)&3; index=(k&127)<<2; if((index == 0)) { /* Here a large cancellation on yh+yl would be a problem, so use double-double RR */ /* all this is exact */ Mul12(&kch_h, &kch_l, kd, RR_DD_MCH); Mul12(&kcm_h, &kcm_l, kd, RR_DD_MCM); Add12 (th,tl, kch_l, kcm_h) ; /* only rounding error in the last multiplication and addition */ Add22 (&yh, &yl, (rri->x + kch_h) , (kcm_l - kd*RR_DD_CL), th, tl) ; goto computeZero; } else { /* index <> 0, don't worry about cancellations on yh+yl */ if (rri->absxhi < XMAX_CODY_WAITE_2) { /* CW 2: all this is exact but the rightmost multiplication */ Add12 (yh,yl, (rri->x - kd*RR_CW2_CH), (kd*RR_CW2_MCL) ) ; } else { /* CW 3: all this is exact but the rightmost multiplication */ Add12Cond(yh,yl, (rri->x - kd*RR_CW3_CH) - kd*RR_CW3_CM, kd*RR_CW3_MCL); } } goto computeNotZero; } else if ( rri->absxhi < XMAX_DDRR ) { /* x sufficiently small for a Cody and Waite in double-double */ DOUBLE2LONGINT(kl, rri->x*INV_PIO256); kd=(double)kl; quadrant = (kl>>7)&3; index=(kl&127)<<2; if(index == 0) { /* Here again a large cancellation on yh+yl would be a problem, so we do the accurate range reduction */ RangeReductionSCS(); /*recomputes k, index, quadrant, and yh and yl*/ /* Now it may happen that the new k differs by 1 of kl, so check that */ if(index==0) /* no surprise */ goto computeZero; else goto computeNotZero; } else { /* index<>0 : double-double range reduction*/ /* all this is exact */ Mul12(&kch_h, &kch_l, kd, RR_DD_MCH); Mul12(&kcm_h, &kcm_l, kd, RR_DD_MCM); Add12 (th,tl, kch_l, kcm_h) ; /* only rounding error in the last multiplication and addition */ Add22 (&yh, &yl, (rri->x + kch_h) , (kcm_l - kd*RR_DD_CL), th, tl) ; goto computeNotZero; } } /* closes if ( absxhi < XMAX_DDRR ) */ else { /* Worst case : x very large, sin(x) probably meaningless, we return correct rounding but do't mind taking time for it */ RangeReductionSCS(); quadrant = (k>>7)&3; if(index == 0) goto computeZero; else goto computeNotZero; } computeZero: switch(rri->function) { case SIN: if (quadrant&1) DoCosZero(&rri->rh, &rri->rl); else DoSinZero(&rri->rh, &rri->rl); rri->changesign=(quadrant==2)||(quadrant==3); return; case COS: if (quadrant&1) DoSinZero(&rri->rh, &rri->rl); else DoCosZero(&rri->rh, &rri->rl); rri->changesign= (quadrant==1)||(quadrant==2); return; case TAN: rri->changesign = quadrant&1; if (quadrant&1) { DoSinZero(&ch, &cl); DoCosZero(&sh, &sl); } else { DoSinZero(&sh, &sl); DoCosZero(&ch, &cl); } Div22(&rri->rh, &rri->rl, sh, sl, ch, cl); return; } computeNotZero: if(index<=(64<<2)) { sah=sincosTable[index+0].d; /* sin(a), high part */ sal=sincosTable[index+1].d; /* sin(a), low part */ cah=sincosTable[index+2].d; /* cos(a), high part */ cal=sincosTable[index+3].d; /* cos(a), low part */ }else { /* cah <= sah */ index=(128<<2) - index; cah=sincosTable[index+0].d; /* cos(a), high part */ cal=sincosTable[index+1].d; /* cos(a), low part */ sah=sincosTable[index+2].d; /* sin(a), high part */ sal=sincosTable[index+3].d; /* sin(a), low part */ } yh2 = yh*yh ; ts = yh2 * (s3.d + yh2*(s5.d + yh2*s7.d)); tc = yh2 * (c2.d + yh2*(c4.d + yh2*c6.d )); switch(rri->function) { case SIN: if (quadrant&1) DoCosNotZero(&rri->rh, &rri->rl); else DoSinNotZero(&rri->rh, &rri->rl); rri->changesign=(quadrant==2)||(quadrant==3); return; case COS: if (quadrant&1) DoSinNotZero(&rri->rh, &rri->rl); else DoCosNotZero(&rri->rh, &rri->rl); rri->changesign=(quadrant==1)||(quadrant==2); return; case TAN: rri->changesign = quadrant&1; if (quadrant&1) { DoSinNotZero(&ch, &cl); DoCosNotZero(&sh, &sl); } else { DoSinNotZero(&sh, &sl); DoCosNotZero(&ch, &cl); } Div22(&rri->rh, &rri->rl, sh, sl, ch, cl); return; } } \end{lstlisting} Here are some comments on the structure of this code (the details on actual range reduction come in the following sections). \begin{itemize} \item The DOUBLETOINT macro at line 13 is called only if $x<\verb!XMAX_CODY_WAITE_3!$ (line 11). This constant is defined (see Listing~\ref{trigo:lst:cw3maple} below) such that the conditions for this macro to work (see Section~\ref{sec:double2int}) are fullfilled. \item Similarly for the DOUBLETOLONGINT macro (see Section~\ref{sec:double2longint}) at line 43, which is called for inputs smaller than \verb!XMAX_DDR! defined in Listing \ref{trigo:lst:cwddrmaple} below. \item There is one subtlety at lines 51 and following. There we take the decision of computing a more accurate range reduction depending on the value of $\mathit{index}=k\mod 256$. However, in the case when $x\times\frac{256}{\pi}$ is very close to the middle between two integers, it may happen (very rarely) that the value of $k\mod 256$ computed by this second range reduction differs from the first by $\pm 1$. In such cases, both values will provide different but equally valid reduced arguments, but we have to ensure that $k$ and the reduced value match, hence the test line 52. \end{itemize} \subsection{Cody and Waite range reduction with two constants} Here we split $C$ into two floating-point constants $C_h$ and $C_l$ such that $C_h$ holds 21 bits of the mantissa of $C$ (the rest being zeroes), and $C_l=\round(C-C_h)$. The following gives the Maple code that computes these constants, and then computes the bound on which this range reduction is valid. \begin{lstlisting}[caption={Maple script for computing constants for Cody and Waite 2}, firstnumber=1, language={sh}, numbers=none]% of course it's maple %Skip a line here, I don't know why, otherwise latex eats the first line bitsCh_0:=32: # ensures at least 53+11 bits # 1/2 <= C/2^(expC+1) <1 Ch:= round(evalf( C * 2^(bitsCh_0-expC-1))) / (2^(bitsCh_0-expC-1)): # recompute bitsCh in case we are lucky (and we are for bitsCh_0=32) bitsCh:=1+log2(op(2,ieeedouble(Ch)[3])) : # this means the log of the denominator Cl:=nearest(C - Ch): # Cody and Waite range reduction will work for |k| 2^(-67); # In these cases we use the double-double range reduction, for |k|=0x7ff00000) return x-x; else if (absxhi < XMAX_SIN_CASE2){ /* CASE 1 : x small enough sin(x)=x */ if (absxhi =0x7ff00000) return x-x; if (absxhi < XMAX_SIN_CASE2){ /* CASE 1 : x small enough, return x suitably rounded */ if (absxhi =0.) return x; else { x_split.l --; return x_split.d; } } \end{lstlisting} \subsection{Exceptional cases in RD mode} \begin{lstlisting}[caption={Exceptional cases for sine RD},firstnumber=1] /* SPECIAL CASES: x=(Nan, Inf) sin(x)=Nan */ if (absxhi>=0x7ff00000) return x-x; if (absxhi < XMAX_SIN_CASE2){ /* CASE 1 : x small enough, return x suitably rounded */ if (absxhi =0x7ff00000) return x-x; if (absxhi < XMAX_SIN_CASE2){ /* CASE 1 : x small enough, return x suitably rounded */ if (absxhi =0x7ff00000) { /* was : return x-x; but it's optimized out by Intel compiler (bug reported). Who cares to be slow in this case anyway... */ x_split.l=0xfff8000000000000LL; return x_split.d-x_split.d; } if (rri.absxhi < XMAX_COS_CASE2){ /* CASE 1 : x small enough cos(x)=1. */ if (rri.absxhi =0x7ff00000) { x_split.l=0xfff8000000000000LL; return x_split.d - x_split.d; } if (rri.absxhi < XMAX_COS_CASE2){ /* CASE 1 : x small enough cos(x)=1. */ if (rri.absxhi =0x7ff00000) { x_split.l=0xfff8000000000000LL; return x_split.d - x_split.d; } if (rri.absxhi < XMAX_COS_CASE2){ if (x==0) return 1; /* CASE 1 : x small enough cos(x)=1. */ if (rri.absxhi =0x7ff00000) { x_split.l=0xfff8000000000000LL; return x_split.d - x_split.d; } if (rri.absxhi < XMAX_COS_CASE2){ if (x==0) return 1; /* CASE 1 : x small enough cos(x)=1. */ if (rri.absxhi =0x7ff00000) { x_split.l=0xfff8000000000000LL; return x_split.d - x_split.d; } if (rri.absxhi < XMAX_TAN_CASE2){ if (rri.absxhi < XMAX_RETURN_X_FOR_TAN) return x; /* Dynamic computation of the rounding constant */ rndcst.i[HI] = 0x3ff00000 + (((rri.absxhi & 0x000fffff)+0x00100000) >> (0x3ff+2 - (rri.absxhi>>20))) ; rndcst.i[LO] =0xffffffff; /* Fast Taylor series */ x2 = x*x; p5 = t5.d + x2*(t7.d + x2*(t9.d + x2*t11.d)); tt = x2*(t3h.d + (t3l.d +x2*p5)); Add12(rri.rh, rri.rl, x, x*tt); /* Test if round to nearest achieved */ if(rri.rh == (rri.rh + (rri.rl * rndcst.d))) return rri.rh; else return scs_tan_rn(x); } else { /* Otherwise : Range reduction then standard evaluation */ rri.x=x; rri.function=TAN; ComputeTrigWithArgred(&rri); /* Test if round to nearest achieved */ if(rri.rh == (rri.rh + (rri.rl * RN_CST_TAN_CASE3))) if(rri.changesign) return -rri.rh; else return rri.rh; else return scs_tan_rn(x); } } \end{lstlisting} There is a peculiarity in lines 19 and 20: We compute the rounding constant dynamically, out of the value of $x$. The idea here is that in the neighborhood of zero, both $tan$ and its approximation are equivalent to $x$ with no order-2 term, therefore the relative error $\maxeps$ is equivalent to $x^2$ and therefore $\maxeps/x$ will vanish as $x\rightarrow 0$ (of course, in the presence of rounding error this has to be proven more rigorously - we will use Gappa below). As the error constant is computed out of $\maxeps$ (see Theorem~\ref{th:roundingRN1} page~\pageref{th:roundingRN1}), for $x$ sufficiently small we can compute $e$ out of $x$ and get a finer rounding constant, hence a lower probability of going through the accurate phase. The lines 19-20 implement $$\mathtt{rndcst} \approx 1 + 2^{-2}|x|$$ with $$\mathtt{rndcst} \ge 1 + 2^{-2}|x|$$ ensured by line 20. To prove that that this rounding constant is correct, we just have to check that it fulills the requirements of Theorem \ref{th:roundingRN1}. Let us note $\maxeps_{TanCase2}$ simply $\maxeps$ in this section. First, we compute in Gappa (file\\ \texttt{maple/trigoTanCase2.gappa} below), using the same constants (produced by the same Maple) as in the C code, a bound $M$ on $\dfrac{\maxeps}{|x|}$. We find that, for $x<2^{-4}$, we have $$\maxeps_{TanCase2} < 2^{-60.9} $$ (hence the $k$ of Theorem \ref{th:roundingRN1} may be chosen as $k=7$) and $$\dfrac{\maxeps}{|x|} < M=2^{-56.5} .$$ Or, $$|x| > \maxeps/M$$ Therefore, $$\mathtt{rndcst} > 1 + 2^{-2}/M\maxeps$$. It is now trivial to check that $2^{-2}/M > \dfrac{2^{54}}{(1-2^{-7})(1-2^{-53})}$, therefore for any $x$ the value of $\mathtt{rndcst}$ thus computed allows to determine correct rounding according to Theorem \ref{th:roundingRN1}. Note that the computation of the rounding constant, although complex, is performed in integer arithmetic and independently of the evaluation of the polynomial. Therefore both computations may be carried out in parallel in a superscalar processor. The input to Gappa is as follows. Note that it needs a bound on $\dfrac{p(x)-\tan(x)}{x \tan(x)}$ which has been computed as an infinite norm in Maple. \lstinputlisting[caption={Gappa input file to prove the previous bounds on $\maxeps_{TanCase2}$ and $\maxeps_{TanCase2}/x$}, language={sh}, numbers=none]{../../gappa/trigos/TanCase2.gappa} \subsection{RU mode} \begin{lstlisting}[caption={Exceptional cases for tangent RU},firstnumber=1] double tan_ru(double x){ double epsilon, p5, tt, x2; db_number x_split; rrinfo rri; x_split.d=x; rri.absxhi = x_split.i[HI] & 0x7fffffff; /* SPECIAL CASES: x=(Nan, Inf) cos(x)=Nan */ if (rri.absxhi>=0x7ff00000) { x_split.l=0xfff8000000000000LL; return x_split.d - x_split.d; } if (rri.absxhi < XMAX_TAN_CASE2){ if (rri.absxhi < XMAX_RETURN_X_FOR_TAN) { if(x<=0.) return x; else { x_split.l ++; return x_split.d; } } else { /* Fast Taylor series */ x2 = x*x; p5 = t5.d + x2*(t7.d + x2*(t9.d + x2*t11.d)); tt = x2*(t3h.d + (t3l.d +x2*p5)); Add12(rri.rh, rri.rl, x, x*tt); /* TODO dynamic computation of error constant */ TEST_AND_RETURN_RU(rri.rh, rri.rl, EPS_TAN_CASE2); /* if the previous block didn't return a value, launch accurate phase */ return scs_tan_ru(x); } } else { /* Normal case: Range reduction then standard evaluation */ rri.x=x; rri.function=TAN; ComputeTrigWithArgred(&rri); epsilon=EPS_TAN_CASE3; if(rri.changesign) { rri.rh= -rri.rh; rri.rl=-rri.rl; } } TEST_AND_RETURN_RU(rri.rh, rri.rl, epsilon); /* if the previous block didn't return a value, launch accurate phase */ return scs_tan_ru(x); } \end{lstlisting} \subsection{RD mode} \begin{lstlisting}[caption={Exceptional cases for tangent RD},firstnumber=1] double tan_rd(double x){ double epsilon, p5, tt, x2; rrinfo rri; db_number x_split; x_split.d=x; rri.absxhi = x_split.i[HI] & 0x7fffffff; /* SPECIAL CASES: x=(Nan, Inf) cos(x)=Nan */ if (rri.absxhi>=0x7ff00000){ x_split.l=0xfff8000000000000LL; return x_split.d - x_split.d; } if (rri.absxhi < XMAX_TAN_CASE2){ if (rri.absxhi < XMAX_RETURN_X_FOR_TAN) { if(x>=0.) return x; else { x_split.l ++; return x_split.d; } } /* Fast Taylor series */ x2 = x*x; p5 = t5.d + x2*(t7.d + x2*(t9.d + x2*t11.d)); tt = x2*(t3h.d + (t3l.d +x2*p5)); Add12(rri.rh, rri.rl, x, x*tt); TEST_AND_RETURN_RD(rri.rh, rri.rl, EPS_TAN_CASE2); /* if the previous block didn't return a value, launch accurate phase */ return scs_tan_rd(x); } else { /* normal case: Range reduction then standard evaluation */ rri.x=x; rri.function=TAN; ComputeTrigWithArgred(&rri); epsilon=EPS_TAN_CASE3; if(rri.changesign) { rri.rh= -rri.rh; rri.rl=-rri.rl; } } TEST_AND_RETURN_RD(rri.rh, rri.rl, epsilon); /* if the previous block didn't return a value, launch accurate phase */ return scs_tan_rd(x); } \end{lstlisting} \subsection{RZ mode} \begin{lstlisting}[caption={Exceptional cases for tangent RZ},firstnumber=1] double tan_rz(double x){ double epsilon, p5, tt, x2; rrinfo rri; db_number x_split; x_split.d=x; rri.absxhi = x_split.i[HI] & 0x7fffffff; /* SPECIAL CASES: x=(Nan, Inf) cos(x)=Nan */ if (rri.absxhi>=0x7ff00000) { x_split.l=0xfff8000000000000LL; return x_split.d - x_split.d; } if (rri.absxhi < XMAX_TAN_CASE2){ if (rri.absxhi < XMAX_RETURN_X_FOR_TAN) { return x; } else{ /* Fast Taylor series */ x2 = x*x; p5 = t5.d + x2*(t7.d + x2*(t9.d + x2*t11.d)); tt = x2*(t3h.d + (t3l.d +x2*p5)); Add12(rri.rh, rri.rl, x, x*tt); TEST_AND_RETURN_RZ(rri.rh, rri.rl, EPS_TAN_CASE2); /* if the TEST_AND_RETURN block didn't return a value, launch accurate phase */ return scs_tan_rz(x); } } else { /* Normal case: Range reduction then standard evaluation */ rri.x=x; rri.function=TAN; ComputeTrigWithArgred(&rri); epsilon=EPS_TAN_CASE3; if(rri.changesign) { rri.rh = -rri.rh; rri.rl = -rri.rl; } } TEST_AND_RETURN_RZ(rri.rh, rri.rl, epsilon); /* if the previous block didn't return a value, launch accurate phase */ return scs_tan_rz(x); } \end{lstlisting} \section{Accurate phase} For simplicity, the accurate phase (in file \texttt{trigo\_accurate.c}) always computes a Payne and Hanek range reduction to $[-\pi/4, \pi/4]$, then a polynomial evaluation using a Taylor formula. The results of the search for worst cases are the following so far: \begin{center} \begin{tabular}{|c|c|c|} \hline Function & interval & worst-case accuracy \\ \hline \hline $\sin(x)$ & $|x|< 2^{-17}$ & $2^{-126}$ \\ & $ 2^{-17} \le |x| \le 2+\frac{4675}{8192}$& $2^{-119}$ \\ \hline $\cos(x)$ & $2^{-25} \le |x| \le 2^{-22}$ & $2^{-142}$ \\ & $2^{-22} \le |x| \le 2^{-18}$ & $2^{-136}$ \\ & $2^{-18} \le |x| \le 2^{-17}$ & $2^{-114}$ \\ & $2^{-17} \le |x| \le \frac{12867}{8192}$ & $2^{-112}$ \\ \hline $\tan(x)$ & $2^{-25} \le |x| \le 2^{-18}$ & $2^{-132}$ \\ & $2^{-18} \le |x| \le \arctan(2)$ & $2^{-111}$ \\ \hline \end{tabular} \end{center} The polynomials used are Pade approximation computed in \texttt{maple/trigo.mpl}. This maple script produces the \texttt{trigo.h} file, and also prints out the approximation error, as follows. \begin{itemize} \item of degree 25 for sine, with an approximation error lower than $2^{-125}$ on $[-\pi/4, \pi/4]$, and lower than $2^{-158}$ for $|x|< 2^{-17}$, \item of degree 26 for cosine, with an approximation error lower than $2^{-132}$ on $[-\pi/4, \pi/4]$, and lower than $2^{-168}$ for $|x|< 2^{-18}$, \item of degree 69 for the tangent, with an approximation error lower than $2^{-30}$ on $[-\pi/4, \pi/4]$, and lower than $2^{-163}$ for $|x|< 2^{-18}$. \end{itemize} The polynomial evaluation is an Horner scheme in SCS, ensuring better than $2^{-200}$ accumulated roundoff errors. Therefore, the overall evaluation error for the accurate phase is lower than the worst case accuracy for each function on each interval of the previous table. This Maple script, and \crlibm\ in general, are designed to allow easy increase of the accuracy, should cases worst than those of this table be found in the future. \section{Performance results} Table~\ref{tbl:sine_abstime} gives performance results for input numbers with random mantissa and exponents uniformely distributed between -20 and 40, by the command:\\ \verb!tests/crlibm_testperf sin RN 10000!. In this case the second step was taken 3 times out of 10000. Which input interval should be used to measure the performance of trigonometric functions is an open question for us. For larger exponents, \texttt{libultim} is faster than \texttt{crlibm}. \begin{table}[!htb] \begin{center} \renewcommand{\arraystretch}{1.2} \begin{tabular}{|l|r|r|r|} \hline \multicolumn{4}{|c|}{Pentium III / Linux Debian sarge / gcc 3.3} \\ \hline & min time & avg time & max time \\ \hline \texttt{libm} & 108 & 118 & 142 \\ \hline \texttt{mpfr} & 16715 & 67153 & 186925 \\ \hline \texttt{libultim} & 91 & 300 & 1294619 \\ \hline \texttt{crlibm} & 81 & 229 & 13616 \\ \hline \end{tabular} \end{center} \caption{Absolute timings for the sine (arbitrary units) \label{tbl:sine_abstime}} \end{table} Results for the cosine are very similar. The tangent leaves more room for improvement, as Table~\ref{tbl:tan_abstime} shows. The culprit is the Div22 procedure, which is very expensive. Directed rounding mode have a penalty of about 50 cycles on a Pentium III, due to the heavy use of integer 64-bit arithmetic. \begin{table}[!htb] \begin{center} \renewcommand{\arraystretch}{1.2} \begin{tabular}{|l|r|r|r|} \hline \multicolumn{4}{|c|}{Pentium III / Linux Debian sarge / gcc 3.3} \\ \hline & min time & avg time & max time \\ \hline \texttt{libm} & 158 & 167 & 183 \\ \hline \texttt{mpfr} & 22759 & 80108 & 222550 \\ \hline \texttt{libultim} & 113 & 428 & 1357592 \\ \hline \texttt{crlibm} & 105 & 367 & 33830 \\ \hline \end{tabular} \end{center} \caption{Absolute timings for the tangent (arbitrary units) \label{tbl:tan_abstime}} \end{table} %%% Local Variables: %%% mode: latex %%% TeX-master: "crlibm" %%% End: interval-3.2.0/src/crlibm/docs/latex/trigpi.tex0000644000000000000000000002773013316017127017624 0ustar 00000000000000% This file is part of crlibm, the correctly rounded mathematical library, % which has been developed by the Arénaire project at École normale supérieure % de Lyon. % % Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, % Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, % and Jean-Michel Muller % % This library is free software; you can redistribute it and/or % modify it under the terms of the GNU Lesser General Public % License as published by the Free Software Foundation; either % version 2.1 of the License, or (at your option) any later version. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public % License along with this library; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA This chapter is contributed by F. de Dinechin. \section{Overview} The trigpi functions are defined as follows: \begin{eqnarray} \sinpi(x) &=& sin(\pi x) \\ \cospi(x) &=& cos(\pi x) \\ \tanpi(x) &=& tan(\pi x) \end{eqnarray} These functions are similar to the trigonometric functions, with two main differences: \begin{itemize} \item Their first argument reduction is exact, and relatively easy: It consists in removing the integer part of $x$, as e.g. $\sinpi(x+n)=\pm \sinpi(x)$ for $n\in\N$. As an important consequence, their worst-case critical accuracy is known on $\F$ as soon as it is known on the interval $[0 1]$. \item Their Taylor expansion, on the other hand, has irrational coefficients, which requires more careful handling around zero. \end{itemize} Apart from these two differences, we use the same secondary argument reduction as for the trigonometric functions in chapter \ref{chap:trigo}. Indeed, we even use the same tabulated values: first, decompose the input value as follows: \begin{equation} \pi x = k\frac{\pi}{256} + \pi y\label{eq:trigpiargred} \end{equation} where $k$ is an integer and $ |y| \leq {1}/{512}$. Contrary to the usual trig functions, $y$ so defined is an exact double: this second argument reduction is errorless, too. Actually, it is performed in the same operations that compute the first. Then, denoting $a=k\pi/256$, we read off a table the following triple-double values: $$sa_h+sa_m+sa_l \approx sin(a)$$ $$ca_h+ca_m+ca_l \approx cos(a)$$ Only 64 pairs of triple-doubles are tabulated (amounting to $64\times 8 \times 6 = 3$ Kbytes), the rest is obtained by periodicity and symmetry, implemented as masks and integer operations on the integer $k$. For instance, $a\mod 2\pi$ is implemented by $k\mod 512$, $\pi/2-a$ is implemented as $128-k$, etc. Then we use the reconstruction steps: \begin{equation} \sinpi(x) = \sin(a + \pi y) = \cos(a) \sinpi(y) + \sin(a) \cospi(y) \label{eq:sinpiapy} \end{equation} \begin{equation} \cospi(x) = \cos(a + \pi y) = \cos(a) \cospi(y) - \sin(a) \sinpi(y) \label{eq:cospiapy} \end{equation} \begin{equation} tanpi(x) = \frac{\sinpi(x)}{\cospi(x)} \label{eq:tanpiapy} \end{equation} \section{Special cases for $\cos(\pi x)$ } $\cospi$ should return a NaN on infinities and NaN. In all the rounding modes, we have $\cospi(x)=1$ for all the even integer values of $|x|$, and $\cospi(x)=-1$ for all the odd integer values of $|x|$. In all the rounding modes, we have $\cospi(x)=1$ for all the even integer values of $|x|$, and $\cospi(x)=-1$ for all the odd integer values of $|x|$. We have $\cospi(x)=+0$ for all the half-integer values of $x$. One could discuss whether having alternate $+0$ and $-0$ would not be better, but there will be a conflict between $\cos(\pi+x)=-\cos(x)$ and $\cos(-x)=\cos(x)$ for e.g. $x=0.5\pi$. Our choice ($+0$ only) is inspired by the LIA2 standard. Concerning small inputs, we have the Taylor expansion: \begin{equation} \cos(\pi x) = 1-(\pi x)^2/2 + O(x^4)\label{eq:cospiTaylor} \end{equation} where $O(x^4)$ is positive. Therefore $\cos(\pi x)$ is rounded to $1$ in RN and RU mode if $(\pi x)^2<{2^{-53}}$. We test this with a constant $C$ which is defined as the upper 32 bits of $\sqrt(2^{-53})/4$. In RD and RZ modes, we have $\cospi(0)=1$ and $\cospi(x)=1-2^{-53}$ for $0<|x| 2^{-52} \cdot \left \vert x_\hi \right \vert$.\\ So we get the following inequality $$2^{-52} \cdot \left \vert x_\hi \right \vert < \mUlp\left( x_\hi \right)$$ Without loss of generality, let us suppose now that $x_\hi > 0$ and that $x_\hi^+ \not = + \infty$ where $x_\hi^+$ is the successor of $x_\hi$ in the ordered set of floating point numbers.\\ So we know by the definition of non-subnormal floating point number in double precision that there exists $m \in \N$ and $e \in \Z$ such that $x_\hi = 2^e \cdot m$ with $2^{52} \leq m < 2^{53}$. Anyway, one can check that $$x_\hi^+ = \left \lbrace \begin{array}{lll} 2^e \cdot \left(m + 1 \right) & \mbox{ if } & m+1 < 2^{53} \\ 2^{e+1} \cdot 2^{52} & \mbox{ otherwise} & \end{array} \right.$$ So 2 cases must be treated separately:\\~\\ {\bf 1st case: $x_\hi^+ = 2^e \cdot \left( m + 1 \right)$} \\ So we get \begin{eqnarray*} 2^e \cdot \left( m + 1 \right) - 2^e \cdot m & > & 2^{-52} \cdot 2^e \cdot m \\ 1 & > & 2^{-52} \cdot m \end{eqnarray*} In contrast, $m \geq 2^{52}$, so we obtain the strict inequality $1 > 1$ which contradicts the hypotheses. \\~\\ {\bf 2nd case: $x_\hi^+ = 2^{e+1} \cdot 2^{52}$} \\ In this case, we know that $m=2^{53} - 1$. \\ We can deduce that \begin{eqnarray*} 2^{e+1} \cdot 2^{52} - 2^e \cdot \left( 2^{53} - 1\right) & > & 2^{-52} \cdot 2^e \cdot \left( 2^{53} - 1 \right) \\ 1 & > & 2 - 2^{-52} \end{eqnarray*} This last inequality is a direct contradiction with the hypotheses.\qed \end{proof} \begin{lemma}[Commutativity of the $x^+$ and $x^-$ operators with unary $-$] \label{commut} ~ \\ Let be $x \in \F$ a positive floating point number.\\ So, $$\left( - x\right)^+ = -\left(x^+\right)$$ and $$\left( - x\right)^- = -\left(x^-\right)$$ \end{lemma} \begin{proof} ~ \\ Since the set of the floating point numbers is symmetrical around $0$, we get $$\left( -x\right)^+ = \pred\left( -x \right) = -\succ\left( x \right) = - \left(x^+\right)$$ and $$\left( -x\right)^- = \succ\left( -x \right) = -\pred\left( x \right) = - \left(x^-\right)$$\qed \end{proof} \begin{lemma}[$x^+$ and $x^-$ for an integer power of $2$] \label{poweroftwo} ~ \\ Let be $x \in \F$ a non-subnormal floating point number such that it exists $e \in \Z$ such that $$x=\pm2^e \cdot 2^p$$ where $p \geq 2$ is the format's precision.\\ So, $$x - x^-= \frac{1}{2} \cdot \left( x^+ - x \right)$$ \end{lemma} \begin{proof} ~\\ If $x > 0$, we get $$x - x^- = 2^e \cdot 2^p - 2^{e-1} \cdot \left( 2^{p+1} - 1 \right) = 2^{e-1}$$ and $$x^+ - x = 2^e \cdot \left( 2^p + 1 \right) - 2^e \cdot 2^p = 2^e$$ If $x$ is negative it suffices to apply lemma \ref{commut}.\qed \end{proof} \begin{lemma}[$x^+$ and $x^-$ for a float different from an integer power of $2$] \label{notpoweroftwo} ~\\ Let be $x \in \F$ a non-subnormal floating point number such that it does not exist any $e \in \Z$ such that $$x=\pm2^e \cdot 2^p$$ where $p \geq 2$ is the format's precision.\\ So, $$x - x^- = x^+ - x$$ \end{lemma} \begin{proof} ~ \\ If $x > 0$ we know that there exist $e \in \Z$ and $m \in \N$ such that $$x = 2^e \cdot m$$ with $$2^p < m < 2^{p-1}$$ because $x$ is not exactly an integer power of $2$. \\ Further, one checks that $$x^+ = 2^e \cdot \left( m + 1 \right)$$ even if $m = 2^{p-1} -1$ and that $$x^- = 2^e \cdot \left( m - 1 \right)$$ because the lower bound given for $m$ is strict. \\ So one gets \begin{eqnarray*} x - x^- & = & 2^e \cdot m - 2^e \cdot \left(m - 1 \right) \\ & = & 2^e \\ & = & 2^e \cdot \left( m + 1 \right) - 2^e \cdot m \\ & = & x^+ - x \end{eqnarray*} If $x$ is negative it suffices to apply lemma \ref{commut}.\qed \end{proof} \begin{lemma}[Factorized integer powers of $2$ and the operators $x^+$ and $x^-$] \label{multhalf} ~\\ Let be $x \in \F$ a non-subnormal floating point number such that $\frac{1}{2} \cdot x$ is still not subnormal.\\ So, $$\left(\frac{1}{2} \cdot x \right)^+ = \frac{1}{2} \cdot x^+$$ and $$\left(\frac{1}{2} \cdot x \right)^- = \frac{1}{2} \cdot x^-$$ \end{lemma} \begin{proof} ~ \\ Without loss of generality let us suppose that $x$ is positive. Otherwise we easily apply lemma \ref{commut}. \\ So, if $x$ can be written $x = 2^e \cdot m$ with $m + 1 \leq 2^{p+1}$ where $p$ is the precision then $$\left( \frac{1}{2} \cdot x \right)^+ = \left( 2^{e-1} \cdot m \right)^+ = 2^{e-1} \cdot \left(m+1\right) = \frac{1}{2} \cdot x^+$$ Otherwise, $$\left( \frac{1}{2} \cdot x \right)^+ = \left( 2^{e-1} \cdot \left( 2^{p+1} -1 \right) \right)^+ = 2^{e-1+1} \cdot 2^p = \frac{1}{2} \cdot x^+$$ One can check that one obtains a completely analogous result for $x^-$.\qed \end{proof} \begin{lemma}[Factor $3$ of an integer power of $2$ in argument of the $x^+$ operator] \label{succtroisfoispuissdeux} ~ \\ Let be $x \in \F$ a positive floating point number such that $x$ is not subnormal, $x^+$ and $\left( 3 \cdot x \right)^+$ are different from $+\infty$, and that $\exists e \in \Z \mbox{ . } x = 2^e \cdot 2^p$ where $p \geq 3$ is the precision of the format $\F$.\\ So the following equation holds $$\left( 3 \cdot x \right)^+ + \mUlp\left( x \right) = 3 \cdot x^+$$ \end{lemma} \begin{proof} ~ \\ We can easily check the following \begin{eqnarray*} \left( 3 \cdot x \right)^+ + \mUlp\left( x \right) & = & \left( 3 \cdot x \right) + \left( x^+ - x \right) \\ & = & \left( 3 \cdot 2^e \cdot 2^p \right)^+ + \left( 2^e \cdot 2^p \right)^+ - 2^e \cdot 2^p \\ & = & \left( \left( 2 + 1 \right) \cdot 2^e \cdot 2^p \right)^+ + 2^e \cdot \left( 2^p + 1 \right) - 2^e \cdot 2^p \\ & = & \left( 2 \cdot 2^e \cdot 2^p + 2 \cdot \frac{1}{2} \cdot 2^e \cdot 2^p \right)^+ + 2^e \\ & = & \left( 2^{e+1} \cdot \left( 2^p + 2^{p-1} \right) \right)^+ + 2^e \\ & = & 2^{e+1} \cdot \left( 2^p + 2^{p-1} + 1 \right) + 2^e \\ & = & 2^{e+1} \cdot \left( 2^p + 2^{p-1} \right) + 2^{e+1} + 2^e \\ & = & 2^{e+1} \cdot \left( 2^p + 2^{p-1} \right) + 3 \cdot 2^e \\ & = & 3 \cdot 2^e \cdot 2^p + 3 \cdot 2^e \\ & = & 3 \cdot 2^e \cdot \left( 2^p + 1 \right) \\ & = & 3 \cdot \left( 2^e \cdot 2^p \right)^+ \\ & = & 3 \cdot x^+ \end{eqnarray*} \qed \end{proof} \begin{lemma}[Monotony of the $\mUlp$ function] \label{ulpmonoton} ~ \\ The $\mUlp$ function is monotonic for non-subnormal positive floating point numbers and it is monotonic for non-subnormal negative floating point numbers, i.e. $$\forall x,y \in \F \mbox{ . } denorm < x \leq y \Rightarrow \mUlp\left( x \right) \leq \mUlp\left( y \right)$$ $$\lor$$ $$\forall x,y \in \F \mbox{ . } x \leq y < -denorm \Rightarrow \mUlp\left( x \right) \geq \mUlp\left( y \right)$$ where $denorm$ is the greatest positive subnormal. \end{lemma} \begin{proof} ~ \\ As a matter of fact it suffices to show that the $\mUlp$ function is monotonic for non-subnormal floating point numbers and to apply its definition \ref{defulp} for the negative case.\\ Let us suppose so that we have two floating point numbers $x, y \in \F$ such that $denorm < x < y$. Without loss of generality we suppose that $x^+ \not = + \infty$ and that $y^+ \not = + \infty$. Otherwise we apply definition \ref{defulp} of the $\mUlp$ function and lemma \ref{multhalf}.\\ So we get $$\mUlp\left( y \right) - \mUlp\left( x \right) = y^+ - y - x^+ + x$$ It suffices now to show that $$y^+ - x^+ - y + x \geq 0$$ We can suppose that we would have \begin{eqnarray*} x & = & 2^{e_x} \cdot m_x \\ y & = & 2^{e_y} \cdot m_y \end{eqnarray*} with $e_x, e_y \in \Z$, $2^p \leq m_x, m_y < 2^{p+1} - 1$.\\ Since $y > x$, we clearly see that $$\left( e_y, m_y \right) \geq_{\mbox{lex}} \left( e_x, m_x \right)$$ \\ So four different cases are possible: \begin{enumerate} \item \begin{eqnarray*} x^+ & = & 2^{e_x} \cdot \left( m_x + 1 \right) \\ y^+ & = & 2^{e_y} \cdot \left( m_y + 1 \right) \end{eqnarray*} Hence \begin{eqnarray*} y^+ - x^+ - y + x & = & 2^{e_y} \cdot \left( m_y + 1 \right) - 2^{e_x} \cdot \left( m_x + 1 \right) - 2^{e_y} \cdot m_y + 2^{e_x} \cdot m_x \\ & = & 2^{e_y} - 2^{e_x} \\ & \geq & 0 \end{eqnarray*} \item \begin{eqnarray*} x^+ & = & 2^{e_x} \cdot \left( m_x + 1 \right) \\ y^+ & = & 2^{e_y+1} \cdot 2^p \end{eqnarray*} which yields to \begin{eqnarray*} y^+ - x^+ - y + x & = & 2^{e_y+1} \cdot 2^p - 2^{e_x} \cdot \left( m_x + 1 \right) - 2^{e_y} \cdot \left( 2^{p+1} - 1 \right) + 2^{e_x} \cdot m_x \\ & = & 2^{e_y} - 2^{e_x} \\ & \geq & 0 \end{eqnarray*} \item \begin{eqnarray*} x^+ & = & 2^{e_x+1} \cdot 2^p \\ y^+ & = & 2^{e_y} \cdot \left( m_y + 1 \right) \end{eqnarray*} One checks that \begin{eqnarray*} y^+ - x^+ - y + x & = & 2^{e_y} \cdot \left( m_y + 1 \right) - 2^{e_x+1} \cdot 2^p - 2^{e_y} \cdot m_y + 2^{e_x} \cdot \left( 2^{p+1} - 1 \right) \\ & = & 2^{e_y} - 2^{e_x} \\ & \geq & 0 \end{eqnarray*} \item \begin{eqnarray*} x^+ & = & 2^{e_x+1} \cdot 2^p \\ y^+ & = & 2^{e_y+1} \cdot 2^p \end{eqnarray*} Thus \begin{eqnarray*} y^+ - x^+ - y + x & = & 2^{e_y+1} \cdot 2^p - 2^{e_x+1} \cdot 2^p - 2^{e_y} \cdot \left( 2^{p+1} - 1 \right) + 2^{e_x} \cdot \left( 2^{p-1} - 1\right) \\ & = & 2^{e_y} - 2^{e_x} \\ & \geq & 0 \end{eqnarray*} \end{enumerate} This finishes the proof.\qed \end{proof} \section{A normal form and renormalization procedures} Let us now analyse a renormalization algorithm. We will prove its correctness be a series of lemmas and a final theorem. \\ Let be the following procedure: \begin{algorithm}[Renormalization] \label{renorm}~\\ {\bf In: $a_\hi, a_\mi, a_\lo \in \F$} verifying the following preconditions:\\ {\bf Preconditions: } \begin{itemize} \item None of the numbers $a_\hi, a_\mi, a_\lo$ is subnormal \item $a_\hi$ and $a_\mi$ do not overlap in more than $51$ bits \item $a_\mi$ and $a_\lo$ do not overlap in more than $51$ bits \end{itemize} which means formally: \begin{eqnarray*} \left \vert a_\mi \right \vert & \leq & 2^{-2} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-2} \cdot \left \vert a_\mi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-4} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} {\bf Out: $r_\hi, r_\mi, r_\lo \in \F$} \begin{eqnarray*} \left(t_{1\hi}, t_{1\lo}\right) & \gets & \mAdd\left(a_\mi,a_\lo\right) \\ \left(r_\hi, t_{2\lo}\right) & \gets & \mAdd\left(a_\hi, t_{1\hi}\right) \\ \left(r_\mi, r_\lo\right) & \gets & \mAdd\left(t_{2\lo}, t_{1\lo}\right) \end{eqnarray*} \end{algorithm} Consult also \cite{Finot-thesis} on the subject of this algorithm. Let us give now some lemmas on the properties of the values returned by algorithm \ref{renorm} and on the intermediate ones. \begin{lemma}[Exact sum] \label{exact} ~\\ For each triple-double number $a_\hi + a_\mi + a_\lo$, algorithm \ref{renorm} returns a triple-double number $r_\hi + r_\mi + r_\lo$ such that $$a_\hi + a_\mi + a_\lo = r_\hi + r_\mi + r_\lo$$ \end{lemma} \begin{proof} ~\\ This fact is a trivial consequence of the properties of the \Add~ algorithm. \qed \end{proof} \begin{lemma}[Rounding of the middle component] \label{properties}~\\ For each triple-double number $a_\hi + a_\mi + a_\lo$, algorithm \ref{renorm} returns a triple-double number $r_\hi + r_\mi + r_\lo$ such that $$r_\mi = \circ \left( r_\mi + r_\lo \right)$$ The same way, the intermediate and final value will verify the following properties: \begin{eqnarray*} t_{1\hi} & = & \circ \left( a_\mi + a_\lo \right) \\ r_\hi & = & \circ \left( a_\hi + t_{1\hi} \right) \\ \left \vert t_{1\lo} \right \vert & \leq & 2^{-53} \cdot \left \vert t_{1\hi} \right \vert \\ \left \vert t_{2\lo} \right \vert & \leq & 2^{-53} \cdot \left \vert r_\hi \right \vert \\ \end{eqnarray*} In particular, $r_\mi$ will not be equal to $0$ if $r_\lo$ is not equal to $0$. \end{lemma} \begin{proof} ~\\ This fact is a trivial consequence of the properties of the \Add~ algorithm. \qed \end{proof} \begin{lemma}[Upper bounds] \label{major}~\\ For all arguments of algorithm \ref{renorm}, the intermediate and final values $t_{1\hi}$, $t_{1\lo}$, $t_{2\lo}$ and $r_\mi$ can be bounded upwards as follows: \begin{eqnarray*} \left \vert t_{1\hi} \right \vert & \leq & 2^{-1} \cdot \left \vert a_\hi \right \vert \\ \left \vert t_{1\lo} \right \vert & \leq & 2^{-54} \cdot \left \vert a_\hi \right \vert \\ \left \vert t_{2\lo} \right \vert & \leq & 2^{-52} \cdot \left \vert a_\hi \right \vert \\ \left \vert t_\mi \right \vert & \leq & 2^{-51} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} \end{lemma} \begin{proof} ~\\ \begin{enumerate} \item {\bf Upper bound for $\left \vert t_{1\hi} \right \vert$:}\\ We have supposed that \begin{eqnarray*} \left \vert a_\mi \right \vert & \leq & 2^{-2} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-4} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} So we can check that \begin{eqnarray*} \left \vert t_{1\hi} \right \vert & \leq & \left \vert a_\mi \right \vert + \left \vert a_\lo \right \vert + 2^{-54} \cdot \left \vert a_\hi \right \vert\\ & \leq & 2^{-2} \cdot \left \vert a_\hi \right \vert + 2^{-4} \cdot \left \vert a_\hi \right \vert + 2^{-54} \cdot \left \vert a_\hi \right \vert \\ & \leq & 2^{-1} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} \item {\bf Upper bound for $\left \vert t_{1\lo} \right \vert$:}\\ Using the properties of the \Add~ algorithm we can get to know that $$\left \vert t_{1\lo} \right \vert \leq 2^{-53} \cdot \left \vert t_{1\hi} \right \vert$$ which yields finally to $$\left \vert t_{1\lo} \right \vert \leq 2^{-54} \cdot \left \vert a_\hi \right \vert$$ \item {\bf Upper bound for $\left \vert t_{2\lo} \right \vert$:} \begin{eqnarray*} \left \vert t_{2\lo} \right \vert & \leq & 2^{-53} \cdot \left \vert r_\hi \right \vert \\ & \leq & 2^{-53} \cdot \circ \left( \left \vert a_\hi \right \vert + \left \vert t_{1\hi} \right \vert \right) \\ & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert + 2^{-53} \cdot \left \vert t_{1\hi} \right \vert + 2^{-106} \cdot \left \vert a_\hi \right \vert + 2^{-106} \cdot \left \vert t_{1\hi} \right \vert \\ & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert + 2^{-54} \cdot \left \vert a_\hi \right \vert + 2^{-106} \cdot \left \vert a_\hi \right \vert + 2^{-107} \cdot \left \vert a_\hi \right \vert \\ & \leq & 2^{-52} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} \item {\bf Upper bound for $\left \vert r_\mi \right \vert$:} \begin{eqnarray*} \left \vert r_\mi \right \vert & \leq & \left \vert t_{2\lo} \oplus t_{1\lo} \right \vert \\ & \leq & \left \vert t_{2\lo} \right \vert + \left \vert t_{1\lo} \right \vert + 2^{-53} \cdot \left \vert t_{2\lo} + t_{1\lo} \right \vert \\ & \leq & 2^{-52} \cdot \left \vert a_\hi \right \vert + 2^{-54} \cdot \left \vert a_\hi \right \vert + 2^{-105} \cdot \left \vert a_\hi \right \vert + 2^{-107} \cdot \left \vert a_\hi \right \vert \\ & \leq & 2^{-51} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} \end{enumerate} ~ \qed \end{proof} \begin{lemma}[Special case for $r_\hi = 0$] \label{specialcaseinzero}~\\ For all arguments verifying the preconditions of algorithm \ref{renorm}, $r_\hi$ will not be equal to $0$ if $r_\mi$ is not equal to $0$. \\ Formally: $$r_\hi = 0 \Rightarrow r_\mi = 0$$ \end{lemma} \begin{proof} ~\\ Let us suppose that $r_\hi = 0$ and that $r_\mi \not = 0$. So we get \begin{eqnarray*} \left \vert r_\hi \right \vert & = & \left \vert \circ \left( a_\hi + t_{1\hi} \right) \right \vert \\ & \geq & \left \vert \circ \left( 2^{-1} \cdot a_\hi \right) \right \vert \\ & = & 2^{-1} \left \vert a_\hi \right \vert \end{eqnarray*} because we have already shown that $$\left \vert t_{1\hi} \right \vert \leq 2^{-1} \cdot \left \vert a_\hi \right \vert$$ So for $r_\hi$ being equal to $0$, $a_\hi$ must be equal to $0$.\\ In contrast, this yields to $t_{1\hi} = 0$ because $$r_\hi = \circ \left( 0 + t_{1\hi} \right) = t_{1\hi}$$ This implies that $t_{1\lo} = 0$ because of the properties of the \Add~ procedure. The same way, we get $t_{2\lo} = 0$.\\ We can deduce from this that $$0 \not = r_\mi = \circ \left( 0 + 0 \right) = 0$$ which is a contradiction.\qed \end{proof} \begin{lemma}[Lower bound for $\left \vert r_\hi \right \vert$] \label{minor}~\\ For all arguments verifying the preconditions of algorithm \ref{renorm}, the final result $r_\hi$ can be bounded in magnitude as follows: $$\left \vert r_\hi \right \vert \geq 2^{-1} \cdot \left \vert a_\hi \right \vert$$ \end{lemma} \begin{proof} ~\\ We have that $$r_\hi = a_\hi \oplus t_{1\hi}$$ Clearly, if $a_\hi$ and $t_{1\hi}$ have the same sign, we get $$\left \vert r_\hi \right \vert \geq \left \vert a_\hi \right \vert \geq 2^{-1} \cdot \left \vert a_\hi \right \vert$$ Otherwise - $a_\hi$ and $t_{1\hi}$ are now of the opposed sign - we have already seen that $$\left \vert t_{1\hi} \right \vert \leq 2^{-1} \cdot \left \vert a_\hi \right \vert$$ So, in this case, too, we get $$\left \vert r_\hi \right \vert \geq 2^{-1} \cdot \left \vert a_\hi \right \vert$$ \qed \end{proof} \begin{corollary}[Additional property on the \Add~procedure] \label{addsupp} ~\\ Let be $r_\hi$ and $r_\lo$ two double precision floating point numbers returned by the \Add~ procedure. \\ So $$\left \vert r_\lo \right \vert \leq \frac{1}{2} \cdot \mUlp\left( r_\hi \right)$$ \end{corollary} \begin{proof} ~\\ By the definition \ref{adddef} of the \Add~ procedure, we have $r_\hi + r_\lo = x + y$ and $r_\hi = \circ \left( x + y \right)$ and $r_\lo = x+y -r_\lo$. Thus the number $r_\lo = \left( x + y \right) - \circ \left( x + y \right) = \left( x + y \right) - \left( x \oplus y \right)$ is the absolute error of correctly rounded IEEE 754 addition. It is bounded by $\frac{1}{2} \cdot \mUlp\left( r_\hi \right)$ which gives us the desired result.\qed \end{proof} \begin{theorem}[Correctness of the renormalization algorithm \ref{renorm}] ~\\ For all arguments verifying the preconditions of procedure \ref{renorm}, the values returned $r_\hi$, $r_\mi$ and $r_\lo$ will not overlap unless they are all equal to $0$ and their sum will be exactly the sum of the values in argument $a_\hi$, $a_\mi$ and $a_\lo$. \end{theorem} \begin{proof} ~ \\ The fact that the sum of the values returned is exactly equal to the sum of the values in argument has already been proven by lemma \ref{exact}.\\ Without loss of generality, we will now suppose that neither $r_\hi$ nor $r_\mi$ will be $0$ in which case all values returned would be equal to $0$ as we have shown it by lemmas \ref{specialcaseinzero} and \ref{properties}.\\ Using lemma \ref{properties}, we know already that $r_\mi$ and $r_\lo$ do not overlap. Let us show now that $r_\hi$ and $r_\mi$ do not overlap by proving that the following inequality is true $$\left \vert r_\mi \right \vert \leq \frac{3}{4} \cdot \mUlp\left( r_\hi \right) < \mUlp\left( r_\hi \right)$$ There are two different cases to be treated. \\ ~ \\ {\bf 1st case: $t_{2\lo} = 0$} \\ We know that $$r_\mi = \circ \left( t_{2\lo} + t_{1\lo} \right) = \circ \left( 0 + t_{1\lo} \right) = t_{1\lo}$$ When showing lemma \ref{major}, we have already proven that $$\left \vert t_{1\lo} \right \vert \leq 2^{-54} \cdot \left \vert a_\hi \right \vert$$ Using lemma \ref{minor}, we therefore know that $$\left \vert r_\mi \right \vert \leq 2^{-53} \cdot \left \vert r_\hi \right \vert$$ which is the result we wanted to prove.\\ ~ \\ {\bf 2nd case: $t_{2\lo} \not = 0$} \\ Still using lemma \ref{major}, we have shown that $$\left \vert t_{1\hi} \right \vert \leq 2^{-1} \cdot \left \vert a_\hi \right \vert$$ In consequence, when the IEEE 754 \cite{IEEE754} addition $r_\hi = a_\hi \oplus t_{1\hi}$ is ported out, the rounding will be done at a bit of weight heigher than one $\mUlp\left(t_{1\hi} \right)$ because $t_{2\lo}$ is strictly greater than $0$ and because $a_\hi$ and $t_{1\hi}$ do not completely overlap. Therefore we can check that $$\left \vert t_{2\lo} \right \vert \geq \mUlp\left( t_{1\hi} \right)$$ With the result of lemma \ref{major} we already mentioned, we can deduce that $$\left \vert t_{2\lo} \right \vert \leq \frac{1}{2} \cdot \mUlp\left( t_{1\hi} \right) \leq \frac{1}{2} \cdot \left \vert t_{2\lo} \right \vert$$ So one can verify the following upper bound using among others lemma \ref{addsupp}: \begin{eqnarray*} \left \vert r_\mi \right \vert & = & \left \vert \circ \left(t_{2\lo} + t_{1\lo} \right) \right \vert \\ & \leq & \circ \left( \frac{3}{2} \cdot \left \vert t_{2\lo} \right \vert \right) \\ & \leq & \circ \left( \frac{3}{4} \cdot \mUlp \left( r_\hi \right) \right) \\ & = & \frac{3}{4} \cdot \mUlp \left( r_\hi \right) \end{eqnarray*} One remarks that the last simplification is correct here because $\mUlp$ is always equal to an integer power of $2$ and because the precision of a double is greater than $4$ bits.\qed \end{proof} \section{Operators on double-double numbers} Since we dispose now of a renormalization procedure which is effective and proven, we can now consider the different addition and multiplication operators we need. They will surely work finally on expansions of size $3$, but the double-double format \cite{Dek71} must be analysed, too, because it is at the base of the triple-double format. We already mentioned that on definition and analysis of this operators, we need not care such a lot of the overlap in the components of a triple-double number any more: as long as the overlap does not make us loose a too much of the final accuracy because several bits of the \ouvguill significand\fermguill~ are represented twice, overlap is not of an issue for intermediate values. At the end of triple-double computations, it will be sufficient to apply once the renormalization procedure. In order to measure the consequences of an overlap in the operands on final accuracy and in order to be able to follow the increase of the overlap during computations in triple-double, we will indicate for each operator which produces a triple double result or which takes a triple-double operand not only a bound for relative and absolute rounding errors but also a bound for the maximal overlap of the values returned. All this bounds will be parameterised by a variable representing the maximal overlap of the triple-double arguments. \subsection{The addition operator \AddDD} Let us analyse first the following addition procedure: \begin{algorithm}[\AddDD] \label{addDDref} ~ \\ {\bf In:} two double-double numbers, $a_\hi + a_\lo$ and $b_\hi + b_\lo$ \\ {\bf Out:} a double-double number $r_\hi + r_\lo$ \\ {\bf Preconditions on the arguments:} $$\left \vert a_\lo \right \vert \leq 2^{-53} \cdot \left \vert a_\hi \right \vert$$ $$\left \vert b_\lo \right \vert \leq 2^{-53} \cdot \left \vert b_\hi \right \vert$$ {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $t_1 \gets a_\hi \oplus b_\hi$ \\ {\bf if} $\left \vert a_\hi \right \vert \geq \left \vert b_\hi \right \vert$ {\bf then} \begin{center} \begin{minipage}[b]{40mm} $t_2 \gets a_\hi \ominus t_1$ \\ $t_3 \gets t_2 \oplus b_\hi$ \\ $t_4 \gets t_3 \oplus b_\lo$ \\ $t_5 \gets t_4 \oplus a_\lo$ \end{minipage} \end{center} {\bf else} \begin{center} \begin{minipage}[b]{40mm} $t_2 \gets b_\hi \ominus t_1$ \\ $t_3 \gets t_2 \oplus a_\hi$ \\ $t_4 \gets t_3 \oplus a_\lo$ \\ $t_5 \gets t_4 \oplus b_\lo$ \end{minipage} \end{center} {\bf end if} \\ $\left( r_\hi, r_\lo \right) \gets \mAdd\left( t_1, t_5 \right)$ \end{minipage} \end{center} \end{algorithm} Compare \cite{crlibmweb} concerning algorithm \ref{addDDref}. \begin{theorem}[Relative error of algorithm \ref{addDDref} \AddDD~ without occurring of cancellation\label{theoAddDDref}] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\lo$ the double-double arguments of algorithm \ref{addDDref} \AddDD.\\ If $a_\hi$ and $b_\hi$ have the same sign, so we know that $$r_\hi + r_\lo = \left(\left(a_\hi + a_\lo \right) + \left( b_\hi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq 2^{-103,5}$$ \end{theorem} \begin{proof} \label{AddDDpreuve} ~ \\ Since the algorithm \AddDD~ ends by a call to the \Add~ procedure, it suffices to show that $$t_1 + t_5 = \left(\left(a_\hi + a_\lo \right) + \left( b_\hi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ Further, since the two branches of the algorithm are symmetrical, we can suppose that $\left \vert a_\hi \right \vert \geq \left \vert b_\hi \right \vert$ and consider only one branch without loss of generality. Finally, we remark that the following lines of the \AddDD~ procedure constitute a non-conditional \Add~ with arguments $a_\hi$ and $b_\hi$ and the result $t_1 + t_3$: \begin{center} \begin{minipage}[b]{50mm} $t_1 = a_\hi \oplus b_\hi$ \\ $t_2 = a_\hi \ominus t_1$ \\ $t_3 = t_2 \oplus b_\hi$ \end{minipage} \end{center} Thus, we get \begin{eqnarray*} t_5 & = & t_4 \oplus a_\lo \\ & = & \left( t_4 + a_\lo \right) \cdot \left( 1 + \epsilon_1 \right) \\ & = & \left( \left( t_3 + bl \right) \cdot \left( 1 + \epsilon_2 \right) + a_\lo \right) \cdot \left( 1 + \epsilon_1 \right) \\ & = & t_3 + a_\lo + b_\lo + \delta \end{eqnarray*} with $$\delta = t_3\cdot\epsilon_2 + b_\lo\cdot\epsilon_2 + t_3\cdot\epsilon_1 + b_\lo\cdot\epsilon_1 + t_3\cdot\epsilon_2\cdot\epsilon_2 + b_\lo\cdot\epsilon_2\cdot\epsilon_2 + a_\lo\cdot\epsilon_1$$ For giving an upper bound for $\left \vert \delta \right \vert$, let us first give an upper bound for $\left \vert t_3 \right \vert$, $\left \vert a_\lo \right \vert$ and $b_\lo$ as function of $\left \vert a_\hi + b_\hi \right \vert$ using the following bounds that we know already: \begin{eqnarray*} \left \vert a_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert b_\hi \right \vert \\ \left \vert t_3 \right \vert & \leq & 2^{-53} \cdot \left \vert t_1 \right \vert \end{eqnarray*} We get therefore \begin{eqnarray*} \left \vert t_3 \right \vert & \leq & 2^{-53} \cdot \left \vert t_1 \right \vert \\ & = & 2^{-53} \cdot \left \vert a_\hi \oplus b_\hi \right \vert \\ & \leq & 2^{-53} \cdot \left \vert a_\hi + b_\hi \right \vert + 2^{-106} \cdot \left \vert a_\hi + b_\lo \right \vert \end{eqnarray*} and than \begin{eqnarray*} \left \vert a_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ & \leq & 2^{-53} \cdot \left \vert a_\hi + b_\hi \right \vert \end{eqnarray*} The last bound is verified because we suppose that $a_\hi$ and $b_\hi$ have the same sign. \\ Finally, since $\left \vert a_\hi \right \vert \geq \left \vert b_\hi \right \vert$, \begin{eqnarray*} \left \vert b_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert b_\hi \right \vert \\ & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ & \leq & 2^{-53} \cdot \left \vert a_\hi + b_\hi \right \vert \end{eqnarray*} Thus we get for $\left \vert \delta \right \vert$: \begin{eqnarray*} \left \vert \delta \right \vert & \leq & \left \vert a_\hi + b_\hi \right \vert \cdot \left( 2^{-106} + 2^{-159} + 2^{-106} + 2^{-106} + 2^{-159} + 2^{-106} + 2^{-159} + 2^{-212} + 2^{-212} + 2^{-106} \right) \\ & \leq & \left \vert a_\hi + b_\hi \right \vert \cdot \left( 2^{-104} + 2^{-106} + 2^{-158} + 2^{-159} + 2^{-211} \right) \end{eqnarray*} Let us now give a lower bound for $\left \vert a_\hi + a_\lo + b_\hi + b_\lo \right \vert$ as a function of $\left \vert a_\hi + b_\hi \right \vert$ in order to be able to give a relative error bound for the procedure \AddDD. We have that \begin{eqnarray*} \left \vert a_\lo + b_\lo \right \vert & \leq & \left \vert a_\lo \right \vert + \left \vert b_\lo \right \vert \\ & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert + 2^{-53} \cdot \left \vert b_\hi \right \vert \\ & \leq & 2^{-52} \cdot \left \vert a_\hi \right \vert \\ & \leq & 2^{-52} \cdot \left \vert a_\hi + b_\hi \right \vert \end{eqnarray*} So we can check that $$\left \vert a_\hi + a_\lo + b_\hi + b_\lo \right \vert \geq \left( 1 - 2^{-52} \right) \cdot \left \vert a_\hi + b_\hi \right \vert$$ Concerning $\left \vert \delta \right \vert$, this yields to $$\left \vert \delta \right \vert \leq \left \vert a_\hi + a_\lo + b_\hi + b_\lo \right \vert \cdot \frac{1}{1-2^{-52}} \cdot \left( 2^{-104} + 2^{-106} + 2^{-158} + 2^{-159} + 2^{-211} \right)$$ One easily checks that $$ \frac{1}{1-2^{-52}} \cdot \left( 2^{-104} + 2^{-106} + 2^{-158} + 2^{-159} + 2^{-211} \right) \leq 2^{-103,5}$$ from which one trivially deduces the affirmation.\qed \end{proof} \begin{theorem}[Relative error of algorithm \ref{addDDref} \AddDD~ with a bounded cancellation\label{theoAddDDrefborn}] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\lo$ the double-double arguments of \ref{addDDref} \AddDD.\\ If $a_\hi$ and $b_\hi$ are of different sign and if one can check that $$\left \vert b_\hi \right \vert \leq 2^{-\mu} \cdot \left \vert a_\hi \right \vert$$ for $\mu \geq 1$ \\ so the returned result will verify $$r_\hi + r_\lo = \left(\left(a_\hi + a_\lo \right) + \left( b_\hi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq 2^{-103}\cdot \frac{1-2^{-\mu - 1}}{1-2^{-\mu}-2^{-52}} \leq 2^{-102}$$ \end{theorem} \begin{proof} ~ \\ Let us reuse the results obtained at the proof \ref{AddDDpreuve} and let us start by giving an upper bound for $\left \vert b_\lo \right \vert$ as a function of $\left \vert a_\hi \right \vert$: $$\left \vert b_\lo \right \vert \leq 2^{-53} \cdot \left \vert b_\hi \right \vert \leq 2^{-53-\mu} \cdot \left \vert a_\hi \right \vert$$ Let us now continue with a lower bound for $\left \vert a_\hi + b_\hi \right \vert$ still as a function of $\left \vert a_\hi \right \vert$: $$\left \vert a_\hi + b_\hi \right \vert \geq \left \vert a_\hi \right \vert \cdot \left( 1 - 2^{-\mu} \right)$$ We get in consequence $$\left \vert a_\lo \right \vert \leq \frac{2^{-53}}{1-2^{-\mu}} \cdot \left \vert a_\hi + b_\hi \right \vert$$ and $$\left \vert b_\lo \right \vert \leq \frac{2^{-53-\mu}}{1-2^{-\mu}} \cdot \left \vert a_\hi + b_\hi \right \vert$$ Thus we can check that $$\left \vert \delta \right \vert \leq \left \vert a_\hi + b_\hi \right \vert \cdot 2^{-103} \cdot \frac{1-2^{-\mu-1}}{1-2^{-\mu}}$$ Once again, we must give a lower bound for $\left \vert a_\hi + a_\lo + b_\hi + b_\lo \right \vert$ with regard to $\left \vert a_\hi + b_\hi \right \vert$: We know that \begin{eqnarray*} \left \vert a_\lo + b_\lo \right \vert & \leq & \left \vert a_\lo \right \vert + \left \vert b_\lo \right \vert \\ & \leq & 2^{-52} \cdot \left \vert a_\hi \right \vert \\ & \leq & \frac{2^{-52}}{1-2^{-\mu}} \cdot \left \vert a_\hi + b_\hi \right \vert \end{eqnarray*} So $$\left \vert a_\hi + a_\lo + b_\hi + b_\lo \right \vert \geq \left \vert a_\hi + b_\hi \right \vert \cdot \frac{1-2^{-\mu}-2^{-52}}{1-2^{-\mu}}$$ Thus we get for $\left \vert \delta \right \vert$ \begin{eqnarray*} \left \vert \delta \right \vert & \leq & \left \vert a_\hi + a_\lo + b_\hi + b_\lo \right \vert \cdot \frac{1-2^{-\mu}}{1-2^{-\mu}-2^{-52}} \cdot 2^{-103} \cdot \frac{1-2^{-\mu-1}}{1-2^{-\mu}} \\ & = & \left \vert a_\hi + a_\lo + b_\hi + b_\lo \right \vert \cdot 2^{-103} \cdot \frac{1-2^{-\mu-1}}{1-2^{-\mu}-2^{-52}} \end{eqnarray*} So finally the following inequality is verified for the relative error $\epsilon$: $$\left \vert \epsilon \right \vert \leq 2^{-103} \cdot \frac{1-2^{-\mu-1}}{1-2^{-\mu}-2^{-52}}$$ We can still give a less exact upper bound for this term by one that does not depend on $\mu$ because $\mu \geq 1$: $$\frac{1-2^{-\mu-1}}{1-2^{-\mu}-2^{-52}}\leq\frac{\frac{3}{4}}{\frac{1}{2}-2^{-52}}\leq 2$$ so $$\left \vert \epsilon \right \vert \leq 2^{-102}$$\qed \end{proof} \begin{theorem}[Absolute error of algorithm \ref{addDDref} \AddDD~ (general case)\label{addDDerrabs}] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\lo$ the double-double arguments of algorithm \ref{addDDref} \AddDD.\\ The result $r_\hi + r_\lo$ returned by the algorithm verifies $$r_\hi + r_\lo = \left(a_\hi + a_\lo \right) + \left( b_\hi + b_\lo \right) + \delta$$ where $\delta$ is bounded as follows: $$\left \vert \delta \right \vert \leq \max\left( 2^{-53} \cdot \left \vert a_\lo + b_\lo \right \vert, 2^{-102} \cdot \left \vert a_\hi + a_\lo + b_\hi + b_\lo \right \vert \right)$$ \end{theorem} \begin{proof} ~ \\ Without loss of generality, we can now suppose that $$\frac{1}{2} \cdot \left \vert a_\hi \right \vert \leq \left \vert b_\hi \right \vert \leq \left \vert a_\hi \right \vert$$ and that $a_\hi$ and $b_\hi$ have different signs because for all other cases, the properties we have to show are a direct consequence of theorems \ref{theoAddDDref} and \ref{theoAddDDrefborn}.\\ So we have $$\frac{1}{2} \cdot \left \vert a_\hi \right \vert \leq \left \vert b_\hi \right \vert \leq 2 \cdot \left \vert a_\hi \right \vert$$ and $$\frac{1}{2} \cdot \left \vert b_\hi \right \vert \leq \left \vert a_\hi \right \vert \leq 2 \cdot \left \vert b_\hi \right \vert$$ So the floating point operation $$t_1 = a_\hi \oplus b_\hi$$ is exact by Sterbenz' lemma \cite{Ste74}. In consequence, $t_3$ will be equal to $0$ because, as we have already mentioned, the operations computing $t_1$ and $t_3$ out of $a_\hi$ and $b_\hi$ constitute a \Add~ whose properties assure that $$t_3 = a_\hi + b_\hi - t_1$$ We can deduce that $$t_4 = t_3 \oplus b_\lo = b_\lo$$ and can finally check that $$t_5 = t_4 \oplus a_\lo = \left( t_4 + a_\lo \right) \cdot \left( 1 + \epsilon^* \right)$$ with $$\left \vert \epsilon^* \right \vert \leq 2^{-53}$$ So we get $$r_\hi + r_\lo = t_1 + t_5 = \left( a_\hi + a_\lo + b_\hi + b_\lo \right) + \delta$$ with $$\left \vert \delta \right \vert \leq 2^{-53} \cdot \left \vert a_\lo + b_\lo \right \vert$$ which yields to the bound to be proven $$\left \vert \delta \right \vert = \max\left( 2^{-53} \cdot \left \vert a_\lo + b_\lo \right \vert, 2^{-102} \cdot \left \vert a_\hi + a_\lo + b_\hi + b_\lo \right \vert \right)$$ \qed \end{proof} \begin{theorem}[Output overlap of algorithm \ref{addDDref} \AddDD] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\lo$ the double-double arguments of algorithm \ref{addDDref} \AddDD.\\ So the values $r_\hi$ and $r_\lo$ returned by the algorithm will not overlap at all and will verify $$\left \vert r_\lo \right \vert \leq 2^{-53} \cdot \left \vert r_\hi \right \vert$$ \end{theorem} \begin{proof} ~\\ The proof of the affirmed property is trivial because the procedure \AddDD~ ends by a call to sequence \Add~ which assures it.\qed \end{proof} \subsection{The multiplication operator \MulDD} Let us now consider the multiplication operator \MulDD: \begin{algorithm}[\MulDD] \label{mulDDref} ~ \\ {\bf In:} two double-double numbers, $a_\hi + a_\lo$ and $b_\hi + b_\lo$ \\ {\bf Out:} a double-double number $r_\hi + r_\lo$ \\ {\bf Preconditions on the arguments:} $$\left \vert a_\lo \right \vert \leq 2^{-53} \cdot \left \vert a_\hi \right \vert$$ $$\left \vert b_\lo \right \vert \leq 2^{-53} \cdot \left \vert b_\hi \right \vert$$ {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left( t_1, t_2 \right) \gets \mMul\left( a_\hi, b_\hi \right)$ \\ $t_3 \gets a_\hi \otimes b_\lo$ \\ $t_4 \gets a_\lo \otimes b_\hi$ \\ $t_5 \gets t_3 \oplus t_4$ \\ $t_6 \gets t_2 \oplus t_5$ \\ $\left(r_\hi, r_\lo \right) \gets \mAdd\left( t_1, t_6 \right)$\\ \end{minipage} \end{center} \end{algorithm} Compare also to \cite{crlibmweb} concerning algorithm \ref{mulDDref}. \begin{theorem}[Relative error of algorithm \ref{mulDDref} \MulDD] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\lo$ the double-double arguments of algorithm \ref{mulDDref} \MulDD.\\ So the values returned $r_\hi$ and $r_\lo$ verify $$r_\hi + r_\lo = \left(\left(a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq 2^{-102}$$ Further $r_\hi$ and $r_\lo$ will not overlap at all and verify $$\left \vert r_\lo \right \vert \leq 2^{-53} \cdot \left \vert r_\hi \right \vert$$ \end{theorem} \begin{proof} ~ \\ Since algorithm \ref{mulDDref} ends by a call to the \Add~ procedure, the properties of the latter yield to the fact that $r_\hi$ and $r_\lo$ do not overlap at all and that $\left \vert r_\lo \right \vert \leq 2^{-53} \cdot \left \vert r_\hi \right \vert$.\\ In order to give upper bounds for the relative and absolute error of the algorithm, let us express $t_6$ as a function of $t_2$, $a_\hi$, $a_\lo$, $b_\hi$ and $b_\lo$ joined by the error term $\delta$.\\ We get \begin{eqnarray*} t_6 & = & t_2 \oplus \left( a_\hi \otimes b_\lo \oplus a_\lo \otimes b_\hi \right) \\ & = & \left( t_2 + \left(a_\hi \cdot b_\lo \cdot \left( 1 + \epsilon_1 \right) + a_\lo \cdot b_\hi \cdot \left( 1 + \epsilon_2 \right) \right) \cdot \left(1 + \epsilon_3 \right) \right)\cdot \left( 1 + \epsilon_4 \right) \end{eqnarray*} where $\left \vert \epsilon_i \right \vert \leq 2^{-53}$, $i=1,2,3,4$.\\ Simplifying this expression, we van verify that $$t_6 = t_2 + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + \delta$$ with \begin{eqnarray*} \left \vert \delta \right \vert & \leq & \left \vert a_\lo \cdot b_\lo + a_\hi \cdot b_\lo \cdot \epsilon_1 + a_\lo \cdot b_\hi \cdot \epsilon_2 + a_\hi \cdot b_\lo \cdot \epsilon_3 + a_\hi \cdot b_\lo \cdot \epsilon_1 \cdot \epsilon_3 + a_\lo \cdot b_\hi \cdot \epsilon_3 + a_\lo \cdot b_\hi \cdot \epsilon_1 \cdot \epsilon_3 \right.\\ & & \left. + a_\hi \cdot b_\lo \cdot \epsilon_4 + a_\lo \cdot b_\hi \cdot \epsilon_4 + a_\hi \cdot b_\lo \cdot \epsilon_1 \cdot \epsilon_4 + a_\lo \cdot b_\hi \cdot \epsilon_2 \cdot \epsilon_4 + a_\hi \cdot b_\lo \cdot \epsilon_3 \cdot \epsilon_4 \right. \\ & & \left. + a_\hi \cdot b_\lo \cdot \epsilon_1 \cdot \epsilon_3 \cdot \epsilon_4 + a_\lo \cdot b_\hi \cdot \epsilon_3 \cdot \epsilon_4 + a_\lo \cdot b_\hi \cdot \epsilon_2 \cdot \epsilon_3 \cdot \epsilon_4 \right \vert \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 7 \cdot 2^{-106} + 6 \cdot 2^{-159} + 2^{-211} \right) \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot 2^{-103} \end{eqnarray*} For checking the given bound, we have supposed the following inequalities: $$\left \vert a_\lo \right \vert \leq 2^{-53} \cdot \left \vert a_\hi \right \vert$$ and $$\left \vert a_\lo \right \vert \leq 2^{-53} \cdot \left \vert a_\hi \right \vert$$ Let us now give a lower bound for $\left \vert \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right)\right \vert$ as a function of $\left \vert a_\hi \cdot b_\hi \right \vert$. For doing so, we give an upper bound for $\left \vert a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\lo \right \vert$. \\ We verify since: \begin{eqnarray*} \left \vert a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\lo \right \vert & \leq & \left \vert a_\hi \cdot b_\lo \right \vert + \left \vert a_\lo \cdot b_\hi \right \vert + \left \vert a_\lo \cdot b_\lo \right \vert \\ & \leq & 2^{-53} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-53} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-106} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \\ & \leq & 2^{-51} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} This yields to \begin{eqnarray*} \left \vert \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right) \right \vert & \geq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left(1 - 2^{-51} \right) \\ & \geq & \frac{1}{2} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} from which we deduce that $$\left \vert \delta \right \vert \leq 2^{-102} \cdot \left \vert \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right) \right \vert$$ which gives us as an bound for the relative error $$r_\hi + r_\lo = \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right) \cdot \left(1 + \epsilon \right)$$ with $\left \vert \epsilon \right \vert \leq 2^{-102}$. \qed \end{proof} \section{Addition operators for triple-double numbers} \subsection{The addition operator \AddTT} We are going to consider now the addition operator \AddTT. We will only analyse a simplified case where the arguments' values verify some bounds statically known. \begin{algorithm}[\AddTT] \label{addTTref} ~ \\ {\bf In:} two triple-double numbers, $a_\hi + a_\mi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert b_\hi \right \vert & \leq & \frac{3}{4} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\mi \right \vert & \leq & 2^{-\alpha_o} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-\alpha_u} \cdot \left \vert a_\mi \right \vert \\ \left \vert b_\mi \right \vert & \leq & 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-\beta_u} \cdot \left \vert b_\mi \right \vert \\ \alpha_o & \geq & 4 \\ \alpha_u & \geq & 1 \\ \beta_o & \geq & 4 \\ \beta_u & \geq & 1 \\ \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left(r_\hi, t_1 \right) \gets \mAdd\left( a_\hi, b_\hi \right)$ \\ $\left(t_2, t_3 \right) \gets \mAdd\left( a_\mi, b_\mi \right)$ \\ $\left(t_7, t_4 \right) \gets \mAdd\left( t_1, t_2 \right)$ \\ $t_6 \gets a_\lo \oplus b_\lo$ \\ $t_5 \gets t_3 \oplus t_4$ \\ $t_8 \gets t_5 \oplus t_6$ \\ $\left( r_\mi, r_\lo \right) \gets \mAdd\left( t_7, t_8 \right)$ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{addTTref} \AddTT\label{theoAddTT}] ~ \\ Let be $a_\hi + a_\mi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ the triple-double arguments of algorithm \ref{addTTref} \AddTT~ verifying the given preconditions.\\ So the following egality will hold for the returned values $r_\hi$, $r_\mi$ and $r_\lo$ $$r_\hi + r_\mi + r_\lo = \left(\left(a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded by: $$\left \vert \epsilon \right \vert \leq 2^{-\min\left(\alpha_o + \alpha_u,\beta_o + \beta_u\right) - 47} + 2^{-\min\left( \alpha_o, \beta_o\right) - 98}$$ The returned values $r_\mi$ and $r_\lo$ will not overlap at all and the overlap of $r_\hi$ and $r_\mi$ will be bounded by the following expression: $$\left \vert r_\mi \right \vert \leq 2^{-\min\left( \alpha_o, \beta_o \right) + 5} \cdot \left \vert r_\hi \right \vert$$ \end{theorem} \begin{proof} ~ \\ The procedure \ref{addTTref} ends by a call to the \Add~ sequence. One can trivially deduce that $r_\mi$ and $r_\lo$ do not overlap at all and verify $$\left \vert r_\lo \right \vert \leq 2^{-53} \cdot \left \vert r_\mi \right \vert$$ Further, it suffices that the bounds given at theorem \ref{theoAddTT} hold for $t_7$ and $t_8$ because the last addition computing $r_\mi$ and $r_\lo$ will be exact. The same way, one can deduce the following inequalities out of the properties of the \Add~ procedure. They will become useful during this proof. $$\left \vert t_1 \right \vert \leq 2^{-53} \cdot \left \vert r_\hi \right \vert$$ $$\left \vert t_3 \right \vert \leq 2^{-53} \cdot \left \vert t_2 \right \vert$$ $$\left \vert t_4 \right \vert \leq 2^{-53} \cdot \left \vert t_7 \right \vert$$ Let us start the proof by giving bounds for the magnitude of $r_\hi$ with regard to $a_\hi$:\\ We have on the one hand \begin{eqnarray*} \left \vert r_\hi \right \vert & = & \left \vert \circ\left( a_\hi + b_\hi \right) \right \vert \\ & = & \circ \left( \left \vert a_\hi + b_\hi \right \vert \right) \\ & \leq & \circ \left( \left \vert a_\hi \right \vert + \left \vert b_\hi \right \vert \right) \\ & \leq & \circ \left( \left \vert a_\hi \right \vert + \frac{3}{4} \cdot \left \vert a_\hi \right \vert \right) \\ & \leq & \circ \left( 2 \cdot \left \vert a_\hi \right \vert \right) \\ & = & 2 \cdot \left \vert a_\hi \right \vert \end{eqnarray*} and on the other \begin{eqnarray*} \left \vert r_\hi \right \vert & = & \circ \left( \left \vert a_\hi + b_\hi \right \vert \right) \\ & \geq & \circ \left( \frac{1}{4} \cdot \left \vert a_\hi \right \vert \right) \\ & = & \frac{1}{4} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} So we know that $\frac{1}{4} \cdot \left \vert a_\hi \right \vert \leq \left \vert r_\hi \right \vert \leq 2 \cdot \left \vert a_\hi \right \vert$.\\ It is now possible to give the following upper bounds for $\left \vert t_1 \right \vert$, $\left \vert t_2 \right \vert$, $\left \vert t_3 \right \vert$, $\left \vert t_7 \right \vert$, $\left \vert t_4 \right \vert$, $\left \vert t_6 \right \vert$ and $\left \vert t_6 \right \vert$: \begin{eqnarray*} \left \vert t_1 \right \vert & \leq & 2^{-53} \cdot \left \vert r_\hi \right \vert \\ & \leq & 2^{-53} \cdot 2^2 \cdot \left \vert a_\hi \right \vert \\ & = & 2^{-51} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} \begin{eqnarray*} \left \vert t_2 \right \vert & \leq & \circ \left( \left \vert a_\mi + b_\mi \right \vert \right) \\ & \leq & \circ \left( \left \vert a_\mi \right \vert + \left \vert b_\mi \right \vert \right) \\ & \leq & \circ \left( 2^{-\alpha_o} \cdot \left \vert a_\hi \right \vert + 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \right) \\ & \leq & \circ \left( 2^{-\alpha_o} \cdot \left \vert a_\hi \right \vert + 2^{-\beta_o} \cdot \frac{3}{4} \cdot \left \vert a_\hi \right \vert \right) \\ & \leq & \circ \left( 2^{-\min\left(\alpha_o,\beta_o\right) + 1} \cdot \left \vert a_\hi \right \vert \right) \\ & = & 2^{-\min\left(\alpha_o,\beta_o\right) + 1} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} \begin{eqnarray*} \left \vert t_3 \right \vert & \leq & 2^{-53} \cdot \left \vert t_2 \right \vert \\ & \leq & 2^{-53} \cdot 2^{-\min\left(\alpha_o,\beta_o\right) + 1} \cdot \left \vert a_\hi \right \vert \\ & = & 2^{-\min\left(\alpha_o,\beta_o\right)-52} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} \begin{eqnarray*} \left \vert t_7 \right \vert & \leq & \circ \left( \left \vert t_1 + t_2 \right \vert \right) \\ & \leq & \circ \left( \left \vert t_1 \right \vert + \left \vert t_2 \right \vert \right) \\ & \leq & \circ \left( 2^{-51} \cdot \left \vert a_\hi \right \vert + 2^{-\min\left(\alpha_o,\beta_o\right) + 1} \cdot \left \vert a_\hi \right \vert \right) \\ & \leq & \circ \left( 2^{-\min\left(\alpha_o,\beta_o\right) + 2} \cdot \left \vert a_\hi \right \vert \right) \\ & = & 2^{-\min\left(\alpha_o,\beta_o\right) + 2} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} \begin{eqnarray*} \left \vert t_4 \right \vert & \leq & 2^{-53} \cdot \left \vert t_7 \right \vert \\ & \leq & 2^{-53} \cdot 2^{-\min\left(\alpha_o,\beta_o\right)+2} \cdot \left \vert a_\hi \right \vert \\ & = & 2^{-\min\left(\alpha_o,\beta_o\right) -51} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} \begin{eqnarray*} \left \vert t_6 \right \vert & \leq & \circ \left( \left \vert a_\lo \right \vert + \left \vert b_\lo \right \vert \right) \\ & \leq & \circ \left( 2^{-\alpha_o} \cdot 2^{-\alpha_u} \cdot \left \vert a_\hi \right \vert + 2^{-\beta_o} \cdot 2^{-\beta_u} \cdot \frac{3}{4} \cdot \left \vert a_\hi \right \vert \right) \\ & \leq & \circ \left( 2^{-\min\left(\alpha_o + \alpha_u,\beta_o + \beta_u\right) + 1} \cdot \left \vert a_\hi \right \vert \right) \\ & = & 2^{-\min\left(\alpha_o + \alpha_u,\beta_o + \beta_u\right) + 1} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} and finally \begin{eqnarray*} \left \vert t_5 \right \vert & \leq & \circ \left( \left \vert t_3 \right \vert + \left \vert t_4 \right \vert \right) \\ & \leq & \circ \left( 2^{-\min\left(\alpha_o,\beta_o\right) -52} \cdot \left \vert a_\hi \right \vert + 2^{-\min\left(\alpha_o,\beta_o\right)-51} \cdot \left \vert a_\hi \right \vert \right) \\ & \leq & \circ \left( 2^{-\min\left(\alpha_o,\beta_o\right) -50} \cdot \left \vert a_\hi \right \vert \right) \\ & = & 2^{-\min\left(\alpha_o,\beta_o\right)-50} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} Using the fact that the addition \Add~ is exact, it is easy to show that we have exactly $$r_\hi + t_7 + t_3 + t_4 = a_\hi + a_\mi + b_\hi + b_\mi$$ Further, we can check \begin{eqnarray*} t_8 & = & \left( t_3 \oplus_2 t_4 \right) \oplus_1 \left( a_\lo \oplus_3 b_\lo \right) \\ & = & t_3 + t_4 + a_\lo + b_\lo + \delta \end{eqnarray*} with \begin{eqnarray*} \left \vert \delta \right \vert & \leq & \left \vert t_3 \right \vert \cdot \epsilon_3 + \left \vert t_4 \right \vert \cdot \epsilon_2 + \left \vert a_\lo \right \vert \cdot \epsilon_3 + \left \vert b_\lo \right \vert \cdot \epsilon_3 + \left \vert t_3 \right \vert \cdot \epsilon_1 + \left \vert t_4 \right \vert \cdot \epsilon_1 + \left \vert t_3 \right \vert \cdot \epsilon_1 \cdot \epsilon_2 \\ & & + \left \vert t_4 \right \vert \cdot \epsilon_1 \cdot \epsilon_2 + \left \vert a_\lo \right \vert \cdot \epsilon_1 + \left \vert b_\lo \right \vert \cdot \epsilon_2 + \left \vert a_\lo \right \vert \cdot \epsilon_1 \cdot \epsilon_3 + \left \vert b_\lo \right \vert \cdot \epsilon_1 \cdot \epsilon_3 \end{eqnarray*} where for $i\in\left\lbrace 1,2,3 \right\rbrace$, $\epsilon_i$ is the relative error bound of the floating point addition $\oplus_i$ and verifies $$\left \vert \epsilon_i \right \vert \leq 2^{-53}$$ So we get immediately $$r_\hi + r_\mi + r_\lo = r_\hi + t_7 + t_8 = \left( a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right) + \delta$$ Let us now express $\left \vert \left( a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right) \right \vert$ as a function of $\left \vert a_\hi \right \vert$: \begin{eqnarray*} \left \vert a_\hi + a_\mi + a_\lo \right \vert & \leq & \left \vert a_\hi \right \vert + \left \vert a_\mi \right \vert + \left \vert a_\lo \right \vert \\ & \leq & \left \vert a_\hi \right \vert + 2^{-\alpha_o} \cdot \left \vert a_\hi \right \vert + 2^{-\alpha_o-\alpha_u} \cdot \left \vert a_\hi \right \vert \\ & \leq & 2 \cdot \left \vert a_\hi \right \vert \end{eqnarray*} and, the same way round, \begin{eqnarray*} \left \vert b_\hi + b_\mi + b_\lo \right \vert & \leq & 2 \cdot \left \vert b_\hi \right \vert \\ & \leq & \frac{3}{2} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} which allows for noting $$\left \vert \left( a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right) \right \vert \leq 2^2 \cdot \left \vert a_\hi \right \vert$$ In order to give a lower bound for this term, let us prove an upper bound for $\left \vert b_\hi + a_\mi + b_\mi + a_\lo + b_\lo \right \vert$ as follows \begin{eqnarray*} \left \vert b_\hi + a_\mi + b_\mi + a_\lo + b_\lo \right \vert & \leq & \left \vert b_\hi \right \vert + \left \vert a_\mi \right \vert + \left \vert b_\mi \right \vert + \left \vert a_\lo \right \vert + \left \vert b_\lo \right \vert \\ & \leq & \frac{3}{4} \cdot \left \vert a_\hi \right \vert + 2^{-\alpha_o} \cdot \left \vert a_\hi \right \vert + 2^{-\beta_o} \cdot \frac{3}{4} \cdot \left \vert a_\hi \right \vert + 2^{-\alpha_o-\alpha_u} \cdot \left \vert a_\hi \right \vert \\ & & + 2^{-\beta_o-\beta_u} \cdot \frac{3}{4} \cdot \left \vert a_\hi \right \vert \\ & \leq & \frac{7}{8} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} So we get $$\left \vert \left( a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right) \right \vert \geq \frac{1}{8} \cdot \left \vert a_\hi \right \vert$$ Using this bounds, we can give upper bounds for the absolute error $\left \vert \delta \right \vert$ first as a function of $\left \vert a_\hi \right \vert$ and than as a function of $\left \vert \left( a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right) \right \vert$ for deducing finally a bound for the relative error. \\ So we get \begin{eqnarray*} \left \vert \delta \right \vert & \leq & \left \vert t_3 \right \vert \cdot \epsilon_3 + \left \vert t_4 \right \vert \cdot \epsilon_2 + \left \vert a_\lo \right \vert \cdot \epsilon_3 + \left \vert b_\lo \right \vert \cdot \epsilon_3 + \left \vert t_3 \right \vert \cdot \epsilon_1 + \left \vert t_4 \right \vert \cdot \epsilon_1 + \left \vert t_3 \right \vert \cdot \epsilon_1 \cdot \epsilon_2 \\ & & + \left \vert t_4 \right \vert \cdot \epsilon_1 \cdot \epsilon_2 + \left \vert a_\lo \right \vert \cdot \epsilon_1 + \left \vert b_\lo \right \vert \cdot \epsilon_2 + \left \vert a_\lo \right \vert \cdot \epsilon_1 \cdot \epsilon_3 + \left \vert b_\lo \right \vert \cdot \epsilon_1 \cdot \epsilon_3 \\ & \leq & \left \vert a_\hi \right \vert \cdot \epsilon^\prime \end{eqnarray*} with \begin{eqnarray*} \epsilon^\prime & \leq & 2^{-53} \cdot 2^{-\min\left(\alpha_o,\beta_o\right)-52} \\ & + & 2^{-53} \cdot 2^{-\min\left(\alpha_o,\beta_o\right)-51} \\ & + & 2^{-53} \cdot 2^{-\alpha_o-\alpha_u} \\ & + & 2^{-53} \cdot 2^{-\beta_o-\beta_u} \\ & + & 2^{-53} \cdot 2^{-\min\left(\alpha_o,\beta_o\right)-52} \\ & + & 2^{-53} \cdot 2^{-\min\left(\alpha_o,\beta_o\right)-51} \\ & + & 2^{-106} \cdot 2^{-\min\left(\alpha_o,\beta_o\right)-52} \\ & + & 2^{-106} \cdot 2^{-\min\left(\alpha_o,\beta_o\right)-51} \\ & + & 2^{-53} \cdot 2^{-\alpha_o-\alpha_u} \\ & + & 2^{-53} \cdot 2^{-\beta_o-\beta_u} \\ & + & 2^{-106} \cdot 2^{-\alpha_o-\alpha_u} \\ & + & 2^{-106} \cdot 2^{-\beta_o-\beta_u} \\ & \leq & 2^{-\min\left(\alpha_o,\beta_o\right)-101} + 2^{-\min\left(\alpha_o+\alpha_u,\beta_o+\beta_u\right)-50} \end{eqnarray*} This yields to $$r_\hi + r_\mi + r_\lo = \left( \left( a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right) \right) \cdot \left(1 + \epsilon \right)$$ with $$\left \vert \epsilon \right \vert \leq 2^{-\min\left(\alpha_o,\beta_o\right)-98} + 2^{-\min\left(\alpha_o+\alpha_u,\beta_o+\beta_u\right)-47}$$ In order to finish the prove, it suffices now to give an upper bound for the maximal overlap between $r_\hi$ and $r_\mi$ because we have already shown that $r_\mi$ and $r_\lo$ do not overlap at all.\\ So we can check \begin{eqnarray*} \left \vert r_8 \right \vert & \leq & \circ \left( \left \vert t_5 \right \vert + \left \vert t_6 \right \vert \right) \\ & \leq & \circ \left( 2^{-\min\left(\alpha_o,\beta_o\right)-50} \cdot \left \vert a_\hi \right \vert + 2^{-\min\left(\alpha_o+\alpha_u,\beta_o+\beta_u\right)+1} \cdot \left \vert a_\hi \right \vert \right)\\ & \leq & \circ \left( 2^{-\min\left(\alpha_o,\beta_o\right)-48} \cdot \left \vert r_\hi \right \vert + 2^{-\min\left(\alpha_o+\alpha_u,\beta_o+\beta_u\right)+3} \cdot \left \vert r_\hi \right \vert \right) \end{eqnarray*} and continue by giving the following upper bound \begin{eqnarray*} \left \vert r_\mi \right \vert & = & \circ \left( \left \vert t_7 + t_8 \right \vert \right) \\ & \leq & \circ \left( \left \vert t_7 \right \vert + \left \vert t_8 \right \vert \right) \\ & \leq & \circ \left( 2^{-\min\left(\alpha_o,\beta_o\right)+4} \cdot \left \vert r_\hi \right \vert + \circ \left( 2^{-\min\left(\alpha_o,\beta_o\right)-48} \cdot \left \vert r_\hi \right \vert + 2^{-\min\left(\alpha_o+\alpha_u,\beta_o+\beta_u\right)+3} \cdot \left \vert r_\hi \right \vert \right) \right) \\ & \leq & \circ \left( \left \vert r_\hi \right \vert \cdot \left( 2^{-\min\left(\alpha_o,\beta_u\right)+4} + 2^{-\min\left(\alpha_o,\beta_o\right)-48} + 2^{-\min\left(\alpha+\alpha_u,\beta_o+\beta_u\right)+3} + \right. \right. \\ & & \left. \left. 2^{-\min\left(\alpha_o,\beta_o\right) -101} + 2^{-\min\left(\alpha_o+\alpha_u,\beta_o+\beta_u\right)-50} \right) \right) \\ & \leq & 2^{-\min\left(\alpha_o,\beta_o\right)+5} \cdot \left \vert r_\hi \right \vert \end{eqnarray*} This is the maximal overlap bound we were looking for; the proof is therefore finished.\qed \end{proof} \begin{theorem}[Special case of algorithm \ref{addTTref} \AddTT] ~ \\ Let be $a_\hi + a_\mi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ the triple-double arguments of algorithm \ref{addTTref} \AddTT~ such that $$a_\hi = a_\mi = a_\lo = 0$$ So the values $r_\hi$, $r_\mi$ and $r_\lo$ returned will be exactly equal to $$r_\hi + r_\mi + r_\lo = b_\hi + b_\mi + b_\lo$$ The values $r_\mi$ and $r_\lo$ will not overlap at all. The overlap of $r_\hi$ and $r_\mi$ must still be evaluated. \end{theorem} \begin{proof} ~\\ We will suppose that the \Add~ procedure is exact for $a_\hi=a_\mi=a_\lo=0$ if even we are using its unconditional version. Under this hypothesis, we get thus: \begin{eqnarray*} r_\hi & = & \circ \left( 0 + b_\hi \right) = b_\hi \\ t_1 & = & 0 + b_\hi - b_\hi = 0 \\ t_2 & = & b_\mi \\ t_3 & = & 0 \\ t_7 & = & \circ \left( 0 + b_\mi \right) = b_\mi \\ t_4 & = & 0 \\ t_6 & = & 0 \oplus b_\lo = b_\lo \\ t_5 & = & 0 \oplus 0 = 0 \\ t_8 & = & 0 \oplus b_\lo = b_\lo \\ r_\mi + r_\lo & = & b_\mi + b_\lo \end{eqnarray*} In consequence, the following holds for the values returned: $$r_\hi + r_\mi + r_\lo = b_\hi + b_\mi + b_\lo$$ Clearly $r_\mi$ and $r_\lo$ do not overlap because the \Add~ procedure the algorithm calls at its last line assures this property.\qed \end{proof} \subsection{The addition operator \AddDTT} Let us consider now the addition operator \AddDTT. We will only analyse a simplified case where the arguments of the algorithm verify statically known bounds. \begin{algorithm}[\AddDTT] \label{addDTTref} ~ \\ {\bf In:} a double-double number $a_\hi + a_\lo$ and a triple-double number $b_\hi + b_\mi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert b_\hi \right \vert & \leq & 2^{-2} \cdot \left \vert a_\hi \right \vert \\ \left \vert a_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ \left \vert b_\mi \right \vert & \leq & 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-\beta_u} \cdot \left \vert b_\mi \right \vert \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left( r_\hi, t_1 \right) \gets \mAdd\left( a_\hi, b_\hi \right)$ \\ $\left( t_2, t_3 \right) \gets \mAdd\left( a_\lo, b_\mi \right)$ \\ $\left( t_4, t_5 \right) \gets \mAdd\left( t_1, t_2 \right)$ \\ $t_6 \gets t_3 \oplus b_\lo$ \\ $t_7 \gets t_6 \oplus t_5$ \\ $\left( r_\mi, r_\lo \right) \gets \mAdd\left( t_4, t_7 \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{addDTTref} \AddDTT] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ the values taken in argument of algorithm \ref{addDTTref} \AddDTT. Let the preconditions hold for this values.\\ So the following holds for the values returned by the algorithm $r_\hi$, $r_\mi$ and $r_\lo$ $$r_\hi + r_\mi + r_\lo = \left(\left(a_\hi + a_\mi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded by $$\left \vert \epsilon \right \vert \leq 2^{-\beta_o - \beta_u - 52} + 2^{-\beta_o - 104} + 2^{-153}$$ The values $r_\mi$ and $r_\lo$ will not overlap at all and the overlap of $r_\hi$ and $r_\mi$ will be bounded by: $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ with $$\gamma \geq \min\left( 45, \beta_o - 4, \beta_o + \beta_u - 2 \right)$$ \end{theorem} \begin{proof} ~ \\ We know using the properties of the \Add~ procedure that \begin{eqnarray*} r_\hi + t_1 & = & a_\hi + b_\hi \\ t_2 + t_3 & = & a_\lo + b_\mi \\ t_4 + t_5 & = & t_1 + t_2 \\ r_\mi + r_\lo = t_4 + t_7 \end{eqnarray*} Supposing that we dispose already of a term of the following form $$t_7 = t_5 + t_3 + b_\lo + \delta$$ with a bounded $\left \vert \delta \right \vert$, we can note that $$r_\hi + r_\mi + r_\lo = \left( a_\hi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right) + \delta$$ Let us now express $t_7$ by $t_5$, $t_3$ and $b_\lo$: \begin{eqnarray*} t_7 & = & t_5 \oplus t_6 \\ & = & t_5 \oplus \left( t_3 \oplus b_\lo \right) \\ & = & \left( t_5 + \left( t_3 + b_\lo \right) \cdot \left( 1 + \epsilon_1 \right) \right) \cdot \left( 1 + \epsilon_2 \right) \end{eqnarray*} with $\left \vert \epsilon_1 \right \vert \leq 2^{-53}$ and $\left \vert \epsilon_2 \right \vert \leq 2^{-53}$.\\ We get in consequence $$t_7 = t_5 + t_3 + b_\lo + t_3 \cdot \epsilon_1 + b_\lo \cdot \epsilon_1 + t_5 \cdot \epsilon_2 + t_3 \cdot \epsilon_2 + b_\lo \cdot \epsilon_2 + t_3 \cdot \epsilon_1 \cdot \epsilon_2 + b_\lo \cdot \epsilon_1 \cdot \epsilon_2$$ and we can verify that the following upper bound holds for the absolute error $\delta$: \begin{eqnarray*} \left \vert \delta \right \vert & = & \left \vert t_3 \cdot \epsilon_1 + b_\lo \cdot \epsilon_1 + t_5 \cdot \epsilon_2 + t_3 \cdot \epsilon_2 + b_\lo \cdot \epsilon_2 + t_3 \cdot \epsilon_1 \cdot \epsilon_2 + b_\lo \cdot \epsilon_1 \cdot \epsilon_2 \right \vert \\ & \leq & 2^{-53} \cdot \left \vert t_3 \right \vert + 2^{-53} \cdot \left \vert b_\lo \right \vert + 2^{-53} \cdot \left \vert t_5 \right \vert + 2^{-53} \cdot \left \vert b_\lo \right \vert + 2^{-106} \cdot \left \vert t_3 \right \vert + 2^{-106} \cdot \left \vert b_\lo \right \vert \\ & \leq & 2^{-52} \cdot \left \vert t_3 \right \vert + 2^{-51} \cdot \left \vert b_\lo \right \vert + 2^{-53} \cdot \left \vert t_5 \right \vert \end{eqnarray*} Let us get now some bounds for $\left \vert t_3 \right \vert$, $\left \vert b_\lo \right \vert$ and $\left \vert t_5 \right \vert$, all as a function of $\left \vert a_\hi \right \vert$: $$\left \vert b_\lo \right \vert \leq 2^{-\beta_o-\beta_u} \cdot \left \vert b_\hi \right \vert \leq 2^{-\beta_o-\beta_u-2} \cdot \left \vert a_\hi \right \vert$$ which can be obtained using the preconditions' hypotheses. Further \begin{eqnarray*} \left \vert t_3 \right \vert & \leq & 2^{-53} \cdot \left \vert t_2 \right \vert \\ & = & 2^{-53} \cdot \left \vert \circ \left( a_\lo + b_\mi \right) \right \vert \\ & \leq & 2^{-52} \cdot \left \vert a_\lo + b_\mi \right \vert \\ & \leq & 2^{-52} \cdot \left \vert a_\lo \right \vert + 2^{-52} \cdot \left \vert b_\mi \right \vert \\ & \leq & 2^{-105} \cdot \left \vert a_\hi \right \vert + 2^{-\beta_o-52} \cdot \left \vert b_\hi \right \vert \\ & \leq & 2^{-105} \cdot \left \vert a_\hi \right \vert + 2^{-\beta_o-54} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} and finally \begin{eqnarray*} \left \vert t_5 \right \vert & \leq & 2^{-53} \cdot \left \vert t_4 \right \vert \\ & = & 2^{-53} \cdot \left \vert \circ \left( t_1 + t_2 \right) \right \vert \\ & \leq & 2^{-52} \cdot \left \vert t_1 + t_2 \right \vert \\ & \leq & 2^{-52} \cdot \left \vert t_1 \right \vert + 2^{-52} \cdot \left \vert t_2 \right \vert \\ & \leq & 2^{-105} \cdot \left \vert r_\hi \right \vert + 2^{-52} \cdot \left \vert \circ \left( a_\lo + b_\mi \right) \right \vert \\ & \leq & 2^{-105} \cdot \left \vert \circ \left( a_\hi + b_\hi \right) \right \vert + 2^{-51} \cdot \left \vert a_\lo + b_\mi \right \vert \\ & \leq & 2^{-104} \cdot \left \vert a_\hi + b_\hi \right \vert + 2^{-51} \cdot \left \vert a_\lo \right \vert + 2^{-51} \cdot \left \vert b_\mi \right \vert \\ & \leq & 2^{-104} \cdot \left \vert a_\hi \right \vert + 2^{-106} \cdot \left \vert a_\hi \right \vert + 2^{-104} \cdot \left \vert a_\hi \right \vert + 2^{-\beta_o-53} \cdot \left \vert a_\hi \right \vert \\ & \leq & \left \vert a_\hi \right \vert \cdot \left( 2^{-102} + 2^{-\beta_o -53} \right) \end{eqnarray*} So we have \begin{eqnarray*} \left \vert \delta \right \vert & \leq & \left \vert a_\hi \right \vert \cdot \left( 2^{-157} + 2^{-\beta_o-106} + 2^{-\beta_o-\beta_u-53} + 2^{-155} + 2^{-\beta_o-106} \right) \\ & \leq & \left \vert a_\hi \right \vert \cdot \left( 2^{-\beta_o-\beta_u-53} + 2^{-\beta_o-105} + 2^{-154} \right) \end{eqnarray*} Let us now give a lower bound for $\left \vert \left( a_\hi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right) \right \vert$ as a function of $\left \vert a_\hi \right \vert$ by getting out an upper bound for $\left \vert a_\lo + b_\hi + b_\mi + b_\lo \right \vert$ as such a function: \begin{eqnarray*} \left \vert a_\lo + b_\hi + b_\mi + b_\lo \right \vert & \leq & \left \vert a_\lo \right \vert + \left \vert b_\hi \right \vert + \left \vert b_\mi \right \vert + \left \vert b_\lo \right \vert \\ & \leq & \left \vert a_\hi \right \vert \cdot \left( 2^{-53} + 2^{-2} + 2^{-\beta_o-2} + 2^{-\beta_o-\beta_u-2} \right) \end{eqnarray*} Since $\beta_o \geq 1$, $\beta_u \geq 1$ we can check that $$\left \vert a_\lo + b_\hi + b_\mi + b_\lo \right \vert \leq 2^{-1} \cdot \left \vert a_\hi \right \vert$$ In consequence $$\left \vert a_\hi + \left( a_\lo + b_\hi + b_\mi + b_\lo \right) \right \vert \geq \frac{1}{2} \cdot \left \vert a_\hi \right \vert$$ Using this lower bound, we can finally give an upper bound for the relative error $\epsilon$ of the considered procedure: $$r_\hi + r_\mi + r_\lo = \left( \left( a_\hi + a_\lo \right) + \left( b_\hi + b_\mi + b_\lo \right) \right) \cdot \left( 1 + \epsilon \right)$$ with $$\left \vert \epsilon \right \vert \leq 2^{-\beta_o-\beta_u-52} + 2^{-\beta_o-104} + 2^{-153}$$ Last but not least, let us now analyse the additional overlaps generated by the procedure. It is clear that $r_\mi$ and $r_\lo$ do not overlap at all because they are computed by the \Add~ procedure. Let us merely examine now the overlap of $r_\hi$ and $r_\mi$. \\ We begin by giving a lower bound for $r_\hi$ as a function of $a_\hi$: \begin{eqnarray*} \left \vert r_\hi \right \vert & = & \left \vert \circ \left( a_\hi + b_\hi \right) \right \vert \\ & \geq & \circ \left( \left \vert a_\hi + b_\hi \right \vert \right) \\ & \geq & \circ \left( \frac{3}{4} \cdot \left \vert a_\hi \right \vert \right) \\ & \geq & \circ \left( \frac{1}{2} \cdot \left \vert a_\hi \right \vert \right) \\ & = & \frac{1}{2} \cdot \left \vert a_\hi \right \vert \end{eqnarray*} Let us then find an upper bound for $\left \vert r_\mi \right \vert$ using also here a term which is a function of $\left \vert a_\hi \right \vert$: \begin{eqnarray*} \left \vert r_\mi \right \vert & = & \left \vert \circ \left( r_\mi + r_\lo \right) \right \vert \\ & \leq & 2 \cdot \left \vert r_\mi + r_\lo \right \vert \\ & = & 2 \cdot \left \vert t_4 + t_7 \right \vert \\ & \leq & 2 \cdot \left \vert t_4 \right \vert + 2 \cdot \left \vert t_5 + t_3 + b_\lo + \delta \right \vert \\ & \leq & 2 \cdot \left \vert t_4 \right \vert + 2 \cdot \left \vert t_5 \right \vert + 2 \cdot \left \vert t_3 \right \vert + 2 \cdot \left \vert b_\lo \right \vert + 2 \cdot \left \vert \delta \right \vert \\ & \leq & 2 \cdot \left \vert t_4 \right \vert + \left \vert a_\hi \right \vert \cdot \left( 2^{-101} + 2^{-\beta_o-52} \right) \\ & & + \left \vert a_\hi \right \vert \cdot \left( 2^{-104} + 2^{-\beta_o-53} \right) + \left \vert a_\hi \right \vert \cdot 2^{-\beta_o-\beta_u-1} \\ & & + \left \vert a_\hi \right \vert \cdot \left( 2^{-\beta_o-\beta_u-52} + 2^{-\beta_o-104} + 2^{-153}\right) \end{eqnarray*} By bounding finally still $\left \vert t_4 \right \vert$ by a term that is function of $\left \vert a_\hi \right \vert$ \begin{eqnarray*} \left \vert t_4 \right \vert & = & \left \vert \circ \left( t_1 + t_2 \right) \right \vert \\ & \leq & 2 \cdot \left \vert t_1 \right \vert + 2 \cdot \left \vert t_2 \right \vert \\ & \leq & 2^{-52} \cdot \left \vert r_\hi \right \vert + 2 \cdot \left \vert \circ \left( a_\lo + b_\mi \right) \right \vert \\ & \leq & 2^{-51} \cdot \left \vert a_\hi + b_\hi \right \vert + 4 \cdot \left \vert a_\lo + b_\mi \right \vert \\ & \leq & \left \vert a_\hi \right \vert \cdot \left( 2^{-\beta_o} + 2^{-49} \right) \end{eqnarray*} we obtain \begin{eqnarray*} \left \vert r_\hi \right \vert & \leq & \left \vert a_\hi \right \vert \cdot \left( 2^{-48} \right. \\ & & + 2^{-\beta_o+1} \\ & & + 2^{-101} \\ & & + 2^{-\beta_o-52} \\ & & + 2^{-104} \\ & & + 2^{-\beta_o-53} \\ & & + 2^{-\beta_o-\beta_u-1} \\ & & + 2^{-\beta_o-\beta_u-52} \\ & & + 2^{-\beta_o-104} \\ & & \left. + 2^{-153} \right) \\ & \leq & \left \vert a_\hi \right \vert \cdot \left( 2^{-47} + 2^{-\beta_o+2} + 2^{-\beta_o-\beta_u} \right) \end{eqnarray*} We finally check that we have $$\left \vert r_\mi \right \vert \leq \left \vert r_\hi \right \vert \cdot \left( 2^{-46} + 2^{-\beta_o+3} + 2^{-\beta_o-\beta_u+1} \right)$$ from which we can deduce the following bound $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ with $$\gamma \geq \min\left( 45, \beta_o-4, \beta_o+\beta_u-2 \right)$$ This finishes the proof.\qed \end{proof} \section{Triple-double multiplication operators} \subsection{The multiplication procedure \MulDT} Let us go on with an analysis of the multiplication procedure \MulDT. \begin{algorithm}[\MulDT] \label{mulDTref} ~ \\ {\bf In:} two double-double numbers $a_\hi + a_\lo$ and $b_\hi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert a_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert b_\hi \right \vert \\ \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{50mm} $\left( r_\hi, t_1 \right) \gets \mMul\left( a_\hi, b_\hi \right)$ \\ $\left( t_2, t_3 \right) \gets \mMul\left( a_\hi, b_\lo \right)$ \\ $\left( t_4, t_5 \right) \gets \mMul\left( a_\lo, b_\hi \right)$ \\ $t_6 \gets a_\lo \otimes b_\lo$ \\ $\left( t_7, t_8 \right) \gets \mAddDD\left( t_2, t_3, t_4, t_5 \right)$ \\ $\left( t_9, t_{10} \right) \gets \mAdd\left( t_1, t_6 \right)$ \\ $\left( r_\mi, r_\lo \right) \gets \mAddDD\left( t_7, t_8, t_9, t_{10} \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{mulDTref} \MulDT] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\lo$ the values taken by arguments of algorithm \ref{mulDTref} \MulDT \\ So the following holds for the values returned $r_\hi$, $r_\mi$ and $r_\lo$: $$r_\hi + r_\mi + r_\lo = \left(\left(a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq 2^{-149}$$ The values returned $r_\mi$ and $r_\lo$ will not overlap at all and the overlap of $r_\hi$ and $r_\mi$ will be bounded as follows: $$\left \vert r_\mi \right \vert \leq 2^{-48} \cdot \left \vert r_\hi \right \vert$$ \end{theorem} \begin{proof} ~ \\ Since algorithm \ref{mulDTref} is relatively long, we will proceed by analysing sub-sequences. So let us consider first the following sequence: \begin{center} \begin{minipage}[b]{50mm} $\left( t_2, t_3 \right) \gets \mMul\left( a_\hi, b_\lo \right)$ \\ $\left( t_4, t_5 \right) \gets \mMul\left( a_\lo, b_\hi \right)$ \\ $\left( t_7, t_8 \right) \gets \mAddDD\left( t_2, t_3, t_4, t_5 \right)$ \end{minipage} \end{center} Clearly $t_7$ and $t_8$ will not overlap. The same way $t_2$ and $t_3$ and $t_4$ and $t_5$ will not overlap and we know that we have exactly the following egalities \begin{eqnarray*} t_2 + t_3 & = & a_\hi \cdot b_\lo \\ t_4 + t_5 & = & b_\hi \cdot a_\lo \end{eqnarray*} Further we can check that \begin{eqnarray*} \left \vert t_3 \right \vert & \leq & 2^{-53} \cdot \left \vert \circ \left( a_\hi \cdot b_\lo \right) \right \vert \\ & \leq & 2^{-52} \cdot \left \vert a_\hi \cdot b_\lo \right \vert \end{eqnarray*} and similarly $$\left \vert t_5 \right \vert \leq 2^{-52} \cdot \left \vert b_\hi \cdot a_\lo \right \vert$$ So we have on the one side \begin{eqnarray*} 2^{-53} \cdot \left \vert t_3 + t_5 \right \vert & \leq & 2^{-53} \cdot \left \vert t_3 \right \vert + 2^{-53} \cdot \left \vert t_5 \right \vert \\ & \leq & 2^{-105} \cdot \left \vert a_\hi \cdot b_\lo \right \vert + 2^{-105} \cdot \left \vert b_\hi \cdot a_\lo \right \vert \end{eqnarray*} and on the other \begin{eqnarray*} 2^{-102} \cdot \left \vert t_2 + t_3 + t_4 + t_5 \right \vert & \leq & 2^{-102} \cdot \left \vert b_\hi \cdot a_\lo + a_\hi \cdot b_\lo \right \vert \\ & \leq & 2^{-102} \cdot \left \vert b_\hi \cdot a_\lo \right \vert + 2^{-102} \cdot \left \vert a_\hi \cdot b_\lo \right \vert \end{eqnarray*} Using theorem \ref{addDDerrabs} it is possible to note $$t_7 + t_8 = a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + \delta_1$$ with $$\left \vert \delta_1 \right \vert \leq 2^{-102} \cdot \left \vert a_\hi \cdot b_\lo \right \vert + 2^{-102} \cdot \left \vert a_\lo \cdot b_\hi \right \vert$$ Let us now consider the following sub-sequence of algorithm \ref{mulDTref}: \begin{center} \begin{minipage}[b]{50mm} $\left( r_\hi, t_1 \right) \gets \mMul\left( a_\hi, b_\hi \right)$ \\ $t_6 \gets a_\lo \otimes b_\lo$ \\ $\left( t_9, t_{10} \right) \gets \mAdd\left( t_1, t_6 \right)$ \end{minipage} \end{center} Trivially $t_9$ and $t_{10}$ do not overlap. Additionally, one sees that we have exactly $$r_\hi + t_1 = a_\hi \cdot b_\hi$$ and, exactly too, $$t_9 + t_{10} = t_1 + t_6$$ So using $$t_6 = a_\lo \otimes b_\lo = a_\lo \cdot b_\lo \cdot \left( 1 + \epsilon \right)$$ where $\left \vert \epsilon \right \vert \leq 2^{-53}$ we get \begin{eqnarray*} r_\hi + t_9 + t_{10} & = & r_\hi + t_1 + t_6 \\ & = & a_\hi \cdot b_\hi + t_6 \\ & = & a_\hi \cdot b_\hi + a_\lo \cdot b_\lo + \delta_2 \end{eqnarray*} with $$\left \vert \delta_2 \right \vert \leq 2^{-53} \cdot \left \vert a_\lo \cdot b_\lo \right \vert$$ Let us now bound $\left \vert t_9 \right \vert$ with regard to $\left \vert a_\hi \cdot b_\hi \right \vert$:\\ We have \begin{eqnarray*} \left \vert t_9 \right \vert & \leq & \circ \left( \left \vert t_1 \right \vert + \left \vert t_6 \right \vert \right) \\ & \leq & \circ \left( \left \vert t_1 \right \vert + \circ \left( \left \vert a_\lo \cdot b_\lo \right \vert \right) \right) \\ & \leq & \circ \left( \left \vert t_1 \right \vert + \circ \left( 2^{-106} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \right) \right) \\ & \leq & \circ \left( 2^{-53} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-105} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \right) \\ & \leq & 2^{-51} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} With inequalities given, we can bound now the absolute and relative error of algorithm \MulDT~ \ref{mulDTref}. \\ We know already that $$t_7 + t_8 = a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + \delta_1$$ where $$\left \vert \delta_1 \right \vert \leq 2^{-102} \cdot \left \vert a_\hi \cdot b_\lo \right \vert + 2^{-102} \cdot \left \vert b_\hi \cdot a_\lo \right \vert$$ and $$r_\hi + t_9 + t_{10} = a_\hi \cdot b_\hi + a_\lo \cdot b_\lo + \delta_2$$ where $$\left \vert \delta_2 \right \vert \leq 2^{-53} \cdot \left \vert a_\lo \cdot b_\lo \right \vert$$ One remarks that \begin{eqnarray*} \left \vert t_8 \right \vert & \leq & 2^{-53} \cdot \left \vert t_7 \right \vert \\ \left \vert t_{10} \right \vert & \leq & 2^{-53} \cdot \left \vert t_9 \right \vert \end{eqnarray*} and easily checks that $$2^{-53} \cdot \left \vert t_{10} + t_8 \right \vert \leq 2^{-101} \cdot \left \vert t_9 \right \vert + 2^{-101} \cdot \left \vert t_7 \right \vert$$ and that $$2^{-102} \cdot \left \vert t_9 + t_{10} + t_7 + t_8 \right \vert \leq 2^{-101} \cdot \left \vert t_9 \right \vert + 2^{-101} \cdot \left \vert t_7 \right \vert$$ So by means of the theorem \ref{addDDerrabs}, we obtain that $$r_\mi + r_\lo = t_9 + t_{10} + t_7 + t_8 + \delta_3$$ where $$\left \vert \delta_3 \right \vert \leq 2^{-101} \cdot \left \vert t_9 \right \vert + 2^{-101} \cdot \left \vert t_7 \right \vert$$ So finally we get $$r_\hi + r_\mi + r_\lo = a_\hi \cdot b_\hi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\lo + \delta$$ where \begin{eqnarray*} \left \vert \delta \right \vert & = & \left \vert \delta_1 + \delta_2 + \delta_3 \right \vert \\ & \leq & \left \vert \delta_1 \right \vert + \left \vert \delta_2 \right \vert + \left \vert \delta_3 \right \vert \\ & \leq & 2^{-102} \cdot \left \vert a_\lo \cdot b_\hi \right \vert \\ & & + 2^{-102} \cdot \left \vert a_\hi \cdot b_\lo \right \vert \\ & & + 2^{-53} \cdot \left \vert a_\lo \cdot b_\lo \right \vert \\ & & + 2^{-152} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \\ & & + 2^{-101} \cdot \left \vert t_7 \right \vert \end{eqnarray*} And for $\left \vert t_7 \right \vert$ we obtain the following inequalities \begin{eqnarray*} \left \vert t_7 \right \vert & \leq & \circ \left( \left \vert t_7 + t_8 \right \vert \right) \\ & \leq & 2 \cdot \left \vert t_7 + t_8 \right \vert \\ & \leq & 2 \cdot \left(\left \vert a_\hi \cdot b_\lo \right \vert + \left \vert a_\lo \cdot b_\hi \right \vert + 2^{-102} \cdot \left \vert a_\lo \cdot b_\hi \right \vert + 2^{-102} \cdot \left \vert a_\hi \cdot b_\lo \right \vert \right) \\ & \leq & 8 \cdot \left \vert a_\hi \cdot b_\lo \right \vert \end{eqnarray*} In consequence we can check $$\left \vert \delta \right \vert \leq 2^{-150} \cdot \left \vert a_\hi \cdot b_\hi \right \vert$$ Let us give now an upper bound for $\left \vert a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\lo \right \vert$ as a function of $\left \vert a_\hi \cdot b_\hi \right \vert$:\\ We have \begin{eqnarray*} \left \vert a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\lo \right \vert & \leq & \left \vert a_\hi \cdot b_\lo \right \vert + \left \vert a_\lo \cdot b_\hi \right \vert + \left \vert a_\lo \cdot b_\lo \right \vert \\ & \leq & 2^{-51} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} from which we deduce that \begin{eqnarray*} \left \vert a_\hi \cdot b_\hi + \left( a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\lo \right) \right \vert & \geq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 1 - 2^{-51} \right) \\ & \geq & \frac{1}{2} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} Thus $$\left \vert \delta \right \vert \leq 2^{-149} \cdot \left \vert a_\hi \cdot b_\hi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\lo \right \vert$$ So we can finally give an upper bound for the relative error $\epsilon$ of the multiplication procedure \MulDT~ defined by algorithm \ref{mulDTref}: $$r_\hi + r_\mi + r_\lo = \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\lo \right) \cdot \left( 1 + \epsilon \right)$$ with $$\left \vert \epsilon \right \vert \leq 2^{-149}$$ Before concluding, we must still analyse the overlap of the different components of the triple-double number returned by the algorithm. It is clear that $r_\mi$ and $r_\lo$ do not overlap because the \AddDD~ brick ensures this. Let us now consider the magnitude of $r_\mi$ with regard to the one of $r_\hi$.\\ We give first a lower bound for $\left \vert r_\hi \right \vert$: \begin{eqnarray*} \left \vert r_\hi \right \vert & = & \left \vert \circ \left( a_\hi \cdot b_\hi \right) \right \vert \\ & \geq & \circ \left( \left \vert a_\hi \cdot b_\hi \right \vert \right) \\ & \geq & \frac{1}{2} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} and then an upper bound for $\left \vert r_\mi \right \vert$: \begin{eqnarray*} \left \vert r_\mi \right \vert & \leq & \circ \left( \left \vert r_\mi + r_\lo \right \vert \right) \\ & \leq & \circ \left( \left \vert t_7 + t_8 \right \vert + \left \vert t_9 + t_{10} \right \vert + \delta_3 \right) \\ & \leq & \circ \left( \left \vert a_\hi \cdot b_\lo \right \vert + \left \vert a_\lo \cdot b_\hi \right \vert + \delta_1 + \left \vert t_9 \right \vert + \left \vert t_{10} \right \vert + \delta_3 \right) \\ & \leq & \circ \left( \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-53} + 2^{-53} + 2^{-155} + 2^{-155} + 2^{-51} + 2^{-104} + 2^{-152} + 2^{-151} \right) \right) \\ & \leq & 2^{-49} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} From this we can deduce the final bound $$\left \vert r_\mi \right \vert \leq 2^{-48} \cdot \left \vert r_\hi \right \vert$$\qed \end{proof} \subsection{The multiplication procedure \MulDTT} Let us concentrate now on the multiplication sequence \MulDTT. \begin{algorithm}[\MulDTT] \label{mulDTTref} ~ \\ {\bf In:} a double-double number $a_\hi + a_\lo$ and a triple-double number $b_\hi + b_\mi + b_\lo$ \\ {\bf Out:} a triple-double number $r_\hi + r_\mi + r_\lo$ \\ {\bf Preconditions on the arguments:} \begin{eqnarray*} \left \vert a_\lo \right \vert & \leq & 2^{-53} \cdot \left \vert a_\hi \right \vert \\ \left \vert b_\mi \right \vert & \leq & 2^{-\beta_o} \cdot \left \vert b_\hi \right \vert \\ \left \vert b_\lo \right \vert & \leq & 2^{-\beta_u} \cdot \left \vert b_\mi \right \vert \end{eqnarray*} with \begin{eqnarray*} \beta_o & \geq & 2 \\ \beta_u & \geq & 1 \end{eqnarray*} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{60mm} $\left( r_\hi, t_1 \right) \gets \mMul\left( a_\hi, b_\hi \right)$ \\ $\left( t_2, t_3 \right) \gets \mMul\left( a_\hi, b_\mi \right)$ \\ $\left( t_4, t_5 \right) \gets \mMul\left( a_\hi, b_\lo \right)$ \\ $\left( t_6, t_7 \right) \gets \mMul\left( a_\lo, b_\hi \right)$ \\ $\left( t_8, t_9 \right) \gets \mMul\left( a_\lo, b_\mi \right)$ \\ $t_{10} \gets a_\lo \otimes b_\lo$ \\ $\left( t_{11}, t_{12} \right) \gets \mAddDD\left( t_2, t_3, t_4, t_5 \right)$ \\ $\left( t_{13}, t_{14} \right) \gets \mAddDD\left( t_6, t_7, t_8, t_9 \right)$ \\ $\left( t_{15}, t_{16} \right) \gets \mAddDD\left( t_{11}, t_{12}, t_{13}, t_{14} \right)$ \\ $\left( t_{17}, t_{18} \right) \gets \mAdd\left( t_1, t_{10} \right)$ \\ $\left( r_\mi, r_\lo \right) \gets \mAddDD\left( t_{17}, t_{18}, t_{15}, t_{16} \right)$ \\ \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Relative error of algorithm \ref{mulDTTref} \MulDTT] ~ \\ Let be $a_\hi + a_\lo$ and $b_\hi + b_\mi + b_\lo$ the values in argument of algorithm \ref{mulDTTref} \MulDTT~ such that the given preconditions hold.\\ So the following will hold for the values $r_\hi$, $r_\mi$ and $r_\lo$ returned $$r_\hi + r_\mi + r_\lo = \left(\left(a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\mi + b_\lo \right)\right) \cdot \left(1 + \epsilon\right)$$ where $\epsilon$ is bounded as follows: $$\left \vert \epsilon \right \vert \leq \frac{2^{-99 - \beta_o} + 2^{-99 - \beta_o - \beta_u} + 2^{-152}} {1 - 2^{-53} - 2^{-\beta_o + 1} - 2^{-\beta_o - \beta_u + 1}} \leq 2^{-97 - \beta_o} + 2^{-97 - \beta_o - \beta_u} + 2^{-150}$$ The values $r_\mi$ and $r_\lo$ will not overlap at all and the following bound will be verified for the overlap of $r_\hi$ and $r_\mi$: $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ where $$\gamma \geq \min\left( 48, \beta_o - 4, \beta_o + \beta_u - 4 \right)$$ \end{theorem} \begin{proof} ~ \\ During this proof we will once again proceed by basic bricks that we will assemble in the end.\\ Let us therefore start by the following one: \begin{center} \begin{minipage}[b]{60mm} $\left( t_2, t_3 \right) \gets \mMul\left( a_\hi, b_\mi \right)$ \\ $\left( t_4, t_5 \right) \gets \mMul\left( a_\hi, b_\lo \right)$ \\ $\left( t_{11}, t_{12} \right) \gets \mAddDD\left( t_2, t_3, t_4, t_5 \right)$ \end{minipage} \end{center} Since we have the exact egalities $$t_2 + t_3 = a_\hi \cdot b_\mi$$ and $$t_4 + t_5 = a_\hi \cdot b_\lo$$ and since we know that $t_2$ and $t_3$ and $t_4$ and $_5$ do not overlap, it suffices to apply the bound proven at theorem \ref{addDDerrabs}. So we can check on the one hand \begin{eqnarray*} 2^{-53} \cdot \left \vert t_3 + t_5 \right \vert & \leq & 2^{-53} \cdot \left \vert t_3 \right \vert + 2^{-53} \cdot \left \vert t_5 \right \vert \\ & \leq & 2^{-106} \cdot \left \vert t_2 \right \vert + 2^{-106} \cdot \left \vert t_4 \right \vert \\ & \leq & 2^{-105} \cdot \left \vert a_\hi \cdot b_\mi \right \vert + 2^{-105} \cdot \left \vert a_\hi \cdot b_\lo \right \vert \\ & \leq & 2^{-105-\beta_o} \cdot \left \vert a_\hi \cdot b_\mi \right \vert + 2^{-105-\beta_o-\beta_u} \cdot \left \vert a_\hi \cdot b_\lo \right \vert \end{eqnarray*} and on the other \begin{eqnarray*} 2^{-102} \cdot \left \vert t_2 + t_3 + t_4 + t_5 \right \vert & = & 2^{-102} \cdot \left \vert a_\hi \cdot b_\mi + a_\hi \cdot b_\lo \right \vert \\ & \leq & 2^{-102} \cdot \left \vert a_\hi \cdot b_\mi \right \vert + 2^{-102} \cdot \left \vert a_\hi \cdot b_\lo \right \vert \\ & \leq & 2^{-102-\beta_o} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-102-\beta_o-\beta_u} \cdot \left \vert a_\hi \cdot b_\lo \right \vert \end{eqnarray*} In consequence, using the mentioned theorem, we obtain $$t_{11} + t_{12} = a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + \delta_1$$ with $$\left \vert \delta_1 \right \vert \leq 2^{-102-\beta_o} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-102-\beta_o-\beta_u} \cdot \left \vert a_\hi \cdot b_\lo \right \vert$$ Let us continue with the following part of the algorithm: \begin{center} \begin{minipage}[b]{60mm} $\left( t_6, t_7 \right) \gets \mMul\left( a_\lo, b_\hi \right)$ \\ $\left( t_8, t_9 \right) \gets \mMul\left( a_\lo, b_\mi \right)$ \\ $\left( t_{13}, t_{14} \right) \gets \mAddDD\left( t_6, t_7, t_8, t_9 \right)$ \end{minipage} \end{center} We have \begin{eqnarray*} 2^{-53} \cdot \left \vert t_7 + t_9 \right \vert & \leq & 2^{-53} \cdot \left \vert t_7 \right \vert + 2^{-53} \cdot \left \vert t_9 \right \vert \\ & \leq & 2^{-106} \cdot \left \vert t_6 \right \vert + 2^{-106} \cdot \left \vert t_8 \right \vert \\ & \leq & 2^{-105} \cdot \left \vert a_\lo \cdot b_\hi \right \vert + 2^{-105} \cdot \left \vert a_\lo \cdot b_\mi \right \vert \\ & \leq & 2^{-158} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-158-\beta_o} \cdot \left \vert a_\hi b_\hi \right \vert \end{eqnarray*} and \begin{eqnarray*} 2^{-102} \cdot \left \vert t_6 + t_7 + t_8 + t_9 \right \vert & = & 2^{-102} \cdot \left \vert a_\lo \cdot b_\hi + a_\lo \cdot b_\mi \right \vert \\ & \leq & 2^{-102} \cdot \left \vert a_\lo \cdot b_\hi \right \vert + 2^{-102} \cdot \left \vert a_\lo \cdot b_\mi \right \vert \\ & \leq & 2^{-155} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-155-\beta_o} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} So we get $$t_{13} + t_{14} = a_\lo \cdot b_\hi + a_\lo \cdot b_\mi + \delta_2$$ with $$\left \vert \delta_2 \right \vert \leq 2^{-155} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-155-\beta_o} \cdot \left \vert a_\hi \cdot b_\hi \right \vert$$ Let us now consider the brick that produces $t_{15}$ and $t_{16}$ out of the values in argument. By the properties of the \AddDD~ procedure, $t_{11}$ and $t_{12}$ and $t_{13}$ and $t_{14}$ do not overlap at all and verify thus the preconditions of the next \AddDD~ brick that will compute $t_{15}$ and $t_{16}$. So it suffices to apply once again the absolute error bound of this procedure for obtaining $$t_{15} + t_{16} = t_{11} + t_{12} + t_{13} + t_{14} + \delta_3$$ with $\left \vert \delta_3 \right \vert$ which remains to be estimated.\\ So we have on the one hand \begin{eqnarray*} 2^{-53} \cdot \left \vert t_{12} + t_{14} \right \vert & \leq & 2^{-53} \cdot \left \vert t_{12} \right \vert + 2^{-53} \cdot \left \vert t_{14} \right \vert \\ & \leq & 2^{-106} \cdot \left \vert t_{11} \right \vert + 2^{-106} \cdot \left \vert t_{13} \right \vert \end{eqnarray*} -- which is an upper bound that can still be estimated by \begin{eqnarray*} \left \vert t_{11} \right \vert & = & \left \vert \circ \left( t_{11} + t_{12} \right) \right \vert \\ & \leq & \left \vert \left( t_{11} + t_{12} \right) \cdot \left( 1 + 2^{-53} \right) \right \vert \\ & \leq & 2 \cdot \left \vert t_{11} + t_{12} \right \vert \\ & \leq & 2 \cdot \left \vert a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + \delta_1 \right \vert \\ & \leq & 2 \cdot \left( \left \vert a_\hi \cdot b_\mi \right \vert + \left \vert a_\hi \cdot b_\lo \right \vert + \left \vert \delta_1 \right \vert \right) \\ & \leq & 2 \cdot \left( 2^{-\beta_o} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-\beta_o-\beta_u} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-\beta_o-102} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-\beta_o-\beta_u-102} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \right) \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-\beta_o+2} + 2^{-\beta_o-\beta_u+2} \right) \end{eqnarray*} which means, using also the following inequalities that \begin{eqnarray*} \left \vert t_{13} \right \vert & = & \left \vert \circ \left( t_{13} + t_{14} \right) \right \vert \\ & \leq & 2 \cdot \left \vert t_{13} + t_{14} \right \vert \\ & \leq & 2 \cdot \left \vert a_\lo \cdot b_\hi + a_\lo \cdot b_\mi + \delta_2 \right \vert \\ & \leq & 2 \cdot \left( \left \vert a_\lo \cdot b_\hi \right \vert + \left \vert a_\lo \cdot b_\mi \right \vert + \left \vert \delta_2 \right \vert \right) \\ & \leq & 2 \cdot \left( 2^{-53} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-53-\beta_o} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-155} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-155-\beta_o} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \right) \\ & \leq & 2^{-50} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} we can finally check that we have on the one side $$2^{-53} \cdot \left \vert t_{12} + t_{14} \right \vert \leq \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-\beta_o-104} + 2^{-\beta_o-\beta_u-104} + 2^{-156} \right)$$ And on the other \begin{eqnarray*} 2^{-102} \cdot \left \vert t_{11} + t_{12} + t_{13} + t_{14} \right \vert & \leq & 2^{-102} \cdot \left \vert a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\mi + \delta_1 + \delta_2 \right \vert \\ & \leq & 2^{-102} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \cdot \\ & & \left( 2^{-\beta_o} \right. \\ & & + 2^{-\beta_o-\beta_u} \\ & & + 2^{-53} \\ & & + 2^{-\beta_o-53} \\ & & + 2^{-\beta_o-102} \\ & & + 2^{-\beta_o-\beta_u-102} \\ & & + 2^{-155} \\ & & \left. + 2^{-\beta_o-155} \right) \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-\beta_o-101} + 2^{-\beta_o-\beta_u-101} + 2^{-154} \right) \end{eqnarray*} So we know that $$t_{15} + t_{16} = t_{11} + t_{12} + t_{13} + t_{14} + \delta_3$$ with $$\left \vert \delta_3 \right \vert \leq \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-\beta_o-101} + 2^{-\beta_o-\beta_u-101} + 2^{-154} \right)$$ With this result we can note now $$t_{15} + t_{16} = a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\mi + \delta_4$$ with \begin{eqnarray*} \left \vert \delta_4 \right \vert & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \\ & & \left( 2^{-\beta_o-102} \right. \\ & & + 2^{-\beta_o-\beta_u-102} \\ & & + 2^{-155} \\ & & + 2^{-\beta_o-155} \\ & & + 2^{-\beta_o-101} \\ & & \left. + 2^{-\beta_o-\beta_u-101} \right) \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-\beta_o-100} + 2^{-\beta_o-\beta_u-100} + 2^{-155} \right) \end{eqnarray*} Let us give now an upper bound for $\delta_5$ defined by the following expression: $$r_\mi + r_\lo = t_1 + a_\lo \cdot b_\lo + t_{15} + t_{16} + \delta_5$$ It is clear that $t_{17}$ and $t_{18}$ do not overlap. In contrast the \Add~ operation which adds $t_1$ to $t_{10}$ is necessary because $t_1$ and $t_{10}$ can overlap and even \ouvguill overtake\fermguill~ each other: $$\left \vert t_1 \right \vert \geq 2^{-106} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \lor t_1 = 0$$ and $$\left \vert t_{10} \right \vert \leq 2^{-\beta_o-\beta_u-52} \cdot \left \vert a_\hi \cdot b_\hi \right \vert$$ The same argument tells us that the \Add~ must be conditional. \\ So we have $$t_{17} + t_{18} = t_1 + t_{10}$$ and $$t_{10} = a_\lo \cdot b_\lo + \delta^\prime$$ with $$\left \vert \delta^\prime \right \vert \leq 2^{-106-\beta_o-\beta_u} \cdot \left \vert a_\hi \cdot b_\hi \right \vert$$ Let us apply once again the bound for the absolute error of the \AddDD~ procedure:\\ So we have on the one hand \begin{eqnarray*} 2^{-53} \cdot \left \vert t_{18} + t_{16} \right \vert & \leq & 2^{-53} \cdot \left \vert t_{18} \right \vert + 2^{-53} \cdot \left \vert t_{18} \right \vert \\ & \leq & 2^{-106} \cdot \left \vert t_{17} \right \vert + 2^{-106} \cdot \left \vert t_{15} \right \vert \end{eqnarray*} We can estimate this by \begin{eqnarray*} \left \vert t_{17} \right \vert & \leq & \left \vert \circ \left( t_1 + t_{10} \right) \right \vert \\ & \leq & 2 \cdot \left \vert t_1 + t_{10} \right \vert \\ & \leq & 2 \cdot \left \vert t_1 \right \vert + 2 \cdot \left \vert t_{10} \right \vert \\ & \leq & 2^{-52} \cdot \left \vert r_\hi \right \vert + 2 \cdot \left \vert \circ \left( a_\lo \cdot b_\lo \right) \right \vert \\ & \leq & 2^{-52} \cdot \left \vert \circ \left( a_\hi \cdot b_\hi \right) \right \vert + 2^2 \cdot \left \vert a_\lo \cdot b_\lo \right \vert \\ & \leq & 2^{-51} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-51-\beta_o-\beta_u} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} and by \begin{eqnarray*} \left \vert t_{15} \right \vert & = & \left \vert \circ \left( t_{15} + t_{16} \right) \right \vert \\ & \leq & 2 \cdot \left \vert t_{15} + t_{16} \right \vert \\ & \leq & 2 \cdot \left \vert a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\mi + \delta_4 \right \vert \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-\beta_o+1} + 2^{-\beta_o-\beta_u+1} + 2^{-52} + 2^{-\beta_o-52} + 2^{-\beta_o-99} + 2^{-\beta_o-\beta_u-99} + 2^{-154} \right) \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-\beta_o+2} + 2^{-\beta_o-\beta_u+2} + 2^{-51} \right) \end{eqnarray*} So finally, we have on the one hand \begin{eqnarray*} 2^{-53} \cdot \left \vert t_{18} + t_{16} \right \vert & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-157} + 2^{-157-\beta_o-\beta_u} + 2^{-104-\beta_o} + 2^{-104-\beta_o-\beta_u} + 2^{-157} \right) \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-\beta_o-104} + 2^{-\beta_o-\beta_u-103} + 2^{-156} \right) \end{eqnarray*} And on the other \begin{eqnarray*} 2^{-102} \cdot \left \vert t_{17} + t_{18} + t_{15} + t_{16} \right \vert & \leq & 2^{-102} \cdot \left \vert t_1 + a_\lo \cdot b_\lo + \delta^\prime + a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi \right. \\ & & \left. + a_\lo \cdot b_\mi + \delta_4 \right \vert \\ & \leq & 2^{-102} \cdot \left( 2^{-53} \cdot \left \vert r_\hi \right \vert \right. \\ & & + 2^{-53-\beta_o-\beta_u} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \\ & & + 2^{-\beta_o} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \\ & & + 2^{-\beta_o-\beta_u} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \\ & & + 2^{-53} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \\ & & + 2^{-53-\beta_o} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \\ & & + 2^{-106-\beta_o-\beta_u} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \\ & & \left. + \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-100-\beta_o} + 2^{-100-\beta_o-\beta_u} + 2^{-155} \right) \right) \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-101-\beta_o} + 2^{-101-\beta_o-\beta_u} + 2^{-153} \right) \end{eqnarray*} which means that we finally obtain the following $$r_\mi + r_\lo = t_1 + a_\lo \cdot b_\lo + a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\mi + \delta_6$$ with $$\left \vert \delta_6 \right \vert \leq \left \vert \delta_4 + \delta_5 \right \vert$$ where $$\left \vert \delta_5 \right \vert \leq \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-101-\beta_o} + 2^{-101-\beta_o-\beta_u} + 2^{-153} \right)$$ Thus we can check that \begin{eqnarray*} \left \vert \delta_6 \right \vert & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-100-\beta_o} + 2^{-100-\beta_o-\beta_u} + 2^{-155} + 2^{-101-\beta_o} + 2^{-101-\beta_o-\beta_u} + 2^{-153} \right) \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-99-\beta_o} + 2^{-99-\beta_o-\beta_u} + 2^{-152} \right) \end{eqnarray*} Let us now integrate the different intermediate results:\\ Since we know that the following egality is exact $$r_\hi + t_1 = a_\hi \cdot b_\hi$$ we can check that $$r_\hi + r_\mi + r_\lo = \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\mi + b_\lo \right) + \delta_6$$ We continue by giving a lower bound for $\left \vert \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\mi + b_\lo \right) \right \vert$ using a term which is a function of $\left \vert a_\hi \cdot b_\hi \right \vert$. We do so for being able to give a relative error bound. We first bound $$\left \vert a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\mi + a_\lo \cdot b_\lo \right \vert$$ by such a term.\\ We have \begin{eqnarray*} \left \vert a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\mi + a_\lo \cdot b_\lo \right \vert & \leq & \left \vert a_\hi \cdot b_\mi \right \vert + \left \vert a_\hi \cdot b_\lo \right \vert + \left \vert a_\lo \cdot b_\hi \right \vert + \left \vert a_\lo \cdot b_\mi \right \vert + \left \vert a_\lo \cdot b_\lo \right \vert \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-\beta_o} + 2^{-\beta_o-\beta_u} + 2^{-53} \right. \\ & & \left. + 2^{-\beta_o-53} + 2^{-\beta_o-53} \right) \\ & \leq & 2^{-\beta_o+1} \cdot \left \vert a_\hi \cdot b_\hi \right \vert + 2^{-\beta_o-\beta_u+1} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \\ & & + 2^{-53} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} and we get $$\left \vert \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\mi + b_\lo \right) \right \vert \geq \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 1 - 2^{-53} - 2^{-\beta_o+1} -2^{-\beta_o-\beta_u+1} \right)$$ from which we deduce (since $\beta_o \geq 2$, $\beta_u \geq 1$) $$\left \vert a_\hi \cdot b_\hi \right \vert \leq \frac{1}{1 - 2^{-53} - 2^{-\beta_o+1} -2^{-\beta_o-\beta_u+1}} \cdot \left \vert \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\mi + b_\lo \right) \right \vert$$ Using this inequality we can finally give a bound for the relative error $\epsilon$ as follows: $$r_\hi + r_\mi + r_\lo = \left( a_\hi + a_\lo \right) \cdot \left( b_\hi + b_\mi + b_\lo \right) \cdot \left( 1 + \epsilon \right)$$ with $$\left \vert \epsilon \right \vert \leq \frac{2^{-99-\beta_o} + 2^{-99-\beta_o-\beta_u} + 2^{-152}}{1 - 2^{-53} - 2^{-\beta_o+1} -2^{-\beta_o-\beta_u+1}}$$ Let us recall that for this inequality, $\beta_o \geq 2$, $\beta_u \geq 1$ must hold which is the case.\\ It is certainly possible to estimate $\left \vert \epsilon \right \vert$ by a term which is slightly less exact: $$\left \vert \epsilon \right \vert \leq 2^{-97 - \beta_o} + 2^{-97 - \beta_o - \beta_u} + 2^{-150}$$ because $$1 - 2^{-53} - 2^{-\beta_o+1} -2^{-\beta_o-\beta_u+1} \geq \frac{1}{4}$$ for $\forall \beta_o \geq 2, \beta_u \geq 1$.\\~\\ In order to finish this proof, we must still give an upper bound for the maximal overlap generated by the algorithm \ref{mulDTTref} \MulDTT. Clearly $r_\mi$ and $r_\lo$ do not overlap because of the properties of the basic brick \AddDD. Let us give an upper bound for the overlap between $r_\hi$ and $r_\mi$ giving a term of the following form: $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ where we constate a lower bound for $\gamma$ using a term in $\beta_o$ and $\beta_u$.\\ Let us start by giving a lower bound for $r_\hi$ as a function of $\left \vert a_\hi \cdot b_\hi \right \vert$.\\ We have \begin{eqnarray*} \left \vert r_\hi \right \vert & = & \left \vert \circ \left( a_\hi \cdot b_\hi \right) \right \vert \\ & \geq & \frac{1}{2} \cdot \left \vert a_\hi \cdot b_\hi \right \vert \end{eqnarray*} Then, let us give an upper bound for $\left \vert r_\mi \right \vert$ using a function of $\left \vert a_\hi \cdot b_\hi \right \vert$: \begin{eqnarray*} \left \vert r_\mi \right \vert & \leq & \left \vert \circ \left( r_\mi + r_\lo \right) \right \vert \\ & \leq & 2 \cdot \left \vert r_\mi + r_\lo \right \vert \\ & \leq & 2 \cdot \left \vert t_1 + a_\lo \cdot b_\lo + a_\hi \cdot b_\mi + a_\hi \cdot b_\lo + a_\lo \cdot b_\hi + a_\lo \cdot b_\mi + \delta_6 \right \vert \\ & \leq & 2 \cdot \left \vert a_\hi \cdot b_\hi \right \vert \cdot \\ & & \cdot \left( 2^{-52} + 2^{-\beta_o-\beta_u-53} + 2^{-\beta_o} + 2^{-\beta_o-\beta_u} + 2^{-53} + 2^{-\beta_o-53} + \right. \\ & & \left. 2^{-\beta_o-99} + 2^{-\beta_o-\beta_u-99} + 2^{-152} \right) \\ & \leq & \left \vert a_\hi \cdot b_\hi \right \vert \cdot \left( 2^{-50} + 2^{-\beta_o-2} + 2^{-\beta_o-\beta_u+2} \right) \end{eqnarray*} This implies that \begin{eqnarray*} \left \vert r_\mi \right \vert & \leq & 2 \cdot \left \vert r_\hi \right \vert \cdot \left( 2^{-50} + 2^{-\beta_o-2} + 2^{-\beta_o-\beta_u+2} \right) \\ & \leq & \left \vert r_\hi \right \vert \cdot \left( 2^{-49} + 2^{-\beta_o-3} + 2^{-\beta_o-\beta_u+3} \right) \end{eqnarray*} From which we can deduce $$\left \vert r_\mi \right \vert \leq 2^{-\gamma} \cdot \left \vert r_\hi \right \vert$$ with $$\gamma \geq \min \left( 48, \beta_o - 4, \beta_o -\beta_u -4 \right)$$ This result finishes the proof.\qed \end{proof} \section{Final rounding procedures} The renormalisation sequence and all computational basic operators on triple-double numbers have been presented only for one reason: allowing for implementing efficiently elementary functions in double precision \cite{Defour-thesis, crlibmweb, DinDefLau2004LIP}. For obtaining this goal we are still lacking an important basic brick: the final rounding of a triple-double number into a double precision number. This rounding must be possible in each of the $4$ known rounding modes \cite{IEEE754}. In particular, we will distinguish between the round-to-nearest sequence and the ones for the directed rounding modes.\\ Let us start this discussion by introducing some notations:\\ We will notate \begin{itemize} \item $\circ \left( x \right) \in \F$ the rounding to the nearest double precision number of a real number $x \in \R$, \item $\vartriangle \left( x \right) \in \F$ the rounding towards $+\infty$ of a real $x \in \R$ into double precision, \item $\triangledown \left( x \right) \in \F$ the rounding towards $-\infty$ of a real $x \in \R$ into double precision and \item $\diamond \left( x \right) \in \F$ the rounding towards $0$ of a real number $x \in \R$ into a double pr\'ecision number. \end{itemize} Since the directed rounding modes behave all in a similar fashion we will make a slight abuse of our notations. An unspecified directed rounding mode will be notated also $\diamond \left( x \right)$. \begin{definition}[Correct rounding procedure] \label{defprocarrcorr} ~ \\ Let be {\bf A} a procedure taking a non-overlapping triple-double number $x_\hi + x_\mi + x_\lo$ as argument. This number be such that $x_\mi = \circ \left( x_\mi + x_\lo \right)$. Let the procedure {\bf A} return a double precision number $x^\prime$.\\ So we will say that {\bf A} is a correct rounding procedure for round-to-nearest-ties-to-even mode iff for all possible entries $$x^\prime = \circ \left( x_\hi + x_\mi + x_\lo \right)$$ The same way {\bf A} is a correct rounding procedure for a directed rounding mode iff for all possible entries $$x^\prime = \diamond \left( x_\hi + x_\mi + x_\lo \right)$$ \end{definition} In the sequel we will present two algorithms for final rounding -- one for round-to-nearest mode, the other one for the directed modes -- and we will prove their correctness with regard to definition \ref{defprocarrcorr}. \subsection{Final rounding to the nearest even} \begin{lemma}[Generation of half an $\mUlp$ or a quarter of an $\mUlp$] \label{genmiquartulp} ~\\ Let be $x$ a non-subnormal floating point number different from $\pm 0$, $\pm \infty$ and $\nan$ and such that $x^-$ is not a subnormal number. \\ Given the following instruction sequence: \begin{center} $t_1 \gets x^-$ \\ $t_2 \gets x \ominus t_1$ \\ $t_3 \gets t_2 \otimes \frac{1}{2}$ \end{center} we know that \begin{itemize} \item if it exists a $k \in \Z$ such that $x=2^k$ exactly so $$\left \vert t_3 \right \vert = \frac{1}{4} \cdot \mUlp \left( x \right)$$ \item if it does not exist any $k \in \Z$ such that $x=2^k$ exactly so $$\left \vert t_3 \right \vert = \frac{1}{2} \cdot \mUlp \left( x \right)$$ \end{itemize} \end{lemma} \begin{proof} ~\\ Without loss of generality, we can suppose that $x$ is positive because the definition of $x^-$ and all floating point operations are symmetrical with regard to the sign \cite{IEEE754} and because the egalities to be proven ignore it. Additionally since the floating point multiplication by an integer power of $2$ is always exact, it suffices to show that $t_2 = \frac{1}{2} \cdot \mUlp \left( x \right)$ if $x$ is exactly an integer power of $2$ and that $t_2 = \mUlp\left( x \right)$ otherwise.\\ Let us begin by showing that we have the exact equation $$t_2 = x - x^-$$ which means that the floating point substraction is exact. This is the case by Sterbenz' lemma \cite{Ste74} if $$\frac{1}{2} \cdot x \leq x^- \leq 2 \cdot x$$ So let us show this inequality. \\ Since $x \not = 0$ and since it is not subnormal we know already that $x^- \not = 0$. Additionally $x^- > 0$ because $x > 0$ and $x^-$ is its direct predecessor with regard to $<$. Further by definition \ref{predsuccdef}, it is trivial to see that $\forall y \in \F.\left( y^- \right)^+ = y = \left( y^+ \right)^-$.\\ Since $x$ is positive and since $x^-$ is therefore its predecessor with regard to $<$ we have $$x^- < x < 2 \cdot x$$ Let us suppose now that $$x^- < \frac{1}{2} \cdot x$$ Since $x$ is not subnormal and since it is positive, there exist $e \in \Z$ and $m \in \N$ such that $$x = 2^e \cdot m$$ with $$2^{p-1} \leq m < 2^p$$ where $p \geq 2$ is the format's precision; in particular, for double precision, $p=53$.\\ Given that $x^-$ is not subnormal neither and positive, too, it is the predecessor of $x$ and verifies $$x^- = \left \lbrace \begin{array}{lll} 2^e \cdot \left(m - 1 \right) & \mbox{ if } & m-1 \geq 2^{p-1} \\ 2^{e-1} \cdot \left( 2^p - 1 \right) & \mbox{ otherwise} & \end{array} \right.$$ So two cases must be treated separately:\\~\\ {\bf 1st case: $x^- = 2^e \cdot \left( m -1 \right)$ } \\ ~ \\ We get here with the hypotheses supposed \begin{eqnarray*} x^- & < & \frac{1}{2} \cdot x \\ 2^e \cdot \left( m - 1 \right) & < & \frac{1}{2} \cdot 2^e \cdot m \\ m-1 & < & \frac{1}{2} \cdot m \\ m & < & 2 \end{eqnarray*} In contrast $m \geq 2^{p-1}$ and $p\geq2$; so we have contradiction in this case. \\ ~ \\ {\bf 2nd case: $x^- = 2^{e-1} \cdot \left( 2^p -1 \right)$ } \\ ~ \\ We can check \begin{eqnarray*} x^- & < & \frac{1}{2} \cdot x \\ 2^{e-1} \cdot \left( 2^{p-1} - 1 \right) & < & \frac{1}{2} \cdot 2^e \cdot m \\ 2^{e-1} \cdot \left( 2^{p-1} - 1 \right) & < & 2^{e-1} \cdot m \\ 2^p - 1 < m \end{eqnarray*} In contrast $m<2^p$, thus $2^p - 1 < m < 2^p$. This is a contradiction because the inequalities are strict and $m \in \N$. \\ ~ \\ So Sterbenz' lemma \cite{Ste74} can be applied and we get the exact equation $$t_2 = x - x^-$$ It is now important to see that $$x^+ = \left \lbrace \begin{array}{lll} 2^e \cdot \left(m + 1 \right) & \mbox{ if } & m+1 < 2^p \\ 2^{e+1} \cdot 2^{p-1} & \mbox{ otherwise} & \end{array} \right.$$ Further, without loss of generality, we can suppose that $x^+ \not = + \infty$ and that therefore $$\mUlp \left( x \right) = x^+ - x$$ If ever we could not suppose this, it would suffice to apply definition \ref{defulp} of the $\mUlp$ function which would only change the exponent $e$ by $1$ in the sequel.\\ So at this stage of the proof, two different cases are to be treated: $x$ is or is not exactly an integer power of $2$. \\ ~ \\ {\bf 1st case: $x$ is not exactly an integer power of $2$ } \\ ~ \\ So we get $x=2^e \cdot m$ with $2^{p-1} < m < 2^p$ from which we deduce that $m-1 \geq 2^{p-1}$ and that, finally, $$x^- = 2^e \cdot \left(m - 1 \right)$$ So still two sub-cases present themselves: \\ ~ \\ {\bf case a): $x^+ = 2^e \cdot \left( m + 1 \right)$} \\ ~ \\ We can check that \begin{eqnarray*} \mUlp \left( x \right) & = & x^+ - x \\ & = & 2^e \cdot \left( m + 1 \right) - 2^e \cdot m \\ & = & 2^e \cdot \left(m + 1 - m \right) \\ & = & 2^e \end{eqnarray*} and \begin{eqnarray*} t_2 & = & x - x^- \\ & = & 2^e \cdot m - 2^e \cdot \left( m - 1 \right) \\ & = & 2^e \cdot \left( m - m + 1 \right) \\ & = & 2^e \end{eqnarray*} So we know that $$t_2 = \mUlp \left( x \right)$$ ~ \\ {\bf case b): $x^+ = 2^e \cdot \left( m + 1 \right)$} \\ ~ \\ So in order to get $x^+$ being equal to $2^e \cdot \left( m + 1 \right)$, we must have $m+1 \geq 2^p$. \\ In contrast we can show that $m+1 \leq 2^p$ as follows: \\ Let us suppose that $m+1 > 2^p$. Since $m < 2^p$ because $x$ is not subnormal we get $$2^p - 1 < m < 2^p$$ In contrast, the inequalities are strict and $m \in \N$, thus contradiction. \\ We therefore know that $$m=2^p - 1$$ So we get \begin{eqnarray*} \mUlp \left( x \right) & = & x^+ - x \\ & = & 2^{e+1} \cdot 2^{p-1} - 2^e \cdot \left( 2^p - 1 \right) \\ & = & 2^e \cdot 2^p - 2^e \cdot 2^p + 2^e \\ & = & 2^e \end{eqnarray*} and \begin{eqnarray*} t_2 & = & x - x^- \\ & = & 2^e \cdot \left( 2^p - 1 \right) - 2^e \cdot \left( 2^p - 2 \right) \\ & = & 2^e \cdot 2^p - 2^e - 2^e \cdot 2^p + 2 \cdot 2^e \\ & = & 2^e \end{eqnarray*} Thus we have still $$t_2 = \mUlp \left( x \right)$$ ~ \\ {\bf 2nd case: $x$ is exactly an integer power of $2$ } \\ ~ \\ So in this case we verify that $$x=2^e \cdot 2^{p-1}$$ and therefore $m=2^{p-1}$. \\ In consequence, $$x^+ = 2^e \cdot \left(2^{p-1} + 1 \right)$$ because we got $2^{p-1} + 1 < 2^p$ since $p \geq 2$. \\ The same way $$x^- = 2^{e-1} \cdot \left(2^p - 1 \right)$$ because, trivially, $2^{p-1} - 1 < 2^{p-1}$.\\ So we get \begin{eqnarray*} \mUlp \left( x \right) & = & x^+ - x \\ & = & 2^e \cdot \left( 2^{p-1} + 1 \right) - 2^e \cdot 2^{p-1} \\ & = & 2^e \cdot 2^{p-1} + 2^e - 2^e \cdot 2^{p-1} \\ & = & 2^e \end{eqnarray*} and \begin{eqnarray*} t_2 & = & x - x^- \\ & = & 2^e \cdot 2^{p-1} - 2^{e-1} \cdot \left( 2^p - 1 \right) \\ & = & 2^e \cdot 2^{p-1} - 2^{e-1} \cdot 2^p + 2^{e-1} \\ & = & 2^{e-1} \\ & = & \frac{1}{2} \cdot 2^e \end{eqnarray*} Thus we can check that $$t_2 = \frac{1}{2} \cdot \mUlp \left( x \right)$$ \qed \end{proof} \begin{lemma}[Generation of half an $\mUlp$] \label{genmiulp} ~\\ Let be $x$ a non-subnormal floating point number different from $\pm 0$, $\pm\infty$ and $\nan$.\\ Let be the following instruction sequence: \begin{center} $t_1 \gets x^+$ \\ $t_2 \gets t_1 \ominus x$ \\ $t_3 \gets t_2 \otimes \frac{1}{2}$ \end{center} So the following holds $$\left \vert t_3 \right \vert = \frac{1}{2} \cdot \mUlp \left( x \right)$$ and one knows that \begin{center} $x > 0$ iff $t_3 > 0$ \end{center} \end{lemma} \begin{proof} ~ \\ In the beginning we will show the first equation; the equivalence of the signs will be shown below. So, without loss of generality, we can suppose that $x$ is positive because the definition of $x^+$ and all floating point operations are symmetrical with regard to the sign \cite{IEEE754} and because the equation to be shown ignorates it. Further since the floating point multiplication by an integer power of $2$ is always exact, it suffices to show that $t_2 = \frac{1}{2} \cdot \mUlp \left( x \right)$.\\ Let us still start the proof by showing that the substraction $$t_2 \gets t_1 \ominus x$$ is exact by Sterbenz' lemma \cite{Ste74}. We must therefore show that $$\frac{1}{2} \cdot x \leq x^+ \leq 2 \cdot x$$ Since $x$ is positive and since $x^+$ is its direct successor in the ordered set of the floating point numbers, we know already that $x < x^+$. So trivially, we get $$\frac{1}{2} \cdot x < x < x^+$$ Let us suppose now that $$x^+ > 2 \cdot x$$ Since $x$ is not subnormal and since it is positive, there exist $e \in \Z$ and $m \in \N$ such that $$x = 2^e \cdot m$$ with $$2^{p-1} \leq m < 2^p$$ where $p\geq 2$ is the precision of the format.\\ Further we know that $$x^+ = \left \lbrace \begin{array}{lll} 2^e \cdot \left(m + 1 \right) & \mbox{ if } & m+1 < 2^p \\ 2^{e+1} \cdot 2^{p-1} & \mbox{ otherwise} & \end{array} \right.$$ So two different cases show up: \\ ~ \\ {\bf 1st case: $x^+ = 2^e \cdot \left( m + 1 \right)$} \\ ~ \\ We have \begin{eqnarray*} x^+ & > & 2 \cdot x \\ 2^e \cdot \left( m + 1 \right) & > & 2 \cdot 2^e \cdot m \\ m+1 & > & 2 \cdot m \\ 1 & > & m \end{eqnarray*} In contrast, $m \geq 2^{p-1}$ and $p \geq 2$, thus contradiction. \\ ~ \\ {\bf 2nd case: $x^+ = 2^{e+1} \cdot 2^{p-1}$} \\ ~ \\ So in this case, we have $m+1\geq 2^p$ and therefore $m=2^p - 1$ because $m \leq 2^p - 1$ holds since $x$ is not subnormal.\\ We get thus \begin{eqnarray*} x^+ & > & 2 \cdot x \\ 2^{e+1} \cdot 2^{p-1} & > & 2 \cdot 2^e \cdot \left( 2^p - 1 \right) \\ 2^e \cdot 2^p & > & 2 \cdot 2^e \cdot 2^p - 2 \cdot 2^e \\ 2^p & > & 2 \cdot 2^p - 2 \\ 2 > 2^p \end{eqnarray*} In contrast $p\geq2$ which is contradictory.\\ So we can apply Sterbenz' lemma \cite{Ste74} and we get immediately that $$t_2 = x^+ - x = \mUlp \left( x \right)$$ by the definition of the $\mUlp$ function \\ Let us show now that $$x > 0 \mbox{ iff } t_3 > 0$$ Let us suppose that $x$ is positive. In consequence $x^+$ is its successor with regard to $<$ and we get $$x^+ - x > 0$$ which means that \begin{eqnarray*} t_2 & = & x^+ \ominus x \\ & = & \circ \left( x^+ - x \right) \\ & > & 0 \end{eqnarray*} because the rounding function is monotonic for positive numbers.\\ In contrast, if $x$ is negative $x^+$ is its predecessor with regard to $<$ and we get thus $x^+ - x < 0$. \\ We conclude in this case in the same way.\qed \end{proof} \begin{lemma}[Signs of the generated values] \label{gensigne} ~\\ Let be $x \in \F$ a non-subnormal floating point number different from $0$.\\ Given the following instruction sequence \begin{center} $t_1 \gets x^-$ \\ $t_2 \gets x \ominus t_1$ \\ $t_3 \gets t_2 \otimes \frac{1}{2}$ \\ $t_4 \gets x^+$ \\ $t_5 \gets t_4 \ominus x$ \\ $t_6 \gets t_5 \otimes \frac{1}{2}$ \end{center} the values $t_3$ and $t_6$ have the same sign. \end{lemma} \begin{proof} ~\\ It is clear that it suffices to show that $t_2$ and $t_5$ have the same sign. Because of definition \ref{predsuccdef} of $x^+$ and $x^-$, we are obliged to treat two different cases which depend on whether $x$ is positive or not.\\ ~ \\ {\bf 1st case: $x>0$} \\ ~ \\ So $x^+$ is the successor of $x$ with regard to the order $<$ on the floating point numbers and $x^-$ is its predecessor. Formally we have $$x^- < x < x^+$$ Thus \begin{eqnarray*} x - x^- & > & 0 \\ x^+ - x & > & 0 \end{eqnarray*} Due to the monotony of the rounding function, we obtain \begin{eqnarray*} \circ \left( x - x^- \right) & > & \circ \left( 0 \right) \\ \circ \left( x^+ - x \right) & > & \circ \left( 0 \right) \end{eqnarray*} and thus, since $0$ is exactly representable, \begin{eqnarray*} x \ominus x^- & > & 0 \\ x^+ \ominus x & > & 0 \end{eqnarray*} which is the fact to be shown. \\ ~ \\ {\bf 2nd case: $x<0$} \\ ~ \\ We get in this case that $x^+ < x < x^-$ and we finish the proof in a complete analogous way to the 1st case.\qed \end{proof} In the sequel, we will use the sign function $\sgn\left( x \right)$ which we define as follows: $$\forall x \in \R\mbox{ . }\sgn\left( x \right) = \left \lbrace \begin{array}{cl} -1 & \mbox{ if } x < 0 \\ 0 & \mbox{ if } x = 0 \\ 1 & \mbox{ otherwise} \end{array} \right.$$ \begin{lemma}[Equivalence between a $\xor$ and a floating point multiplication] \label{equivxormult} ~ \\ Let be $x, y \in \F$ two floating point numbers such that $x \not = 0$, $y \not = 0$. \\ So, \vspace{-5mm} \begin{center} $$x \otimes y \geq 0$$ implies $$x > 0 \xor y > 0$$ \end{center} \end{lemma} \begin{proof} ~ \\ Clearly $x \otimes y \geq 0$ implies $\circ \left( x \cdot y \right) \geq 0$. By monotony of the rounding function, this yields to $x \cdot y \geq 0$. Trivially one sees that this means that $x \geq 0 \xor y \geq 0$. Since the equations are not possible by hypothesis, we can conclude.\qed \end{proof} \begin{lemma}[Round-to-nearest-ties-to-even of the lower significance parts] \label{arrpairfaible} ~ \\ Let be $x_\mi$ and $x_\lo$ two non-subnormal floating point numbers such that $\exists e \in \Z \mbox{ . } 2^e = t$ such that $x_\mi = t^-$ and that $x_\lo = \frac{1}{4} \cdot \mUlp\left( t \right)$. \\ So, $$x_\mi \not = \circ \left( x_\mi + x_\lo \right)$$ Similar, let be $x_\mi$ and $x_\lo$ two non-subnormal floating point numbers such that $\exists e \in \Z \mbox{ . } 2^e = t$ such that $x_\mi = t^+$ and that $x_\lo = \frac{1}{2} \cdot \mUlp\left( t \right)$. \\ So, $$x_\mi \not = \circ \left( x_\mi - x_\lo \right)$$ \end{lemma} \begin{proof} ~\\ In both cases $t$ is representable as a floating point number because $x_\mi$ is not subnormal. Since $t$ is an integer power of $2$, the significand of $t$ is even. Therefore the significand of $x_\mi$ is odd in both cases because $x_\mi$ is either the direct predecessor or the direct successor of $t$. \\ Let us show now that $\left \vert x_\lo \right \vert = \frac{1}{2} \cdot \mUlp\left(x_\mi \right)$. If $x_\mi = t^-$ then we can deduce \begin{eqnarray*} \frac{1}{2} \cdot \mUlp\left( x_\mi \right) & = & \frac{1}{2} \cdot \left( x_\mi^+ - x_\mi \right) \\ & = & \frac{1}{2} \cdot \left( t - t^- \right) \\ & = & - \frac{1}{4} \cdot \left( t^+ - t \right) \\ & = & - \frac{1}{4} \cdot \mUlp\left( t \right) \\ & = & - x_\lo \end{eqnarray*} using amongst others lemma \ref{poweroftwo}. If $x_\mi = t^+$ then we know that $x_\mi$ is not an integer power of $2$ because $t$ is one and we are supposing that the format's precision $p$ is greater than $2$ bits. So it exists $e \in \Z$ and $m = 2^p$ such that $t = 2^e \cdot m$ \begin{eqnarray*} \frac{1}{2} \cdot \mUlp\left( x_\mi \right) & = & \frac{1}{2} \cdot \left( x_\mi^+ - x_\mi \right) \\ & = & \frac{1}{2} \cdot \left( 2^e \cdot \left( m + 2 \right) - 2^e \cdot \left( m + 1 \right) \right) \\ & = & \frac{1}{2} \cdot \left( 2^e \cdot \left( m + 1 \right) - 2^e \cdot m \right) \\ & = & \frac{1}{2} \cdot \mUlp\left( t \right) \\ & = & x_\lo \end{eqnarray*} So, in both cases, $x_\mi + x_\lo$ is located exactly at the middle of two floating point numbers that can be expressed with the exponent of $x_\mi$ or its successor and its predecessor. Since $x_\mi$ has an odd significand the rounding with done away from it.\qed \end{proof} \begin{algorithm}[Final rounding to the nearest (even)] \label{algarrpres} ~ \\ {\bf In:} a triple-double number $x_\hi + x_\mi + x_\lo$ \\ {\bf Out:} a double precision number $x^\prime$ returned by the algorithm \\ {\bf Preconditions on the arguments:} \begin{itemize} \item $x_\hi$ and $x_\mi$ as well as $x_\mi$ and $x_\lo$ do not overlap \item $x_\mi = \circ \left( x_\mi + x_\lo \right)$ \item $x_\hi \not = 0$, $x_\mi \not = 0$ and $x_\lo \not = 0$ \item $\circ \left( x_\hi + x_\mi \right) \not \in \left \lbrace x_\hi^-, x_\hi, x_\hi^+ \right \rbrace \Rightarrow \left \vert \left( x_\hi + x_\mi \right) - \circ\left( x_\hi + x_\mi \right) \right \vert \not = \frac{1}{2} \cdot \mUlp\left( \circ \left( x_\hi + x_\mi \right) \right)$ \end{itemize} {\bf Algorithm:} \\ \begin{center} \begin{minipage}[b]{80mm} $t_1 \gets x_\hi^-$ \\ $t_2 \gets x_\hi \ominus t_1$ \\ $t_3 \gets t_2 \otimes \frac{1}{2}$ \\ $t_4 \gets x_\hi^+$ \\ $t_5 \gets t_4 \ominus x_\hi$ \\ $t_6 \gets t_5 \otimes \frac{1}{2}$ \\ ~ \\ {\bf if} $\left( x_\mi \not = -t_3 \right)$ {\bf and} $\left( x_\mi \not = t_6 \right)$ {\bf then} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{70mm} \vspace{-2.4mm} {\bf return } $\left( x_\hi \oplus x_\mi \right)$ \end{minipage} \end{center} \vspace{-2.4mm} {\bf else} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{70mm} {\bf if} $\left( x_\mi \otimes x_\lo > 0.0 \right)$ {\bf then} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{60mm} {\bf if} $\left( x_\hi \otimes x_\lo > 0.0 \right)$ {\bf then} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{50mm} \vspace{-2.4mm} {\bf return } $x_\hi^+ $ \end{minipage} \end{center} \vspace{-2.4mm} {\bf else} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{50mm} \vspace{-2.4mm} {\bf return } $x_\hi^- $ \end{minipage} \end{center} \vspace{-2.4mm} {\bf end if} \end{minipage} \end{center} \vspace{-2.4mm} {\bf else} \vspace{-2.4mm} \begin{center} \begin{minipage}[b]{60mm} \vspace{-2.4mm} {\bf return } $x_\hi $ \end{minipage} \end{center} \vspace{-2.4mm} {\bf end if} \end{minipage} \end{center} \vspace{-2.4mm} {\bf end if} \end{minipage} \end{center} \end{algorithm} \begin{theorem}[Correctness of the final rounding procedure \ref{algarrpres}]\label{corralgpluspres} ~\\ Let be {\bf A} the algorithm \ref{algarrpres} said \ouvguill Final rounding to the nearest (even)\fermguill. Let be $x_\hi + x_\mi + x_\lo$ triple-double number for which the preconditions of algorithm {\bf A} hold. Let us notate $x^\prime$ the double precision number returned by the procedure. \\ So $$x^\prime = \circ \left( x_\hi + x_\mi + x_\lo \right)$$ i.e. {\bf A} is a correct rounding procedure for round-to-nearest-ties-to-even mode. \end{theorem} \begin{proof} ~ \\ During this proof we will proceed as follows: one easily sees that the presented procedure can only return four different results which are $x_\hi \oplus x_\mi$, $x_\hi$, $x_\hi^+$ and $x_\hi^-$. The choices made by the branches of the algorithm imply for each of this results additional hypotheses on the arguments' values. It will therefore suffice to show for each of this four choices that the rounding of the arguments is equal to the result returned under this hypotheses. In contrast, the one that can be easily deduced from the tests on the branches, which use a floating point multiplication in fact, are not particularly adapted to what is needed in the proof. Using amongst others lemma \ref{equivxormult}, one sees that $9$ different simply analysable cases are possible out of which one is a special one and $8$ have a very regular form: \begin{enumerate} \item If the first branch is taken, we know that $$x_\mi \not = \sgn\left( x_\hi \right) \cdot \frac{1}{2} \cdot \mUlp \left( x_\hi \right)$$ and that $$x_\mi \not = - \sgn\left( x_\hi \right) \cdot \left \lbrace \begin{array}{ll} \frac{1}{4} \cdot \mUlp \left( x_\hi \right) & \mbox{ if } \exists e \in \Z \mbox{ . } 2^e = x_\hi \\ \frac{1}{2} \cdot \mUlp \left( x_\hi \right) & \mbox{ otherwise} \end{array} \right.$$ as per lemmas \ref{genmiquartulp}, \ref{genmiulp} and \ref{gensigne}. In this case $x_\hi \oplus x_\mi$ will be returned. \item If the first branch is not taken, we know already very well the absolute value of $x_\mi$: we can therefore suppose that $$\left \vert x_\mi \right \vert = \left \lbrace \begin{array}{ll} \frac{1}{4} \cdot \mUlp \left( x_\hi \right) & \mbox{ if } \exists e \in \Z \mbox{ . } 2^e = x_\hi \\ \frac{1}{2} \cdot \mUlp \left( x_\hi \right) & \mbox{ otherwise} \end{array} \right.$$ It is thus natural that $x_\mi$ does not play any role in the following computations of the value to be returned but by its sign. Using \ref{equivxormult} we know that the two tests that follow are equivalent to {{\bf if} $x_\mi > 0 \xor x_\lo > 0$} and to {{\bf if} $x_\hi > 0 \xor x_\lo > 0$}. It is easy to check that the values returned depending on the signs of $x_\hi$, $x_\mi$ and $x_\lo$ obey to this scheme: \begin{center} \begin{tabular}{l|ccc|cc|c|c} Case & $x_\hi$ & $x_\mi$ & $x_\lo$ & $x_\mi \xor x_\lo$ & $x_\hi \xor x_\lo$ & Return val. $x^\prime$ & Interpreted val. $x^\prime$ \\ \hline a.) & + & + & + & + & + & $x_\hi^+$ & $\succ\left( x_\hi \right)$ \\ b.) & + & + & - & - & - & $x_\hi$ & $x_\hi$ \\ c.) & + & - & + & - & + & $x_\hi$ & $x_\hi$ \\ d.) & + & - & - & + & - & $x_\hi^-$ & $\pred\left( x_\hi \right)$ \\ e.) & - & + & + & + & - & $x_\hi^-$ & $\succ\left( x_\hi \right)$ \\ f.) & - & + & - & - & + & $x_\hi$ & $x_\hi$ \\ g.) & - & - & + & - & - & $x_\hi$ & $x_\hi$ \\ h.) & - & - & - & + & + & $x_\hi^+$ & $\pred\left( x_\hi \right)$ \end{tabular} \end{center} We see now that the returned value $x^\prime$ expressed as $x_\hi$, $\succ\left(x_\hi\right)$ or $\pred\left(x_\hi\right)$ in cases a.) through d.) are equivalent to cases h.) through e.). We will consider them thus equivalently; of course, doing so, we will not any longer be able to suppose anything concerning the magnitude and the sign of $x_\hi$. \end{enumerate} Let us start the proof by showing the correctness of the first case. Since $x_\hi$ and $x_\mi$ do not overlap by hypothesis, we know by definition \ref{defoverlap} that $$\left \vert x_\mi \right \vert < \mUlp\left( x_\hi \right)$$ So we can notate the following $$x_\mi \in I^\prime_1 \cup I^\prime_2 \cup I^\prime_3 \cup I^\prime_4 \cup I^\prime_5 \cup I^\prime_6$$ with \begin{eqnarray*} I^\prime_1 & = & \left] - \mUlp\left( x_\hi \right) ; -\frac{3}{4} \cdot \mUlp\left(x_\hi \right) \right] \\ I^\prime_2 & = & \left] -\frac{3}{4} \cdot \mUlp\left(x_\hi \right) ; - \frac{1}{2} \cdot \mUlp\left(x_\hi \right) \right[ \\ I^\prime_3 & = & \left[ - \frac{1}{2} \cdot \mUlp\left(x_\hi \right); -\tau \right[ \\ I^\prime_4 & = & \left] -\tau ; 0 \right] \\ I^\prime_5 & = & \left[ 0; \frac{1}{2} \cdot \mUlp\left(x_\hi\right) \right[ \\ I^\prime_6 & = & \left ] \frac{1}{2} \cdot \mUlp\left( x_\hi \right) ; \mUlp\left( x_\hi \right) \right [ \end{eqnarray*} where $$\tau = \left \lbrace \begin{array}{ll} \frac{1}{4} \cdot \mUlp \left( x_\hi \right) & \mbox{ if } \exists e \in \Z \mbox{ . } 2^e = x_\hi \\ \frac{1}{2} \cdot \mUlp \left( x_\hi \right) & \mbox{ otherwise} \end{array} \right.$$ This is equivalent to claiming $$x_\mi \in I_1 \cup I_2 \cup I_3 \cup I_4 \cup I_5 \cup I_6$$ where \begin{eqnarray*} I_1 & = & \left [ \left( -\mUlp\left( x_\hi \right) \right)^- ; \left( -\frac{3}{4} \cdot \mUlp\left(x_\hi \right) \right)^+ \right] \\ I_2 & = & \left [ \left( \frac{3}{4} \cdot \mUlp\left( x_\hi \right) \right)^- ; \left(- \frac{1}{2} \cdot \mUlp\left(x_\hi \right)\right)^+ \right] \\ I_3 & = & \left [ \left( -\frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^- ; \left( -\tau \right)^+ \right] \\ I_4 & = & \left [ \left( -\tau \right)^- ; 0 \right] \\ I_5 & = & \left [ 0 ; \left( \frac{1}{2} \cdot \mUlp\left(x_\hi\right) \right)^- \right] \\ I_6 & = & \left [ \left(\frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^+ ; \left( \mUlp\left( x_\hi \right) \right)^- \right ] \end{eqnarray*} because $x_\mi$ is a floating point number and because all bounds of the intervals are floating point numbers, too. So we can express their predecessors and successors by $z^+$ and $z^-$. Thus $\forall i=1,\dots,6 \mbox{ . } I^\prime_i = I_i$. It is clear that the set of floating point numbers $I_3$ is empty if $\tau = \frac{1}{2} \cdot \mUlp\left( x_\hi \right)$.\\ Further we know that $x_\mi$ and $x_\lo$ do not overlap and that $x_\mi = \circ \left( x_\mi + x_\lo \right)$ by hypothesis. This means that $$\left \vert x_\lo \right \vert \leq \frac{1}{2} \cdot \mUlp \left( x_\mi \right) \leq \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right)$$ and we can write $$x_\mi + x_\lo \in \left( J_1 \cup J_2 \cup J_3 \cup J_4 \cup J_5 \cup J_6\right) \backslash U$$ with \begin{eqnarray*} J_1 & = & \left [ \left( -\mUlp\left( x_\hi \right) \right)^- - \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right) ; \left( - \frac{3}{4} \cdot \mUlp\left( x_\hi \right) \right)^+ + \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) \right] \\ J_2 & = & \left[ \left( - \frac{3}{4} \cdot \mUlp\left( x_\hi \right) \right)^- - \frac{1}{2} \cdot \mUlp \left( \mUlp\left( x_\hi \right) \right) ; \left(-\frac{1}{2} \cdot \mUlp\left(x_\hi \right)\right)^+ + \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right) \right] \\ J_3 & = & \left [ \left(- \frac{1}{2} \cdot \mUlp\left(x_\hi \right)\right)^- - \frac{1}{2} \cdot \mUlp\left( \xi_1 \right) ; \left( -\tau \right)^+ + \frac{1}{2} \cdot \mUlp\left( \xi_1 \right) \right] \\ J_4 & = & \left [ \left( -\tau \right)^- - \frac{1}{2} \cdot \mUlp\left( \xi_2 \right) ; 0 \right] \\ J_5 & = & \left [ 0; \left( \frac{1}{2} \cdot \mUlp\left(x_\hi\right) \right)^- + \frac{1}{2} \cdot \mUlp\left( \xi_3 \right) \right] \\ J_6 & = & \left [ \left(\frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^+ - \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right); \left( \mUlp\left( x_\hi \right) \right)^- + \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right) \right ] \end{eqnarray*} where \begin{eqnarray*} \xi_1 & = & \frac{1}{2} \cdot \mUlp\left(x_\hi\right) \in I_3 \\ \xi_2 & = & \tau \in I_4 \\ \xi_3 & = & \frac{1}{2} \cdot \mUlp\left(x_\hi\right) \in I_5 \end{eqnarray*} and where $U$ is the set of the impossible cases for $x_\mi + x_\lo$. The word \ouvguill impossible\fermguill~ refers here to the facts caused by the property that $x_\mi = \circ \left( x_\mi + x_\lo \right)$. \\ Let us still remark that the intervals $J_3$, $J_4$ and $J_5$ are well defined as per lemma \ref{ulpmonoton} and that it is important to see that it does not suffice to estimate their bounds by the less exact inequality that follows: $$\mUlp \left( x_\mi \right) \leq \mUlp\left( \mUlp \left( x_\hi \right) \right)$$ which would mean that $$\xi_i = \mUlp\left( x_\hi \right)$$ Since the images of the $\mUlp$ function are always integer powers of $2$, the difference of their predecessors and themselves can be as small as half an $\mUlp$ of an $\mUlp$ of $x_\hi$ which would be a too inexact estimate. \\ Let us continue now with the simplification of the bounds of the intervals $J_i$. The purpose of this will be showing that $x_\mi + x_\lo$ are always intervals such that one can decide the rounding $\circ \left( x_\hi + \left( x_\mi + x_\lo \right) \right)$ without using the rule of even rounding. Let us remark already that we know that $\forall i=1,\dots,6 \mbox{ . } I_i \subseteq J_i$.\\ Since $\mUlp\left( x_\hi \right)$ is a non-subnormal floating point number that is positive and equal to an integer power of $2$, we get using lemmas \ref{commut} and \ref{poweroftwo} that \begin{eqnarray*} \left( - \mUlp\left( x_\hi \right) \right)^- - \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) & = & - \mUlp\left( x_\hi \right)^- - \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & - \mUlp\left( x_\hi \right) + \left( \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi \right)^- \right) \\ & & - \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & - \mUlp\left( x_\hi \right) \end{eqnarray*} and similarly \begin{eqnarray*} \mUlp\left( x_\hi \right)^- + \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) & = & \mUlp\left( x_\hi \right)^- + \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & \mUlp\left( x_\hi \right)^- + \left( \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi \right)^- \right) \\ & = & \mUlp\left( x_\hi \right) \end{eqnarray*} Further, still analogously to the previous cases and using lemma \ref{multhalf}, \begin{eqnarray*} \left( \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^- + \frac{1}{2} \cdot \mUlp\left( \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right) & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right)^- + \frac{1}{4} \mUlp\left( \mUlp\left( x_\hi \right) \right) \\ & = & \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^- + \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \right) \\ & = & \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^- + \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi \right)^- \right) \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} and \begin{eqnarray*} \left( \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^+ - \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right)^+ - \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} Then \begin{eqnarray*} \left( - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^- - \frac{1}{2} \cdot \mUlp\left( \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right) & = & - \frac{1}{2} \cdot \mUlp\left( x_\hi \right)^- - \frac{1}{4} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & \frac{1}{2} \cdot \left( - \mUlp\left( x_\hi \right)^- - \left( \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi \right)^- \right) \right) \\ & = & - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} further, using also lemma \ref{succtroisfoispuissdeux}, \begin{eqnarray*} \left( - \frac{3}{4} \cdot \mUlp\left( x_\hi \right) \right)^+ + \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) & = & - \frac{1}{4} \cdot \left( 3 \cdot \mUlp\left( x_\hi \right) \right)^+ + \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) \\ & = & - \frac{1}{4} \cdot \left( 3 \cdot \mUlp\left( x_\hi \right)^+ - \mUlp\left( \mUlp\left( x_\hi \right)\right)\right) \\ & & + \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) \\ & = & - \frac{3}{4} \cdot \mUlp\left( x_\hi \right)^+ + \frac{3}{4} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) \\ & = & \frac{3}{4}\cdot\left( \mUlp\left( x_\hi \right)^+ -\mUlp\left( x_\hi\right) -\mUlp\left( x_\hi \right)^+ \right) \\ & = & -\frac{3}{4} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} and, still with the same lemmas, \begin{eqnarray*} \left( - \frac{3}{4} \cdot \mUlp\left( x_\hi \right) \right)^- - \frac{1}{2} \cdot \mUlp \left( \mUlp\left( x_\hi \right) \right) & = & \frac{1}{4} \left( - 3 \mUlp\left( x_\hi \right) \right)^- - \frac{1}{2} \mUlp\left( \mUlp\left( x_\hi \right) \right) \\ & = & \frac{1}{4} \cdot \left( 3 \cdot \mUlp\left( x_\hi \right) - \left( 3 \cdot \mUlp\left( x_\hi \right) \right)^- - 3 \cdot \mUlp\left( x_\hi \right) \right) \\ & & - \frac{1}{2} \cdot \mUlp \left( \mUlp \left( x_\hi \right) \right) \\ & = & \frac{1}{4} \cdot \left( \left( 3 \cdot \mUlp\left( x_\hi \right) \right)^+ - 6 \cdot \mUlp\left( x_\hi \right) \right) - \frac{1}{2} \cdot \mUlp \left( \mUlp \left( x_\hi \right) \right) \\ & = & \frac{1}{4} \cdot \left( 3 \cdot \mUlp\left( x_\hi \right) \right)^+ - \frac{3}{2} \cdot \mUlp\left( x_\hi \right) - \frac{1}{2} \cdot \mUlp \left( \mUlp \left( x_\hi \right) \right) \\ & = & \frac{1}{4} \cdot \left( 3 \cdot \mUlp\left( x_\hi \right)^+ - \mUlp\left(\mUlp\left(x_\hi\right)\right) \right)\\ & & - \frac{3}{2} \cdot \mUlp\left( x_\hi \right) - \frac{1}{2} \cdot \mUlp \left( \mUlp\left( x_\hi \right) \right) \\ & = & \frac{3}{4} \cdot \left( \mUlp\left( x_\hi \right)^+ - 2 \cdot \mUlp\left( x_\hi \right) - \mUlp\left( \mUlp \left( x_\hi \right) \right) \right) \\ & = & \frac{3}{4} \cdot \left( \mUlp\left( x_\hi \right)^+ - 2 \cdot \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi\right)^+ + \mUlp\left( x_\hi \right) \right) \\ & = & - \frac{3}{4} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} and finally \begin{eqnarray*} \left( - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^+ + \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) & = & \frac{1}{2} \cdot \left( - \mUlp\left( x_\hi \right)^+ + \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} For each bound that depends on $\tau$ we are obliged to treat two different cases.\\ Let us suppose first that $$\tau = \frac{1}{4} \cdot \mUlp \left( x_\hi \right) $$ So we get \begin{eqnarray*} \left( - \frac{1}{4} \cdot \mUlp\left( x_\hi \right) \right)^- - \frac{1}{2} \cdot \mUlp\left( \frac{1}{4} \cdot \mUlp\left( x_\hi \right) \right) & = & \frac{1}{4} \cdot \left( - \mUlp\left( x_\hi \right)^- - \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \right) \\ & = & \frac{1}{4} \cdot \left( - \mUlp\left( x_\hi \right)^- - \left( \mUlp\left( x_\hi \right)^- - \mUlp\left( x_\hi \right) \right) \right) \\ & = & \frac{1}{4} \cdot \left( - \mUlp\left( x_\hi \right)^- - \mUlp\left( x_\hi \right)^- + \mUlp\left( x_\hi \right) \right) \\ & = & \frac{1}{4} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} and \begin{eqnarray*} \left( - \frac{1}{4} \cdot \mUlp\left( x_\hi \right) \right)^+ + \frac{1}{2} \cdot \mUlp\left( \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right) & = & \frac{1}{4} \cdot \left( - \mUlp\left( x_\hi \right)^+ + \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & - \frac{1}{4} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} Let us suppose now $$\tau = \frac{1}{2} \cdot \mUlp \left( x_\hi \right) $$ We get thus \begin{eqnarray*} \left( - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^- - \frac{1}{2} \cdot \mUlp\left( \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right) & = & \frac{1}{2} \cdot \left( - \mUlp\left( x_\hi \right)^- - \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \right) \\ & = & \frac{1}{2} \cdot \left( - \mUlp\left( x_\hi \right)^- - \left( \mUlp\left( x_\hi \right)^- - \mUlp\left( x_\hi \right) \right) \right) \\ & = & \frac{1}{2} \cdot \left( - \mUlp\left( x_\hi \right)^- - \mUlp\left( x_\hi \right)^- + \mUlp\left( x_\hi \right) \right) \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} and \begin{eqnarray*} \left( - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^+ + \frac{1}{2} \cdot \mUlp\left( \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right) & = & \left(- \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^+ + \frac{1}{4} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) \\ & \leq & \left(- \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right)^+ + \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) \\ & = & -\frac{1}{2} \cdot \mUlp\left( x_\hi \right) \end{eqnarray*} Finally, for all cases, we observe the following intervals: $$x_\mi + x_\lo \in \left( J_1 \cup J_2 \cup J_3 \cup J_4 \cup J_5 \cup J_6 \right) \backslash U$$ with \begin{eqnarray*} J_1 & = & \left[ - \mUlp\left( x_\hi \right) ; - \frac{3}{4} \cdot \mUlp\left( x_\hi \right) \right] \\ J_2 & = & \left[ - \frac{3}{4} \cdot \mUlp\left( x_\hi \right) ; - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right] \\ J_3 & = & \left[ - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) ; - \tau \right] \\ J_4 & = & \left[ - \tau ; 0 \right] \\ J_5 & = & \left[ 0 ; \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right] \\ J_6 & = & \left[ \frac{1}{2} \cdot \mUlp\left( x_\hi \right) ; \mUlp\left( x_\hi \right) \right] \end{eqnarray*} Let us now consider more precisely the set $U$ if impossible cases due to the property that $x_\mi = \circ \left( x_\mi + x_\lo \right)$ and due to the fact that $x_\lo \not = 0$: \\ Let us show that $\frac{1}{2} \cdot \mUlp\left( x_\hi \right) \in U$, i.e. $$x_\mi + x_\lo \not = \frac{1}{2} \cdot \mUlp\left( x_\hi \right)$$ Let us suppose that this would not be the case. We would get $$x_\mi + x_\lo = \frac{1}{2} \cdot \mUlp\left( x_\hi \right)$$ As $x_\mi \not = \frac{1}{2} \cdot \mUlp\left( x_\hi \right)$ as per hypothesis in this branch of the algorithm and because $x_\lo \not = 0$, there must exist a number $\mu \in \R \backslash \left \lbrace 0 \right \rbrace$ such that $x_\mi = \frac{1}{2} \cdot \mUlp\left( x_\hi \right) + \mu$ and that $x_\lo = -\mu$. \\ Since $x_\lo = \mu$ must hold, $\mu$ must be a floating point number. Further $$\left \vert \mu \right \vert = \left \vert x_\lo \right \vert \leq \frac{1}{2} \cdot \mUlp\left( x_\mi \right)$$ must be justified. So there exist two floating point numbers $\frac{1}{2} \cdot \mUlp\left( x_\hi \right)$ and $x_\mi$ such that their difference verifies \begin{eqnarray*} \left \vert x_\mi - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right \vert & = & \left \vert \frac{1}{2} \cdot \mUlp\left( x_\hi \right) + \mu - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right \vert \\ & = & \left \vert \mu \right \vert \\ & \leq & \frac{1}{2} \cdot \mUlp\left( x_\mi \right) \end{eqnarray*} which is possible only if $x_\mi$ is exactly an integer power of $2$. In contrast, as $\frac{1}{2} \cdot \mUlp\left( x_\hi \right)$ is the only one in the interval that is possible for $x_\mi$, which is by the way $\left] \frac{1}{4} \cdot \mUlp\left( x_\hi \right) ; \mUlp\left( x_\hi \right) \right[$, we obtain a contradiction. \\ Using a completely analogous argument, one sees further that $$-\tau \in U$$ Clearly $0 \in U$ because $x_\lo \not = 0$ and it is less in magnitude than $x_\mi$. \\ Let us show finally that $-\mUlp\left( x_\hi \right) \in U$ and that $\mUlp\left( x_\hi \right) \in U$.\\ Let us suppose that we would have $$\left \vert x_\mi + x_\lo \right \vert = \mUlp\left( x_\hi \right)$$ In contrast we know that $\left \vert x_\mi \right \vert < \mUlp\left( x_\hi \right)$. Since $x_\mi$ is a floating point number, this means that $$\left \vert x_\mi \right \vert \leq \mUlp\left( x_\hi \right)^-$$ which yields to \begin{eqnarray*} \left \vert x_\lo \right \vert & \geq & \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi \right)^- \\ & = & \frac{1}{2} \cdot \left( \mUlp\left(x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & \frac{1}{2} \cdot \mUlp \left( \mUlp \left( x_\hi \right) \right) \end{eqnarray*} Further we know that $\left \vert x_\mi \right \vert \leq \mUlp\left( x_\hi \right)^-$ and that $\left \vert x_\lo \right \vert \leq \frac{1}{2} \cdot \mUlp\left( x_\mi \right)$. So we can check that \begin{eqnarray*} \left \vert x_\lo \right \vert & \leq & \frac{1}{2} \cdot \mUlp\left( x_\mi \right) \\ & = & \frac{1}{2} \cdot \left( \left( \mUlp\left( x_\hi \right)^- \right)^+ - \mUlp\left( x_\hi \right)^+ \right) \\ & = & \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi \right)^- \right) \\ & = & \frac{1}{4} \cdot \mUlp \left( \mUlp \left( x_\hi \right) \right) \end{eqnarray*} We have thus obtained a contradiction to the hypothesis that says that $-\mUlp\left( x_\hi \right) \not \in U$ and that $\mUlp\left( x_\hi \right) \not \in U$. \\ Let us still show that in the case where $x_\hi$ is an integer power of $2$, i.e. $\exists e \in \Z \mbox{ . } x_\hi = 2^e$, $-\frac{3}{4} \cdot \mUlp\left( x_\hi \right) \in U$. Since $x_\lo \not = 0$, using a similar argument as the one given above, the problem can be reduced to showing that $x_\mi = - \frac{3}{4} \cdot \mUlp \left( x_\hi \right)$ is impossible if $x_\hi$ is an integer power of $2$. Let us suppose the contrary. Since $x_\hi$ is an integer power of $2$, its significand is even. In consequence the significand of $x_\hi^-$ is odd and the one of $x_\hi^{--}$ is again even. So $\circ\left( x_\hi + x_\mi \right) = x_\hi^{--}$ because $x_\hi + x_\mi$ is at the exact middle between $x_\hi^{--}$ and $x_\hi^{-}$ and the significand of $x_\hi^{--}$ is even. It follows that $\left( x_\hi + x_\mi \right) - \circ\left( x_\hi + x_\mi \right) = \frac{1}{2} \cdot \mUlp \left( \circ\left( x_\hi + x_\mi \right) \right)$ which is impossible as per hypothesis. \par Having shown which numbers are in $U$, we can rewrite our intervals as follows $$x_\mi + x_\lo \in J^\prime_1 \cup J^\prime_2 \cup J^\prime_3 \cup J^\prime_4 \cup J^\prime_5 \cup J^\prime_6$$ with \begin{eqnarray*} J^\prime_1 & = & \left] - \mUlp\left( x_\hi \right) ; - \frac{3}{4} \cdot \mUlp\left( x_\hi \right) \right] \\ J^\prime_2 & = & \left] - \frac{3}{4} \cdot \mUlp\left( x_\hi \right) ; - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right[ \\ J^\prime_3 & = & \left] - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) ; - \tau \right[ \\ J^\prime_4 & = & \left] - \tau ; 0 \right] \\ J^\prime_5 & = & \left[ 0 ; \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \right[ \\ J^\prime_6 & = & \left] \frac{1}{2} \cdot \mUlp\left( x_\hi \right) ; \mUlp\left( x_\hi \right) \right[ \end{eqnarray*} One can trivially check that the rounding $\circ \left( x_\hi + \left( x_\mi + x_\lo \right) \right)$ can be decided without using the rule for even rounding. In particular the cases present themselves as follows \cite{IEEE754}: $$\circ \left( x_\hi + \left( x_\mi + x_\lo\right) \right) = \left \lbrace \begin{array}{ll} x_\hi^{--} & \mbox{ if } x_\mi + x_\lo \in J^\prime_1 \land \exists e \in \Z \mbox{ . } 2^e = x_\hi \\ x_\hi^- & \mbox{ if } x_\mi + x_\lo \in J^\prime_1 \land \lnot \exists e \in \Z \mbox{ . } 2^e = x_\hi \\ x_\hi^- & \mbox{ if } x_\mi + x_\lo \in J^\prime_2\\ x_\hi^- & \mbox{ if } x_\mi + x_\lo \in J^\prime_3\\ x_\hi & \mbox{ if } x_\mi + x_\lo \in J^\prime_4 \\ x_\hi & \mbox{ if } x_\mi + x_\lo \in J^\prime_5\\ x_\hi^+ & \mbox{ if } x_\mi + x_\lo \in J^\prime_6\\ \end{array} \right.$$ which can be compared to $$\circ \left( x_\hi + x_\mi \right) = \left \lbrace \begin{array}{ll} x_\hi^{--} & \mbox{ if } x_\mi \in I^\prime_1 \land \exists e \in \Z \mbox{ . } 2^e = x_\hi \\ x_\hi^- & \mbox{ if } x_\mi \in I^\prime_1 \land \lnot \exists e \in \Z \mbox{ . } 2^e = x_\hi \\ x_\hi^- & \mbox{ if } x_\mi \in I^\prime_2\\ x_\hi^- & \mbox{ if } x_\mi \in I^\prime_3\\ x_\hi & \mbox{ if } x_\mi \in I^\prime_4 \\ x_\hi & \mbox{ if } x_\mi \in I^\prime_5\\ x_\hi^+ & \mbox{ if } x_\mi \in I^\prime_6\\ \end{array} \right.$$ Additionally we check that $$\forall i=1, \dots ,6 \mbox{ . } J^\prime_i \subseteq I^\prime_i$$ We would therefore get an immediate contradiction if we supposed that $$\circ \left( x_\hi + \left( x_\mi + x_\lo \right) \right) \not = \circ \left( x_\hi + x_\mi \right)$$ This finishes the proof for the first case.\\ ~ \\ Let us consider now subcases a.) through d.) of the second main case of the proof. We have already shown that the subcases h.) through e.) are equal to the first ones. Without loss of generality we will only analyse the case where $x_\hi > 0$. The set of the floating point numbers as well as the rounding function $\circ \left( \hat{x} \right)$ are symmetrical around $0$. We can therefore suppose that $$x_\mi = - \left \lbrace \begin{array}{ll} \frac{1}{4} \cdot \mUlp\left(x_\hi \right) & \mbox{if } \exists e \in \Z \mbox{ . } 2^e = x_\hi \\ \frac{1}{2} \cdot \mUlp\left(x_\hi \right) & \mbox{otherwise} \end{array} \right.$$ or that $$x_\mi = \frac{1}{2} \cdot \mUlp\left(x_\hi \right)$$ depending on whether $x_\mi$ is negative or positive.\\ It is clear that one can suppose that $$\left \vert x_\mi + x_\lo \right \vert < \mUlp\left( x_\hi \right)$$ because otherwise we would have $\left \vert x_\lo \right \vert \geq \frac{1}{2} \cdot \mUlp\left( x_\hi \right)$ whilst $\left \vert x_\lo \right \vert \leq 2^{-53} \cdot \mUlp\left( x_\hi \right)$.\\ Let us treat now the four cases one after another: { \renewcommand{\labelenumi}{\alph{enumi}.)} \begin{enumerate} \item We can suppose in this case that $x_\mi > 0$ and that $x_\lo > 0$: \\ So $$\mUlp\left( x_\hi \right) > x_\mi + x_\lo > \frac{1}{2} \cdot \mUlp\left(x_\hi \right)$$ Thus since the inequalities are strict $$\circ \left( x_\hi + \left( x_\mi + x_\lo \right) \right) = x_\hi^+ = \succ\left( x_\hi \right)$$ which is the number returned by the algorithm. \item We have here $x_\mi > 0$ and $x_\lo < 0$: \\ So the same way, we know that $$x_\mi + x_\lo < \frac{1}{2} \cdot \mUlp\left(x_\hi \right)$$ Additionally, we know that $x_\lo \geq -2^{-53} \cdot \mUlp\left(x_\hi \right) > -\frac{1}{4} \cdot \mUlp\left( x_\hi \right)$. This yields thus to $$\circ \left( x_\hi + \left( x_\mi + x_\lo \right) \right) = x_\hi$$ The correctness of the algorithm is therefore verified also in this case. \item In this case one knows that $x_\mi < 0$ and $x_\lo > 0$. In consequence $$x_\mi = - \tau$$ with $$\tau = \left \lbrace \begin{array}{ll} \frac{1}{4} \cdot \mUlp\left(x_\hi \right) & \mbox{if } \exists e \in \Z \mbox{ . } 2^e = x_\hi \\ \frac{1}{2} \cdot \mUlp\left(x_\hi \right) & \mbox{otherwise} \end{array} \right.$$ Thus we get $$\frac{1}{4} \cdot \mUlp\left( x_\hi \right) > 2^{-53} \cdot \mUlp \left( x_\hi \right) > x_\mi + x_\lo > -\tau$$ mentioning analogous arguments as the ones given above. This yields to $$\circ \left( x_\hi + \left( x_\mi + x_\lo \right) \right) = x_\hi$$ which is the number returned by the algorithm. \item Finally if $x_\mi < 0$ and $x_\lo < 0$ one checks that $$-2 \cdot \tau < x_\mi + x_\lo < -\tau$$ The lower bound given for $x_\mi + x_\lo$ can be explained as follows. If $\tau = \frac{1}{2} \cdot \mUlp\left( x_\hi \right)$, it trivially holds due to the bound: $$\left \vert x_\mi + x_\lo \right \vert < \mUlp\left( x_\hi \right)$$ We have already indicated this bound. Otherwise we know that $\tau = \frac{1}{4} \cdot \mUlp\left( x_\hi \right)$ and that $x_\mi = -\tau$. Since $\left \vert x_\lo \right \vert \leq 2^{-53} \cdot \left \vert x_\mi \right \vert$, one gets $$x_\mi + x_\lo > - \left( \frac{1}{4} + 2^{-55} \right) \cdot \mUlp\left( x_\hi \right) > -2 \cdot \tau$$ Thus the bounds obtained for $x_\mi + x_\lo$ imply always that $$\circ \left( x_\hi + \left( x_\mi + x_\lo \right) \right) = x_\hi^- = \pred\left( x_\hi \right)$$ Thus in this subcase, too, and therefore in all cases, the algorithm returns a floating point number $x^\prime$ which is equal to $\circ \left( x_\hi + x_\mi + x_\lo \right)$. \end{enumerate} } By this final statement we have finished the proof.\qed \end{proof} \subsection{Final rounding for the directed modes} As we have already mentioned, the three directed rounding modes behave all in a similar fashion. On the one hand we have $$\forall \hat{x} \in \R \mbox{ . } \diamond \left( \hat{x} \right) = \left \lbrace \begin{array}{ll} \triangledown \left( \hat{x} \right) & \mbox{ if } \hat{x} < 0 \\ \vartriangle \left( \hat{x} \right) & \mbox{ otherwise} \end{array} \right. $$ On the other hand, one can check that $$\forall \hat{x} \in \R \mbox{ . } \vartriangle \left( \hat{x} \right) = - \triangledown \left( - \hat{x} \right)$$ The given equations are also verified on the set of the floating point numbers $\F$ \cite{Defour-thesis, IEEE754}. We will therefore refrain from treating each directed rounding mode separately but we will consider them all in common. So slightly deriving from our notations, we will notate $\diamond$ the rounding function of all possible three directed rounding modes.\par Further we suppose that we dispose of a correct rounding procedure for each directed rounding mode capable of rounding a double number $x_\hi + x_\lo$. This procedure will return in fact $\diamond \left( x_\hi + x_\lo \right)$ \cite{crlibmweb, Defour-thesis}. For constructing a correct rounding procedure for triple-double precision, we will try to give a reduction procedure for reducing a triple-double number into a double-double number such that the directed rounding of both triple-double and double-double numbers be equal. \begin{lemma}[Directed rounding decision] \label{decarrdir} ~ \\ Let be $x \in \F$ a floating point number. \\ Let be $\mu, \nu \in \R$ two real numbers such that $\left \vert \mu \right \vert < \mUlp\left( x \right)$ and $\left \vert \nu \right \vert < \mUlp\left( x \right)$ and that $$\sgn\left( \mu \right) = \sgn\left( \nu \right)$$ So the following equation holds $$\diamond \left( x + \mu \right) = \diamond\left( x + \nu \right)$$ \end{lemma} \begin{proof} ~ \\ We know by definition of the rounding mode, e.g. by the one of rounding $\vartriangle$ towards $+\infty$ that $$\forall y \in \F, \mu \in \R, \left \vert \mu \right \vert < \mUlp\left( y \right) \mbox{ . } \vartriangle \left( y + \rho \right) = \left \lbrace \begin{array}{ll} \succ\left(y\right) & \mbox{ if } \rho > 0 \\ y & \mbox{ otherwise} \end{array} \right. $$ In fact, the rounding result $\vartriangle\left( y + \rho \right)$ is the smallest floating point number greater or equal to $y + \rho$. \\ Since $x$ is a floating point number and as $\pred\left( x \right) < x + \mu < \succ\left( x \right)$ and $\pred\left( x \right) < x + \mu < \succ\left( x \right)$ because $\left \vert \mu \right \vert < \mUlp\left( x \right)$ and $\left \vert \mu \right \vert < \mUlp\left( x \right)$, supposing that $\diamond \left( x + \mu \right) \not = \diamond \left( x + \nu \right)$ would yield to an immediate contradiction.\qed \end{proof} \begin{lemma}[Disturbed directed rounding] \label{arrdirper} ~ \\ Let be $\hat{x} \in \R$ a real number and $x = \circ\left( \hat{x} \right) \in \F$ the (even) floating point number nearest to $\hat{x}$. Let be $\xi\left(\hat{x}\right) = \hat{x} - x$. \\ Let be $\delta \in \R$ such that $$\left \vert \delta \right \vert < \left \vert \xi\left(\hat{x}\right) \right \vert$$ So the following equation holds $$\diamond \left( \hat{x} \right) = \diamond \left( \hat{x} + \delta \right)$$ \end{lemma} Let us remark still that the inequality in hypothesis -- $\left \vert \delta \right \vert < \left \vert \xi\left( \hat{x} \right) \right \vert$ -- must be assured to be strict. \begin{proof} ~ \\ We know already that $$\diamond \left( \hat{x} + \delta \right) = \diamond \left( x + \xi\left( \hat{x} \right) + \delta \right)$$ Let us show now that $\xi\left( \hat{x} \right)$ and $\xi\left( \hat{x} \right) + \delta$ have the same sign. Let us therefore suppose that this would not be the case. Without loss of generality, it suffices to consider the case where $\xi\left( \hat{x} \right)$ is positive; the inverse case can be treated completely analogously. \\ Thus $$\xi\left( \hat{x} \right) \geq 0$$ and $$\xi\left( \hat{x} \right) + \delta < 0$$ In consequence $$\xi\left( \hat{x} \right) < - \delta$$ On the other hand $$\left \vert \delta \right \vert < \left \vert \xi\left( \hat{x} \right) \right \vert$$ Thus $$0 \leq \xi\left( \hat{x} \right) < \xi\left( \hat{x} \right)$$ which yields to $$\xi\left( \hat{x} \right) = 0$$ In this case we know that $$\delta = 0$$ as per the hypotheses of the theorem. Thus contradiction and we know that $\xi\left( \hat{x} \right)$ and $\xi\left( \hat{x} \right) + \delta$ have really the same sign.\\ It is clear that $\xi\left( \hat{x} \right) \leq \frac{1}{2} \cdot \mUlp\left( x \right)$ because the rounding of $\hat{x}$ towards $x$ is done to the nearest floating point number. In consequence, since $\delta < \xi\left( \hat{x} \right)$ we obtain $$\xi\left( \hat{x} \right) + \delta < \mUlp\left( x \right)$$ As $x$ is a floating point number it suffices thus to conclude using lemma \ref{decarrdir} by putting $\mu = \xi\left( \hat{x} \right)$ and $\nu = \xi\left( \hat{x} \right) + \delta$.\qed \end{proof} \begin{lemma}[Reduction of a triple-double into a double-double -- simple case] \label{moinsquunmiulp} ~ \\ Let be $x_\hi + x_\mi + x_\lo \in \F + \F + \F$ a non-overlapping triple-double number such that $x_\lo$ is not subnormal, such that $x_\mi = \circ \left( x_\mi + x_\lo \right)$ and such that $\left \vert x_\mi \right \vert < \tau$ where $$\tau = \left \lbrace \begin{array}{ll} \frac{1}{4} \cdot \mUlp\left( x_\hi \right) & \mbox{ if } \exists e \in \Z \mbox{ . } 2^e = \left \vert x_\hi \right \vert \land \sgn\left( x_\mi \right) = -\sgn\left( x_\hi \right)\\ \frac{1}{2} \cdot \mUlp\left( x_\hi \right) & \mbox{ otherwise} \end{array} \right.$$ Given the instruction sequence below: \begin{center} \begin{minipage}[b]{50mm} $\left( t_1, t_2 \right) \gets \mAdd\left( x_\hi, x_\mi \right)$ \\ $t_3 \gets t_2 \oplus x_\lo$ \end{minipage} \end{center} the following equation holds after the execution of the sequence $$\diamond\left( t_1 + t_3 \right) = \diamond\left( x_\hi + x_\mi + x_\lo \right)$$ \end{lemma} \begin{proof} ~ \\ Due to the hypothesis that $\left \vert x_\mi \right \vert < \tau$ we can suppose that $x_\hi = \circ \left( x_\hi + x_\mi \right)$. In consequence, using the properties of the \Add~ procedure, we know that we have exactly $$t_1 = \circ \left( x_\hi + x_\mi \right) = x_\hi$$ and $$t_2 = x_\hi + x_\mi - t_1 = x_\mi$$ So since as per hypothesis we have $x_\mi = \circ \left( x_\mi + x_\lo \right)$, we know also that $t_3$ verifies exactly $$t_3 = x_\mi \oplus x_\lo = \circ\left( x_\mi + x_\lo \right) = x_\mi$$ Let us put now $$\delta = x_\lo$$ and $$\hat{x} = t_1 + t_3$$ Clearly we get \begin{eqnarray*} \xi\left( \hat{x} \right) & = & \hat{x} - \circ\left( \hat{x} \right) \\ & = & t_1 + t_3 - \circ\left( t_1 + t_3 \right) \\ & = & x_\hi + x_\mi - \circ\left( x_\hi + x_\mi \right) \\ & = & x_\hi + x_\mi - x_\hi \\ & = & x_\mi \end{eqnarray*} Let us show now that $$\left \vert \delta \right \vert < \left \vert \xi\left( \hat{x} \right) \right \vert$$ Amongst other by the lemma's hypotheses and due to the fact that $x_\mi \not = 0$, we can check that \begin{eqnarray*} \left \vert \xi\left( \hat{x} \right) \right \vert & = & \left \vert x_\mi \right \vert \\ & > & 2^{-53} \cdot \left \vert x_\mi \right \vert \\ & \geq & \left \vert x_\lo \right \vert \end{eqnarray*} The inequality the lemma \ref{arrdirper} asks for in hypothesis is well verified.\\ So as per the same lemma \ref{arrdirper} we know that $$\diamond \left( \hat{x} + \delta \right) = \diamond\left( \hat{x} \right)$$ This means that $$\diamond \left( x_\hi + x_\mi + x_\lo \right) = \diamond\left( t_1 + t_3 \right)$$ which is the equation that was to be shown.\qed \end{proof} \begin{lemma}[Reduction of a triple-double into a double-double -- difficult case] \label{plusdunmiulp} ~ \\ Let be $x_\hi + x_\mi + x_\lo \in \F + \F + \F$ a non-overlapping triple-double number such that $x_\lo$ is not subnormal, such that $x_\mi = \circ \left( x_\mi + x_\lo \right)$ and that $\left \vert x_\mi \right \vert \geq \tau$ where $$\tau = \left \lbrace \begin{array}{ll} \frac{1}{4} \cdot \mUlp\left( x_\hi \right) & \mbox{ if } \exists e \in \Z \mbox{ . } 2^e = \left \vert x_\hi \right \vert \land \sgn\left( x_\mi \right) = -\sgn\left( x_\hi \right)\\ \frac{1}{2} \cdot \mUlp\left( x_\hi \right) & \mbox{ otherwise} \end{array} \right.$$ Given the instruction sequence below \begin{center} \begin{minipage}[b]{50mm} $\left( t_1, t_2 \right) \gets \mAdd\left( x_\hi, x_\mi \right)$ \\ $t_3 \gets t_2 \oplus x_\lo$ \end{minipage} \end{center} the following equation holds after the execution of the sequence $$\diamond\left( t_1 + t_3 \right) = \diamond\left( x_\hi + x_\mi + x_\lo \right)$$ \end{lemma} \begin{proof} ~ \\ Without loss of generality, let us suppose in the sequel that $x_\hi > 0$. This is legitime because the set of the floating point numbers is symmetrical around $0$. In fact it suffices to apply lemma \ref{commut} and definition \ref{defulp} in order to obtain a proof for each case.\\ In what follows we will proceed as that: we will decompose the problem in several cases and subcases that we will treat one after another. For each of this subcases we will show either directly the desired result or the fact that $\left \vert t_2 \right \vert \geq \left \vert x_\lo \right \vert$. In the end we will prove that this fact yields to the correctness of the lemma in each case.\\ Let us start by considering the case where $\tau = \frac{1}{2} \cdot \mUlp\left( x_\hi \right)$. Thus $x_\hi$ is not an exact integer power of $2$.\\ We therefore get $$\frac{1}{2} \leq \left \vert x_\mi \right \vert < \mUlp\left( x_\hi \right)$$ which is equivalent to $$\frac{1}{2} \leq \left \vert x_\mi \right \vert \leq \mUlp\left( x_\hi \right)^-$$ because $x_\mi$ is a floating point number.\\ We can check now that $$t_1 = \circ \left( x_\hi + x_\mi \right) = \left \lbrace \begin{array}{ll} x_\hi^+ & \mbox{ if } x_\mi > 0 \\ x_\hi & \mbox{ if } x_\mi = \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \mbox{ and the significand of } x_\hi \mbox{ is even} \\ x_\hi^- & \mbox{ if } x_\mi < 0 \end{array} \right.$$ This implies the handling of three different subcases. \\ Let as treat first the case where $t_1 = x_\hi$: \\ We get here \begin{eqnarray*} t_2 & = & x_hi + x_\mi - t_1 \\ & = & x_\hi + x_\mi - x_\hi \\ & = & x_\mi \end{eqnarray*} and further \begin{eqnarray*} t_3 & = & t_2 \oplus x_\lo \\ & = & x_\mi \oplus x_\lo \\ & = & \circ \left( x_\mi + x_\lo \right) \\ & = & x_\mi \end{eqnarray*} as per the hypothesis on the arguments. \\ So let us put \begin{eqnarray*} \hat{x} & = & t_1 + t_3 \\ \delta & = & x_\lo \end{eqnarray*} Thus \begin{eqnarray*} \hat{x} & = & x_\hi + x_\mi \\ \xi\left( \hat{x} \right) & = & \circ \left( \hat{x} \right) \\ & = & \circ \left( t_1 + t_2 \right) \\ & = & t_2 \\ & = & t_3 \end{eqnarray*} and $$\left \vert \delta \right \vert < \left \vert \xi\left( \hat{x} \right) \right \vert$$ because $$\left \vert x_\lo \right \vert \leq 2^{-53} \cdot \left \vert x_\mi \right \vert$$ et $$x_\mi \not = 0$$ Applying lemma \ref{arrdirper} we thus obtain $$\diamond \left( t_1 + t_3 \right) = \diamond \left( x_\hi + x_\mi + x_\lo \right)$$ Let us continue with the case where $t_1 = x_\hi^+$: \\ We get here \begin{eqnarray*} t_2 & = & x_\hi + x_\mi + t_1 \\ & = & x_\hi + x_\mi - x_\hi^+ \\ & = & - \left( x_\hi^+ - x_\hi \right) + x_\mi \\ & = & - \mUlp\left( x_\hi \right) + x_\mi \\ & \leq & -\mUlp\left( x_\hi \right) + \mUlp\left( x_\hi \right)^- \\ & = & - \left( \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi \right)^- \right) \\ & = & - \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & - \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right) \end{eqnarray*} Thus $$\left \vert t_2 \right \vert \geq \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right)$$ In contrast $\left \vert x_\lo \right \vert \leq \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right)$ as per hypothesis which implies $$\left \vert t_2 \right \vert \geq \left \vert x_\lo \right \vert$$ Let us finally check the properties to be show for the third and last subcase, supposing now that $t_1 = x_\hi^-$. \\ Since $x_\hi$ is not exactly an integer power of $2$, we can check the following applying amongst other lemma \ref{notpoweroftwo}: \begin{eqnarray*} t_2 & = & x_\hi + x_\mi - t_1 \\ & = & x_\hi + x_\mi - x_\hi^- \\ & = & x_\hi^+ - x_\hi + x_\mi \\ & = & \mUlp\left( x_\hi \right) + x_\mi \\ & \geq & \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi \right)^- \\ & = & \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right) \end{eqnarray*} We therefore still get $$\left \vert t_2 \right \vert \geq \left \vert x_\lo \right \vert$$ using the same argument as the one given above. \\ ~ \\ Let us handle now the case where $\tau = \frac{1}{4} \cdot \mUlp\left( x_\hi \right)$: \\ We can suppose in this case that $x_\hi$ is an exact integer power of $2$ and that $x_\mi$ is negative because we had already supposed that $x_\hi$ is positive and because we know that $\sgn\left( x_\hi \right) = -\sgn\left( x_\mi \right)$. We get further the following bounds for $x_\mi$: $$\frac{1}{4} \cdot \mUlp\left( x_\hi \right) \leq \left \vert x_\mi \right \vert \leq \mUlp\left( x_\hi \right)^-$$ which means that $$-\mUlp\left( x_\hi \right)^- \leq x_\mi \leq -\frac{1}{4} \cdot \mUlp\left( x_\hi \right)$$ still because $x_\mi$ is a floating point number. \\ Since $x_\hi$ is an integer power of $2$ and as for this reason, its significand is even, one can check that $$t_1 = \circ \left( x_\hi + x_\mi \right) = \left \lbrace \begin{array}{ll} x_\hi & \mbox{ if } x_\mi = -\frac{1}{4} \cdot \mUlp\left( x_\hi \right) \\ x_\hi^- & \mbox{ if } -\frac{1}{2} \cdot \mUlp\left( x_\hi \right) < x_\mi < -\frac{1}{4} \cdot \mUlp\left( x_\hi \right) \\ x_\hi^- & \mbox{ if } x_\mi = -\frac{1}{2} \cdot \mUlp\left( x_\hi \right) \\ x_\hi^- & \mbox{ if } -\frac{3}{4} \cdot \mUlp\left( x_\hi \right) < x_\mi < -\frac{1}{2} \cdot \mUlp\left( x_\hi \right) \\ x_\hi^{--} & \mbox{ if } -\mUlp\left( x_\hi \right)^- \leq x_\mi \leq -\frac{3}{4} \cdot \mUlp\left( x_\hi \right) \end{array} \right. $$ The assertion that $t_1 = x_\hi^-$ if $x_\mi = -\frac{1}{2} \cdot \mUlp\left( x_\hi \right)$ can be explained as follows:\\ We have \begin{eqnarray*} x_\hi + x_\mi & = & x_\hi - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \\ & = & x_\hi - \frac{1}{2} \cdot \left( x_\hi^+ - x_\hi \right) \\ & = & x_\hi - \left( x_\hi - x_\hi^- \right) \\ & = & x_\hi^- \end{eqnarray*} Thus $$\circ \left( x_\hi + x_\mi \right) = \circ \left( x_\hi^- \right) = x_\hi^-$$ because $x_\hi^-$ is clearly a floating point number. Let us consider now first the cases where we have equations, i.e. the cases where $x_\mi = -\frac{1}{4} \cdot \mUlp\left( x_\hi \right)$ and $x_\mi = - \frac{1}{2} \cdot \mUlp\left( x_\hi \right)$: \\ Let us commence by the case where $x_\mi = -\frac{1}{4} \cdot \mUlp\left( x_\hi \right)$: \\ We get here \begin{eqnarray*} t_2 & = & x_\hi + x_\mi - t_1 \\ & = & x_\hi + x_\mi - x_\hi \\ & = & x_\mi \end{eqnarray*} and we can check that the following holds by the hypotheses on the arguments \begin{eqnarray*} t_3 & = & x_\mi \oplus x_\lo \\ & = & \circ \left( x_\mi + x_\lo \right) \\ & = & x_\mi \end{eqnarray*} Let us put now \begin{eqnarray*} \hat{x} & = & t_1 + t_3 \\ \delta & = & x_\lo \\ \xi\left( \hat{x} \right) & = & \circ\left( \hat{x} \right) - \hat{x} = t_3 \end{eqnarray*} So by applying lemma \ref{arrdirper}, we get $$\diamond \left( t_1 + t_3 \right) = \diamond \left( x_\hi + x_\mi + x_\lo \right)$$ because $$\left \vert x_\lo \right \vert \leq 2^{-53} \cdot \left \vert x_\mi \right \vert$$ and $x_\mi \not = 0$ which is a hypothesis of the lemma to prove. \\ Let us now handle the second of these particular cases, i.e. the cases where $x_\mi = -\frac{1}{2} \cdot \mUlp\left( x_\hi \right)$: \\ We get \begin{eqnarray*} t_2 & = & x_\hi + x_\mi - t_1 \\ & = & x_\hi + x_\mi - x_\hi^- \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) + x_\mi \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) - \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \\ & = & 0 \end{eqnarray*} So in consequence we have \begin{eqnarray*} t_3 & = & t_2 \oplus x_\lo \\ & = & 0 \oplus x_\lo \\ & = & x_\lo \end{eqnarray*} And we thus obtain finally \begin{eqnarray*} \diamond \left( x_\hi + x_\mi + x_\lo \right) & = & \diamond \left( t_1 + t_2 + x_\lo \right) \\ & = & \diamond \left( t_1 + 0 + x_\lo \right) \\ & = & \diamond \left( t_1 + t_3 \right) \end{eqnarray*} Let us now analyse the other principal cases, starting with the case where $$-\frac{1}{2} \cdot \mUlp\left( x_\hi \right) < x_\mi < -\frac{1}{4} \cdot \mUlp\left( x_\hi \right)$$ This inequality bounding $x_\mi$ is in fact equivalent to the following one because $x_\mi$ is a floating point number: $$-\frac{1}{2} \cdot \mUlp\left( x_\hi \right)^- \leq x_\mi \leq -\frac{1}{4} \cdot \mUlp\left( x_\hi \right)^+$$ So we can check \begin{eqnarray*} t_2 & = & x_\hi + x_\mi - t_1 \\ & = & x_\hi + x_\mi - x_\hi^- \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) + x_\mi \\ & \geq & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) - \frac{1}{2} \cdot \mUlp\left( x_\hi \right)^- \\ & = & \frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right) - \mUlp\left( x_\hi \right)^- \right) \\ & = & \frac{1}{4} \mUlp\left( \mUlp\left( x_\hi \right) \right) \end{eqnarray*} In contrast we know that $$\left \vert x_\lo \right \vert \leq \frac{1}{2} \cdot \mUlp \left( x_\mi \right)$$ Since in the currently treated case the following holds $$\left \vert x_\mi \right \vert \leq \frac{1}{2} \cdot \mUlp\left( x_\hi \right)$$ we get as per lemma \ref{multhalf} $$\left \vert x_\lo \right \vert \leq \frac{1}{4} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right)$$ which yields to $$\left \vert t_2 \right \vert \geq \left \vert x_\lo \right \vert$$ Let us now consider the second and one but not least case. We suppose here that $$-\frac{3}{4} \cdot \mUlp\left( x_\hi \right) < x_\mi < -\frac{1}{2} \cdot \mUlp\left( x_\hi \right)$$ which is equivalent to $$-\left(\frac{3}{4} \cdot \mUlp\left( x_\hi \right)\right)^- \leq x_\mi < -\frac{1}{2} \cdot \mUlp\left( x_\hi \right)^+$$ We therefore get \begin{eqnarray*} t_2 &= & x_\hi + x_\mi - t_1 \\ & = & x_\hi + x_\mi - x_\hi^- \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) + x_\mi \\ & \leq & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) - \frac{1}{2} \cdot \mUlp\left( x_\hi \right)^+ \\ & = & -\frac{1}{2} \cdot \left( \mUlp\left( x_\hi \right)^+ - \mUlp\left( x_\hi \right) \right) \\ & = & -\frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) \end{eqnarray*} which gives us $$\left \vert t_2 \right \vert \geq \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right)$$ We can deduce from that, still using the argument that $\left \vert x_\lo \right \vert \leq \frac{1}{2} \cdot \mUlp\left( \mUlp \left( x_\hi \right) \right)$, that $$\left \vert t_2 \right \vert \geq \left \vert x_\lo \right \vert $$ Let us finally handle the last case where $-\mUlp\left( x_\hi \right)^- \leq x_\mi \leq - \frac{3}{4} \cdot \mUlp\left( x_\hi \right)$: \\ Using the property that $x_\hi^-$ is an exact integer power of $2$ and using further lemma \ref{notpoweroftwo}, we can check now that \begin{eqnarray*} t_2 & = & x_\hi + x_\mi - t_1 \\ & = & x_\hi + x_\mi - x_\hi^{--} \\ & = & x_\hi + x_\mi - x_\hi^{--} + x_\hi^- - x_\hi^- \\ & = & x_\hi - x_\hi^- + x_\mi + x_\hi^- - x_\hi^{--} \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) + x_\mi + \left( x_\hi^- \right)^+ - x_\hi^- \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) + x_\mi + x_\hi - x_\hi^- \\ & = & \frac{1}{2} \cdot \mUlp\left( x_\hi \right) + x_\mi + \frac{1}{2} \cdot \mUlp\left( x_\hi \right) \\ & = & \mUlp\left( x_\hi \right) + x_\mi \\ & \geq & \mUlp\left( x_\hi \right) + \mUlp\left( x_\hi \right)^- \\ & = & \frac{1}{2} \cdot \mUlp\left( \mUlp\left( x_\hi \right) \right) \end{eqnarray*} In consequence we still get the same upper bound for $\left \vert x_\lo \right \vert$, i.e. $$\left \vert t_2 \right \vert \geq \left \vert x_\lo \right \vert$$ Since we have now treated all the cases that have been showing up, it suffices now to show that the upper bound already mentioned yields to the property to be proven. Once again, we decompose the problem in cases and subcases.\\ Let us start by showing the property for the equation $\left \vert t_2 \right \vert = \left \vert x_\lo \right \vert$: \\ If $\sgn\left( t_2 \right) = \sgn\left( x_\lo \right)$ we get \begin{eqnarray*} t_3 & = & t_2 \oplus x_\lo \\ & = & x_\lo \oplus x_\lo \\ & = & \circ \left( 2 \cdot x_\lo \right) \\ & = & 2 \cdot x_\lo \end{eqnarray*} So we have exactly $$t_1 + t_3 = x_\hi + x_\mi + x_\lo$$ and thus $$\diamond \left( t_1 + t_3 \right) = \diamond \left( x_\hi + x_\mi + x\lo \right)$$ Otherwise, we have $\sgn\left( t_2 \right) = -\sgn\left( x_\lo \right)$ and get \begin{eqnarray*} t_3 & = & t_2 \oplus x_\lo \\ & = & - x_\lo \oplus x_\lo \\ & = & 0 \end{eqnarray*} exactly. This means finally that \begin{eqnarray*} \diamond \left( t_1 + t_3 \right) & = & \diamond \left( t_1 \right) \\ & = & \diamond \left( t_1 + t_2 - t_2 \right) \\ & = & \diamond \left( x_\hi + x_\mi + x_\lo \right) \end{eqnarray*} In the end let us consider the case where one can suppose that $\left \vert t_2 \right \vert > \left \vert x_\lo \right \vert$: \\ We can suppose here \begin{eqnarray*} t_3 & = & t_2 \oplus x_\lo \\ & = & t_2 + x_\lo + \delta \end{eqnarray*} with $$\left \vert \delta \right \vert \leq 2^{-53} \cdot \left \vert t_2 + x_\lo \right \vert$$ Let us show now that $t_2$ and $t_3$ have the same sign. For doing so let us suppose that this would not be true.\\ Clearly, $t_2$ and $t_2 + x_\lo$ have the same sign because we know that $\left \vert t_2 \right \vert > \left \vert x_\lo \right \vert$. \\ So in order to have $\sgn\left( t_2 \right) = -1 \cdot \sgn\left( t_3 \right)$ to hold, we must have $$\left \vert \delta \right \vert > \left \vert t_2 + x_\lo \right \vert$$ Thus we would obtain $$2^{-53} \cdot \left \vert t_2 + x_\lo \right \vert > \left \vert t_2 + x_\lo \right \vert$$ which is not true because $$t_2 + x_\lo = 0$$ This would yield to $\left \vert t_2 \right \vert = \left \vert x_\lo \right \vert$ which is excluded by hypotheses. Thus, contradiction. \\ The values $t_2$ and $t_3$ have therefore the same sign. By applying lemma \ref{decarrdir}, we get: $$\diamond \left( t_1 + t_2 \right) = \diamond \left( t_1 + t_3 \right)$$ Let us show now that $$\diamond \left( t_1 + t_2 \right) = \diamond \left( x_\hi + x_\mi + x_\lo \right)$$ in order to be able to conclude. \\ For doing so, let us put \begin{eqnarray*} \hat{x} & = & t_1 + t_2 \\ \delta^\prime & = & x_\lo \\ \xi\left( \hat{x} \right) & = & t_2 \end{eqnarray*} and let us check that \begin{eqnarray*} \left \vert \delta^\prime \right \vert & = & \left \vert x_\lo \right \vert \\ & < & \left \vert t_2 \right \vert \\ & = & \left \vert \xi\left(\hat{x}\right) \right \vert \end{eqnarray*} We can now apply lemma \ref{arrdirper} and obtain: $$\diamond \left( t_1 + t_3 \right) = \diamond \left( x_\hi + x_\mi + x_\lo \right)$$ This is the equation to be shown.\qed \end{proof} \begin{theorem}[Directed final rounding of a triple-double number] \label{arrdir} ~ \\ Let be $x_\hi + x_\mi + x_\lo \in \F + \F + \F$ a non-overlapping triple-double number. \\ Let be $\diamond$ a directed rounding mode.\\ Let be {\bf A} the following instruction sequence: \begin{center} \begin{minipage}[b]{50mm} $\left( t_1, t_2 \right) \gets \mAdd\left( x_\hi, x_\mi \right)$ \\ $t_3 \gets t_2 \oplus x_\lo$ \\ {\bf return } $\diamond\left( t_1 + t_3 \right)$ \end{minipage} \end{center} So {\bf A} is a correct rounding procedure for the rounding mode $\diamond$. \end{theorem} \begin{proof} ~\\ Trivial as per lemmas \ref{moinsquunmiulp} and \ref{plusdunmiulp}.\qed \end{proof} \bibliographystyle{plain} \bibliography{elem-fun.bib} \end{document} interval-3.2.0/src/crlibm/double-extended.h0000644000000000000000000005542013316017127016755 0ustar 00000000000000/* * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __DOUBLE_EXTENDED_H #define __DOUBLE_EXTENDED_H #if (defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)) #include typedef long double double_ext; #endif #if defined(CRLIBM_TYPECPU_ITANIUM) && defined(__INTEL_COMPILER) typedef __fpreg double_ext; #endif /* For debugging */ typedef union { int i[3]; long double d; } db_ext_number; #define DE_EXP 2 #define DE_MANTISSA_HI 1 #define DE_MANTISSA_LO 0 #define print_ext(_s, _y) {\ db_ext_number _yy; _yy.d=_y; \ printf("%s %04x %08x %08x \n",_s, 0xffff&_yy.i[DE_EXP], _yy.i[DE_MANTISSA_HI], _yy.i[DE_MANTISSA_LO]); \ } /**************************************************************************************/ /*********************************Rounding tests***************************************/ /**************************************************************************************/ /* These test work by observing the bits of your double-extended after the 53rd. mask should be 7ff if you trust your 64 bits (hum) 7fe if you trust 63 (if you have proven that maxepsilon<2^(-63) ) 7fc 62 7f8 61 7f0 60 etc */ /* Mask constants for rounding test */ #define ACCURATE_TO_64_BITS 0x7ff #define ACCURATE_TO_63_BITS 0x7fe #define ACCURATE_TO_62_BITS 0x7fc #define ACCURATE_TO_61_BITS 0x7f8 #define ACCURATE_TO_60_BITS 0x7f0 #define ACCURATE_TO_59_BITS 0x7e0 #if (defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)) static const unsigned short RN_Double = (_FPU_DEFAULT & ~_FPU_EXTENDED)|_FPU_DOUBLE; static const unsigned short RN_DoubleDown = (_FPU_DEFAULT & ~_FPU_EXTENDED & ~_FPU_RC_NEAREST)|_FPU_DOUBLE | _FPU_RC_DOWN; static const unsigned short RN_DoubleUp = (_FPU_DEFAULT & ~_FPU_EXTENDED & ~_FPU_RC_NEAREST)|_FPU_DOUBLE | _FPU_RC_UP; static const unsigned short RN_DoubleExt = _FPU_DEFAULT; #define DOUBLE_EXTENDED_MODE _FPU_SETCW(RN_DoubleExt) #define DOUBLE_UP_MODE _FPU_SETCW(RN_DoubleUp) #define DOUBLE_DOWN_MODE _FPU_SETCW(RN_DoubleDown) #define BACK_TO_DOUBLE_MODE _FPU_SETCW(RN_Double) /* Two rounding tests to the nearest. On Pentium 3, gcc3.3, the second is faster by 12 cycles (and also improves the worst-case time by 60 cycles since it doesn't switch processor rounding mode in this case). However it uses a coarser error estimation. */ #define DE_TEST_AND_RETURN_RN_ZIV(y,rncst) \ { double yh, yl; \ yh = (double) y; \ yl = y-yh; \ BACK_TO_DOUBLE_MODE; \ if(yh==yh + yl*rncst) return yh; \ DOUBLE_EXTENDED_MODE; \ } #define DE_TEST_AND_RETURN_RN(_y, _mask) \ { \ db_ext_number _z; double _yd; \ int _lo; \ _z.d = _y; \ _yd = (double) _y; \ _lo = _z.i[DE_MANTISSA_LO] &(_mask); \ if((_lo!=(0x3ff&(_mask))) && (_lo!= (0x400&(_mask)))) { \ BACK_TO_DOUBLE_MODE; \ return _yd; \ } \ } #define DE_TEST_AND_RETURN_RD(_y, _mask) \ { \ double _result; int _bits; \ db_ext_number _z; \ _z.d = _y; \ DOUBLE_DOWN_MODE; \ _bits = _z.i[DE_MANTISSA_LO] &(_mask); \ _result = (double)(_y); \ if( (_bits != (0xfff&(_mask))) && (_bits != (0x000&(_mask))) ) { \ BACK_TO_DOUBLE_MODE; \ return _result; \ } \ DOUBLE_EXTENDED_MODE; \ } #define DE_TEST_AND_RETURN_RU(_y, _mask) \ { \ double _result; int _bits; \ db_ext_number _z; \ _z.d = _y; \ DOUBLE_UP_MODE; \ _bits = _z.i[DE_MANTISSA_LO] &(_mask); \ _result = (double)(_y); \ if( (_bits != (0xfff&(_mask))) && (_bits != (0x000&(_mask))) ) { \ BACK_TO_DOUBLE_MODE; \ return _result; \ } \ DOUBLE_EXTENDED_MODE; \ } /* Use this one if you want a final computation step to overlap with the rounding test. Examples: multiplication by a sign or by a power of 2 */ #define DE_TEST_AND_RETURN_RN2(_ytest, _yreturn, _mask) \ { \ db_ext_number _z; double _y_return_d; \ int _bits; \ _z.d = _ytest; \ _y_return_d = (double) (_yreturn); \ _bits = _z.i[DE_MANTISSA_LO] &(_mask); \ if((_bits!=(0x3ff&(_mask))) && (_bits!= (0x400&(_mask)))) {\ BACK_TO_DOUBLE_MODE; \ return _y_return_d; \ } \ } /* Slow macros with two changes of precision, but who cares, they are used at the end of the second step */ #define RETURN_SUM_ROUNDED_DOWN(_rh, _rl) {\ double _result; \ DOUBLE_DOWN_MODE; \ _result = (_rh+_rl); \ BACK_TO_DOUBLE_MODE; \ return _result; \ } #define RETURN_SUM_ROUNDED_UP(_rh, _rl) {\ double _result; \ DOUBLE_UP_MODE; \ _result = (_rh+_rl); \ BACK_TO_DOUBLE_MODE; \ return _result; \ } #else /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ #if !defined(CRLIBM_TYPECPU_ITANIUM) #error "This file should be compiled only for IA32 or IA64 architecture " #endif /* TODO Add what it takes to compile under HP-UX */ #if !defined(__INTEL_COMPILER) #error "Use icc, version 8.1 or higher to compile for IA64 architecture" #endif #define DOUBLE_EXTENDED_MODE {} #define BACK_TO_DOUBLE_MODE {} #define DE_TEST_AND_RETURN_RN(_y, _mask) \ { uint64_t _mantissa, _bits; double _yd; \ _yd = _Asm_fma(2/*_FR_D*/, 1.0, _y, 0.0, 0/*SF0*/); \ _mantissa = _Asm_getf(4/*_FR_SIG*/, _y); \ _bits = _mantissa & (0x7ff&(_mask)); \ if(__builtin_expect( \ (_bits!=(0x3ff&(_mask))) && (_bits != (0x400&(_mask))), \ 1+1==2)) \ return _yd; \ } /* Slower by 5 cycles as of 2005... Let us keep it, you never know */ #define DE_TEST_AND_RETURN_RN_ZIV(y,rncst) \ { double yh, yl; \ yh = (double) y; \ yl = y-yh; \ if(__builtin_expect(yh == yh + yl*rncst, 1+1==2)) return yh; \ } /* Use this one if you want a final computation step to overlap with the rounding test. Examples: multiplication by a sign or by a power of 2 */ #define DE_TEST_AND_RETURN_RN2(_ytest, _yreturn, _mask) \ { uint64_t _mantissa, _bits; \ _mantissa = _Asm_getf(4/*_FR_SIG*/, _ytest); \ _bits = _mantissa & (0x7ff&(_mask)); \ if(__builtin_expect( \ (_bits!=(0x3ff&(_mask))) && (_bits != (0x400&(_mask))), \ 1+1==2)) \ return _yreturn; \ } #define DE_TEST_AND_RETURN_RD(_y, _mask) \ { uint64_t _mantissa, _bits; double _yd; \ _yd = _Asm_fma(2/*_FR_D*/, -1.0, _y, 0.0, 3/*SF3*/); \ _mantissa = _Asm_getf(4/*_FR_SIG*/, _y); \ _bits = _mantissa & (0x7ff&(_mask)); \ if(__builtin_expect( \ (_bits!=(0x000&(_mask))) && (_bits != (0x7ff&(_mask))), \ 1+1==2)) \ return -_yd; \ } #define DE_TEST_AND_RETURN_RU(_y, _mask) \ { uint64_t _mantissa, _bits; double _yd; \ _yd = _Asm_fma(2/*_FR_D*/, 1.0, _y, 0.0, 3/*SF3*/); \ _mantissa = _Asm_getf(4/*_FR_SIG*/, _y); \ _bits = _mantissa & (0x7ff&(_mask)); \ if(__builtin_expect( \ (_bits!=(0x000&(_mask))) && (_bits != (0x7ff&(_mask))), \ 1+1==2)) \ return _yd; \ } #define RETURN_SUM_ROUNDED_DOWN(_rh, _rl) \ return -_Asm_fma(2/*_FR_D*/, -1.0, _rh, -_rl, 3/*SF3*/); #define RETURN_SUM_ROUNDED_UP(_rh, _rl) \ return _Asm_fma(2/*_FR_D*/, 1.0, _rh, _rl, 3/*SF3*/); #if 0 /* This test doesn'use SF2 and SF3 Kept as a model for Pentium implementation, to erase afterwards */ #define DE_TEST_AND_RETURN_RU(_y, _mask) \ { \ db_ext_number _z; double _yd; \ unsigned long int _mantissa, _y_double, _isNegative ,_wasRoundedUp, _bits; \ _yd=(double) _y; \ _mantissa = _Asm_getf(4/*_FR_SIG*/, _y); \ _y_double = _Asm_getf(2/*_FR_D*/, _yd); \ _bits = _mantissa & (0x7ff&(_mask)); \ _wasRoundedUp = ((_mantissa >>11) & 1) != (_y_double & 1); \ _bits = _mantissa & (0x7ff&(_mask)); \ _isNegative = _y_double >> 63; \ if(_isNegative) { \ if(_wasRoundedUp) { /* RN was RD */ \ if( _bits != (0x7ff&(_mask)) ) { \ _y_double--; \ return (double) _Asm_setf(2/*_FR_D*/, _y_double); \ } /* else launch accurate phase */ \ } \ else{ /* RN was RU, so need to check */ \ if( _bits != (0x000&(_mask)) ) { \ return _yd; \ } /* else launch accurate phase */ \ } \ } \ else{ /* Positive number */ \ if(_wasRoundedUp) { /* RN was RU */ \ if( _bits != (0x7ff&(_mask)) ) { \ return _yd; \ } /* else launch accurate phase */ \ } \ else{ /* RN was RD, */ \ if( _bits != (0x000&(_mask)) ) { \ _y_double++; /* beware, does not work for -0 */ \ return (double) _Asm_setf(2/*_FR_D*/, _y_double); \ } /* else launch accurate phase */ \ } \ } \ } #define DE_TEST_AND_RETURN_RD(_y, _mask) \ { \ db_ext_number _z; double _yd; \ unsigned long int _mantissa, _y_double, _isNegative ,_wasRoundedUp, _bits; \ _yd=(double) _y; \ _mantissa = _Asm_getf(4/*_FR_SIG*/, _y); \ _y_double = _Asm_getf(2/*_FR_D*/, _yd); \ _bits = _mantissa & (0x7ff&(_mask)); \ _wasRoundedUp = ((_mantissa >>11) & 1) != (_y_double & 1); \ _bits = _mantissa & (0x7ff&(_mask)); \ _isNegative = _y_double >> 63; \ if(_isNegative) { \ if(_wasRoundedUp) { /* RN was RD */ \ if( _bits != (0x7ff&(_mask)) ) { \ return (double) _y; \ } /* else launch accurate phase */ \ } \ else{ /* RN was RU */ \ if( _bits != (0x000&(_mask)) ) { \ _y_double++; \ return (double) _Asm_setf(2/*_FR_D*/, _y_double); \ } /* else launch accurate phase */ \ } \ } \ else{ /* Positive number */ \ if(_wasRoundedUp) { /* RN was RU */ \ if( _bits != (0x7ff&(_mask)) ) { \ _y_double--; \ return (double) _Asm_setf(2/*_FR_D*/, _y_double); \ } /* else launch accurate phase */ \ } \ else{ /* RN was RD, */ \ if( _bits != (0x000&(_mask)) ) { \ return (double) _y; \ } /* else launch accurate phase */ \ } \ } \ } #endif /* 0 */ #endif /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ /**************************************************************************************/ /************************Double double-extended arithmetic*****************************/ /**************************************************************************************/ #define Add12_ext(prh, prl, a, b) \ { \ double_ext _z, _a, _b; \ _a = a; _b = b; \ *prh = _a + _b; \ _z = *prh - _a; \ *prl = _b - _z; \ } #if (defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)) #define Mul12_ext(prh,prl,u,v) \ { \ const double_ext _c = 4294967297.L; /* 2^32 +1 */ \ double_ext _up, _u1, _u2, _vp, _v1, _v2; \ double_ext _u =u, _v=v; \ \ _up = _u*_c; _vp = _v*_c; \ _u1 = (_u-_up)+_up; _v1 = (_v-_vp)+_vp; \ _u2 = _u-_u1; _v2 = _v-_v1; \ \ *prh = _u*_v; \ *prl = _u1*_v1 - *prh; \ *prl = *prl + _u1*_v2; \ *prl = *prl + _u2*_v1; \ *prl = *prl + _u2*_v2; \ } #define Mul22_ext(prh,prl, ah,al, bh,bl) \ { \ double_ext mh, ml; \ Mul12_ext(&mh,&ml,(ah),(bh)); \ ml += (ah)*(bl) + (al)*(bh); \ Add12_ext(prh,prl, mh,ml); \ } #define FMA22_ext(prh,prl, ah,al, bh,bl, ch,cl) \ { \ Mul22_ext(prh,prl, (ah),(al), (bh),(bl)); \ Add22_ext(prh,prl, ch,cl, *prh, *prl); \ } #else /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ #define Mul12_ext( prh,prl, a, b ) \ { \ *prh = (a) * (b); \ *prl = _Asm_fms( 3/*_PC_NONE*/, (a), (b), *prh, 1 ); \ } #if 0 /* transcription of Alexey's */ #define Mul22_ext( prh,prl, ah,al, bh,bl ) \ { \ double_ext _t1,_t2,_t3; \ *prh = (ah) * (bh); \ _t1 = (ah)*(bl); \ _t2 = _Asm_fms( 3/*_PC_NONE*/, (ah), (bh), *prh, 1 ); \ _t3 = (al) * (bh) + _t1; \ *prl = (_t2 + _t3); \ } #else #define Mul22_ext( prh,prl, ah,al, bh,bl ) \ { \ double_ext ph, pl; \ ph = (ah)*(bh); \ pl = _Asm_fms( 3/*_PC_NONE*/, ah, bh, ph, 1/*_SF1*/ ); \ pl = (ah)*(bl) + pl; \ pl = (al)*(bh) + pl; \ Add12_ext(prh,prl, ph,pl); \ } #endif /* res = a*b + c, assume |a*b| <= |c| * res, a and b in X format * c in L format */ #if 0 #define FMA22_ext(prh,prl, ah,al, bh,bl, ch,cl) \ { \ Mul22_ext(prh,prl, (ah),(al), (bh),(bl)); \ Add22_ext(prh,prl, ch,cl, *prh, *prl); \ } #else #define FMA22_ext( prh,prl, ah,al, bh,bl, ch,cl) \ { \ double_ext __xfmagxxx_r_hi__,__xfmagxxx_r_lo__, \ __xfmagxxx_t1__,__xfmagxxx_t2__, \ __xfmagxxx_t3__,__xfmagxxx_t4__; \ __xfmagxxx_r_hi__ = ah * bh + ch; \ __xfmagxxx_t1__ = al * bh + cl; \ __xfmagxxx_t2__ = __xfmagxxx_r_hi__ - ch; \ __xfmagxxx_t3__ = ah * bl + __xfmagxxx_t1__; \ __xfmagxxx_t4__ = _Asm_fms( 3/*_PC_NONE*/, ah, bh, __xfmagxxx_t2__, 1/*_SF1*/ ); \ __xfmagxxx_r_lo__ = (__xfmagxxx_t3__ + __xfmagxxx_t4__); \ *prh = __xfmagxxx_r_hi__; *prl = __xfmagxxx_r_lo__; \ } #endif #endif /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ #define Div22_ext(prh,prl,xh,xl,yh,yl) \ { \ double_ext ch,cl,uh,ul; \ ch = (xh)/(yh); \ Mul12_ext(&uh,&ul,ch,(yh)); \ cl = (xh)-uh; \ cl = cl - ul; \ cl = cl + (xl); \ cl = cl - ch*(yl); \ cl = cl / (yh); \ Add12(prh,prl, ch, cl) ; \ } #define Add22_ext(prh,prl,xh,xl,yh,yl) \ do { \ double_ext _r,_s; \ _r = (xh)+(yh); \ _s = (xh)-_r; \ _s = _s + (yh); \ _s = _s + (yl); \ _s = _s + (xl); \ Add12_ext(prh,prl,_r,_s); \ } while(0) #endif /* ifndef __DOUBLE_EXTENDED_H*/ interval-3.2.0/src/crlibm/exp-td-standalone.c0000644000000000000000000000701113316017127017220 0ustar 00000000000000/* * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "exp-td.h" #define AVOID_FMA 0 extern void exp_td_accurate(double *polyTblh, double *polyTblm, double *polyTbll, double rh, double rm, double rl, double tbl1h, double tbl1m, double tbl1l, double tbl2h, double tbl2m, double tbl2l); /* Function exp13 Computes exp(x) with an accuracy of 113 bits as 2^exponent * (exph + expm + expl) \approx exp(x) Unless the subnormal case for x, no special cases are handled. The triple-double exph + expm + expl is non-overlapping. The domain for exph + expm + expl is 1/2..2 The integer exponent is in the range -1024..1024. The value 2^(exponent) may therefore be non-representable whereas 2^exponent * (exph + expm + expl) is. */ void exp13(int *exponent, double *exph, double *expm, double *expl, double x) { double rh, rm, rl, tbl1h, tbl1m, tbl1l; double tbl2h, tbl2m, tbl2l; double xMultLog2InvMult2L, shiftedXMult, kd; double msLog2Div2LMultKh, msLog2Div2LMultKm, msLog2Div2LMultKl; double t1, t2; db_number shiftedXMultdb, xdb; int k, M, index1, index2, xIntHi; /* Argument reduction and filtering for special cases */ /* Compute k as a double and as an int */ xdb.d = x; xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; /* Special cases tests */ xIntHi = xdb.i[HI]; /* Test if argument is a denormal or zero */ if ((xIntHi & 0x7ff00000) == 0) { /* We are in the RN case, return 1.0 in all cases */ *exph = 1.0; *expm = 0.0; *expl = 0.0; return; } k = shiftedXMultdb.i[LO]; M = k >> L; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> LHALF; /* Table reads */ tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Argument reduction */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Polynomial approximation and reconstruction: factorized code */ exp_td_accurate(exph, expm, expl, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l); *exponent = M; } interval-3.2.0/src/crlibm/exp-td.c0000644000000000000000000013720513316017127015103 0ustar 00000000000000/* * This function computes exp, correctly rounded, * using experimental techniques based on triple double arithmetics * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author : Christoph Lauter * christoph.lauter at ens-lyon.fr * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA THIS IS EXPERIMENTAL SOFTWARE To have it replace the crlibm exp, do: gcc -DHAVE_CONFIG_H -I. -fPIC -O2 -c exp-td.c; mv exp-td.o exp_fast.o; make */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "exp-td.h" #ifdef BUILD_INTERVAL_FUNCTIONS #include "interval.h" #endif #define AVOID_FMA 0 #define EVAL_PERF 1 void exp_td_accurate(double *polyTblh, double *polyTblm, double *polyTbll, double rh, double rm, double rl, double tbl1h, double tbl1m, double tbl1l, double tbl2h, double tbl2m, double tbl2l) { double highPoly, highPolyMulth, highPolyMultm, highPolyMultl; double rhSquareh, rhSquarel, rhSquareHalfh, rhSquareHalfl; double rhCubeh, rhCubem, rhCubel; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5, t6; double lowPolyh, lowPolym, lowPolyl; double ph, pm, pl, phnorm, pmnorm, rmlMultPh, rmlMultPl; double qh, ql, fullPolyh, fullPolym, fullPolyl; double polyWithTbl1h, polyWithTbl1m, polyWithTbl1l; double polyAddOneh,polyAddOnem,polyAddOnel; double polyWithTablesh, polyWithTablesm, polyWithTablesl; #if EVAL_PERF crlibm_second_step_taken++; #endif #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(accPolyC7,rh,accPolyC6),rh,accPolyC5); #else highPoly = accPolyC5 + rh * (accPolyC6 + rh * accPolyC7); #endif Mul12(&t1h,&t1l,rh,highPoly); Add22(&t2h,&t2l,accPolyC4h,accPolyC4l,t1h,t1l); Mul22(&t3h,&t3l,rh,0,t2h,t2l); Add22(&t4h,&t4l,accPolyC3h,accPolyC3l,t3h,t3l); Mul12(&rhSquareh,&rhSquarel,rh,rh); Mul23(&rhCubeh,&rhCubem,&rhCubel,rh,0,rhSquareh,rhSquarel); rhSquareHalfh = 0.5 * rhSquareh; rhSquareHalfl = 0.5 * rhSquarel; Renormalize3(&lowPolyh,&lowPolym,&lowPolyl,rh,rhSquareHalfh,rhSquareHalfl); Mul233(&highPolyMulth,&highPolyMultm,&highPolyMultl,t4h,t4l,rhCubeh,rhCubem,rhCubel); Add33(&ph,&pm,&pl,lowPolyh,lowPolym,lowPolyl,highPolyMulth,highPolyMultm,highPolyMultl); Add12(phnorm,pmnorm,ph,pm); Mul22(&rmlMultPh,&rmlMultPl,rm,rl,phnorm,pmnorm); Add22(&qh,&ql,rm,rl,rmlMultPh,rmlMultPl); Add233Cond(&fullPolyh,&fullPolym,&fullPolyl,qh,ql,ph,pm,pl); Add12(polyAddOneh,t5,1,fullPolyh); Add12Cond(polyAddOnem,t6,t5,fullPolym); polyAddOnel = t6 + fullPolyl; Mul33(&polyWithTbl1h,&polyWithTbl1m,&polyWithTbl1l,tbl1h,tbl1m,tbl1l,polyAddOneh,polyAddOnem,polyAddOnel); Mul33(&polyWithTablesh,&polyWithTablesm,&polyWithTablesl, tbl2h,tbl2m,tbl2l, polyWithTbl1h,polyWithTbl1m,polyWithTbl1l); Renormalize3(polyTblh,polyTblm,polyTbll,polyWithTablesh,polyWithTablesm,polyWithTablesl); } /************************************************************* ************************************************************* * ROUNDED TO NEAREST * ************************************************************* *************************************************************/ double exp_rn(double x){ double rh, rm, rl, tbl1h, tbl1m, tbl1l; double tbl2h, tbl2m, tbl2l; double xMultLog2InvMult2L, shiftedXMult, kd; double msLog2Div2LMultKh, msLog2Div2LMultKm, msLog2Div2LMultKl; double t1, t2, t3, t4, polyTblh, polyTblm, polyTbll; db_number shiftedXMultdb, twoPowerMdb, xdb, t4db, t4db2, polyTblhdb, resdb; int k, M, index1, index2, xIntHi, mightBeDenorm; double t5, t6, t7, t8, t9, t10, t11, t12, t13; double rhSquare, rhSquareHalf, rhC3, rhFour, monomialCube; double highPoly, highPolyWithSquare, monomialFour; double tablesh, tablesl; double s1, s2, s3, s4, s5; double res; /* Argument reduction and filtering for special cases */ /* Compute k as a double and as an int */ xdb.d = x; xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; /* Special cases tests */ xIntHi = xdb.i[HI]; mightBeDenorm = 0; /* Test if argument is a denormal or zero */ if ((xIntHi & 0x7ff00000) == 0) { /* We are in the RN case, return 1.0 in all cases */ return 1.0; } /* Test if argument is greater than approx. 709 in magnitude */ if ((xIntHi & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) { /* If we are here, the result might be overflowed, underflowed, inf, or NaN */ /* Test if +/- Inf or NaN */ if ((xIntHi & 0x7fffffff) >= 0x7ff00000) { /* Either NaN or Inf in this case since exponent is maximal */ /* Test if NaN: mantissa is not 0 */ if (((xIntHi & 0x000fffff) | xdb.i[LO]) != 0) { /* x = NaN, return NaN */ return x + x; } else { /* +/- Inf */ /* Test sign */ if ((xIntHi & 0x80000000)==0) /* x = +Inf, return +Inf */ return x; else /* x = -Inf, return 0 */ return 0; } /* End which in NaN, Inf */ } /* End NaN or Inf ? */ /* If we are here, we might be overflowed, denormalized or underflowed in the result but there is no special case (NaN, Inf) left */ /* Test if actually overflowed */ if (x > OVRFLWBOUND) { /* We are actually overflowed in the result */ return LARGEST * LARGEST; } /* Test if surely underflowed */ if (x <= UNDERFLWBOUND) { /* We are actually sure to be underflowed and not denormalized any more So we return 0 and raise the inexact flag */ return SMALLEST * SMALLEST; } /* Test if possibly denormalized */ if (x <= DENORMBOUND) { /* We know now that we are not sure to be normalized in the result We just set an internal flag for a further test */ mightBeDenorm = 1; } } /* End might be a special case */ /* If we are here, we are sure to be neither +/- Inf nor NaN nor overflowed nor denormalized in the argument but we might be denormalized in the result We continue the argument reduction for the quick phase and table reads for both phases */ #if 0 Mul12(&s1,&s2,msLog2Div2Lh,kd); s3 = kd * msLog2Div2Lm; s4 = s2 + s3; s5 = x + s1; Add12Cond(rh,rm,s5,s4); #else /* Cody and Waite like, accurate to 2^-84 */ double Log2h= 0xb.17217f8p-16 ; double Log2l= -0x2.e308654361c4cp-48 ; Add12Cond(rh,rm, x-kd*Log2h, -kd*Log2l); #endif k = shiftedXMultdb.i[LO]; M = k >> L; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> LHALF; /* Table reads */ tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; /* Test now if it is sure to launch the quick phase because no denormalized result is possible */ if (mightBeDenorm == 1) { /* The result might be denormalized, we launch the accurate phase in all cases */ /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh, &polyTblm, &polyTbll, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l); /* Final rounding and multiplication with 2^M We first multiply the highest significant byte by 2^M in two steps and adjust it then depending on the lower significant parts. We cannot multiply directly by 2^M since M is less than -1022. We first multiply by 2^(-1000) and then by 2^(M+1000). */ t3 = polyTblh * twoPowerM1000; /* Form now twoPowerM with adjusted M */ twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M + 2023) << 20; /* Multiply with the rest of M, the result will be denormalized */ t4 = t3 * twoPowerMdb.d; /* For x86, force the compiler to pass through memory for having the right rounding */ t4db.d = t4; /* Do not #if-ify this line, we need the copy */ #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) t4db2.i[HI] = t4db.i[HI]; t4db2.i[LO] = t4db.i[LO]; t4 = t4db2.d; #endif /* Remultiply by 2^(-M) for manipulating the rounding error and the lower significant parts */ M *= -1; twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M + 23) << 20; t5 = t4 * twoPowerMdb.d; t6 = t5 * twoPower1000; t7 = polyTblh - t6; /* The rounding decision is made at 1/2 ulp of a denormal, i.e. at 2^(-1075) We construct this number and by comparing with it we get to know whether we are in a difficult rounding case or not. If not we just return the known result. Otherwise we continue with further tests. */ twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M - 52) << 20; if (ABS(t7) != twoPowerMdb.d) return t4; /* If we are here, we are in a difficult rounding case */ /* We have to adjust the result iff the sign of the error on rounding 2^M * polyTblh (which must be an ulp of a denormal) and polyTblm +arith polyTbll is the same which means that the error made was greater than an ulp of an denormal. */ polyTblm = polyTblm + polyTbll; if (t7 > 0.0) { if (polyTblm > 0.0) { t4db.l++; return t4db.d; } else return t4; } else { if (polyTblm < 0.0) { t4db.l--; return t4db.d; } else return t4; } } /* End accurate phase launched as there might be a denormalized result */ /* No more underflow nor denormal is possible. There may be the case where M is 1024 and the value 2^M is to be multiplied may be less than 1 So the final result will be normalized and representable by the multiplication must be made in 2 steps */ /* Quick phase starts here */ rhSquare = rh * rh; rhC3 = c3 * rh; rhSquareHalf = 0.5 * rhSquare; monomialCube = rhC3 * rhSquare; rhFour = rhSquare * rhSquare; monomialFour = c4 * rhFour; highPoly = monomialCube + monomialFour; highPolyWithSquare = rhSquareHalf + highPoly; Mul22(&tablesh,&tablesl,tbl1h,tbl1m,tbl2h,tbl2m); t8 = rm + highPolyWithSquare; t9 = rh + t8; t10 = tablesh * t9; Add12(t11,t12,tablesh,t10); t13 = t12 + tablesl; Add12(polyTblh,polyTblm,t11,t13); /* Rounding test Since we know that the result of the final multiplication with 2^M will always be representable, we can do the rounding test on the factors and multiply only the final result. We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ if(polyTblh == (polyTblh + (polyTblm * ROUNDCST))) { polyTblhdb.d = polyTblh; polyTblhdb.i[HI] += M << 20; return polyTblhdb.d; } else { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh, &polyTblm, &polyTbll, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l); /* Since the final multiplication is exact, we can do the final rounding before multiplying We overcome this way also the cases where the final result is not underflowed whereas the lower parts of the intermediate final result are. */ RoundToNearest3(&res,polyTblh,polyTblm,polyTbll); /* Final multiplication with 2^M We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ resdb.d = res; resdb.i[HI] += M << 20; return resdb.d; } /* Accurate phase launched after rounding test*/ } /************************************************************* ************************************************************* * ROUNDED UPWARDS * ************************************************************* *************************************************************/ double exp_ru(double x) { double rh, rm, rl, tbl1h, tbl1m, tbl1l; double tbl2h, tbl2m, tbl2l; double xMultLog2InvMult2L, shiftedXMult, kd; double msLog2Div2LMultKh, msLog2Div2LMultKm, msLog2Div2LMultKl; double t1, t2, t3, t4, polyTblh, polyTblm, polyTbll; db_number shiftedXMultdb, twoPowerMdb, xdb, t4db, t4db2, resdb; int k, M, index1, index2, xIntHi, mightBeDenorm, roundable; double t5, t6, t7, t8, t9, t10, t11, t12, t13; double rhSquare, rhSquareHalf, rhC3, rhFour, monomialCube; double highPoly, highPolyWithSquare, monomialFour; double tablesh, tablesl; double s1, s2, s3, s4, s5; double res; /* Argument reduction and filtering for special cases */ /* Compute k as a double and as an int */ xdb.d = x; xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; /* Special cases tests */ xIntHi = xdb.i[HI]; mightBeDenorm = 0; /* Test if argument is a denormal or zero */ if ((xIntHi & 0x7ff00000) == 0) { /* If the argument is exactly zero, we just return 1.0 which is the mathematical image of the function */ if (x == 0.0) return 1.0; /* If the argument is a negative denormal, we must return 1.0 and raise the inexact flag. */ if (x < 0.0) return 1.0 + SMALLEST; /* Otherwise, we return 1.0 + 1ulp since exp(greatest denorm) < 1.0 + 1ulp We must do the addition dynamically for raising the inexact flag. */ return 1.0 + twoM52; } /* Test if argument is greater than approx. 709 in magnitude */ if ((xIntHi & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) { /* If we are here, the result might be overflowed, underflowed, inf, or NaN */ /* Test if +/- Inf or NaN */ if ((xIntHi & 0x7fffffff) >= 0x7ff00000) { /* Either NaN or Inf in this case since exponent is maximal */ /* Test if NaN: mantissa is not 0 */ if (((xIntHi & 0x000fffff) | xdb.i[LO]) != 0) { /* x = NaN, return NaN */ return x + x; } else { /* +/- Inf */ /* Test sign */ if ((xIntHi & 0x80000000)==0) /* x = +Inf, return +Inf */ return x; else /* x = -Inf, return 0 (even in RU!) */ return 0; } /* End which in NaN, Inf */ } /* End NaN or Inf ? */ /* If we are here, we might be overflowed, denormalized or underflowed in the result but there is no special case (NaN, Inf) left */ /* Test if actually overflowed */ if (x > OVRFLWBOUND) { /* We are actually overflowed in the result */ return LARGEST * LARGEST; } /* Test if surely underflowed */ if (x <= UNDERFLWBOUND) { /* We are actually sure to be underflowed and not denormalized any more (at least where computing makes sense); since we are in the round upwards case, we return the smallest denormal possible. */ return SMALLEST; } /* Test if possibly denormalized */ if (x <= DENORMBOUND) { /* We know now that we are not sure to be normalized in the result We just set an internal flag for a further test */ mightBeDenorm = 1; } } /* End might be a special case */ /* If we are here, we are sure to be neither +/- Inf nor NaN nor overflowed nor denormalized in the argument but we might be denormalized in the result We continue the argument reduction for the quick phase and table reads for both phases */ #if 0 Mul12(&s1,&s2,msLog2Div2Lh,kd); s3 = kd * msLog2Div2Lm; s4 = s2 + s3; s5 = x + s1; Add12Cond(rh,rm,s5,s4); #else /* Cody and Waite like, accurate to 2^-84 */ double Log2h= 0xb.17217f8p-16 ; double Log2l= -0x2.e308654361c4cp-48 ; Add12Cond(rh,rm, x-kd*Log2h, -kd*Log2l); #endif k = shiftedXMultdb.i[LO]; M = k >> L; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> LHALF; /* Table reads */ tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; /* Test now if it is sure to launch the quick phase because no denormalized result is possible */ if (mightBeDenorm == 1) { /* The result might be denormalized, we launch the accurate phase in all cases */ /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh, &polyTblm, &polyTbll, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l); /* Final rounding and multiplication with 2^M We first multiply the highest significant byte by 2^M in two steps and adjust it then depending on the lower significant parts. We cannot multiply directly by 2^M since M is less than -1022. We first multiply by 2^(-1000) and then by 2^(M+1000). */ t3 = polyTblh * twoPowerM1000; /* Form now twoPowerM with adjusted M */ twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M + 2023) << 20; /* Multiply with the rest of M, the result will be denormalized */ t4 = t3 * twoPowerMdb.d; /* For x86, force the compiler to pass through memory for having the right rounding */ t4db.d = t4; /* Do not #if-ify this line, we need the copy */ #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) t4db2.i[HI] = t4db.i[HI]; t4db2.i[LO] = t4db.i[LO]; t4 = t4db2.d; #endif /* Remultiply by 2^(-M) for manipulating the rounding error and the lower significant parts */ M *= -1; twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M + 23) << 20; t5 = t4 * twoPowerMdb.d; t6 = t5 * twoPower1000; t7 = polyTblh - t6; /* The rounding can be decided using the sign of the arithmetical sum of the round-to-nearest-error (i.e. t7) and the lower part(s) of the final result. We add first the lower parts and add the result to the error in t7. We have to keep in mind that everything is scaled by 2^(-M). t8 can never be exactly 0 since we filter out the cases where the image of the function is algebraic and the implementation is exacter than the TMD worst case. */ polyTblm = polyTblm + polyTbll; t8 = t7 + polyTblm; /* Since we are rounding upwards, the round-to-nearest-rounding result in t4 is equal to the final result if the rounding error (i.e. the error plus the lower parts) is negative, i.e. if the rounding-to-nearest was upwards. */ if (t8 < 0.0) return t4; /* If we are here, we must adjust the final result by +1ulp Relying on the fact that the exponential is always positive, we can simplify this adjustment */ t4db.l++; return t4db.d; } /* End accurate phase launched as there might be a denormalized result */ /* No more underflow nor denormal is possible. There may be the case where M is 1024 and the value 2^M is to be multiplied may be less than 1 So the final result will be normalized and representable by the multiplication must be made in 2 steps */ /* Quick phase starts here */ rhSquare = rh * rh; rhC3 = c3 * rh; rhSquareHalf = 0.5 * rhSquare; monomialCube = rhC3 * rhSquare; rhFour = rhSquare * rhSquare; monomialFour = c4 * rhFour; highPoly = monomialCube + monomialFour; highPolyWithSquare = rhSquareHalf + highPoly; Mul22(&tablesh,&tablesl,tbl1h,tbl1m,tbl2h,tbl2m); t8 = rm + highPolyWithSquare; t9 = rh + t8; t10 = tablesh * t9; Add12(t11,t12,tablesh,t10); t13 = t12 + tablesl; Add12(polyTblh,polyTblm,t11,t13); /* Rounding test Since we know that the result of the final multiplication with 2^M will always be representable, we can do the rounding test on the factors and multiply only the final result. We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ TEST_AND_COPY_RU(roundable,res,polyTblh,polyTblm,RDROUNDCST); if (roundable) { resdb.d = res; resdb.i[HI] += M << 20; return resdb.d; } else { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh, &polyTblm, &polyTbll, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l); /* Since the final multiplication is exact, we can do the final rounding before multiplying We overcome this way also the cases where the final result is not underflowed whereas the lower parts of the intermediate final result are. */ RoundUpwards3(&res,polyTblh,polyTblm,polyTbll); /* Final multiplication with 2^M We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ resdb.d = res; resdb.i[HI] += M << 20; return resdb.d; } /* Accurate phase launched after rounding test*/ } /************************************************************* ************************************************************* * ROUNDED DOWNWARDS * ************************************************************* *************************************************************/ double exp_rd(double x) { double rh, rm, rl, tbl1h, tbl1m, tbl1l; double tbl2h, tbl2m, tbl2l; double xMultLog2InvMult2L, shiftedXMult, kd; double msLog2Div2LMultKh, msLog2Div2LMultKm, msLog2Div2LMultKl; double t1, t2, t3, t4, polyTblh, polyTblm, polyTbll; db_number shiftedXMultdb, twoPowerMdb, xdb, t4db, t4db2, resdb; int k, M, index1, index2, xIntHi, mightBeDenorm, roundable; double t5, t6, t7, t8, t9, t10, t11, t12, t13; double rhSquare, rhSquareHalf, rhC3, rhFour, monomialCube; double highPoly, highPolyWithSquare, monomialFour; double tablesh, tablesl; double s1, s2, s3, s4, s5; double res; /* Argument reduction and filtering for special cases */ /* Compute k as a double and as an int */ xdb.d = x; xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; /* Special cases tests */ xIntHi = xdb.i[HI]; mightBeDenorm = 0; /* Test if argument is a denormal or zero */ if ((xIntHi & 0x7ff00000) == 0) { /* If the argument is exactly zero, we just return 1.0 which is the mathematical image of the function */ if (x == 0.0) return 1.0; /* If the argument is a positive denormal, we must return 1.0 and raise the inexact flag. */ if (x > 0.0) return 1.0 + SMALLEST; /* Otherwise, we return 1.0 - 1ulp since exp(-greatest denorm) > 1.0 - 1ulp We must do the addition dynamically for raising the inexact flag. */ return 1.0 + mTwoM53; } /* Test if argument is greater than approx. 709 in magnitude */ if ((xIntHi & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) { /* If we are here, the result might be overflowed, underflowed, inf, or NaN */ /* Test if +/- Inf or NaN */ if ((xIntHi & 0x7fffffff) >= 0x7ff00000) { /* Either NaN or Inf in this case since exponent is maximal */ /* Test if NaN: mantissa is not 0 */ if (((xIntHi & 0x000fffff) | xdb.i[LO]) != 0) { /* x = NaN, return NaN */ return x + x; } else { /* +/- Inf */ /* Test sign */ if ((xIntHi & 0x80000000)==0) /* x = +Inf, return +Inf */ return x; else /* x = -Inf, return 0 */ return 0; } /* End which in NaN, Inf */ } /* End NaN or Inf ? */ /* If we are here, we might be overflowed, denormalized or underflowed in the result but there is no special case (NaN, Inf) left */ /* Test if actually overflowed */ if (x > OVRFLWBOUND) { /* We would be overflowed but as we are rounding downwards the nearest number lesser than the exact result is the greatest normal. In any case, we must raise the inexact flag. */ return LARGEST * (1.0 + SMALLEST); } /* Test if surely underflowed */ if (x <= UNDERFLWBOUND) { /* We are actually sure to be underflowed and not denormalized any more (at least where computing makes sense); since we are in the round upwards case, we return the smallest denormal possible. */ return SMALLEST * SMALLEST; } /* Test if possibly denormalized */ if (x <= DENORMBOUND) { /* We know now that we are not sure to be normalized in the result We just set an internal flag for a further test */ mightBeDenorm = 1; } } /* End might be a special case */ /* If we are here, we are sure to be neither +/- Inf nor NaN nor overflowed nor denormalized in the argument but we might be denormalized in the result We continue the argument reduction for the quick phase and table reads for both phases */ #if 0 Mul12(&s1,&s2,msLog2Div2Lh,kd); s3 = kd * msLog2Div2Lm; s4 = s2 + s3; s5 = x + s1; Add12Cond(rh,rm,s5,s4); #else /* Cody and Waite like, accurate to 2^-84 */ double Log2h= 0xb.17217f8p-16 ; double Log2l= -0x2.e308654361c4cp-48 ; Add12Cond(rh,rm, x-kd*Log2h, -kd*Log2l); #endif k = shiftedXMultdb.i[LO]; M = k >> L; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> LHALF; /* Table reads */ tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; /* Test now if it is sure to launch the quick phase because no denormalized result is possible */ if (mightBeDenorm == 1) { /* The result might be denormalized, we launch the accurate phase in all cases */ /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh, &polyTblm, &polyTbll, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l); /* Final rounding and multiplication with 2^M We first multiply the highest significant byte by 2^M in two steps and adjust it then depending on the lower significant parts. We cannot multiply directly by 2^M since M is less than -1022. We first multiply by 2^(-1000) and then by 2^(M+1000). */ t3 = polyTblh * twoPowerM1000; /* Form now twoPowerM with adjusted M */ twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M + 2023) << 20; /* Multiply with the rest of M, the result will be denormalized */ t4 = t3 * twoPowerMdb.d; /* For x86, force the compiler to pass through memory for having the right rounding */ t4db.d = t4; /* Do not #if-ify this line, we need the copy */ #if defined(CRLIBM_TYPECPU_AMD64) || defined(CRLIBM_TYPECPU_X86) t4db2.i[HI] = t4db.i[HI]; t4db2.i[LO] = t4db.i[LO]; t4 = t4db2.d; #endif /* Remultiply by 2^(-M) for manipulating the rounding error and the lower significant parts */ M *= -1; twoPowerMdb.i[LO] = 0; twoPowerMdb.i[HI] = (M + 23) << 20; t5 = t4 * twoPowerMdb.d; t6 = t5 * twoPower1000; t7 = polyTblh - t6; /* The rounding can be decided using the sign of the arithmetical sum of the round-to-nearest-error (i.e. t7) and the lower part(s) of the final result. We add first the lower parts and add the result to the error in t7. We have to keep in mind that everything is scaled by 2^(-M). t8 can never be exactly 0 since we filter out the cases where the image of the function is algebraic and the implementation is exacter than the TMD worst case. */ polyTblm = polyTblm + polyTbll; t8 = t7 + polyTblm; /* Since we are rounding downwards, the round-to-nearest-rounding result in t4 is equal to the final result if the rounding error (i.e. the error plus the lower parts) is positive, i.e. if the rounding-to-nearest was downwards. */ if (t8 > 0.0) return t4; /* If we are here, we must adjust the final result by +1ulp Relying on the fact that the exponential is always positive, we can simplify this adjustment */ t4db.l--; return t4db.d; } /* End accurate phase launched as there might be a denormalized result */ /* No more underflow nor denormal is possible. There may be the case where M is 1024 and the value 2^M is to be multiplied may be less than 1 So the final result will be normalized and representable by the multiplication must be made in 2 steps */ /* Quick phase starts here */ rhSquare = rh * rh; rhC3 = c3 * rh; rhSquareHalf = 0.5 * rhSquare; monomialCube = rhC3 * rhSquare; rhFour = rhSquare * rhSquare; monomialFour = c4 * rhFour; highPoly = monomialCube + monomialFour; highPolyWithSquare = rhSquareHalf + highPoly; Mul22(&tablesh,&tablesl,tbl1h,tbl1m,tbl2h,tbl2m); t8 = rm + highPolyWithSquare; t9 = rh + t8; t10 = tablesh * t9; Add12(t11,t12,tablesh,t10); t13 = t12 + tablesl; Add12(polyTblh,polyTblm,t11,t13); /* Rounding test Since we know that the result of the final multiplication with 2^M will always be representable, we can do the rounding test on the factors and multiply only the final result. We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ TEST_AND_COPY_RD(roundable,res,polyTblh,polyTblm,RDROUNDCST); if (roundable) { resdb.d = res; resdb.i[HI] += M << 20; return resdb.d; } else { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh, &polyTblm, &polyTbll, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l); /* Since the final multiplication is exact, we can do the final rounding before multiplying We overcome this way also the cases where the final result is not underflowed whereas the lower parts of the intermediate final result are. */ RoundDownwards3(&res,polyTblh,polyTblm,polyTbll); /* Final multiplication with 2^M We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ resdb.d = res; resdb.i[HI] += M << 20; return resdb.d; } /* Accurate phase launched after rounding test*/ } #ifdef BUILD_INTERVAL_FUNCTIONS interval j_exp(interval x) { interval res; double x_inf, x_sup; double rh_sup, rm_sup, rl_sup, tbl1h_sup, tbl1m_sup, tbl1l_sup; double tbl2h_sup, tbl2m_sup, tbl2l_sup; double xMultLog2InvMult2L_sup, shiftedXMult_sup, kd_sup; double msLog2Div2LMultKh_sup, msLog2Div2LMultKm_sup, msLog2Div2LMultKl_sup; double t1_sup, t2_sup, polyTblh_sup, polyTblm_sup, polyTbll_sup; db_number shiftedXMultdb_sup, xdb_sup, resdb_sup; int k_sup, M_sup, index1_sup, index2_sup, xIntHi_sup, mightBeDenorm_sup, roundable; double t8_sup, t9_sup, t10_sup, t11_sup, t12_sup, t13_sup; double rhSquare_sup, rhSquareHalf_sup, rhC3_sup, rhFour_sup, monomialCube_sup; double highPoly_sup, highPolyWithSquare_sup, monomialFour_sup; double tablesh_sup, tablesl_sup; double s1_sup, s2_sup, s3_sup, s4_sup, s5_sup; double res_sup; double rh_inf, rm_inf, rl_inf, tbl1h_inf, tbl1m_inf, tbl1l_inf; double tbl2h_inf, tbl2m_inf, tbl2l_inf; double xMultLog2InvMult2L_inf, shiftedXMult_inf, kd_inf; double msLog2Div2LMultKh_inf, msLog2Div2LMultKm_inf, msLog2Div2LMultKl_inf; double t1_inf, t2_inf, polyTblh_inf, polyTblm_inf, polyTbll_inf; db_number shiftedXMultdb_inf, xdb_inf, resdb_inf; int k_inf, M_inf, index1_inf, index2_inf, xIntHi_inf, mightBeDenorm_inf; double t8_inf, t9_inf, t10_inf, t11_inf, t12_inf, t13_inf; double rhSquare_inf, rhSquareHalf_inf, rhC3_inf, rhFour_inf, monomialCube_inf; double highPoly_inf, highPolyWithSquare_inf, monomialFour_inf; double tablesh_inf, tablesl_inf; double s1_inf, s2_inf, s3_inf, s4_inf, s5_inf; double res_inf; double res_simple_inf, res_simple_sup; int infDone=0; int supDone=0; x_inf=LOW(x); x_sup=UP(x); /* Argument reduction and filtering for special cases */ /* Compute k as a double and as an int */ xdb_sup.d = x_sup; xdb_inf.d = x_inf; xMultLog2InvMult2L_sup = x_sup * log2InvMult2L; xMultLog2InvMult2L_inf = x_inf * log2InvMult2L; shiftedXMult_sup = xMultLog2InvMult2L_sup + shiftConst; shiftedXMult_inf = xMultLog2InvMult2L_inf + shiftConst; kd_sup = shiftedXMult_sup - shiftConst; kd_inf = shiftedXMult_inf - shiftConst; shiftedXMultdb_sup.d = shiftedXMult_sup; shiftedXMultdb_inf.d = shiftedXMult_inf; /* Special cases tests */ xIntHi_sup = xdb_sup.i[HI]; mightBeDenorm_sup = 0; /* Special cases tests */ xIntHi_inf = xdb_inf.i[HI]; mightBeDenorm_inf = 0; if ( __builtin_expect( ((xIntHi_sup & 0x7ff00000) == 0) || (((xIntHi_sup & 0x7ff00000) == 0) && (x_sup == 0.0)) || (((xIntHi_sup & 0x7ff00000) == 0) && (x_sup < 0.0)) || (((xIntHi_sup & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && ((xIntHi_sup & 0x7fffffff) >= 0x7ff00000)) || (((xIntHi_sup & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && ((xIntHi_sup & 0x7fffffff) >= 0x7ff00000) && (((xIntHi_sup & 0x000fffff) | xdb_sup.i[LO]) != 0)) || (((xIntHi_sup & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && ((xIntHi_sup & 0x7fffffff) >= 0x7ff00000) && ((xIntHi_sup & 0x80000000)==0)) || (((xIntHi_sup & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && (x_sup > OVRFLWBOUND)) || (((xIntHi_sup & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && (x_sup <= UNDERFLWBOUND)) || (((xIntHi_sup & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && (x_sup <= DENORMBOUND)) || ((xIntHi_inf & 0x7ff00000) == 0) || (((xIntHi_inf & 0x7ff00000) == 0) && (x_inf == 0.0)) || (((xIntHi_inf & 0x7ff00000) == 0) && (x_inf > 0.0)) || (((xIntHi_inf & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && ((xIntHi_inf & 0x7fffffff) >= 0x7ff00000)) || (((xIntHi_inf & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && ((xIntHi_inf & 0x7fffffff) >= 0x7ff00000) && (((xIntHi_inf & 0x000fffff) | xdb_inf.i[LO]) != 0)) || (((xIntHi_inf & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && ((xIntHi_inf & 0x7fffffff) >= 0x7ff00000) && ((xIntHi_inf & 0x80000000)==0)) || (((xIntHi_inf & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && (x_inf > OVRFLWBOUND)) || (((xIntHi_inf & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && (x_inf <= UNDERFLWBOUND)) || (((xIntHi_inf & 0x7fffffff) >= OVRUDRFLWSMPLBOUND) && (x_inf <= DENORMBOUND)) ,FALSE)) { ASSIGN_LOW(res,exp_rd(LOW(x))); ASSIGN_UP(res,exp_ru(UP(x))); return res; } /* Test if argument is a denormal or zero */ /* If we are here, we are sure to be neither +/- Inf nor NaN nor overflowed nor denormalized in the argument but we might be denormalized in the result We continue the argument reduction for the quick phase and table reads for both phases */ Mul12(&s1_sup,&s2_sup,msLog2Div2Lh,kd_sup); Mul12(&s1_inf,&s2_inf,msLog2Div2Lh,kd_inf); s3_sup = kd_sup * msLog2Div2Lm; s3_inf = kd_inf * msLog2Div2Lm; s4_sup = s2_sup + s3_sup; s4_inf = s2_inf + s3_inf; s5_sup = x_sup + s1_sup; s5_inf = x_inf + s1_inf; Add12Cond(rh_sup,rm_sup,s5_sup,s4_sup); Add12Cond(rh_inf,rm_inf,s5_inf,s4_inf); k_sup = shiftedXMultdb_sup.i[LO]; k_inf = shiftedXMultdb_inf.i[LO]; M_sup = k_sup >> L; M_inf = k_inf >> L; index1_sup = k_sup & INDEXMASK1; index1_inf = k_inf & INDEXMASK1; index2_sup = (k_sup & INDEXMASK2) >> LHALF; index2_inf = (k_inf & INDEXMASK2) >> LHALF; /* Table reads */ tbl1h_sup = twoPowerIndex1[index1_sup].hi; tbl1h_inf = twoPowerIndex1[index1_inf].hi; tbl1m_sup = twoPowerIndex1[index1_sup].mi; tbl1m_inf = twoPowerIndex1[index1_inf].mi; tbl2h_sup = twoPowerIndex2[index2_sup].hi; tbl2h_inf = twoPowerIndex2[index2_inf].hi; tbl2m_sup = twoPowerIndex2[index2_sup].mi; tbl2m_inf = twoPowerIndex2[index2_inf].mi; /* No more underflow nor denormal is possible. There may be the case where M is 1024 and the value 2^M is to be multiplied may be less than 1 So the final result will be normalized and representable by the multiplication must be made in 2 steps */ /* Quick phase starts here */ rhSquare_sup = rh_sup * rh_sup; rhSquare_inf = rh_inf * rh_inf; rhC3_sup = c3 * rh_sup; rhC3_inf = c3 * rh_inf; rhSquareHalf_sup = 0.5 * rhSquare_sup; rhSquareHalf_inf = 0.5 * rhSquare_inf; monomialCube_sup = rhC3_sup * rhSquare_sup; monomialCube_inf = rhC3_inf * rhSquare_inf; rhFour_sup = rhSquare_sup * rhSquare_sup; rhFour_inf = rhSquare_inf * rhSquare_inf; monomialFour_sup = c4 * rhFour_sup; monomialFour_inf = c4 * rhFour_inf; highPoly_sup = monomialCube_sup + monomialFour_sup; highPoly_inf = monomialCube_inf + monomialFour_inf; highPolyWithSquare_sup = rhSquareHalf_sup + highPoly_sup; highPolyWithSquare_inf = rhSquareHalf_inf + highPoly_inf; Mul22(&tablesh_sup,&tablesl_sup,tbl1h_sup,tbl1m_sup,tbl2h_sup,tbl2m_sup); Mul22(&tablesh_inf,&tablesl_inf,tbl1h_inf,tbl1m_inf,tbl2h_inf,tbl2m_inf); t8_sup = rm_sup + highPolyWithSquare_sup; t8_inf = rm_inf + highPolyWithSquare_inf; t9_sup = rh_sup + t8_sup; t9_inf = rh_inf + t8_inf; t10_sup = tablesh_sup * t9_sup; t10_inf = tablesh_inf * t9_inf; Add12(t11_sup,t12_sup,tablesh_sup,t10_sup); Add12(t11_inf,t12_inf,tablesh_inf,t10_inf); t13_sup = t12_sup + tablesl_sup; t13_inf = t12_inf + tablesl_inf; Add12(polyTblh_sup,polyTblm_sup,t11_sup,t13_sup); Add12(polyTblh_inf,polyTblm_inf,t11_inf,t13_inf); /* Rounding test Since we know that the result of the final multiplication with 2^M will always be representable, we can do the rounding test on the factors and multiply only the final result. We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ if (infDone==1) res_inf=res_simple_inf; if (supDone==1) res_sup=res_simple_sup; // TEST_AND_COPY_RDRU_EXP(roundable,infDone,supDone,res_inf,polyTblh_inf,polyTblm_inf,res_sup,polyTblh_sup,polyTblm_sup,RDROUNDCST); db_number yh_inf, yl_inf, u53_inf, yh_sup, yl_sup, u53_sup; int yh_inf_neg, yl_inf_neg, yh_sup_neg, yl_sup_neg; int rd_ok, ru_ok; double save_res_inf=res_inf; double save_res_sup=res_sup; yh_inf.d = polyTblh_inf; yl_inf.d = polyTblm_inf; yh_inf_neg = (yh_inf.i[HI] & 0x80000000); yl_inf_neg = (yl_inf.i[HI] & 0x80000000); yh_inf.l = yh_inf.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ yl_inf.l = yl_inf.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ u53_inf.l = (yh_inf.l & ULL(7ff0000000000000)) + ULL(0010000000000000); yh_sup.d = polyTblh_sup; yl_sup.d = polyTblm_sup; yh_sup_neg = (yh_sup.i[HI] & 0x80000000); yl_sup_neg = (yl_sup.i[HI] & 0x80000000); yh_sup.l = yh_sup.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ yl_sup.l = yl_sup.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ u53_sup.l = (yh_sup.l & ULL(7ff0000000000000)) + ULL(0010000000000000); roundable = 0; rd_ok=(yl_inf.d > RDROUNDCST * u53_inf.d); ru_ok=(yl_sup.d > RDROUNDCST * u53_sup.d); if(yl_inf_neg) { /* The case yl==0 is filtered by the above test*/ /* return next down */ yh_inf.d = polyTblh_inf; if(yh_inf_neg) yh_inf.l++; else yh_inf.l--; /* Beware: fails for zero */ res_inf = yh_inf.d; } else { res_inf = polyTblh_inf; } if(!yl_sup_neg) { /* The case yl==0 is filtered by the above test*/ /* return next up */ yh_sup.d = polyTblh_sup; if(yh_sup_neg) yh_sup.l--; else yh_sup.l++; /* Beware: fails for zero */ res_sup = yh_sup.d; } else { res_sup = polyTblh_sup; } if(infDone) res_inf=save_res_inf; if(supDone) res_sup=save_res_sup; if(rd_ok && ru_ok){ roundable=3; } else if (rd_ok){ roundable=1; } else if (ru_ok){ roundable=2; } resdb_inf.d = res_inf; resdb_sup.d = res_sup; if (roundable==3) { if (infDone==0){ resdb_inf.i[HI] += M_inf << 20; } ASSIGN_LOW(res,resdb_inf.d); if (supDone==0){ resdb_sup.i[HI] += M_sup << 20; } ASSIGN_UP(res,resdb_sup.d); return res; } if(roundable==1) { if(infDone==0){ resdb_inf.i[HI] += M_inf << 20; } ASSIGN_LOW(res,resdb_inf.d); if(supDone==0){ /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh_sup,&msLog2Div2LMultKm_sup,&msLog2Div2LMultKl_sup,kd_sup,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1_sup = x_sup + msLog2Div2LMultKh_sup; Add12Cond(rh_sup,t2_sup,t1_sup,msLog2Div2LMultKm_sup); Add12Cond(rm_sup,rl_sup,t2_sup,msLog2Div2LMultKl_sup); /* Table reads for accurate phase */ tbl1l_sup = twoPowerIndex1[index1_sup].lo; tbl2l_sup = twoPowerIndex2[index2_sup].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh_sup, &polyTblm_sup, &polyTbll_sup, rh_sup, rm_sup, rl_sup, tbl1h_sup, tbl1m_sup, tbl1l_sup, tbl2h_sup, tbl2m_sup, tbl2l_sup); /* Since the final multiplication is exact, we can do the final rounding before multiplying We overcome this way also the cases where the final result is not underflowed whereas the lower parts of the intermediate final result are. */ RoundUpwards3(&res_sup,polyTblh_sup,polyTblm_sup,polyTbll_sup); /* Final multiplication with 2^M We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ resdb_sup.d = res_sup; resdb_sup.i[HI] += M_sup << 20; } ASSIGN_UP(res,resdb_sup.d); return res; } /* Accurate phase launched after rounding test*/ if (roundable==2) { if (infDone==0){ /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh_inf,&msLog2Div2LMultKm_inf,&msLog2Div2LMultKl_inf,kd_inf,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1_inf = x_inf + msLog2Div2LMultKh_inf; Add12Cond(rh_inf,t2_inf,t1_inf,msLog2Div2LMultKm_inf); Add12Cond(rm_inf,rl_inf,t2_inf,msLog2Div2LMultKl_inf); /* Table reads for accurate phase */ tbl1l_inf = twoPowerIndex1[index1_inf].lo; tbl2l_inf = twoPowerIndex2[index2_inf].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh_inf, &polyTblm_inf, &polyTbll_inf, rh_inf, rm_inf, rl_inf, tbl1h_inf, tbl1m_inf, tbl1l_inf, tbl2h_inf, tbl2m_inf, tbl2l_inf); /* Since the final multiplication is exact, we can do the final rounding before multiplying We overcome this way also the cases where the final result is not underflowed whereas the lower parts of the intermediate final result are. */ RoundDownwards3(&res_inf,polyTblh_inf,polyTblm_inf,polyTbll_inf); /* Final multiplication with 2^M We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ resdb_inf.d = res_inf; resdb_inf.i[HI] += M_inf << 20; } ASSIGN_LOW(res,resdb_inf.d); if(supDone==0){ resdb_sup.i[HI] += M_sup << 20; } ASSIGN_UP(res,resdb_sup.d); return res; } /* Accurate phase launched after rounding test*/ if(roundable==0) { if(supDone==0){ /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh_sup,&msLog2Div2LMultKm_sup,&msLog2Div2LMultKl_sup,kd_sup,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1_sup = x_sup + msLog2Div2LMultKh_sup; Add12Cond(rh_sup,t2_sup,t1_sup,msLog2Div2LMultKm_sup); Add12Cond(rm_sup,rl_sup,t2_sup,msLog2Div2LMultKl_sup); /* Table reads for accurate phase */ tbl1l_sup = twoPowerIndex1[index1_sup].lo; tbl2l_sup = twoPowerIndex2[index2_sup].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh_sup, &polyTblm_sup, &polyTbll_sup, rh_sup, rm_sup, rl_sup, tbl1h_sup, tbl1m_sup, tbl1l_sup, tbl2h_sup, tbl2m_sup, tbl2l_sup); /* Since the final multiplication is exact, we can do the final rounding before multiplying We overcome this way also the cases where the final result is not underflowed whereas the lower parts of the intermediate final result are. */ RoundUpwards3(&res_sup,polyTblh_sup,polyTblm_sup,polyTbll_sup); /* Final multiplication with 2^M We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ resdb_sup.d = res_sup; resdb_sup.i[HI] += M_sup << 20; } ASSIGN_UP(res,resdb_sup.d); if (infDone==0){ /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh_inf,&msLog2Div2LMultKm_inf,&msLog2Div2LMultKl_inf,kd_inf,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1_inf = x_inf + msLog2Div2LMultKh_inf; Add12Cond(rh_inf,t2_inf,t1_inf,msLog2Div2LMultKm_inf); Add12Cond(rm_inf,rl_inf,t2_inf,msLog2Div2LMultKl_inf); /* Table reads for accurate phase */ tbl1l_inf = twoPowerIndex1[index1_inf].lo; tbl2l_inf = twoPowerIndex2[index2_inf].lo; /* Call accurate phase */ exp_td_accurate(&polyTblh_inf, &polyTblm_inf, &polyTbll_inf, rh_inf, rm_inf, rl_inf, tbl1h_inf, tbl1m_inf, tbl1l_inf, tbl2h_inf, tbl2m_inf, tbl2l_inf); /* Since the final multiplication is exact, we can do the final rounding before multiplying We overcome this way also the cases where the final result is not underflowed whereas the lower parts of the intermediate final result are. */ RoundDownwards3(&res_inf,polyTblh_inf,polyTblm_inf,polyTbll_inf); /* Final multiplication with 2^M We implement the multiplication in integer computations to overcome the problem of the non-representability of 2^1024 if M = 1024 */ resdb_inf.d = res_inf; resdb_inf.i[HI] += M_inf << 20; } ASSIGN_LOW(res,resdb_inf.d); return res; } /* Accurate phase launched after rounding test*/ return res; } #endif interval-3.2.0/src/crlibm/exp-td.h0000644000000000000000000011533313316017127015106 0ustar 00000000000000/* * This function computes exp, correctly rounded, * using experimental techniques based on triple double arithmetics * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" /*File generated by maple/exp-td.mpl*/ #define L 12 #define LHALF 6 #define log2InvMult2L 5.90927888748119403317105025053024291992187500000000e+03 #define msLog2Div2Lh -1.69225385878892892145206050535932718048570677638054e-04 #define msLog2Div2Lm -5.66173538536694228129338642508144915789549786200850e-21 #define msLog2Div2Ll -1.39348350547270802387134479195513221596886344528448e-37 #define shiftConst 6.75539944105574400000000000000000000000000000000000e+15 #define INDEXMASK1 0x0000003f #define INDEXMASK2 0x00000fc0 #define OVRUDRFLWSMPLBOUND 0x4086232b #define OVRFLWBOUND 7.09782712893383973096206318587064743041992187500000e+02 #define LARGEST 1.79769313486231570814527423731704356798070567525845e+308 #define SMALLEST 4.94065645841246544176568792868221372365059802614325e-324 #define DENORMBOUND -7.08396418532264078748994506895542144775390625000000e+02 #define UNDERFLWBOUND -7.45133219101941222106688655912876129150390625000000e+02 #define twoPowerM1000 9.33263618503218878990089544723817169617091446371708e-302 #define twoPower1000 1.07150860718626732094842504906000181056140481170553e+301 #define ROUNDCST 1.00097751710654947574476244840271277078237100388308e+00 #define RDROUNDCST 5.42101086242752217003726400434970855712890625000000e-20 #define twoM52 2.22044604925031308084726333618164062500000000000000e-16 #define mTwoM53 -1.11022302462515654042363166809082031250000000000000e-16 #define c3 1.66666666696497128841158996692684013396501541137695e-01 #define c4 4.16666666766101478902584176466916687786579132080078e-02 #define accPolyC3h 1.66666666666666657414808128123695496469736099243164e-01 #define accPolyC3l 9.25185853854303382711778796549658869198239876296876e-18 #define accPolyC4h 4.16666666666666643537020320309238741174340248107910e-02 #define accPolyC4l 2.31256737763466047834406500740034679807274635559840e-18 #define accPolyC5 8.33333333333333321768510160154619370587170124053955e-03 #define accPolyC6 1.38888888911084160647513296993338371976278722286224e-03 #define accPolyC7 1.98412698447204637443655461659375305316643789410591e-04 typedef struct tPi_t_tag {double hi; double mi; double lo;} tPi_t; static const tPi_t twoPowerIndex1[64] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1hi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1mi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1lo[0] */ } , { 1.00016923970530213772178740327944979071617126464844e+00, /* twoPowerIndex1hi[1] */ 9.33618533547846199388179470637929281332443150415515e-17, /* twoPowerIndex1mi[1] */ 3.77297954885090084710073756456287936644477196404411e-33, /* twoPowerIndex1lo[1] */ } , { 1.00033850805268231809463941317517310380935668945312e+00, /* twoPowerIndex1hi[2] */ -5.14133393131895706530678267769194263660821897510018e-18, /* twoPowerIndex1mi[2] */ 3.65532984508913994275805274025238001612209382982528e-34, /* twoPowerIndex1lo[2] */ } , { 1.00050780504698755279946453811135143041610717773438e+00, /* twoPowerIndex1hi[3] */ 6.96242402202057255168575283120383384543281723609229e-17, /* twoPowerIndex1mi[3] */ 5.20646484360987194687938744912769762301408608274186e-34, /* twoPowerIndex1lo[3] */ } , { 1.00067713069306640782940576173132285475730895996094e+00, /* twoPowerIndex1hi[4] */ -5.11512329768566763581175858027414623025077801052578e-17, /* twoPowerIndex1mi[4] */ 6.98198098827029289611306311409722598417652045670746e-34, /* twoPowerIndex1lo[4] */ } , { 1.00084648499576744917760606767842546105384826660156e+00, /* twoPowerIndex1hi[5] */ 8.42299002458648658027371639395540881533737558365359e-17, /* twoPowerIndex1mi[5] */ 2.36970468083963275494383447607242933566525306383712e-33, /* twoPowerIndex1lo[5] */ } , { 1.00101586795994101919404783984646201133728027343750e+00, /* twoPowerIndex1hi[6] */ -2.82452207477616780689379931990767172214919031737312e-17, /* twoPowerIndex1mi[6] */ -1.95728551891328398835983018867545661396300096090192e-33, /* twoPowerIndex1lo[6] */ } , { 1.00118527959043746022871346212923526763916015625000e+00, /* twoPowerIndex1hi[7] */ -7.18042456559213166577815896739695813826899291527385e-17, /* twoPowerIndex1mi[7] */ -4.76259460142737667571053552520587169925041399888400e-33, /* twoPowerIndex1lo[7] */ } , { 1.00135471989210822485460994357708841562271118164062e+00, /* twoPowerIndex1hi[8] */ -1.89737284167929933536294189134998232481318340155287e-17, /* twoPowerIndex1mi[8] */ -1.14644761608474571162584330231223616391499645510675e-34, /* twoPowerIndex1lo[8] */ } , { 1.00152418886980565382316399336559697985649108886719e+00, /* twoPowerIndex1hi[9] */ 9.06044106726912172835402556659442028244667434824268e-17, /* twoPowerIndex1mi[9] */ -9.28795936877474030548429956901821606468166518236870e-34, /* twoPowerIndex1lo[9] */ } , { 1.00169368652838319810882694582687690854072570800781e+00, /* twoPowerIndex1hi[10] */ -7.17327634990031997530849131951948428542423257707819e-17, /* twoPowerIndex1mi[10] */ 6.07647560689104755979568262152596670382288431776872e-33, /* twoPowerIndex1lo[10] */ } , { 1.00186321287269430868605013529304414987564086914062e+00, /* twoPowerIndex1hi[11] */ -1.33071962467226606689858482393149015112554043251841e-17, /* twoPowerIndex1mi[11] */ -3.85443386097781554341108465500150047004226523597749e-34, /* twoPowerIndex1lo[11] */ } , { 1.00203276790759399084151937131537124514579772949219e+00, /* twoPowerIndex1hi[12] */ 2.57269259432211179649018725316354562817431777421067e-17, /* twoPowerIndex1mi[12] */ 6.79751255613789265201334995370535043187556454092516e-34, /* twoPowerIndex1lo[12] */ } , { 1.00220235163793791599573523853905498981475830078125e+00, /* twoPowerIndex1hi[13] */ -3.92993778548451720552933864302152846562830407163222e-17, /* twoPowerIndex1mi[13] */ 2.22740945016647607963332576015739728975193247400334e-33, /* twoPowerIndex1lo[13] */ } , { 1.00237196406858219965840817167190834879875183105469e+00, /* twoPowerIndex1hi[14] */ 8.46137724799471749932697856411684097253648908880386e-17, /* twoPowerIndex1mi[14] */ -1.15795350476069740873680647805085951983720786847012e-33, /* twoPowerIndex1lo[14] */ } , { 1.00254160520438451165148308064090088009834289550781e+00, /* twoPowerIndex1hi[15] */ -4.19488324163994025318330321149973224973566383682287e-17, /* twoPowerIndex1mi[15] */ -1.10867727371575753136248480661711257993643946476249e-33, /* twoPowerIndex1lo[15] */ } , { 1.00271127505020252179690487537300214171409606933594e+00, /* twoPowerIndex1hi[16] */ -3.63661592869226394431650732319448247819940912156384e-17, /* twoPowerIndex1mi[16] */ -6.58076018413558386665763067745208065096307047224855e-34, /* twoPowerIndex1lo[16] */ } , { 1.00288097361089523218424801598303020000457763671875e+00, /* twoPowerIndex1hi[17] */ -2.61094406324393831074545742903203024867557691172893e-17, /* twoPowerIndex1mi[17] */ 1.20560913995705683042979390390212408639703633013464e-33, /* twoPowerIndex1lo[17] */ } , { 1.00305070089132231103690173767972737550735473632812e+00, /* twoPowerIndex1hi[18] */ 1.75307847798233211014008193947934807324617806015147e-17, /* twoPowerIndex1mi[18] */ 1.13393213893456062969952574781413432615748154285102e-33, /* twoPowerIndex1lo[18] */ } , { 1.00322045689634431475667497579706832766532897949219e+00, /* twoPowerIndex1hi[19] */ 5.75392352562826744411122442879351687879645730521252e-17, /* twoPowerIndex1mi[19] */ -2.67723202763627633853056570968049475423332897231238e-33, /* twoPowerIndex1lo[19] */ } , { 1.00339024163082268792379636579426005482673645019531e+00, /* twoPowerIndex1hi[20] */ -8.68492200511795617368964392061338881522209699276521e-18, /* twoPowerIndex1mi[20] */ -3.48402050975972235345434529928044249018150775634918e-34, /* twoPowerIndex1lo[20] */ } , { 1.00356005509961931920770439319312572479248046875000e+00, /* twoPowerIndex1hi[21] */ 9.49003543098177759384527648244793376993805358019830e-17, /* twoPowerIndex1mi[21] */ -2.72838479693459377473949067074824993718971708464416e-34, /* twoPowerIndex1lo[21] */ } , { 1.00372989730759765159007201873464509844779968261719e+00, /* twoPowerIndex1hi[22] */ -8.71038060581842237129503222771273097866222639659196e-17, /* twoPowerIndex1mi[22] */ 1.08618280977421918449964280592134822915254002216492e-33, /* twoPowerIndex1lo[22] */ } , { 1.00389976825962090600796727812848985195159912109375e+00, /* twoPowerIndex1hi[23] */ 3.49589169585715450145113080496294928974704413200507e-17, /* twoPowerIndex1mi[23] */ -2.94144759791575889018758341844218078845293410867033e-33, /* twoPowerIndex1lo[23] */ } , { 1.00406966796055407975529760733479633927345275878906e+00, /* twoPowerIndex1hi[24] */ 9.75378754984024099793268477195846557070899843396028e-17, /* twoPowerIndex1mi[24] */ 5.64300142720863839874652371486135387544215443970822e-33, /* twoPowerIndex1lo[24] */ } , { 1.00423959641526283625978521740762516856193542480469e+00, /* twoPowerIndex1hi[25] */ -1.05762211962928569325595987354393790031696252155330e-16, /* twoPowerIndex1mi[25] */ 5.83707943855262433756426258532402998630656838432942e-33, /* twoPowerIndex1lo[25] */ } , { 1.00440955362861283894915231940103694796562194824219e+00, /* twoPowerIndex1hi[26] */ 4.20918873812712592966120368574870018412444102186114e-17, /* twoPowerIndex1mi[26] */ 2.17971061415864797757688538084764343153482363480001e-33, /* twoPowerIndex1lo[26] */ } , { 1.00457953960547174965256544965086504817008972167969e+00, /* twoPowerIndex1hi[27] */ -1.67001668575547876279593068362269006396955075031486e-17, /* twoPowerIndex1mi[27] */ 8.56552273127180632250100064178508499726804497630949e-34, /* twoPowerIndex1lo[27] */ } , { 1.00474955435070723019919114449294283986091613769531e+00, /* twoPowerIndex1hi[28] */ -1.62314635541245143576050143734168865049382925451905e-17, /* twoPowerIndex1mi[28] */ 9.28530603331304279248127378347521992965436217888846e-35, /* twoPowerIndex1lo[28] */ } , { 1.00491959786918805264122056541964411735534667968750e+00, /* twoPowerIndex1hi[29] */ 2.30285392780281171183781407072193459566423534757738e-17, /* twoPowerIndex1mi[29] */ -4.94345170697772961451844215454960159293576885861471e-34, /* twoPowerIndex1lo[29] */ } , { 1.00508967016578387720926457404857501387596130371094e+00, /* twoPowerIndex1hi[30] */ 1.64180469767730323539044065876968510741128671646342e-17, /* twoPowerIndex1mi[30] */ -1.40120338097898451052996285664279342840562084008057e-34, /* twoPowerIndex1lo[30] */ } , { 1.00525977124536503026774880709126591682434082031250e+00, /* twoPowerIndex1hi[31] */ 3.72669843182841367415839881731427710949489409371967e-17, /* twoPowerIndex1mi[31] */ -6.47401139805376556406832921347318553328966160972009e-34, /* twoPowerIndex1lo[31] */ } , { 1.00542990111280272635951860138447955250740051269531e+00, /* twoPowerIndex1hi[32] */ 9.49918653545503175702165599813853704096085691656846e-17, /* twoPowerIndex1mi[32] */ 2.69197614795285565383714012654266434015814803945559e-33, /* twoPowerIndex1lo[32] */ } , { 1.00560005977296929025044391892151907086372375488281e+00, /* twoPowerIndex1hi[33] */ -8.68093131444458156819420437418787120833640771986467e-17, /* twoPowerIndex1mi[33] */ 1.70120132411898592857823454488038166970266621441155e-33, /* twoPowerIndex1lo[33] */ } , { 1.00577024723073704670639472169568762183189392089844e+00, /* twoPowerIndex1hi[34] */ 4.00054749103011688253297776917861866454998331259826e-17, /* twoPowerIndex1mi[34] */ 1.31925963209617013098908877209722537258440391267352e-33, /* twoPowerIndex1lo[34] */ } , { 1.00594046349098009685008037195075303316116333007812e+00, /* twoPowerIndex1hi[35] */ 7.19049911150997399545071999536183023264065701084941e-17, /* twoPowerIndex1mi[35] */ 5.87388840736458866162752231275781178461761843642826e-33, /* twoPowerIndex1lo[35] */ } , { 1.00611070855857298589342008199309930205345153808594e+00, /* twoPowerIndex1hi[36] */ -1.39080686710657830063564897325456873924612265621065e-17, /* twoPowerIndex1mi[36] */ -1.04608842475341479042763417006066485614641577765254e-33, /* twoPowerIndex1lo[36] */ } , { 1.00628098243839092518214783922303467988967895507812e+00, /* twoPowerIndex1hi[37] */ -8.14020864257304964668281784838729787981918541118695e-17, /* twoPowerIndex1mi[37] */ 9.81687621053626949463979101287162593669867055078380e-34, /* twoPowerIndex1lo[37] */ } , { 1.00645128513531001424041733116609975695610046386719e+00, /* twoPowerIndex1hi[38] */ -5.76215104374953424938341851527793234314721266620465e-17, /* twoPowerIndex1mi[38] */ -2.57074696660737495074482007072094547944536206743811e-33, /* twoPowerIndex1lo[38] */ } , { 1.00662161665420724077080194547306746244430541992188e+00, /* twoPowerIndex1hi[39] */ 6.74527847731045679518854873240614524466814727371618e-17, /* twoPowerIndex1mi[39] */ 3.78807035520293397050945635744099720111701312971531e-33, /* twoPowerIndex1lo[39] */ } , { 1.00679197699996070269889969495125114917755126953125e+00, /* twoPowerIndex1hi[40] */ 1.89985572403462958330039110072328316553950667129559e-17, /* twoPowerIndex1mi[40] */ -9.63431595756658515104002497950853752466876076619761e-34, /* twoPowerIndex1lo[40] */ } , { 1.00696236617744894203951844247058033943176269531250e+00, /* twoPowerIndex1hi[41] */ -9.63743003231640715845365699595418727819327585110316e-17, /* twoPowerIndex1mi[41] */ 5.37739172125896523173793245498965828230574349410153e-34, /* twoPowerIndex1lo[41] */ } , { 1.00713278419155116694128082599490880966186523437500e+00, /* twoPowerIndex1hi[42] */ -1.25286544624539788678561179100718466970708089928402e-17, /* twoPowerIndex1mi[42] */ 6.73461401738595970431440883296934068477066941591536e-34, /* twoPowerIndex1lo[42] */ } , { 1.00730323104714791782043903367593884468078613281250e+00, /* twoPowerIndex1hi[43] */ 3.02057888784369419361601396858156577301726732087163e-17, /* twoPowerIndex1mi[43] */ 2.28748779695564659338938424768062274005093770790899e-33, /* twoPowerIndex1lo[43] */ } , { 1.00747370674912040122706002875929698348045349121094e+00, /* twoPowerIndex1hi[44] */ -4.86939425860856490657306074829518805252629724182687e-17, /* twoPowerIndex1mi[44] */ -2.15005825118530979132585793750524459885823808259600e-33, /* twoPowerIndex1lo[44] */ } , { 1.00764421130235026780042062455322593450546264648438e+00, /* twoPowerIndex1hi[45] */ 5.22402993768745316546273304631524097955173932918745e-17, /* twoPowerIndex1mi[45] */ 1.56859855755260687389551771821040360984576895950448e-33, /* twoPowerIndex1lo[45] */ } , { 1.00781474471172072249203210958512499928474426269531e+00, /* twoPowerIndex1hi[46] */ -9.36154355147845590745647945463041972879607082944076e-17, /* twoPowerIndex1mi[46] */ 2.73525232969860711971224663796949142049450209755900e-33, /* twoPowerIndex1lo[46] */ } , { 1.00798530698211497025340577238239347934722900390625e+00, /* twoPowerIndex1hi[47] */ -8.65251323306194956904999437269495581443314540350323e-17, /* twoPowerIndex1mi[47] */ 3.95202635576858744637745517221782298786195221857564e-33, /* twoPowerIndex1lo[47] */ } , { 1.00815589811841754830368245166027918457984924316406e+00, /* twoPowerIndex1hi[48] */ -3.25205875608430806088583499076669170064325943797327e-17, /* twoPowerIndex1mi[48] */ 2.46355206137317856028163445564386882918089954604456e-33, /* twoPowerIndex1lo[48] */ } , { 1.00832651812551388204042268625926226377487182617188e+00, /* twoPowerIndex1hi[49] */ -9.91723226806091428304981281566311898208154515630026e-17, /* twoPowerIndex1mi[49] */ -5.54888559019883709197982155449053331751526019176611e-33, /* twoPowerIndex1lo[49] */ } , { 1.00849716700828984095039686508243903517723083496094e+00, /* twoPowerIndex1hi[50] */ -7.13604740416252276802131825807759910735798752142063e-17, /* twoPowerIndex1mi[50] */ 4.98539917129953776836361552714923793985513981224277e-33, /* twoPowerIndex1lo[50] */ } , { 1.00866784477163240474340000218944624066352844238281e+00, /* twoPowerIndex1hi[51] */ -1.72686837122432199045769102324975071816159176955755e-17, /* twoPowerIndex1mi[51] */ 1.49699250027049460850618457278328039699137666243513e-33, /* twoPowerIndex1lo[51] */ } , { 1.00883855142042944130764681176515296101570129394531e+00, /* twoPowerIndex1hi[52] */ -6.61995469367394011396161169543794432105455894234207e-17, /* twoPowerIndex1mi[52] */ -1.37180394060118324236386341775148249159351409372011e-33, /* twoPowerIndex1lo[52] */ } , { 1.00900928695956926262056185805704444646835327148438e+00, /* twoPowerIndex1hi[53] */ 3.56545690151302037529536411250390721695546928174132e-17, /* twoPowerIndex1mi[53] */ -3.04973969952342772070810129193852120178103073824881e-33, /* twoPowerIndex1lo[53] */ } , { 1.00918005139394151292719925550045445561408996582031e+00, /* twoPowerIndex1hi[54] */ 3.71731001370881785990046067286312459291233468170260e-17, /* twoPowerIndex1mi[54] */ 2.33846700487585833881864340821781209486455210644683e-33, /* twoPowerIndex1lo[54] */ } , { 1.00935084472843628056182296859333291649818420410156e+00, /* twoPowerIndex1hi[55] */ 7.06257240682552768409771521622687712943771198652841e-17, /* twoPowerIndex1mi[55] */ -2.69254581845265407066861039619808678678301305791490e-33, /* twoPowerIndex1lo[55] */ } , { 1.00952166696794476408172158699017018079757690429688e+00, /* twoPowerIndex1hi[56] */ -1.43214123034288192889278157016818203958577074101904e-17, /* twoPowerIndex1mi[56] */ 1.18343254028162625925516501493235924385911429505127e-33, /* twoPowerIndex1lo[56] */ } , { 1.00969251811735860613339355040807276964187622070312e+00, /* twoPowerIndex1hi[57] */ 1.56681880131341096294393603553275561732689802958880e-17, /* twoPowerIndex1mi[57] */ -7.81531085085694011629938080711347719818453468652371e-34, /* twoPowerIndex1lo[57] */ } , { 1.00986339818157078163096684875199571251869201660156e+00, /* twoPowerIndex1hi[58] */ -1.10436957803936884179513517801130489140214758906396e-16, /* twoPowerIndex1mi[58] */ 2.26009746193166539328485913376118607218426838997178e-33, /* twoPowerIndex1lo[58] */ } , { 1.01003430716547448753317439695820212364196777343750e+00, /* twoPowerIndex1hi[59] */ -5.76731742716039801926309676866051407637690838590278e-17, /* twoPowerIndex1mi[59] */ -2.78217177127226696492717790709599913537289113429847e-33, /* twoPowerIndex1lo[59] */ } , { 1.01020524507396425306637866015080362558364868164062e+00, /* twoPowerIndex1hi[60] */ 4.83548497844038273903057565303994337100835235326315e-18, /* twoPowerIndex1mi[60] */ 2.61454310671247390892899439237254056446677108734060e-34, /* twoPowerIndex1lo[60] */ } , { 1.01037621191193527359075687854783609509468078613281e+00, /* twoPowerIndex1hi[61] */ 7.01512128971544209746870624992521939688820868468409e-17, /* twoPowerIndex1mi[61] */ -5.58161827166019262256128049263563333632096890407031e-33, /* twoPowerIndex1lo[61] */ } , { 1.01054720768428363264490599249256774783134460449219e+00, /* twoPowerIndex1hi[62] */ 7.16180287361957384315239192590148379997244337618299e-17, /* twoPowerIndex1mi[62] */ -2.02563561553844543425647289447795720504633264470840e-34, /* twoPowerIndex1lo[62] */ } , { 1.01071823239590607990123771742219105362892150878906e+00, /* twoPowerIndex1hi[63] */ 1.05046591340840499506734116899577087874840087102554e-16, /* twoPowerIndex1mi[63] */ 2.18415845005431430458109722226729544983351542501345e-33, /* twoPowerIndex1lo[63] */ } }; static const tPi_t twoPowerIndex2[64] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex2hi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex2mi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex2lo[0] */ } , { 1.01088928605170047525518839393043890595436096191406e+00, /* twoPowerIndex2hi[1] */ -1.52347786033685771762884896542837070154735103108242e-17, /* twoPowerIndex2mi[1] */ -1.20527773363982029579667170059568717373235495431222e-33, /* twoPowerIndex2lo[1] */ } , { 1.02189714865411662714222984504885971546173095703125e+00, /* twoPowerIndex2hi[2] */ 5.10922502897344389358977529484899213711118891193073e-17, /* twoPowerIndex2mi[2] */ 7.88422656496927442160138555121324022911581088833303e-34, /* twoPowerIndex2lo[2] */ } , { 1.03302487902122841489926940994337201118469238281250e+00, /* twoPowerIndex2hi[3] */ 7.60083887402708848935418174694583720224989620170520e-18, /* twoPowerIndex2mi[3] */ 4.17547660336499599627565312970423748685953776150432e-34, /* twoPowerIndex2lo[3] */ } , { 1.04427378242741375480306942336028441786766052246094e+00, /* twoPowerIndex2hi[4] */ 8.55188970553796489217080231819249267647451456689049e-17, /* twoPowerIndex2mi[4] */ -4.33079108057472301914865017639792677602990877842667e-33, /* twoPowerIndex2lo[4] */ } , { 1.05564517836055715704901558638084679841995239257812e+00, /* twoPowerIndex2hi[5] */ 1.75932573877209198413667791203269037000656546957040e-18, /* twoPowerIndex2mi[5] */ -1.30396724977978376996223394717384715710429730879060e-34, /* twoPowerIndex2lo[5] */ } , { 1.06714040067682369716806078940862789750099182128906e+00, /* twoPowerIndex2hi[6] */ -7.89985396684158212226333428391940791349522867645719e-17, /* twoPowerIndex2mi[6] */ 2.48773924323047906697979838020484860096229450391065e-33, /* twoPowerIndex2lo[6] */ } , { 1.07876079775711986030728439800441265106201171875000e+00, /* twoPowerIndex2hi[7] */ -6.65666043605659260344452997720816205593857378631714e-17, /* twoPowerIndex2mi[7] */ -3.65812580131923690564246115619834327696213789275798e-33, /* twoPowerIndex2lo[7] */ } , { 1.09050773266525768967483145388541743159294128417969e+00, /* twoPowerIndex2hi[8] */ -3.04678207981247114696551170541257032193091359539676e-17, /* twoPowerIndex2mi[8] */ 2.01705487848848619150139275849815038703452970938356e-33, /* twoPowerIndex2lo[8] */ } , { 1.10238258330784089089604549371870234608650207519531e+00, /* twoPowerIndex2hi[9] */ 5.26603687157069438656191942579725322612448063343618e-17, /* twoPowerIndex2mi[9] */ 6.45805397536721410708490440561131106837447579889036e-34, /* twoPowerIndex2lo[9] */ } , { 1.11438674259589243220602838846389204263687133789062e+00, /* twoPowerIndex2hi[10] */ 1.04102784568455709549461912557590544266030834754874e-16, /* twoPowerIndex2mi[10] */ 1.47570167344000313963428137759389241586071635800536e-33, /* twoPowerIndex2lo[10] */ } , { 1.12652161860824184813623105583246797323226928710938e+00, /* twoPowerIndex2hi[11] */ 5.16585675879545673703180814711785602957687143067887e-17, /* twoPowerIndex2mi[11] */ -5.65916686170716220063974592097473710424342945964456e-34, /* twoPowerIndex2lo[11] */ } , { 1.13878863475669156457570352358743548393249511718750e+00, /* twoPowerIndex2hi[12] */ 8.91281267602540777782023808215740339330966556723006e-17, /* twoPowerIndex2mi[12] */ -2.00741463283249448727846279877956608996968961458494e-33, /* twoPowerIndex2lo[12] */ } , { 1.15118922995298267331065744656370952725410461425781e+00, /* twoPowerIndex2hi[13] */ 3.25071021886382721197741051783883831627922464835734e-17, /* twoPowerIndex2mi[13] */ 8.89091931637927159755660842958283684863470887791663e-34, /* twoPowerIndex2lo[13] */ } , { 1.16372485877757747552152522985124960541725158691406e+00, /* twoPowerIndex2hi[14] */ 3.82920483692409349872159816102110059722238312159091e-17, /* twoPowerIndex2mi[14] */ 7.19709831987676327409679245188515478735702972651365e-34, /* twoPowerIndex2lo[14] */ } , { 1.17639699165028122074261318630306050181388854980469e+00, /* twoPowerIndex2hi[15] */ 5.55420325421807896276684328889766000203735373777665e-17, /* twoPowerIndex2mi[15] */ -1.48842929343368511961710849782815827921712348302943e-33, /* twoPowerIndex2lo[15] */ } , { 1.18920711500272102689734765590401366353034973144531e+00, /* twoPowerIndex2hi[16] */ 3.98201523146564611098029654755651628169309930562261e-17, /* twoPowerIndex2mi[16] */ 1.14195965688545340101163692105448367710482873511510e-33, /* twoPowerIndex2lo[16] */ } , { 1.20215673145270307564658196497475728392601013183594e+00, /* twoPowerIndex2hi[17] */ 6.64498149925230124489270286991048474954122885069094e-17, /* twoPowerIndex2mi[17] */ -3.85685255336907654452995968372311171004938395576078e-33, /* twoPowerIndex2lo[17] */ } , { 1.21524735998046895524282717815367504954338073730469e+00, /* twoPowerIndex2hi[18] */ -7.71263069268148813091257203929615917892526180720328e-17, /* twoPowerIndex2mi[18] */ 4.71720614288499816545262331753743129502653902881319e-33, /* twoPowerIndex2lo[18] */ } , { 1.22848053610687002468182527081808075308799743652344e+00, /* twoPowerIndex2hi[19] */ -1.89878163130252995311948719658078062677878185721429e-17, /* twoPowerIndex2mi[19] */ 6.18469453652103848424687212656185051850860290411013e-34, /* twoPowerIndex2lo[19] */ } , { 1.24185781207348400201340155035723000764846801757812e+00, /* twoPowerIndex2hi[20] */ 4.65802759183693679122616767654141683800114091774588e-17, /* twoPowerIndex2mi[20] */ -2.31439910378785985764079190411324307370918857557275e-33, /* twoPowerIndex2lo[20] */ } , { 1.25538075702469109629078047873917967081069946289062e+00, /* twoPowerIndex2hi[21] */ -6.71138982129687841852821870522008036246320680675952e-18, /* twoPowerIndex2mi[21] */ -5.76846264325028352862497671463784812858487529613818e-35, /* twoPowerIndex2lo[21] */ } , { 1.26905095719173321988648694969015195965766906738281e+00, /* twoPowerIndex2hi[22] */ 2.66793213134218609522998616502989391061315227839969e-18, /* twoPowerIndex2mi[22] */ -5.01723570938719050333027020376949013774930719140568e-35, /* twoPowerIndex2lo[22] */ } , { 1.28287001607877826359072059858590364456176757812500e+00, /* twoPowerIndex2hi[23] */ 1.71359491824356096814175768900864730928374054987756e-17, /* twoPowerIndex2mi[23] */ 7.25131491282819461838977871983760669047046080773478e-34, /* twoPowerIndex2lo[23] */ } , { 1.29683955465100964055125132290413603186607360839844e+00, /* twoPowerIndex2hi[24] */ 2.53825027948883149592910250791940344234383392801619e-17, /* twoPowerIndex2mi[24] */ 1.68678246461832500334243039646153124282288438904092e-34, /* twoPowerIndex2lo[24] */ } , { 1.31096121152476441373835314152529463171958923339844e+00, /* twoPowerIndex2hi[25] */ -7.18153613551945385697245613605196258733040544776187e-17, /* twoPowerIndex2mi[25] */ -2.12629266743969557140434977160228094057588798528197e-34, /* twoPowerIndex2lo[25] */ } , { 1.32523664315974132321684919588733464479446411132812e+00, /* twoPowerIndex2hi[26] */ -2.85873121003886137327027220806882812126373511580572e-17, /* twoPowerIndex2mi[26] */ 7.62021406397260431456821182703024347950927217409368e-34, /* twoPowerIndex2lo[26] */ } , { 1.33966752405330291608720472140703350305557250976562e+00, /* twoPowerIndex2hi[27] */ 8.92728259483173198426255486589831591472085466011828e-17, /* twoPowerIndex2mi[27] */ -7.69657983531899254540849298389093495155758992415150e-34, /* twoPowerIndex2lo[27] */ } , { 1.35425554693689265128853094211081042885780334472656e+00, /* twoPowerIndex2hi[28] */ 7.70094837980298946162338224151128414915778826123523e-17, /* twoPowerIndex2mi[28] */ -2.24074836437395028882100810844688282941385619430371e-33, /* twoPowerIndex2lo[28] */ } , { 1.36900242297459051599162194179370999336242675781250e+00, /* twoPowerIndex2hi[29] */ 9.59379791911884877255545693637832999511204427845953e-17, /* twoPowerIndex2mi[29] */ -4.88674958784947176959607858061848292445663702071206e-33, /* twoPowerIndex2lo[29] */ } , { 1.38390988196383202257777611521305516362190246582031e+00, /* twoPowerIndex2hi[30] */ -6.77051165879478628715737183479431151106043475381389e-17, /* twoPowerIndex2mi[30] */ 5.25954134785524271676320971772030766300829615286373e-34, /* twoPowerIndex2lo[30] */ } , { 1.39897967253831123635166022722842171788215637207031e+00, /* twoPowerIndex2hi[31] */ -9.61421320905132307233280072508933760749140842467170e-17, /* twoPowerIndex2mi[31] */ 3.97465190077505680357285219692652769985214754647576e-33, /* twoPowerIndex2lo[31] */ } , { 1.41421356237309514547462185873882845044136047363281e+00, /* twoPowerIndex2hi[32] */ -9.66729331345291345105469972976694765012981670542977e-17, /* twoPowerIndex2mi[32] */ 4.13867530869941356271900493210877889450985709540127e-33, /* twoPowerIndex2lo[32] */ } , { 1.42961333839197002326670826732879504561424255371094e+00, /* twoPowerIndex2hi[33] */ -1.20316424890536551791763281075597751007148682598677e-17, /* twoPowerIndex2mi[33] */ 3.96492532243389364766543780399018506300743370884771e-35, /* twoPowerIndex2lo[33] */ } , { 1.44518080697704665027458759141154587268829345703125e+00, /* twoPowerIndex2hi[34] */ -3.02375813499398731939978948265280760393682335269040e-17, /* twoPowerIndex2mi[34] */ -1.77301195820250091791088617662298487007284882395542e-33, /* twoPowerIndex2lo[34] */ } , { 1.46091779418064704465507475106278434395790100097656e+00, /* twoPowerIndex2hi[35] */ -5.60037718607521580013156831807759453639536208267684e-17, /* twoPowerIndex2mi[35] */ -4.80948804890004400970317146361816382779746350931714e-33, /* twoPowerIndex2lo[35] */ } , { 1.47682614593949934622685304930200800299644470214844e+00, /* twoPowerIndex2hi[36] */ -3.48399455689279579579151031868718147769491495422105e-17, /* twoPowerIndex2mi[36] */ -1.21157704523090580028169713170353136148082368354920e-34, /* twoPowerIndex2lo[36] */ } , { 1.49290772829126483500772337720263749361038208007812e+00, /* twoPowerIndex2hi[37] */ 1.41929201542840357707378184476885202767753055101956e-17, /* twoPowerIndex2mi[37] */ 2.77326329344780505247628358108799734324783290873618e-34, /* twoPowerIndex2lo[37] */ } , { 1.50916442759342284141155232646269723773002624511719e+00, /* twoPowerIndex2hi[38] */ -1.01645532775429503910501990740249618370059871055172e-16, /* twoPowerIndex2mi[38] */ 2.04191706967403438352422808603561166583202022922508e-34, /* twoPowerIndex2lo[38] */ } , { 1.52559815074453841710067081294255331158638000488281e+00, /* twoPowerIndex2hi[39] */ -1.10249417123425609363148008789604625195179292613569e-16, /* twoPowerIndex2mi[39] */ -2.99382882637137806007903782085057425945683820190483e-33, /* twoPowerIndex2lo[39] */ } , { 1.54221082540794074411394376511452719569206237792969e+00, /* twoPowerIndex2hi[40] */ 7.94983480969762085616103882937991564856794389991833e-17, /* twoPowerIndex2mi[40] */ -9.15995637410036729585390444224530830478731117122757e-34, /* twoPowerIndex2lo[40] */ } , { 1.55900440023783692922165755589958280324935913085938e+00, /* twoPowerIndex2hi[41] */ 3.78120705335752750188190562589679090842557793649900e-17, /* twoPowerIndex2mi[41] */ 5.94230221045385633407443935898656310894518533675204e-35, /* twoPowerIndex2lo[41] */ } , { 1.57598084510788649659218663146020844578742980957031e+00, /* twoPowerIndex2hi[42] */ -1.01369164712783039807957177429288269249745537889645e-17, /* twoPowerIndex2mi[42] */ 5.43913851556220712785038586461119929989856637311730e-34, /* twoPowerIndex2lo[42] */ } , { 1.59314215134226699888131406623870134353637695312500e+00, /* twoPowerIndex2hi[43] */ -1.00944065423119637216151952902063201612012779755882e-16, /* twoPowerIndex2mi[43] */ 4.60848399034962572477662350836868643017178368092553e-33, /* twoPowerIndex2lo[43] */ } , { 1.61049033194925428347232809755951166152954101562500e+00, /* twoPowerIndex2hi[44] */ 2.47071925697978878522451183466139791436957933053447e-17, /* twoPowerIndex2mi[44] */ 1.06968477888935897586507304780358756526593706030066e-33, /* twoPowerIndex2lo[44] */ } , { 1.62802742185734783397776936908485367894172668457031e+00, /* twoPowerIndex2hi[45] */ -6.71295508470708408629558620522800193343463268850872e-17, /* twoPowerIndex2mi[45] */ 1.86124288813399584090278118171650158752835667500490e-33, /* twoPowerIndex2lo[45] */ } , { 1.64575547815396494577555586147354915738105773925781e+00, /* twoPowerIndex2hi[46] */ -1.01256799136747726037875241569662212149731136230039e-16, /* twoPowerIndex2mi[46] */ -6.73838498803664271467304077725442401461793880458369e-34, /* twoPowerIndex2lo[46] */ } , { 1.66367658032673637613640948984539136290550231933594e+00, /* twoPowerIndex2hi[47] */ 5.89099269671309967045155789620226639428173542900082e-17, /* twoPowerIndex2mi[47] */ 2.37785299276765025315795732233641105960161859663372e-33, /* twoPowerIndex2lo[47] */ } , { 1.68179283050742900407215074665145948529243469238281e+00, /* twoPowerIndex2hi[48] */ 8.19901002058149652012724391042374107310082144797238e-17, /* twoPowerIndex2mi[48] */ 5.10351519472809316392686812760480457926425713861784e-33, /* twoPowerIndex2lo[48] */ } , { 1.70010635371852347752508194389520213007926940917969e+00, /* twoPowerIndex2hi[49] */ -8.02371937039770024588528464451482959960563128920877e-18, /* twoPowerIndex2mi[49] */ 4.50894675051846528463958043437010583905518288996850e-34, /* twoPowerIndex2lo[49] */ } , { 1.71861929812247793414314855908742174506187438964844e+00, /* twoPowerIndex2hi[50] */ -1.85138041826311098821086356969536380719870481925638e-17, /* twoPowerIndex2mi[50] */ 6.41562962530571009881963439719259893730039269925891e-34, /* twoPowerIndex2lo[50] */ } , { 1.73733383527370621735030908894259482622146606445312e+00, /* twoPowerIndex2hi[51] */ 3.16438929929295694659064288262436215220581330791541e-17, /* twoPowerIndex2mi[51] */ 2.46812086524635182684409036079744664142196277491485e-33, /* twoPowerIndex2lo[51] */ } , { 1.75625216037329945351075366488657891750335693359375e+00, /* twoPowerIndex2hi[52] */ 2.96014069544887330703087179323550026749650613893620e-17, /* twoPowerIndex2mi[52] */ 1.23348227448930022362949427574612725745479960698002e-33, /* twoPowerIndex2lo[52] */ } , { 1.77537649252652118825324123463360592722892761230469e+00, /* twoPowerIndex2hi[53] */ 6.42973179655657203395602172161574258202382771355994e-17, /* twoPowerIndex2mi[53] */ -3.05903038196122316059732104267589318807211463677414e-33, /* twoPowerIndex2lo[53] */ } , { 1.79470907500310716820024481421569362282752990722656e+00, /* twoPowerIndex2hi[54] */ 1.82274584279120867697625715862678123206602563412216e-17, /* twoPowerIndex2mi[54] */ 1.42176433874694971095041068746172287320972847635154e-33, /* twoPowerIndex2lo[54] */ } , { 1.81425217550039885594514998956583440303802490234375e+00, /* twoPowerIndex2hi[55] */ -9.96953153892034881983229632097342495877571562964276e-17, /* twoPowerIndex2mi[55] */ -5.86224914377491774994695195482808191103744720514440e-33, /* twoPowerIndex2lo[55] */ } , { 1.83400808640934243065601094713201746344566345214844e+00, /* twoPowerIndex2hi[56] */ 3.28310722424562720351405816760294702167288526703081e-17, /* twoPowerIndex2mi[56] */ -6.42508934795304248095271046696049734574532048424330e-34, /* twoPowerIndex2lo[56] */ } , { 1.85397912508338547077357816306175664067268371582031e+00, /* twoPowerIndex2hi[57] */ 9.76188749072759353840331670682321086158335176176729e-17, /* twoPowerIndex2mi[57] */ 4.61481577205566482307976345637533484680898060020057e-33, /* twoPowerIndex2lo[57] */ } , { 1.87416763411029996255763307999586686491966247558594e+00, /* twoPowerIndex2hi[58] */ -6.12276341300414256163658402373731493255704994623650e-17, /* twoPowerIndex2mi[58] */ 5.28588559402507397372575432425046614667899080733482e-33, /* twoPowerIndex2lo[58] */ } , { 1.89457598158696560730618330126162618398666381835938e+00, /* twoPowerIndex2hi[59] */ 3.40340353521652967060147928999507962708632290832738e-17, /* twoPowerIndex2mi[59] */ 1.72475099549343225430579028439403217279441019556785e-33, /* twoPowerIndex2lo[59] */ } , { 1.91520656139714740007207183225546032190322875976562e+00, /* twoPowerIndex2hi[60] */ -1.06199460561959626376283195555328606320260702029334e-16, /* twoPowerIndex2mi[60] */ -3.05776975679132548538006102719337626149343902119718e-33, /* twoPowerIndex2lo[60] */ } , { 1.93606179349229434727419629780342802405357360839844e+00, /* twoPowerIndex2hi[61] */ 1.03323859606763257447769151803649788699571393339738e-16, /* twoPowerIndex2mi[61] */ 6.05301367682062275405664830597304146844867569493449e-33, /* twoPowerIndex2lo[61] */ } , { 1.95714412417540017941064434126019477844238281250000e+00, /* twoPowerIndex2hi[62] */ 8.96076779103666776760155050762912042076490756639488e-17, /* twoPowerIndex2mi[62] */ -9.63267661361827588458686334472185443533033181828620e-34, /* twoPowerIndex2lo[62] */ } , { 1.97845602638795092786949680885300040245056152343750e+00, /* twoPowerIndex2hi[63] */ 4.03887531092781665749784154795462589642365074083484e-17, /* twoPowerIndex2mi[63] */ 3.58120371667786223934924900740488031476290303118010e-34, /* twoPowerIndex2lo[63] */ } }; interval-3.2.0/src/crlibm/expm1-standalone.c0000644000000000000000000001106413316017127017054 0ustar 00000000000000/* * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "expm1.h" #define AVOID_FMA 0 extern void expm1_direct_td(double *expm1h, double *expm1m, double *expm1l, double x, double xSqHalfh, double xSqHalfl, double xSqh, double xSql, int expoX); extern void expm1_common_td(double *expm1h, double *expm1m, double *expm1l, double rh, double rm, double rl, double tbl1h, double tbl1m, double tbl1l, double tbl2h, double tbl2m, double tbl2l, int M); /* Function expm1_13 Computes exp(x)-1 with an accuracy of 120 bits (128 for |x| <= 2^(-5)) as (expm1h + expm1m + expm1l) \approx exp(x) - 1 There is no special case handling. |x| is supposed to be greater than 2^(-53) x is supposed to be in the range -37...709 The triple-double exph + expm + expl is non-overlapping. */ void expm1_13(double *expm1h, double *expm1m, double *expm1l, double x) { db_number xdb, shiftedXMultdb; int xIntHi, expoX, k, M, index1, index2; double xSqh, xSql, xSqHalfh, xSqHalfl; double t1, t2; double msLog2Div2LMultKh, msLog2Div2LMultKm, msLog2Div2LMultKl; double xMultLog2InvMult2L, shiftedXMult, kd, rh, rm, rl; double tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l; xdb.d = x; xIntHi = xdb.i[HI] & 0x7fffffff; /* Test if we have |x| <= 1/4-1/2ulp(1/4) for knowing if we use exp(x) or approximate directly */ if (xIntHi < DIRECTINTERVALBOUND) { /* We approximate expm1 directly after a range reduction as follows expm1(x) = (expm1(x/2) + 2) * expm1(x/2) We perform the range reduction in such a way that finally |x| < 1/32 */ /* Extract the exponent of |x| and add 5 (2^5 = 32) */ expoX = ((xIntHi & 0x7ff00000) >> 20) - (1023 - 5); /* If this particularily biased exponent expoX is negative, we are already less than 1/32 */ if (expoX >= 0) { /* If we are here, we must perform range reduction */ /* We multiply x by 2^(-expoX-1) by bit manipulation x cannot be denormalized so there is no danger */ xdb.i[HI] += (-expoX-1) << 20; /* We reassign the new x and maintain xIntHi */ xIntHi = xdb.i[HI] & 0x7fffffff; x = xdb.d; } /* Here, we have always |x| < 1/32 */ /* Double precision evaluation steps and one double-double step */ Mul12(&xSqh,&xSql,x,x); xSqHalfh = 0.5 * xSqh; xSqHalfl = 0.5 * xSql; expm1_direct_td(expm1h, expm1m, expm1l, x, xSqHalfh, xSqHalfl, xSqh, xSql, expoX); } else { /* If we are here, we can use expm1(x) = exp(x) - 1 */ /* Range reduction - exact part: compute k as double and as int */ xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; k = shiftedXMultdb.i[LO]; M = k >> 12; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> 6; Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; expm1_common_td(expm1h, expm1m, expm1l, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l, M); } } interval-3.2.0/src/crlibm/expm1.c0000644000000000000000000023241513316017127014733 0ustar 00000000000000/* * Correctly rounded expm1 = e^x - 1 * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author : Christoph Lauter (ENS Lyon) * One bug fix by Florent de Dinechin * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "expm1.h" #ifdef BUILD_INTERVAL_FUNCTIONS #include "interval.h" #endif #define DEBUG 0 void expm1_direct_td(double *expm1h, double *expm1m, double *expm1l, double x, double xSqHalfh, double xSqHalfl, double xSqh, double xSql, int expoX) { double highPoly, tt1h, t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l; double tt6h, tt6m, tt6l, t7h, t7m, t7l, lowPolyh, lowPolym, lowPolyl; double fullHighPolyh, fullHighPolym, fullHighPolyl, polyh, polym, polyl; double xCubeh, xCubem, xCubel, tt7h, tt7m, tt7l, t8h, t8m, t8l; double expm1hover, expm1mover, expm1lover; double r1h, r1m, r1l, r2h, r2m, r2l, r3h, r3m, r3l; double rr1h, rr1m, rr1l, rr2h, rr2m, rr2l, rr3h, rr3m, rr3l; double fullHighPolyhover, fullHighPolymover, fullHighPolylover; /* Double precision evaluation steps */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(accuDirectpolyC15h ,x,accuDirectpolyC14h),x,accuDirectpolyC13h),x, accuDirectpolyC12h),x,accuDirectpolyC11h); #else highPoly = accuDirectpolyC11h + x * (accuDirectpolyC12h + x * (accuDirectpolyC13h + x * ( accuDirectpolyC14h + x * accuDirectpolyC15h))); #endif tt1h = x * highPoly; /* Triple-double steps for x + x^2/2 and x^3*/ Add123(&lowPolyh,&lowPolym,&lowPolyl,x,xSqHalfh,xSqHalfl); /* infty - 52/53 */ Mul123(&xCubeh,&xCubem,&xCubel,x,xSqh,xSql); /* 154 - 47/53 */ /* Double-double evaluation steps */ Add12(t1h,t1l,accuDirectpolyC10h,tt1h); MulAdd212(&t2h,&t2l,accuDirectpolyC9h,accuDirectpolyC9m,x,t1h,t1l); MulAdd212(&t3h,&t3l,accuDirectpolyC8h,accuDirectpolyC8m,x,t2h,t2l); MulAdd212(&t4h,&t4l,accuDirectpolyC7h,accuDirectpolyC7m,x,t3h,t3l); MulAdd212(&t5h,&t5l,accuDirectpolyC6h,accuDirectpolyC6m,x,t4h,t4l); MulAdd212(&t6h,&t6l,accuDirectpolyC5h,accuDirectpolyC5m,x,t5h,t5l); /* Triple-double evaluation steps */ Mul123(&tt6h,&tt6m,&tt6l,x,t6h,t6l); /* 154 - 47/53 */ Add233(&t7h,&t7m,&t7l,accuDirectpolyC4h,accuDirectpolyC4m,tt6h,tt6m,tt6l); /* 150 - 43/53 */ Mul133(&tt7h,&tt7m,&tt7l,x,t7h,t7m,t7l); /* 143 - 38/53 */ Add33(&t8h,&t8m,&t8l,accuDirectpolyC3h,accuDirectpolyC3m,accuDirectpolyC3l,tt7h,tt7m,tt7l); /* 135 - 33/53 */ Mul33(&fullHighPolyhover,&fullHighPolymover,&fullHighPolylover,xCubeh,xCubem,xCubel,t8h,t8m,t8l); /* 130 - 29/53 */ Renormalize3(&fullHighPolyh,&fullHighPolym,&fullHighPolyl, fullHighPolyhover,fullHighPolymover,fullHighPolylover); /* infty - 52/53 */ Add33(&polyh,&polym,&polyl,lowPolyh,lowPolym,lowPolyl,fullHighPolyh,fullHighPolym,fullHighPolyl); /* 149 - 47/53 */ /* Reconstruction steps */ /* If we have not performed any range reduction, we have no reconstruction to do */ if (expoX >= 0) { /* If we are here, we must perform reconstruction */ /* First reconstruction step */ Add133(&r1h,&r1m,&r1l,2,polyh,polym,polyl); Mul33(&rr1h,&rr1m,&rr1l,r1h,r1m,r1l,polyh,polym,polyl); if (expoX >= 1) { /* Second reconstruction step */ Add133(&r2h,&r2m,&r2l,2,rr1h,rr1m,rr1l); Mul33(&rr2h,&rr2m,&rr2l,r2h,r2m,r2l,rr1h,rr1m,rr1l); if (expoX >= 2) { /* Third reconstruction step */ Add133(&r3h,&r3m,&r3l,2,rr2h,rr2m,rr2l); Mul33(&rr3h,&rr3m,&rr3l,r3h,r3m,r3l,rr2h,rr2m,rr2l); /* expoX may be maximally 2 */ expm1hover = rr3h; expm1mover = rr3m; expm1lover = rr3l; } else { expm1hover = rr2h; expm1mover = rr2m; expm1lover = rr2l; } } else { expm1hover = rr1h; expm1mover = rr1m; expm1lover = rr1l; } } else { expm1hover = polyh; expm1mover = polym; expm1lover = polyl; } /* Renormalize before returning */ Renormalize3(expm1h,expm1m,expm1l,expm1hover,expm1mover,expm1lover); } void expm1_common_td(double *expm1h, double *expm1m, double *expm1l, double rh, double rm, double rl, double tbl1h, double tbl1m, double tbl1l, double tbl2h, double tbl2m, double tbl2l, int M) { double highPoly, highPolyMulth, highPolyMultm, highPolyMultl; double rhSquareh, rhSquarel, rhSquareHalfh, rhSquareHalfl; double rhCubeh, rhCubem, rhCubel; double t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5, t6; double lowPolyh, lowPolym, lowPolyl; double ph, pm, pl, phnorm, pmnorm, rmlMultPh, rmlMultPl; double qh, ql, fullPolyh, fullPolym, fullPolyl; double polyWithTbl1h, polyWithTbl1m, polyWithTbl1l; double polyAddOneh,polyAddOnem,polyAddOnel; double polyWithTablesh, polyWithTablesm, polyWithTablesl; double exph, expm, expl, expm1hover, expm1mover, expm1lover; db_number polyWithTableshdb, polyWithTablesmdb, polyWithTablesldb; /* Polynomial approximation - double precision steps */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(accuCommonpolyC7h,rh,accuCommonpolyC6h),rh,accuCommonpolyC5h); #else highPoly = accuCommonpolyC5h + rh * (accuCommonpolyC6h + rh * accuCommonpolyC7h); #endif /* Polynomial approximation - double-double precision steps */ Mul12(&t1h,&t1l,rh,highPoly); Add22(&t2h,&t2l,accuCommonpolyC4h,accuCommonpolyC4m,t1h,t1l); Mul122(&t3h,&t3l,rh,t2h,t2l); Add22(&t4h,&t4l,accuCommonpolyC3h,accuCommonpolyC3m,t3h,t3l); Mul12(&rhSquareh,&rhSquarel,rh,rh); Mul123(&rhCubeh,&rhCubem,&rhCubel,rh,rhSquareh,rhSquarel); rhSquareHalfh = 0.5 * rhSquareh; rhSquareHalfl = 0.5 * rhSquarel; /* Polynomial approximation - triple-double precision steps */ Renormalize3(&lowPolyh,&lowPolym,&lowPolyl,rh,rhSquareHalfh,rhSquareHalfl); Mul233(&highPolyMulth,&highPolyMultm,&highPolyMultl,t4h,t4l,rhCubeh,rhCubem,rhCubel); Add33(&ph,&pm,&pl,lowPolyh,lowPolym,lowPolyl,highPolyMulth,highPolyMultm,highPolyMultl); /* Reconstruction */ Add12(phnorm,pmnorm,ph,pm); Mul22(&rmlMultPh,&rmlMultPl,rm,rl,phnorm,pmnorm); Add22(&qh,&ql,rm,rl,rmlMultPh,rmlMultPl); Add233Cond(&fullPolyh,&fullPolym,&fullPolyl,qh,ql,ph,pm,pl); Add12(polyAddOneh,t5,1,fullPolyh); Add12Cond(polyAddOnem,t6,t5,fullPolym); polyAddOnel = t6 + fullPolyl; Mul33(&polyWithTbl1h,&polyWithTbl1m,&polyWithTbl1l,tbl1h,tbl1m,tbl1l,polyAddOneh,polyAddOnem,polyAddOnel); Mul33(&polyWithTablesh,&polyWithTablesm,&polyWithTablesl, tbl2h,tbl2m,tbl2l, polyWithTbl1h,polyWithTbl1m,polyWithTbl1l); /* Multiplication by 2^(M) We perform it in integer to overcome the non-representability of 2^(1024) This case is possible for M = 1024 and polyWithTablesh < 1 The overlap in the triple-double polyWithTables[hml] stays unchanged. */ polyWithTableshdb.d = polyWithTablesh; polyWithTablesmdb.d = polyWithTablesm; polyWithTablesldb.d = polyWithTablesl; /* TODO FIXME probably at least the first of these tests is useless, but I leave this to Christoph to check it. Let us be conservative. Florent */ if(polyWithTableshdb.d!=0) polyWithTableshdb.i[HI] += M << 20; if(polyWithTablesmdb.d!=0) polyWithTablesmdb.i[HI] += M << 20; if(polyWithTablesldb.d!=0) polyWithTablesldb.i[HI] += M << 20; exph = polyWithTableshdb.d; expm = polyWithTablesmdb.d; expl = polyWithTablesldb.d; /* Subtraction of -1 We use a conditional Add133 */ Add133Cond(&expm1hover,&expm1mover,&expm1lover,-1,exph,expm,expl); /* Renormalization */ Renormalize3(expm1h,expm1m,expm1l,expm1hover,expm1mover,expm1lover); } double expm1_rn(double x) { db_number xdb, shiftedXMultdb, polyTblhdb, polyTblmdb; int xIntHi, expoX, k, M, index1, index2; double highPoly, tt1h, t1h, t1l, xSqh, xSql, xSqHalfh, xSqHalfl, xCubeh, xCubel, t2h, t2l, templ, tt3h, tt3l; double polyh, polyl, expm1h, expm1m, expm1l; double r1h, r1l, r1t, rr1h, rr1l; double r2h, r2l, r2t, rr2h, rr2l; double r3h, r3l, r3t, rr3h, rr3l; double xMultLog2InvMult2L, shiftedXMult, kd, s1, s2, s3, s4, s5, rh, rm, rl; double rhSquare, rhC3, rhSquareHalf, monomialCube, rhFour, monomialFour; double tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l; double highPolyWithSquare, tablesh, tablesl, t8, t9, t10, t11, t12, t13; double exph, expm, t1, t2, t3; double msLog2Div2LMultKh, msLog2Div2LMultKm, msLog2Div2LMultKl; double middlePoly, doublePoly; xdb.d = x; /* Strip off the sign of x for the following tests */ xIntHi = xdb.i[HI] & 0x7fffffff; /* Test if we are so small that we can return (a corrected) x as correct rounding */ if (xIntHi < RETURNXBOUND) { return x; } /* Filter out special cases like overflow, -1 in result, infinities and NaNs The filters are not sharp, we have positive arguments that flow through */ if (xIntHi >= SIMPLEOVERFLOWBOUND) { /* Test if we are +/-inf or NaN */ if (xIntHi >= 0x7ff00000) { /* Test if NaN */ if (((xIntHi & 0x000fffff) | xdb.i[LO]) != 0) { /* NaN */ return x+x; /* return NaN */ } /* Test if +inf or -inf */ if (xdb.i[HI] > 0) { /* +inf */ return x+x; /* return +inf */ } /* If we are here, we are -inf */ return -1.0; } /* If we are here, we are overflowed or a common case that flows through */ /* Test if we are actually overflowed */ if (x > OVERFLOWBOUND) { return LARGEST * LARGEST; /* return +inf and set flag */ } } /* Test if we know already that we are -1.0 (+ correction depending on rounding mode) in result */ if (x < MINUSONEBOUND) { return -1.0; } /* Test if we have |x| <= 1/4-1/2ulp(1/4) for knowing if we use exp(x) or approximate directly */ if (xIntHi < DIRECTINTERVALBOUND) { /* We approximate expm1 directly after a range reduction as follows expm1(x) = (expm1(x/2) + 2) * expm1(x/2) We perform the range reduction in such a way that finally |x| < 1/32 */ /* Extract the exponent of |x| and add 5 (2^5 = 32) */ expoX = ((xIntHi & 0x7ff00000) >> 20) - (1023 - 5); /* If this particularily biased exponent expoX is negative, we are already less than 1/32 */ if (expoX >= 0) { /* If we are here, we must perform range reduction */ /* We multiply x by 2^(-expoX-1) by bit manipulation x cannot be denormalized so there is no danger */ xdb.i[HI] += (-expoX-1) << 20; /* We reassign the new x and maintain xIntHi */ xIntHi = xdb.i[HI] & 0x7fffffff; x = xdb.d; } /* Here, we have always |x| < 1/32 */ /* Double precision evaluation steps and one double-double step */ Mul12(&xSqh,&xSql,x,x); #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) middlePoly = FMA(quickDirectpolyC5h,x,quickDirectpolyC4h); #else middlePoly = quickDirectpolyC4h + x * quickDirectpolyC5h; #endif doublePoly = middlePoly; /* Special path: for small |x| we can truncate the polynomial */ if (xIntHi > SPECIALINTERVALBOUND) { #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(quickDirectpolyC9h ,x,quickDirectpolyC8h),x, quickDirectpolyC7h),x,quickDirectpolyC6h); #else highPoly = quickDirectpolyC6h + x * (quickDirectpolyC7h + x * ( quickDirectpolyC8h + x * quickDirectpolyC9h)); #endif highPolyWithSquare = xSqh * highPoly; doublePoly = middlePoly + highPolyWithSquare; } /* Double-double evaluation steps */ tt1h = x * doublePoly; xSqHalfh = 0.5 * xSqh; xSqHalfl = 0.5 * xSql; Add12(t2h,templ,x,xSqHalfh); t2l = templ + xSqHalfl; Add12(t1h,t1l,quickDirectpolyC3h,tt1h); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt3h,&tt3l,xCubeh,xCubel,t1h,t1l); Add22(&polyh,&polyl,t2h,t2l,tt3h,tt3l); /* Reconstruction */ /* If we have not performed any range reduction, we have no reconstruction to do */ if (expoX >= 0) { /* If we are here, we must perform reconstruction */ /* First reconstruction step */ Add12(r1h,r1t,2,polyh); r1l = r1t + polyl; Mul22(&rr1h,&rr1l,r1h,r1l,polyh,polyl); if (expoX >= 1) { /* Second reconstruction step */ Add12(r2h,r2t,2,rr1h); r2l = r2t + rr1l; Mul22(&rr2h,&rr2l,r2h,r2l,rr1h,rr1l); if (expoX >= 2) { /* Third reconstruction step */ Add12(r3h,r3t,2,rr2h); r3l = r3t + rr2l; Mul22(&rr3h,&rr3l,r3h,r3l,rr2h,rr2l); /* expoX may be maximally 2 */ expm1h = rr3h; expm1m = rr3l; } else { expm1h = rr2h; expm1m = rr2l; } } else { expm1h = rr1h; expm1m = rr1l; } } else { expm1h = polyh; expm1m = polyl; } /* Rounding test */ if(expm1h == (expm1h + (expm1m * ROUNDCSTDIRECTRN))) return expm1h; else { #if DEBUG printf("Launch accurate phase (direct interval)\n"); #endif expm1_direct_td(&expm1h, &expm1m, &expm1l, x, xSqHalfh, xSqHalfl, xSqh, xSql, expoX); ReturnRoundToNearest3(expm1h, expm1m, expm1l); } /* Accurate phase launched */ /* We cannot be here, since we return in all cases before */ } /* If we are here, we can use expm1(x) = exp(x) - 1 */ /* Range reduction - exact part: compute k as double and as int */ xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; k = shiftedXMultdb.i[LO]; M = k >> 12; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> 6; /* Range reduction - part affected by error - must be redone in accurate phase */ Mul12(&s1,&s2,msLog2Div2Lh,kd); s3 = kd * msLog2Div2Lm; s4 = s2 + s3; s5 = x + s1; Add12Cond(rh,rm,s5,s4); /* Table reads - read only two double-doubles by now */ tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; /* Quick phase starts here */ rhSquare = rh * rh; rhC3 = quickCommonpolyC3h * rh; rhSquareHalf = 0.5 * rhSquare; monomialCube = rhC3 * rhSquare; rhFour = rhSquare * rhSquare; monomialFour = quickCommonpolyC4h * rhFour; highPoly = monomialCube + monomialFour; highPolyWithSquare = rhSquareHalf + highPoly; /* Reconstruction: integration of table values */ Mul22(&tablesh,&tablesl,tbl1h,tbl1m,tbl2h,tbl2m); t8 = rm + highPolyWithSquare; t9 = rh + t8; t10 = tablesh * t9; Add12(t11,t12,tablesh,t10); t13 = t12 + tablesl; Add12(polyTblhdb.d,polyTblmdb.d,t11,t13); /* Reconstruction: multiplication by 2^M */ /* Implement the multiplication by addition to overcome the problem of the non-representability of 2^1024 (M = 1024) This case is possible if polyTblhdb.d < 1 */ polyTblhdb.i[HI] += M << 20; if(polyTblmdb.d!=0.0) /* predicted true, but it happens for x=-4.1588039009762204, thanks Morten */ polyTblmdb.i[HI] += M << 20; exph = polyTblhdb.d; expm = polyTblmdb.d; /* Subtraction of 1 Testing if the operation is necessary is more expensive than performing it in any case. We may cancellate at most 2 bits in the subtraction for arguments 1/4 <= x <= ln(2) (0.25 <= x <= 0.69) We must therefore use conditional Add12s Since we perform a subtraction, we may not have addition overflow towards +inf */ Add12Cond(t1,t2,-1,exph); t3 = t2 + expm; Add12Cond(expm1h,expm1m,t1,t3); /* Rounding test */ if(expm1h == (expm1h + (expm1m * ROUNDCSTCOMMONRN))) { return expm1h; } else { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; #if DEBUG printf("Launch accurate phase (common interval)\n"); #endif /* Call accurate phase */ expm1_common_td(&expm1h, &expm1m, &expm1l, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l, M); /* Final rounding */ ReturnRoundToNearest3(expm1h, expm1m, expm1l); } /* Accurate phase launched */ /* We cannot be here since we return before in any case */ } double expm1_rd(double x) { db_number xdb, shiftedXMultdb, polyTblhdb, polyTblmdb; int xIntHi, expoX, k, M, index1, index2; double highPoly, tt1h, t1h, t1l, xSqh, xSql, xSqHalfh, xSqHalfl, xCubeh, xCubel, t2h, t2l, templ, tt3h, tt3l; double polyh, polyl, expm1h, expm1m, expm1l; double r1h, r1l, r1t, rr1h, rr1l; double r2h, r2l, r2t, rr2h, rr2l; double r3h, r3l, r3t, rr3h, rr3l; double xMultLog2InvMult2L, shiftedXMult, kd, s1, s2, s3, s4, s5, rh, rm, rl; double rhSquare, rhC3, rhSquareHalf, monomialCube, rhFour, monomialFour; double tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l; double highPolyWithSquare, tablesh, tablesl, t8, t9, t10, t11, t12, t13; double exph, expm, t1, t2, t3; double msLog2Div2LMultKh, msLog2Div2LMultKm, msLog2Div2LMultKl; double middlePoly, doublePoly; xdb.d = x; /* Strip off the sign of x for the following tests */ xIntHi = xdb.i[HI] & 0x7fffffff; /* Test if we are so small that we can return (a corrected) x as correct rounding */ if (xIntHi < RETURNXBOUND) { /* The only algebraic result is 0 for x = +/- 0; in this case, we can return x = +/- 0 The truncation rest x^2/2 + x^3/6 + ... is always positive but less than 1 ulp in this case, so we round down by returning x */ return x; } /* Filter out special cases like overflow, -1 in result, infinities and NaNs The filters are not sharp, we have positive arguments that flow through */ if (xIntHi >= SIMPLEOVERFLOWBOUND) { /* Test if we are +/-inf or NaN */ if (xIntHi >= 0x7ff00000) { /* Test if NaN */ if (((xIntHi & 0x000fffff) | xdb.i[LO]) != 0) { /* NaN */ return x+x; /* return NaN */ } /* Test if +inf or -inf */ if (xdb.i[HI] > 0) { /* +inf */ return x+x; /* return +inf */ } /* If we are here, we are -inf */ return -1.0; } /* If we are here, we are overflowed or a common case that flows through */ /* Test if we are actually overflowed */ if (x > OVERFLOWBOUND) { /* We would be overflowed but as we are rounding downwards the nearest number lesser than the exact result is the greatest normal. In any case, we must raise the inexact flag. */ return LARGEST * (1.0 + SMALLEST); } } /* Test if we know already that we are -1.0 (+ correction depending on rounding mode) in result */ if (x < MINUSONEBOUND) { /* We round down, so we are -1.0 */ return -1.0; } /* Test if we have |x| <= 1/4-1/2ulp(1/4) for knowing if we use exp(x) or approximate directly */ if (xIntHi < DIRECTINTERVALBOUND) { /* We approximate expm1 directly after a range reduction as follows expm1(x) = (expm1(x/2) + 2) * expm1(x/2) We perform the range reduction in such a way that finally |x| < 1/32 */ /* Extract the exponent of |x| and add 5 (2^5 = 32) */ expoX = ((xIntHi & 0x7ff00000) >> 20) - (1023 - 5); /* If this particularily biased exponent expoX is negative, we are already less than 1/32 */ if (expoX >= 0) { /* If we are here, we must perform range reduction */ /* We multiply x by 2^(-expoX-1) by bit manipulation x cannot be denormalized so there is no danger */ xdb.i[HI] += (-expoX-1) << 20; /* We reassign the new x and maintain xIntHi */ xIntHi = xdb.i[HI] & 0x7fffffff; x = xdb.d; } /* Here, we have always |x| < 1/32 */ /* Double precision evaluation steps and one double-double step */ Mul12(&xSqh,&xSql,x,x); #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) middlePoly = FMA(quickDirectpolyC5h,x,quickDirectpolyC4h); #else middlePoly = quickDirectpolyC4h + x * quickDirectpolyC5h; #endif doublePoly = middlePoly; /* Special path: for small |x| we can truncate the polynomial */ if (xIntHi > SPECIALINTERVALBOUND) { #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(quickDirectpolyC9h ,x,quickDirectpolyC8h),x, quickDirectpolyC7h),x,quickDirectpolyC6h); #else highPoly = quickDirectpolyC6h + x * (quickDirectpolyC7h + x * ( quickDirectpolyC8h + x * quickDirectpolyC9h)); #endif highPolyWithSquare = xSqh * highPoly; doublePoly = middlePoly + highPolyWithSquare; } /* Double-double evaluation steps */ tt1h = x * doublePoly; xSqHalfh = 0.5 * xSqh; xSqHalfl = 0.5 * xSql; Add12(t2h,templ,x,xSqHalfh); t2l = templ + xSqHalfl; Add12(t1h,t1l,quickDirectpolyC3h,tt1h); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt3h,&tt3l,xCubeh,xCubel,t1h,t1l); Add22(&polyh,&polyl,t2h,t2l,tt3h,tt3l); /* Reconstruction */ /* If we have not performed any range reduction, we have no reconstruction to do */ if (expoX >= 0) { /* If we are here, we must perform reconstruction */ /* First reconstruction step */ Add12(r1h,r1t,2,polyh); r1l = r1t + polyl; Mul22(&rr1h,&rr1l,r1h,r1l,polyh,polyl); if (expoX >= 1) { /* Second reconstruction step */ Add12(r2h,r2t,2,rr1h); r2l = r2t + rr1l; Mul22(&rr2h,&rr2l,r2h,r2l,rr1h,rr1l); if (expoX >= 2) { /* Third reconstruction step */ Add12(r3h,r3t,2,rr2h); r3l = r3t + rr2l; Mul22(&rr3h,&rr3l,r3h,r3l,rr2h,rr2l); /* expoX may be maximally 2 */ expm1h = rr3h; expm1m = rr3l; } else { expm1h = rr2h; expm1m = rr2l; } } else { expm1h = rr1h; expm1m = rr1l; } } else { expm1h = polyh; expm1m = polyl; } /* Rounding test */ TEST_AND_RETURN_RD(expm1h, expm1m, ROUNDCSTDIRECTRD); { expm1_direct_td(&expm1h, &expm1m, &expm1l, x, xSqHalfh, xSqHalfl, xSqh, xSql, expoX); ReturnRoundDownwards3(expm1h, expm1m, expm1l); } /* Accurate phase launched */ /* We cannot be here, since we return in all cases before */ } /* If we are here, we can use expm1(x) = exp(x) - 1 */ /* Range reduction - exact part: compute k as double and as int */ xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; k = shiftedXMultdb.i[LO]; M = k >> 12; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> 6; /* Range reduction - part affected by error - must be redone in accurate phase */ Mul12(&s1,&s2,msLog2Div2Lh,kd); s3 = kd * msLog2Div2Lm; s4 = s2 + s3; s5 = x + s1; Add12Cond(rh,rm,s5,s4); /* Table reads - read only two double-doubles by now */ tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; /* Quick phase starts here */ rhSquare = rh * rh; rhC3 = quickCommonpolyC3h * rh; rhSquareHalf = 0.5 * rhSquare; monomialCube = rhC3 * rhSquare; rhFour = rhSquare * rhSquare; monomialFour = quickCommonpolyC4h * rhFour; highPoly = monomialCube + monomialFour; highPolyWithSquare = rhSquareHalf + highPoly; /* Reconstruction: integration of table values */ Mul22(&tablesh,&tablesl,tbl1h,tbl1m,tbl2h,tbl2m); t8 = rm + highPolyWithSquare; t9 = rh + t8; t10 = tablesh * t9; Add12(t11,t12,tablesh,t10); t13 = t12 + tablesl; Add12(polyTblhdb.d,polyTblmdb.d,t11,t13); /* Reconstruction: multiplication by 2^M */ /* Implement the multiplication by addition to overcome the problem of the non-representability of 2^1024 (M = 1024) This case is possible if polyTblhdb.d < 1 */ polyTblhdb.i[HI] += M << 20; if(polyTblmdb.d!=0.0) /* predicted true, but it happens for x=-4.1588039009762204, thanks Morten */ polyTblmdb.i[HI] += M << 20; exph = polyTblhdb.d; expm = polyTblmdb.d; /* Subtraction of 1 Testing if the operation is necessary is more expensive than performing it in any case. We may cancellate at most 2 bits in the subtraction for arguments 1/4 <= x <= ln(2) (0.25 <= x <= 0.69) We must therefore use conditional Add12s Since we perform a subtraction, we may not have addition overflow towards +inf */ Add12Cond(t1,t2,-1,exph); t3 = t2 + expm; Add12Cond(expm1h,expm1m,t1,t3); /* Rounding test */ TEST_AND_RETURN_RD(expm1h, expm1m, ROUNDCSTCOMMONRD); { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Call accurate phase */ expm1_common_td(&expm1h, &expm1m, &expm1l, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l, M); /* Final rounding */ ReturnRoundDownwards3(expm1h, expm1m, expm1l); } /* Accurate phase launched */ /* We cannot be here since we return before in any case */ } double expm1_ru(double x) { db_number xdb, shiftedXMultdb, polyTblhdb, polyTblmdb; int xIntHi, expoX, k, M, index1, index2; double highPoly, tt1h, t1h, t1l, xSqh, xSql, xSqHalfh, xSqHalfl, xCubeh, xCubel, t2h, t2l, templ, tt3h, tt3l; double polyh, polyl, expm1h, expm1m, expm1l; double r1h, r1l, r1t, rr1h, rr1l; double r2h, r2l, r2t, rr2h, rr2l; double r3h, r3l, r3t, rr3h, rr3l; double xMultLog2InvMult2L, shiftedXMult, kd, s1, s2, s3, s4, s5, rh, rm, rl; double rhSquare, rhC3, rhSquareHalf, monomialCube, rhFour, monomialFour; double tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l; double highPolyWithSquare, tablesh, tablesl, t8, t9, t10, t11, t12, t13; double exph, expm, t1, t2, t3; double msLog2Div2LMultKh, msLog2Div2LMultKm, msLog2Div2LMultKl; double middlePoly, doublePoly; xdb.d = x; /* Strip off the sign of x for the following tests */ xIntHi = xdb.i[HI] & 0x7fffffff; /* Test if we are so small that we can return (a corrected) x as correct rounding */ if (xIntHi < RETURNXBOUND) { /* The only algebraic result is 0 for x = +/-0; in this case, we return x = +/-0 The truncation rest x^2/2 + x^3/6 + ... is always positive but less than 1 ulp in this case, so we round by adding 1 ulp */ if (x == 0.0) return x; if (xdb.i[HI] & 0x80000000) { /* x is negative We add 1 ulp by subtracting 1 in long */ xdb.l--; } else { /* x is positive We add 1 ulp by adding 1 in long */ xdb.l++; } return xdb.d; } /* Filter out special cases like overflow, -1 in result, infinities and NaNs The filters are not sharp, we have positive arguments that flow through */ if (xIntHi >= SIMPLEOVERFLOWBOUND) { /* Test if we are +/-inf or NaN */ if (xIntHi >= 0x7ff00000) { /* Test if NaN */ if (((xIntHi & 0x000fffff) | xdb.i[LO]) != 0) { /* NaN */ return x+x; /* return NaN */ } /* Test if +inf or -inf */ if (xdb.i[HI] > 0) { /* +inf */ return x+x; /* return +inf */ } /* If we are here, we are -inf */ return -1.0; } /* If we are here, we are overflowed or a common case that flows through */ /* Test if we are actually overflowed */ if (x > OVERFLOWBOUND) { return LARGEST * LARGEST; /* return +inf and set flag */ } } /* Test if we know already that we are -1.0 (+ correction depending on rounding mode) in result */ if (x < MINUSONEBOUND) { /* Round up so we are -1.0 + 1ulp */ return MINUSONEPLUSONEULP; } /* Test if we have |x| <= 1/4-1/2ulp(1/4) for knowing if we use exp(x) or approximate directly */ if (xIntHi < DIRECTINTERVALBOUND) { /* We approximate expm1 directly after a range reduction as follows expm1(x) = (expm1(x/2) + 2) * expm1(x/2) We perform the range reduction in such a way that finally |x| < 1/32 */ /* Extract the exponent of |x| and add 5 (2^5 = 32) */ expoX = ((xIntHi & 0x7ff00000) >> 20) - (1023 - 5); /* If this particularily biased exponent expoX is negative, we are already less than 1/32 */ if (expoX >= 0) { /* If we are here, we must perform range reduction */ /* We multiply x by 2^(-expoX-1) by bit manipulation x cannot be denormalized so there is no danger */ xdb.i[HI] += (-expoX-1) << 20; /* We reassign the new x and maintain xIntHi */ xIntHi = xdb.i[HI] & 0x7fffffff; x = xdb.d; } /* Here, we have always |x| < 1/32 */ /* Double precision evaluation steps and one double-double step */ Mul12(&xSqh,&xSql,x,x); #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) middlePoly = FMA(quickDirectpolyC5h,x,quickDirectpolyC4h); #else middlePoly = quickDirectpolyC4h + x * quickDirectpolyC5h; #endif doublePoly = middlePoly; /* Special path: for small |x| we can truncate the polynomial */ if (xIntHi > SPECIALINTERVALBOUND) { #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(quickDirectpolyC9h ,x,quickDirectpolyC8h),x, quickDirectpolyC7h),x,quickDirectpolyC6h); #else highPoly = quickDirectpolyC6h + x * (quickDirectpolyC7h + x * ( quickDirectpolyC8h + x * quickDirectpolyC9h)); #endif highPolyWithSquare = xSqh * highPoly; doublePoly = middlePoly + highPolyWithSquare; } /* Double-double evaluation steps */ tt1h = x * doublePoly; xSqHalfh = 0.5 * xSqh; xSqHalfl = 0.5 * xSql; Add12(t2h,templ,x,xSqHalfh); t2l = templ + xSqHalfl; Add12(t1h,t1l,quickDirectpolyC3h,tt1h); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt3h,&tt3l,xCubeh,xCubel,t1h,t1l); Add22(&polyh,&polyl,t2h,t2l,tt3h,tt3l); /* Reconstruction */ /* If we have not performed any range reduction, we have no reconstruction to do */ if (expoX >= 0) { /* If we are here, we must perform reconstruction */ /* First reconstruction step */ Add12(r1h,r1t,2,polyh); r1l = r1t + polyl; Mul22(&rr1h,&rr1l,r1h,r1l,polyh,polyl); if (expoX >= 1) { /* Second reconstruction step */ Add12(r2h,r2t,2,rr1h); r2l = r2t + rr1l; Mul22(&rr2h,&rr2l,r2h,r2l,rr1h,rr1l); if (expoX >= 2) { /* Third reconstruction step */ Add12(r3h,r3t,2,rr2h); r3l = r3t + rr2l; Mul22(&rr3h,&rr3l,r3h,r3l,rr2h,rr2l); /* expoX may be maximally 2 */ expm1h = rr3h; expm1m = rr3l; } else { expm1h = rr2h; expm1m = rr2l; } } else { expm1h = rr1h; expm1m = rr1l; } } else { expm1h = polyh; expm1m = polyl; } /* Rounding test */ TEST_AND_RETURN_RU(expm1h, expm1m, ROUNDCSTDIRECTRD); { expm1_direct_td(&expm1h, &expm1m, &expm1l, x, xSqHalfh, xSqHalfl, xSqh, xSql, expoX); ReturnRoundUpwards3(expm1h, expm1m, expm1l); } /* Accurate phase launched */ /* We cannot be here, since we return in all cases before */ } /* If we are here, we can use expm1(x) = exp(x) - 1 */ /* Range reduction - exact part: compute k as double and as int */ xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; k = shiftedXMultdb.i[LO]; M = k >> 12; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> 6; /* Range reduction - part affected by error - must be redone in accurate phase */ Mul12(&s1,&s2,msLog2Div2Lh,kd); s3 = kd * msLog2Div2Lm; s4 = s2 + s3; s5 = x + s1; Add12Cond(rh,rm,s5,s4); /* Table reads - read only two double-doubles by now */ tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; /* Quick phase starts here */ rhSquare = rh * rh; rhC3 = quickCommonpolyC3h * rh; rhSquareHalf = 0.5 * rhSquare; monomialCube = rhC3 * rhSquare; rhFour = rhSquare * rhSquare; monomialFour = quickCommonpolyC4h * rhFour; highPoly = monomialCube + monomialFour; highPolyWithSquare = rhSquareHalf + highPoly; /* Reconstruction: integration of table values */ Mul22(&tablesh,&tablesl,tbl1h,tbl1m,tbl2h,tbl2m); t8 = rm + highPolyWithSquare; t9 = rh + t8; t10 = tablesh * t9; Add12(t11,t12,tablesh,t10); t13 = t12 + tablesl; Add12(polyTblhdb.d,polyTblmdb.d,t11,t13); /* Reconstruction: multiplication by 2^M */ /* Implement the multiplication by addition to overcome the problem of the non-representability of 2^1024 (M = 1024) This case is possible if polyTblhdb.d < 1 */ polyTblhdb.i[HI] += M << 20; if(polyTblmdb.d!=0.0) /* predicted true, but it happens for x=-4.1588039009762204, thanks Morten */ polyTblmdb.i[HI] += M << 20; exph = polyTblhdb.d; expm = polyTblmdb.d; /* Subtraction of 1 Testing if the operation is necessary is more expensive than performing it in any case. We may cancellate at most 2 bits in the subtraction for arguments 1/4 <= x <= ln(2) (0.25 <= x <= 0.69) We must therefore use conditional Add12s Since we perform a subtraction, we may not have addition overflow towards +inf */ Add12Cond(t1,t2,-1,exph); t3 = t2 + expm; Add12Cond(expm1h,expm1m,t1,t3); /* Rounding test */ TEST_AND_RETURN_RU(expm1h, expm1m, ROUNDCSTCOMMONRD); { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Call accurate phase */ expm1_common_td(&expm1h, &expm1m, &expm1l, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l, M); /* Final rounding */ ReturnRoundUpwards3(expm1h, expm1m, expm1l); } /* Accurate phase launched */ /* We cannot be here since we return before in any case */ } double expm1_rz(double x) { db_number xdb, shiftedXMultdb, polyTblhdb, polyTblmdb; int xIntHi, expoX, k, M, index1, index2; double highPoly, tt1h, t1h, t1l, xSqh, xSql, xSqHalfh, xSqHalfl, xCubeh, xCubel, t2h, t2l, templ, tt3h, tt3l; double polyh, polyl, expm1h, expm1m, expm1l; double r1h, r1l, r1t, rr1h, rr1l; double r2h, r2l, r2t, rr2h, rr2l; double r3h, r3l, r3t, rr3h, rr3l; double xMultLog2InvMult2L, shiftedXMult, kd, s1, s2, s3, s4, s5, rh, rm, rl; double rhSquare, rhC3, rhSquareHalf, monomialCube, rhFour, monomialFour; double tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l; double highPolyWithSquare, tablesh, tablesl, t8, t9, t10, t11, t12, t13; double exph, expm, t1, t2, t3; double msLog2Div2LMultKh, msLog2Div2LMultKm, msLog2Div2LMultKl; double middlePoly, doublePoly; xdb.d = x; /* Strip off the sign of x for the following tests */ xIntHi = xdb.i[HI] & 0x7fffffff; /* Test if we are so small that we can return (a corrected) x as correct rounding */ if (xIntHi < RETURNXBOUND) { /* The only algebraic result is 0 for x = +/- 0; in this case, we can return x = +/- 0 expm1 is positive for positive x, negative for negative x The truncation rest x^2/2 + x^3/6 + ... is always positive but less than 1 ulp in this case, so we round as follows: - x is positive => expm1 is positive => round downwards => truncate by returning x - x is negative => expm1 is negative => round upwards => add 1 ulp */ if (x == 0.0) return x; if (xdb.i[HI] & 0x80000000) { /* x is negative We add 1 ulp by subtracting 1 in long */ xdb.l--; return xdb.d; } else { /* x is positive We do nothing (see above) */ return x; } } /* Filter out special cases like overflow, -1 in result, infinities and NaNs The filters are not sharp, we have positive arguments that flow through */ if (xIntHi >= SIMPLEOVERFLOWBOUND) { /* Test if we are +/-inf or NaN */ if (xIntHi >= 0x7ff00000) { /* Test if NaN */ if (((xIntHi & 0x000fffff) | xdb.i[LO]) != 0) { /* NaN */ return x+x; /* return NaN */ } /* Test if +inf or -inf */ if (xdb.i[HI] > 0) { /* +inf */ return x+x; /* return +inf */ } /* If we are here, we are -inf */ return -1.0; } /* If we are here, we are overflowed or a common case that flows through */ /* Test if we are actually overflowed */ if (x > OVERFLOWBOUND) { /* We would be overflowed but as we are rounding towards zero, i.e. downwards, the nearest number lesser than the exact result is the greatest normal. In any case, we must raise the inexact flag. */ return LARGEST * (1.0 + SMALLEST); } } /* Test if we know already that we are -1.0 (+ correction depending on rounding mode) in result */ if (x < MINUSONEBOUND) { /* We round towards zero, i.e. upwards, so we return -1.0+1ulp */ return MINUSONEPLUSONEULP; } /* Test if we have |x| <= 1/4-1/2ulp(1/4) for knowing if we use exp(x) or approximate directly */ if (xIntHi < DIRECTINTERVALBOUND) { /* We approximate expm1 directly after a range reduction as follows expm1(x) = (expm1(x/2) + 2) * expm1(x/2) We perform the range reduction in such a way that finally |x| < 1/32 */ /* Extract the exponent of |x| and add 5 (2^5 = 32) */ expoX = ((xIntHi & 0x7ff00000) >> 20) - (1023 - 5); /* If this particularily biased exponent expoX is negative, we are already less than 1/32 */ if (expoX >= 0) { /* If we are here, we must perform range reduction */ /* We multiply x by 2^(-expoX-1) by bit manipulation x cannot be denormalized so there is no danger */ xdb.i[HI] += (-expoX-1) << 20; /* We reassign the new x and maintain xIntHi */ xIntHi = xdb.i[HI] & 0x7fffffff; x = xdb.d; } /* Here, we have always |x| < 1/32 */ /* Double precision evaluation steps and one double-double step */ Mul12(&xSqh,&xSql,x,x); #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) middlePoly = FMA(quickDirectpolyC5h,x,quickDirectpolyC4h); #else middlePoly = quickDirectpolyC4h + x * quickDirectpolyC5h; #endif doublePoly = middlePoly; /* Special path: for small |x| we can truncate the polynomial */ if (xIntHi > SPECIALINTERVALBOUND) { #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(quickDirectpolyC9h ,x,quickDirectpolyC8h),x, quickDirectpolyC7h),x,quickDirectpolyC6h); #else highPoly = quickDirectpolyC6h + x * (quickDirectpolyC7h + x * ( quickDirectpolyC8h + x * quickDirectpolyC9h)); #endif highPolyWithSquare = xSqh * highPoly; doublePoly = middlePoly + highPolyWithSquare; } /* Double-double evaluation steps */ tt1h = x * doublePoly; xSqHalfh = 0.5 * xSqh; xSqHalfl = 0.5 * xSql; Add12(t2h,templ,x,xSqHalfh); t2l = templ + xSqHalfl; Add12(t1h,t1l,quickDirectpolyC3h,tt1h); Mul122(&xCubeh,&xCubel,x,xSqh,xSql); Mul22(&tt3h,&tt3l,xCubeh,xCubel,t1h,t1l); Add22(&polyh,&polyl,t2h,t2l,tt3h,tt3l); /* Reconstruction */ /* If we have not performed any range reduction, we have no reconstruction to do */ if (expoX >= 0) { /* If we are here, we must perform reconstruction */ /* First reconstruction step */ Add12(r1h,r1t,2,polyh); r1l = r1t + polyl; Mul22(&rr1h,&rr1l,r1h,r1l,polyh,polyl); if (expoX >= 1) { /* Second reconstruction step */ Add12(r2h,r2t,2,rr1h); r2l = r2t + rr1l; Mul22(&rr2h,&rr2l,r2h,r2l,rr1h,rr1l); if (expoX >= 2) { /* Third reconstruction step */ Add12(r3h,r3t,2,rr2h); r3l = r3t + rr2l; Mul22(&rr3h,&rr3l,r3h,r3l,rr2h,rr2l); /* expoX may be maximally 2 */ expm1h = rr3h; expm1m = rr3l; } else { expm1h = rr2h; expm1m = rr2l; } } else { expm1h = rr1h; expm1m = rr1l; } } else { expm1h = polyh; expm1m = polyl; } /* Rounding test */ TEST_AND_RETURN_RZ(expm1h, expm1m, ROUNDCSTDIRECTRD); { expm1_direct_td(&expm1h, &expm1m, &expm1l, x, xSqHalfh, xSqHalfl, xSqh, xSql, expoX); ReturnRoundTowardsZero3(expm1h, expm1m, expm1l); } /* Accurate phase launched */ /* We cannot be here, since we return in all cases before */ } /* If we are here, we can use expm1(x) = exp(x) - 1 */ /* Range reduction - exact part: compute k as double and as int */ xMultLog2InvMult2L = x * log2InvMult2L; shiftedXMult = xMultLog2InvMult2L + shiftConst; kd = shiftedXMult - shiftConst; shiftedXMultdb.d = shiftedXMult; k = shiftedXMultdb.i[LO]; M = k >> 12; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> 6; /* Range reduction - part affected by error - must be redone in accurate phase */ Mul12(&s1,&s2,msLog2Div2Lh,kd); s3 = kd * msLog2Div2Lm; s4 = s2 + s3; s5 = x + s1; Add12Cond(rh,rm,s5,s4); /* Table reads - read only two double-doubles by now */ tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; /* Quick phase starts here */ rhSquare = rh * rh; rhC3 = quickCommonpolyC3h * rh; rhSquareHalf = 0.5 * rhSquare; monomialCube = rhC3 * rhSquare; rhFour = rhSquare * rhSquare; monomialFour = quickCommonpolyC4h * rhFour; highPoly = monomialCube + monomialFour; highPolyWithSquare = rhSquareHalf + highPoly; /* Reconstruction: integration of table values */ Mul22(&tablesh,&tablesl,tbl1h,tbl1m,tbl2h,tbl2m); t8 = rm + highPolyWithSquare; t9 = rh + t8; t10 = tablesh * t9; Add12(t11,t12,tablesh,t10); t13 = t12 + tablesl; Add12(polyTblhdb.d,polyTblmdb.d,t11,t13); /* Reconstruction: multiplication by 2^M */ /* Implement the multiplication by addition to overcome the problem of the non-representability of 2^1024 (M = 1024) This case is possible if polyTblhdb.d < 1 */ polyTblhdb.i[HI] += M << 20; if(polyTblmdb.d!=0.0) /* predicted true, but it happens for x=-4.1588039009762204, thanks Morten */ polyTblmdb.i[HI] += M << 20; exph = polyTblhdb.d; expm = polyTblmdb.d; /* Subtraction of 1 Testing if the operation is necessary is more expensive than performing it in any case. We may cancellate at most 2 bits in the subtraction for arguments 1/4 <= x <= ln(2) (0.25 <= x <= 0.69) We must therefore use conditional Add12s Since we perform a subtraction, we may not have addition overflow towards +inf */ Add12Cond(t1,t2,-1,exph); t3 = t2 + expm; Add12Cond(expm1h,expm1m,t1,t3); /* Rounding test */ TEST_AND_RETURN_RZ(expm1h, expm1m, ROUNDCSTCOMMONRD); { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh,&msLog2Div2LMultKm,&msLog2Div2LMultKl,kd,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1 = x + msLog2Div2LMultKh; Add12Cond(rh,t2,t1,msLog2Div2LMultKm); Add12Cond(rm,rl,t2,msLog2Div2LMultKl); /* Table reads for accurate phase */ tbl1l = twoPowerIndex1[index1].lo; tbl2l = twoPowerIndex2[index2].lo; /* Call accurate phase */ expm1_common_td(&expm1h, &expm1m, &expm1l, rh, rm, rl, tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l, M); /* Final rounding */ ReturnRoundTowardsZero3(expm1h, expm1m, expm1l); } /* Accurate phase launched */ /* We cannot be here since we return before in any case */ } #ifdef BUILD_INTERVAL_FUNCTIONS interval j_expm1(interval x) { interval res; db_number xdb_inf, shiftedXMultdb_inf, polyTblhdb_inf, polyTblmdb_inf; int xIntHi_inf, expoX_inf, k_inf, M_inf, index1_inf, index2_inf; double x_inf, x_sup; double res_inf,res_sup; double restemp_inf, restemp_sup; double highPoly_inf, tt1h_inf, t1h_inf, t1l_inf, xSqh_inf, xSql_inf, xSqHalfh_inf, xSqHalfl_inf, xCubeh_inf, xCubel_inf, t2h_inf, t2l_inf, templ_inf, tt3h_inf, tt3l_inf; double polyh_inf, polyl_inf, expm1h_inf, expm1m_inf, expm1l_inf; double r1h_inf, r1l_inf, r1t_inf, rr1h_inf, rr1l_inf; double r2h_inf, r2l_inf, r2t_inf, rr2h_inf, rr2l_inf; double r3h_inf, r3l_inf, r3t_inf, rr3h_inf, rr3l_inf; double xMultLog2InvMult2L_inf, shiftedXMult_inf, kd_inf, s1_inf, s2_inf, s3_inf, s4_inf, s5_inf, rh_inf, rm_inf, rl_inf; double rhSquare_inf, rhC3_inf, rhSquareHalf_inf, monomialCube_inf, rhFour_inf, monomialFour_inf; double tbl1h_inf, tbl1m_inf, tbl1l_inf, tbl2h_inf, tbl2m_inf, tbl2l_inf; double highPolyWithSquare_inf, tablesh_inf, tablesl_inf, t8_inf, t9_inf, t10_inf, t11_inf, t12_inf, t13_inf; double exph_inf, expm_inf, t1_inf, t2_inf, t3_inf; double msLog2Div2LMultKh_inf, msLog2Div2LMultKm_inf, msLog2Div2LMultKl_inf; double middlePoly_inf, doublePoly_inf; int roundable; int infDone, supDone; infDone=0; supDone=0; db_number xdb_sup, shiftedXMultdb_sup, polyTblhdb_sup, polyTblmdb_sup; int xIntHi_sup, expoX_sup, k_sup, M_sup, index1_sup, index2_sup; double highPoly_sup, tt1h_sup, t1h_sup, t1l_sup, xSqh_sup, xSql_sup, xSqHalfh_sup, xSqHalfl_sup, xCubeh_sup, xCubel_sup, t2h_sup, t2l_sup, templ_sup, tt3h_sup, tt3l_sup; double polyh_sup, polyl_sup, expm1h_sup, expm1m_sup, expm1l_sup; double r1h_sup, r1l_sup, r1t_sup, rr1h_sup, rr1l_sup; double r2h_sup, r2l_sup, r2t_sup, rr2h_sup, rr2l_sup; double r3h_sup, r3l_sup, r3t_sup, rr3h_sup, rr3l_sup; double xMultLog2InvMult2L_sup, shiftedXMult_sup, kd_sup, s1_sup, s2_sup, s3_sup, s4_sup, s5_sup, rh_sup, rm_sup, rl_sup; double rhSquare_sup, rhC3_sup, rhSquareHalf_sup, monomialCube_sup, rhFour_sup, monomialFour_sup; double tbl1h_sup, tbl1m_sup, tbl1l_sup, tbl2h_sup, tbl2m_sup, tbl2l_sup; double highPolyWithSquare_sup, tablesh_sup, tablesl_sup, t8_sup, t9_sup, t10_sup, t11_sup, t12_sup, t13_sup; double exph_sup, expm_sup, t1_sup, t2_sup, t3_sup; double msLog2Div2LMultKh_sup, msLog2Div2LMultKm_sup, msLog2Div2LMultKl_sup; double middlePoly_sup, doublePoly_sup; x_inf=LOW(x); x_sup=UP(x); xdb_inf.d = x_inf; xdb_sup.d = x_sup; /* Strip off the sign of x for the following tests */ xIntHi_inf = xdb_inf.i[HI] & 0x7fffffff; xIntHi_sup = xdb_sup.i[HI] & 0x7fffffff; /* Test if we are so small that we can return (a corrected) x as correct rounding */ if ( __builtin_expect( (xIntHi_inf < RETURNXBOUND) || ((xIntHi_inf >= SIMPLEOVERFLOWBOUND) && (xIntHi_inf >= 0x7ff00000)) || ((xIntHi_inf >= SIMPLEOVERFLOWBOUND) && (xIntHi_inf >= 0x7ff00000) && (((xIntHi_inf & 0x000fffff) | xdb_inf.i[LO]) != 0)) || ((xIntHi_inf >= SIMPLEOVERFLOWBOUND) && (xIntHi_inf >= 0x7ff00000) && (xdb_inf.i[HI] > 0)) || ((xIntHi_inf >= SIMPLEOVERFLOWBOUND) && (x_inf > OVERFLOWBOUND)) || (x_inf < MINUSONEBOUND) || (xIntHi_sup < RETURNXBOUND) || ((xIntHi_sup < RETURNXBOUND) && (x_sup == 0.0)) || ((xIntHi_sup >= SIMPLEOVERFLOWBOUND) && (xIntHi_sup >= 0x7ff00000)) || ((xIntHi_sup >= SIMPLEOVERFLOWBOUND) && (xIntHi_sup >= 0x7ff00000) && (((xIntHi_sup & 0x000fffff) | xdb_sup.i[LO]) != 0)) || ((xIntHi_sup >= SIMPLEOVERFLOWBOUND) && (xIntHi_sup >= 0x7ff00000) && (xdb_sup.i[HI] > 0)) || ((xIntHi_sup >= SIMPLEOVERFLOWBOUND) && (x_sup > OVERFLOWBOUND)) || (x_sup < MINUSONEBOUND) ,FALSE)) { ASSIGN_LOW(res,expm1_rd(LOW(x))); ASSIGN_UP(res,expm1_ru(UP(x))); return res; } if (__builtin_expect((xIntHi_inf < DIRECTINTERVALBOUND) && (xIntHi_sup < DIRECTINTERVALBOUND),TRUE)) { /* We approximate expm1 directly after a range reduction as follows expm1(x) = (expm1(x/2) + 2) * expm1(x/2) We perform the range reduction in such a way that finally |x| < 1/32 */ /* Extract the exponent of |x| and add 5 (2^5 = 32) */ expoX_inf = ((xIntHi_inf & 0x7ff00000) >> 20) - (1023 - 5); expoX_sup = ((xIntHi_sup & 0x7ff00000) >> 20) - (1023 - 5); /* If this particularily biased exponent expoX is negative, we are already less than 1/32 */ if (expoX_inf >= 0) { /* If we are here, we must perform range reduction */ /* We multiply x by 2^(-expoX-1) by bit manipulation x cannot be denormalized so there is no danger */ xdb_inf.i[HI] += (-expoX_inf-1) << 20; /* We reassign the new x and maintain xIntHi */ xIntHi_inf = xdb_inf.i[HI] & 0x7fffffff; x_inf = xdb_inf.d; } if (expoX_sup >= 0) { /* If we are here, we must perform range reduction */ /* We multiply x by 2^(-expoX-1) by bit manipulation x cannot be denormalized so there is no danger */ xdb_sup.i[HI] += (-expoX_sup-1) << 20; /* We reassign the new x and maintain xIntHi */ xIntHi_sup = xdb_sup.i[HI] & 0x7fffffff; x_sup = xdb_sup.d; } /* Here, we have always |x| < 1/32 */ /* Double precision evaluation steps and one double-double step */ Mul12(&xSqh_inf,&xSql_inf,x_inf,x_inf); Mul12(&xSqh_sup,&xSql_sup,x_sup,x_sup); #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) middlePoly_inf = FMA(quickDirectpolyC5h,x_inf,quickDirectpolyC4h); middlePoly_sup = FMA(quickDirectpolyC5h,x_sup,quickDirectpolyC4h); #else middlePoly_inf = quickDirectpolyC4h + x_inf * quickDirectpolyC5h; middlePoly_sup = quickDirectpolyC4h + x_sup * quickDirectpolyC5h; #endif doublePoly_inf = middlePoly_inf; doublePoly_sup = middlePoly_sup; /* Special path: for small |x| we can truncate the polynomial */ if (xIntHi_inf > SPECIALINTERVALBOUND) { #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly_inf = FMA(FMA(FMA(quickDirectpolyC9h ,x_inf,quickDirectpolyC8h),x_inf, quickDirectpolyC7h),x_inf,quickDirectpolyC6h); #else highPoly_inf = quickDirectpolyC6h + x_inf * (quickDirectpolyC7h + x_inf * ( quickDirectpolyC8h + x_inf * quickDirectpolyC9h)); #endif highPolyWithSquare_inf = xSqh_inf * highPoly_inf; doublePoly_inf = middlePoly_inf + highPolyWithSquare_inf; } if (xIntHi_sup > SPECIALINTERVALBOUND) { #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly_sup = FMA(FMA(FMA(quickDirectpolyC9h ,x_sup,quickDirectpolyC8h),x_sup, quickDirectpolyC7h),x_sup,quickDirectpolyC6h); #else highPoly_sup = quickDirectpolyC6h + x_sup * (quickDirectpolyC7h + x_sup * ( quickDirectpolyC8h + x_sup * quickDirectpolyC9h)); #endif highPolyWithSquare_sup = xSqh_sup * highPoly_sup; doublePoly_sup = middlePoly_sup + highPolyWithSquare_sup; } /* Double-double evaluation steps */ tt1h_inf = x_inf * doublePoly_inf; tt1h_sup = x_sup * doublePoly_sup; xSqHalfh_inf = 0.5 * xSqh_inf; xSqHalfh_sup = 0.5 * xSqh_sup; xSqHalfl_inf = 0.5 * xSql_inf; xSqHalfl_sup = 0.5 * xSql_sup; Add12(t2h_inf,templ_inf,x_inf,xSqHalfh_inf); Add12(t2h_sup,templ_sup,x_sup,xSqHalfh_sup); t2l_inf = templ_inf + xSqHalfl_inf; t2l_sup = templ_sup + xSqHalfl_sup; Add12(t1h_inf,t1l_inf,quickDirectpolyC3h,tt1h_inf); Add12(t1h_sup,t1l_sup,quickDirectpolyC3h,tt1h_sup); Mul122(&xCubeh_inf,&xCubel_inf,x_inf,xSqh_inf,xSql_inf); Mul122(&xCubeh_sup,&xCubel_sup,x_sup,xSqh_sup,xSql_sup); Mul22(&tt3h_inf,&tt3l_inf,xCubeh_inf,xCubel_inf,t1h_inf,t1l_inf); Mul22(&tt3h_sup,&tt3l_sup,xCubeh_sup,xCubel_sup,t1h_sup,t1l_sup); Add22(&polyh_inf,&polyl_inf,t2h_inf,t2l_inf,tt3h_inf,tt3l_inf); Add22(&polyh_sup,&polyl_sup,t2h_sup,t2l_sup,tt3h_sup,tt3l_sup); /* Reconstruction */ /* If we have not performed any range reduction, we have no reconstruction to do */ if (expoX_inf >= 0) { /* If we are here, we must perform reconstruction */ /* First reconstruction step */ Add12(r1h_inf,r1t_inf,2,polyh_inf); r1l_inf = r1t_inf + polyl_inf; Mul22(&rr1h_inf,&rr1l_inf,r1h_inf,r1l_inf,polyh_inf,polyl_inf); if (expoX_inf >= 1) { /* Second reconstruction step */ Add12(r2h_inf,r2t_inf,2,rr1h_inf); r2l_inf = r2t_inf + rr1l_inf; Mul22(&rr2h_inf,&rr2l_inf,r2h_inf,r2l_inf,rr1h_inf,rr1l_inf); if (expoX_inf >= 2) { /* Third reconstruction step */ Add12(r3h_inf,r3t_inf,2,rr2h_inf); r3l_inf = r3t_inf + rr2l_inf; Mul22(&rr3h_inf,&rr3l_inf,r3h_inf,r3l_inf,rr2h_inf,rr2l_inf); /* expoX may be maximally 2 */ expm1h_inf = rr3h_inf; expm1m_inf = rr3l_inf; } else { expm1h_inf = rr2h_inf; expm1m_inf = rr2l_inf; } } else { expm1h_inf = rr1h_inf; expm1m_inf = rr1l_inf; } } else { expm1h_inf = polyh_inf; expm1m_inf = polyl_inf; } if (expoX_sup >= 0) { /* If we are here, we must perform reconstruction */ /* First reconstruction step */ Add12(r1h_sup,r1t_sup,2,polyh_sup); r1l_sup = r1t_sup + polyl_sup; Mul22(&rr1h_sup,&rr1l_sup,r1h_sup,r1l_sup,polyh_sup,polyl_sup); if (expoX_sup >= 1) { /* Second reconstruction step */ Add12(r2h_sup,r2t_sup,2,rr1h_sup); r2l_sup = r2t_sup + rr1l_sup; Mul22(&rr2h_sup,&rr2l_sup,r2h_sup,r2l_sup,rr1h_sup,rr1l_sup); if (expoX_sup >= 2) { /* Third reconstruction step */ Add12(r3h_sup,r3t_sup,2,rr2h_sup); r3l_sup = r3t_sup + rr2l_sup; Mul22(&rr3h_sup,&rr3l_sup,r3h_sup,r3l_sup,rr2h_sup,rr2l_sup); /* expoX may be maximally 2 */ expm1h_sup = rr3h_sup; expm1m_sup = rr3l_sup; } else { expm1h_sup = rr2h_sup; expm1m_sup = rr2l_sup; } } else { expm1h_sup = rr1h_sup; expm1m_sup = rr1l_sup; } } else { expm1h_sup = polyh_sup; expm1m_sup = polyl_sup; } /* Rounding test */ TEST_AND_COPY_RDRU_EXPM1(roundable,restemp_inf,expm1h_inf, expm1m_inf, restemp_sup,expm1h_sup, expm1m_sup, ROUNDCSTDIRECTRD); if((roundable==2) || (roundable==0)) { expm1_direct_td(&expm1h_inf, &expm1m_inf, &expm1l_inf, x_inf, xSqHalfh_inf, xSqHalfl_inf, xSqh_inf, xSql_inf, expoX_inf); RoundDownwards3(&restemp_inf,expm1h_inf, expm1m_inf, expm1l_inf); } /* Accurate phase launched */ if((roundable==1) || (roundable==0)) { expm1_direct_td(&expm1h_sup, &expm1m_sup, &expm1l_sup, x_sup, xSqHalfh_sup, xSqHalfl_sup, xSqh_sup, xSql_sup, expoX_sup); RoundUpwards3(&restemp_sup,expm1h_sup, expm1m_sup, expm1l_sup); } /* Accurate phase launched */ ASSIGN_LOW(res,restemp_inf); ASSIGN_UP(res,restemp_sup); return res; } /* Test if we have |x| <= 1/4-1/2ulp(1/4) for knowing if we use exp(x) or approximate directly */ if (xIntHi_inf < DIRECTINTERVALBOUND) { /* We approximate expm1 directly after a range reduction as follows expm1(x) = (expm1(x/2) + 2) * expm1(x/2) We perform the range reduction in such a way that finally |x| < 1/32 */ /* Extract the exponent of |x| and add 5 (2^5 = 32) */ expoX_inf = ((xIntHi_inf & 0x7ff00000) >> 20) - (1023 - 5); /* If this particularily biased exponent expoX is negative, we are already less than 1/32 */ if (expoX_inf >= 0) { /* If we are here, we must perform range reduction */ /* We multiply x by 2^(-expoX-1) by bit manipulation x cannot be denormalized so there is no danger */ xdb_inf.i[HI] += (-expoX_inf-1) << 20; /* We reassign the new x and maintain xIntHi */ xIntHi_inf = xdb_inf.i[HI] & 0x7fffffff; x_inf = xdb_inf.d; } /* Here, we have always |x| < 1/32 */ /* Double precision evaluation steps and one double-double step */ Mul12(&xSqh_inf,&xSql_inf,x_inf,x_inf); #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) middlePoly_inf = FMA(quickDirectpolyC5h,x_inf,quickDirectpolyC4h); #else middlePoly_inf = quickDirectpolyC4h + x_inf * quickDirectpolyC5h; #endif doublePoly_inf = middlePoly_inf; /* Special path: for small |x| we can truncate the polynomial */ if (xIntHi_inf > SPECIALINTERVALBOUND) { #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly_inf = FMA(FMA(FMA(quickDirectpolyC9h ,x_inf,quickDirectpolyC8h),x_inf, quickDirectpolyC7h),x_inf,quickDirectpolyC6h); #else highPoly_inf = quickDirectpolyC6h + x_inf * (quickDirectpolyC7h + x_inf * ( quickDirectpolyC8h + x_inf * quickDirectpolyC9h)); #endif highPolyWithSquare_inf = xSqh_inf * highPoly_inf; doublePoly_inf = middlePoly_inf + highPolyWithSquare_inf; } /* Double-double evaluation steps */ tt1h_inf = x_inf * doublePoly_inf; xSqHalfh_inf = 0.5 * xSqh_inf; xSqHalfl_inf = 0.5 * xSql_inf; Add12(t2h_inf,templ_inf,x_inf,xSqHalfh_inf); t2l_inf = templ_inf + xSqHalfl_inf; Add12(t1h_inf,t1l_inf,quickDirectpolyC3h,tt1h_inf); Mul122(&xCubeh_inf,&xCubel_inf,x_inf,xSqh_inf,xSql_inf); Mul22(&tt3h_inf,&tt3l_inf,xCubeh_inf,xCubel_inf,t1h_inf,t1l_inf); Add22(&polyh_inf,&polyl_inf,t2h_inf,t2l_inf,tt3h_inf,tt3l_inf); /* Reconstruction */ /* If we have not performed any range reduction, we have no reconstruction to do */ if (expoX_inf >= 0) { /* If we are here, we must perform reconstruction */ /* First reconstruction step */ Add12(r1h_inf,r1t_inf,2,polyh_inf); r1l_inf = r1t_inf + polyl_inf; Mul22(&rr1h_inf,&rr1l_inf,r1h_inf,r1l_inf,polyh_inf,polyl_inf); if (expoX_inf >= 1) { /* Second reconstruction step */ Add12(r2h_inf,r2t_inf,2,rr1h_inf); r2l_inf = r2t_inf + rr1l_inf; Mul22(&rr2h_inf,&rr2l_inf,r2h_inf,r2l_inf,rr1h_inf,rr1l_inf); if (expoX_inf >= 2) { /* Third reconstruction step */ Add12(r3h_inf,r3t_inf,2,rr2h_inf); r3l_inf = r3t_inf + rr2l_inf; Mul22(&rr3h_inf,&rr3l_inf,r3h_inf,r3l_inf,rr2h_inf,rr2l_inf); /* expoX may be maximally 2 */ expm1h_inf = rr3h_inf; expm1m_inf = rr3l_inf; } else { expm1h_inf = rr2h_inf; expm1m_inf = rr2l_inf; } } else { expm1h_inf = rr1h_inf; expm1m_inf = rr1l_inf; } } else { expm1h_inf = polyh_inf; expm1m_inf = polyl_inf; } /* Rounding test */ infDone=1; TEST_AND_COPY_RD(roundable,restemp_inf,expm1h_inf, expm1m_inf, ROUNDCSTDIRECTRD); if(roundable==0) { expm1_direct_td(&expm1h_inf, &expm1m_inf, &expm1l_inf, x_inf, xSqHalfh_inf, xSqHalfl_inf, xSqh_inf, xSql_inf, expoX_inf); RoundDownwards3(&restemp_inf,expm1h_inf, expm1m_inf, expm1l_inf); } /* Accurate phase launched */ } /* Test if we have |x| <= 1/4-1/2ulp(1/4) for knowing if we use exp(x) or approximate directly */ if (xIntHi_sup < DIRECTINTERVALBOUND) { /* We approximate expm1 directly after a range reduction as follows expm1(x) = (expm1(x/2) + 2) * expm1(x/2) We perform the range reduction in such a way that finally |x| < 1/32 */ /* Extract the exponent of |x| and add 5 (2^5 = 32) */ expoX_sup = ((xIntHi_sup & 0x7ff00000) >> 20) - (1023 - 5); /* If this particularily biased exponent expoX is negative, we are already less than 1/32 */ if (expoX_sup >= 0) { /* If we are here, we must perform range reduction */ /* We multiply x by 2^(-expoX-1) by bit manipulation x cannot be denormalized so there is no danger */ xdb_sup.i[HI] += (-expoX_sup-1) << 20; /* We reassign the new x and maintain xIntHi */ xIntHi_sup = xdb_sup.i[HI] & 0x7fffffff; x_sup = xdb_sup.d; } /* Here, we have always |x| < 1/32 */ /* Double precision evaluation steps and one double-double step */ Mul12(&xSqh_sup,&xSql_sup,x_sup,x_sup); #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) middlePoly_sup = FMA(quickDirectpolyC5h,x_sup,quickDirectpolyC4h); #else middlePoly_sup = quickDirectpolyC4h + x_sup * quickDirectpolyC5h; #endif doublePoly_sup = middlePoly_sup; /* Special path: for small |x| we can truncate the polynomial */ if (xIntHi_sup > SPECIALINTERVALBOUND) { #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly_sup = FMA(FMA(FMA(quickDirectpolyC9h ,x_sup,quickDirectpolyC8h),x_sup, quickDirectpolyC7h),x_sup,quickDirectpolyC6h); #else highPoly_sup = quickDirectpolyC6h + x_sup * (quickDirectpolyC7h + x_sup * ( quickDirectpolyC8h + x_sup * quickDirectpolyC9h)); #endif highPolyWithSquare_sup = xSqh_sup * highPoly_sup; doublePoly_sup = middlePoly_sup + highPolyWithSquare_sup; } /* Double-double evaluation steps */ tt1h_sup = x_sup * doublePoly_sup; xSqHalfh_sup = 0.5 * xSqh_sup; xSqHalfl_sup = 0.5 * xSql_sup; Add12(t2h_sup,templ_sup,x_sup,xSqHalfh_sup); t2l_sup = templ_sup + xSqHalfl_sup; Add12(t1h_sup,t1l_sup,quickDirectpolyC3h,tt1h_sup); Mul122(&xCubeh_sup,&xCubel_sup,x_sup,xSqh_sup,xSql_sup); Mul22(&tt3h_sup,&tt3l_sup,xCubeh_sup,xCubel_sup,t1h_sup,t1l_sup); Add22(&polyh_sup,&polyl_sup,t2h_sup,t2l_sup,tt3h_sup,tt3l_sup); /* Reconstruction */ /* If we have not performed any range reduction, we have no reconstruction to do */ if (expoX_sup >= 0) { /* If we are here, we must perform reconstruction */ /* First reconstruction step */ Add12(r1h_sup,r1t_sup,2,polyh_sup); r1l_sup = r1t_sup + polyl_sup; Mul22(&rr1h_sup,&rr1l_sup,r1h_sup,r1l_sup,polyh_sup,polyl_sup); if (expoX_sup >= 1) { /* Second reconstruction step */ Add12(r2h_sup,r2t_sup,2,rr1h_sup); r2l_sup = r2t_sup + rr1l_sup; Mul22(&rr2h_sup,&rr2l_sup,r2h_sup,r2l_sup,rr1h_sup,rr1l_sup); if (expoX_sup >= 2) { /* Third reconstruction step */ Add12(r3h_sup,r3t_sup,2,rr2h_sup); r3l_sup = r3t_sup + rr2l_sup; Mul22(&rr3h_sup,&rr3l_sup,r3h_sup,r3l_sup,rr2h_sup,rr2l_sup); /* expoX may be maximally 2 */ expm1h_sup = rr3h_sup; expm1m_sup = rr3l_sup; } else { expm1h_sup = rr2h_sup; expm1m_sup = rr2l_sup; } } else { expm1h_sup = rr1h_sup; expm1m_sup = rr1l_sup; } } else { expm1h_sup = polyh_sup; expm1m_sup = polyl_sup; } /* Rounding test */ supDone=1; TEST_AND_COPY_RU(roundable,restemp_sup,expm1h_sup, expm1m_sup, ROUNDCSTDIRECTRD); if(roundable==0) { expm1_direct_td(&expm1h_sup, &expm1m_sup, &expm1l_sup, x_sup, xSqHalfh_sup, xSqHalfl_sup, xSqh_sup, xSql_sup, expoX_sup); RoundUpwards3(&restemp_sup,expm1h_sup, expm1m_sup, expm1l_sup); } /* Accurate phase launched */ } if((infDone==0) && (supDone==0)) { /* If we are here, we can use expm1(x) = exp(x) - 1 */ /* Range reduction - exact part: compute k as double and as int */ xMultLog2InvMult2L_inf = x_inf * log2InvMult2L; xMultLog2InvMult2L_sup = x_sup * log2InvMult2L; shiftedXMult_inf = xMultLog2InvMult2L_inf + shiftConst; shiftedXMult_sup = xMultLog2InvMult2L_sup + shiftConst; kd_inf = shiftedXMult_inf - shiftConst; kd_sup = shiftedXMult_sup - shiftConst; shiftedXMultdb_inf.d = shiftedXMult_inf; shiftedXMultdb_sup.d = shiftedXMult_sup; k_inf = shiftedXMultdb_inf.i[LO]; k_sup = shiftedXMultdb_sup.i[LO]; M_inf = k_inf >> 12; M_sup = k_sup >> 12; index1_inf = k_inf & INDEXMASK1; index1_sup = k_sup & INDEXMASK1; index2_inf = (k_inf & INDEXMASK2) >> 6; index2_sup = (k_sup & INDEXMASK2) >> 6; /* Range reduction - part affected by error - must be redone in accurate phase */ Mul12(&s1_inf,&s2_inf,msLog2Div2Lh,kd_inf); Mul12(&s1_sup,&s2_sup,msLog2Div2Lh,kd_sup); s3_inf = kd_inf * msLog2Div2Lm; s3_sup = kd_sup * msLog2Div2Lm; s4_inf = s2_inf + s3_inf; s4_sup = s2_sup + s3_sup; s5_inf = x_inf + s1_inf; s5_sup = x_sup + s1_sup; Add12Cond(rh_inf,rm_inf,s5_inf,s4_inf); Add12Cond(rh_sup,rm_sup,s5_sup,s4_sup); /* Table reads - read only two double-doubles by now */ tbl1h_inf = twoPowerIndex1[index1_inf].hi; tbl1h_sup = twoPowerIndex1[index1_sup].hi; tbl1m_inf = twoPowerIndex1[index1_inf].mi; tbl1m_sup = twoPowerIndex1[index1_sup].mi; tbl2h_inf = twoPowerIndex2[index2_inf].hi; tbl2h_sup = twoPowerIndex2[index2_sup].hi; tbl2m_inf = twoPowerIndex2[index2_inf].mi; tbl2m_sup = twoPowerIndex2[index2_sup].mi; /* Quick phase starts here */ rhSquare_inf = rh_inf * rh_inf; rhSquare_sup = rh_sup * rh_sup; rhC3_inf = quickCommonpolyC3h * rh_inf; rhC3_sup = quickCommonpolyC3h * rh_sup; rhSquareHalf_inf = 0.5 * rhSquare_inf; rhSquareHalf_sup = 0.5 * rhSquare_sup; monomialCube_inf = rhC3_inf * rhSquare_inf; monomialCube_sup = rhC3_sup * rhSquare_sup; rhFour_inf = rhSquare_inf * rhSquare_inf; rhFour_sup = rhSquare_sup * rhSquare_sup; monomialFour_inf = quickCommonpolyC4h * rhFour_inf; monomialFour_sup = quickCommonpolyC4h * rhFour_sup; highPoly_inf = monomialCube_inf + monomialFour_inf; highPoly_sup = monomialCube_sup + monomialFour_sup; highPolyWithSquare_inf = rhSquareHalf_inf + highPoly_inf; highPolyWithSquare_sup = rhSquareHalf_sup + highPoly_sup; /* Reconstruction: integration of table values */ Mul22(&tablesh_inf,&tablesl_inf,tbl1h_inf,tbl1m_inf,tbl2h_inf,tbl2m_inf); Mul22(&tablesh_sup,&tablesl_sup,tbl1h_sup,tbl1m_sup,tbl2h_sup,tbl2m_sup); t8_inf = rm_inf + highPolyWithSquare_inf; t8_sup = rm_sup + highPolyWithSquare_sup; t9_inf = rh_inf + t8_inf; t9_sup = rh_sup + t8_sup; t10_inf = tablesh_inf * t9_inf; t10_sup = tablesh_sup * t9_sup; Add12(t11_inf,t12_inf,tablesh_inf,t10_inf); Add12(t11_sup,t12_sup,tablesh_sup,t10_sup); t13_inf = t12_inf + tablesl_inf; t13_sup = t12_sup + tablesl_sup; Add12(polyTblhdb_inf.d,polyTblmdb_inf.d,t11_inf,t13_inf); Add12(polyTblhdb_sup.d,polyTblmdb_sup.d,t11_sup,t13_sup); /* Reconstruction: multiplication by 2^M */ /* Implement the multiplication by addition to overcome the problem of the non-representability of 2^1024 (M = 1024) This case is possible if polyTblhdb.d < 1 */ polyTblhdb_inf.i[HI] += M_inf << 20; polyTblhdb_sup.i[HI] += M_sup << 20; if(polyTblmdb_inf.d!=0.0) /* predicted true, but it happens for x=-4.1588039009762204, thanks Morten */ polyTblmdb_inf.i[HI] += M_inf << 20; if(polyTblmdb_sup.d!=0.0) /* predicted true, but it happens for x=-4.1588039009762204, thanks Morten */ polyTblmdb_sup.i[HI] += M_sup << 20; exph_inf = polyTblhdb_inf.d; exph_sup = polyTblhdb_sup.d; expm_inf = polyTblmdb_inf.d; expm_sup = polyTblmdb_sup.d; /* Subtraction of 1 Testing if the operation is necessary is more expensive than performing it in any case. We may cancellate at most 2 bits in the subtraction for arguments 1/4 <= x <= ln(2) (0.25 <= x <= 0.69) We must therefore use conditional Add12s Since we perform a subtraction, we may not have addition overflow towards +inf */ Add12Cond(t1_inf,t2_inf,-1,exph_inf); Add12Cond(t1_sup,t2_sup,-1,exph_sup); t3_inf = t2_inf + expm_inf; t3_sup = t2_sup + expm_sup; Add12Cond(expm1h_inf,expm1m_inf,t1_inf,t3_inf); Add12Cond(expm1h_sup,expm1m_sup,t1_sup,t3_sup); /* Rounding test */ TEST_AND_COPY_RDRU_EXPM1(roundable,res_inf,expm1h_inf, expm1m_inf, res_sup,expm1h_sup, expm1m_sup, ROUNDCSTCOMMONRD); if((roundable==2) || (roundable==0)) { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh_inf,&msLog2Div2LMultKm_inf,&msLog2Div2LMultKl_inf,kd_inf,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1_inf = x_inf + msLog2Div2LMultKh_inf; Add12Cond(rh_inf,t2_inf,t1_inf,msLog2Div2LMultKm_inf); Add12Cond(rm_inf,rl_inf,t2_inf,msLog2Div2LMultKl_inf); /* Table reads for accurate phase */ tbl1l_inf = twoPowerIndex1[index1_inf].lo; tbl2l_inf = twoPowerIndex2[index2_inf].lo; /* Call accurate phase */ expm1_common_td(&expm1h_inf, &expm1m_inf, &expm1l_inf, rh_inf, rm_inf, rl_inf, tbl1h_inf, tbl1m_inf, tbl1l_inf, tbl2h_inf, tbl2m_inf, tbl2l_inf, M_inf); /* Final rounding */ RoundDownwards3(&res_inf,expm1h_inf, expm1m_inf, expm1l_inf); } /* Accurate phase launched */ if((roundable==1) || (roundable==0)) { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh_sup,&msLog2Div2LMultKm_sup,&msLog2Div2LMultKl_sup,kd_sup,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1_sup = x_sup + msLog2Div2LMultKh_sup; Add12Cond(rh_sup,t2_sup,t1_sup,msLog2Div2LMultKm_sup); Add12Cond(rm_sup,rl_sup,t2_sup,msLog2Div2LMultKl_sup); /* Table reads for accurate phase */ tbl1l_sup = twoPowerIndex1[index1_sup].lo; tbl2l_sup = twoPowerIndex2[index2_sup].lo; /* Call accurate phase */ expm1_common_td(&expm1h_sup, &expm1m_sup, &expm1l_sup, rh_sup, rm_sup, rl_sup, tbl1h_sup, tbl1m_sup, tbl1l_sup, tbl2h_sup, tbl2m_sup, tbl2l_sup, M_sup); /* Final rounding */ RoundUpwards3(&res_sup,expm1h_sup, expm1m_sup, expm1l_sup); } /* Accurate phase launched */ ASSIGN_LOW(res,res_inf); ASSIGN_UP(res,res_sup); return res; } if((supDone==1)) { /* If we are here, we can use expm1(x) = exp(x) - 1 */ /* Range reduction - exact part: compute k as double and as int */ xMultLog2InvMult2L_inf = x_inf * log2InvMult2L; shiftedXMult_inf = xMultLog2InvMult2L_inf + shiftConst; kd_inf = shiftedXMult_inf - shiftConst; shiftedXMultdb_inf.d = shiftedXMult_inf; k_inf = shiftedXMultdb_inf.i[LO]; M_inf = k_inf >> 12; index1_inf = k_inf & INDEXMASK1; index2_inf = (k_inf & INDEXMASK2) >> 6; /* Range reduction - part affected by error - must be redone in accurate phase */ Mul12(&s1_inf,&s2_inf,msLog2Div2Lh,kd_inf); s3_inf = kd_inf * msLog2Div2Lm; s4_inf = s2_inf + s3_inf; s5_inf = x_inf + s1_inf; Add12Cond(rh_inf,rm_inf,s5_inf,s4_inf); /* Table reads - read only two double-doubles by now */ tbl1h_inf = twoPowerIndex1[index1_inf].hi; tbl1m_inf = twoPowerIndex1[index1_inf].mi; tbl2h_inf = twoPowerIndex2[index2_inf].hi; tbl2m_inf = twoPowerIndex2[index2_inf].mi; /* Quick phase starts here */ rhSquare_inf = rh_inf * rh_inf; rhC3_inf = quickCommonpolyC3h * rh_inf; rhSquareHalf_inf = 0.5 * rhSquare_inf; monomialCube_inf = rhC3_inf * rhSquare_inf; rhFour_inf = rhSquare_inf * rhSquare_inf; monomialFour_inf = quickCommonpolyC4h * rhFour_inf; highPoly_inf = monomialCube_inf + monomialFour_inf; highPolyWithSquare_inf = rhSquareHalf_inf + highPoly_inf; /* Reconstruction: integration of table values */ Mul22(&tablesh_inf,&tablesl_inf,tbl1h_inf,tbl1m_inf,tbl2h_inf,tbl2m_inf); t8_inf = rm_inf + highPolyWithSquare_inf; t9_inf = rh_inf + t8_inf; t10_inf = tablesh_inf * t9_inf; Add12(t11_inf,t12_inf,tablesh_inf,t10_inf); t13_inf = t12_inf + tablesl_inf; Add12(polyTblhdb_inf.d,polyTblmdb_inf.d,t11_inf,t13_inf); /* Reconstruction: multiplication by 2^M */ /* Implement the multiplication by addition to overcome the problem of the non-representability of 2^1024 (M = 1024) This case is possible if polyTblhdb.d < 1 */ polyTblhdb_inf.i[HI] += M_inf << 20; if(polyTblmdb_inf.d!=0.0) /* predicted true, but it happens for x=-4.1588039009762204, thanks Morten */ polyTblmdb_inf.i[HI] += M_inf << 20; exph_inf = polyTblhdb_inf.d; expm_inf = polyTblmdb_inf.d; /* Subtraction of 1 Testing if the operation is necessary is more expensive than performing it in any case. We may cancellate at most 2 bits in the subtraction for arguments 1/4 <= x <= ln(2) (0.25 <= x <= 0.69) We must therefore use conditional Add12s Since we perform a subtraction, we may not have addition overflow towards +inf */ Add12Cond(t1_inf,t2_inf,-1,exph_inf); t3_inf = t2_inf + expm_inf; Add12Cond(expm1h_inf,expm1m_inf,t1_inf,t3_inf); /* Rounding test */ TEST_AND_COPY_RD(roundable,res_inf,expm1h_inf, expm1m_inf, ROUNDCSTCOMMONRD); if(roundable==0) { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh_inf,&msLog2Div2LMultKm_inf,&msLog2Div2LMultKl_inf,kd_inf,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1_inf = x_inf + msLog2Div2LMultKh_inf; Add12Cond(rh_inf,t2_inf,t1_inf,msLog2Div2LMultKm_inf); Add12Cond(rm_inf,rl_inf,t2_inf,msLog2Div2LMultKl_inf); /* Table reads for accurate phase */ tbl1l_inf = twoPowerIndex1[index1_inf].lo; tbl2l_inf = twoPowerIndex2[index2_inf].lo; /* Call accurate phase */ expm1_common_td(&expm1h_inf, &expm1m_inf, &expm1l_inf, rh_inf, rm_inf, rl_inf, tbl1h_inf, tbl1m_inf, tbl1l_inf, tbl2h_inf, tbl2m_inf, tbl2l_inf, M_inf); /* Final rounding */ RoundDownwards3(&res_inf,expm1h_inf, expm1m_inf, expm1l_inf); } /* Accurate phase launched */ } if(infDone==1) { /* If we are here, we can use expm1(x) = exp(x) - 1 */ /* Range reduction - exact part: compute k as double and as int */ xMultLog2InvMult2L_sup = x_sup * log2InvMult2L; shiftedXMult_sup = xMultLog2InvMult2L_sup + shiftConst; kd_sup = shiftedXMult_sup - shiftConst; shiftedXMultdb_sup.d = shiftedXMult_sup; k_sup = shiftedXMultdb_sup.i[LO]; M_sup = k_sup >> 12; index1_sup = k_sup & INDEXMASK1; index2_sup = (k_sup & INDEXMASK2) >> 6; /* Range reduction - part affected by error - must be redone in accurate phase */ Mul12(&s1_sup,&s2_sup,msLog2Div2Lh,kd_sup); s3_sup = kd_sup * msLog2Div2Lm; s4_sup = s2_sup + s3_sup; s5_sup = x_sup + s1_sup; Add12Cond(rh_sup,rm_sup,s5_sup,s4_sup); /* Table reads - read only two double-doubles by now */ tbl1h_sup = twoPowerIndex1[index1_sup].hi; tbl1m_sup = twoPowerIndex1[index1_sup].mi; tbl2h_sup = twoPowerIndex2[index2_sup].hi; tbl2m_sup = twoPowerIndex2[index2_sup].mi; /* Quick phase starts here */ rhSquare_sup = rh_sup * rh_sup; rhC3_sup = quickCommonpolyC3h * rh_sup; rhSquareHalf_sup = 0.5 * rhSquare_sup; monomialCube_sup = rhC3_sup * rhSquare_sup; rhFour_sup = rhSquare_sup * rhSquare_sup; monomialFour_sup = quickCommonpolyC4h * rhFour_sup; highPoly_sup = monomialCube_sup + monomialFour_sup; highPolyWithSquare_sup = rhSquareHalf_sup + highPoly_sup; /* Reconstruction: integration of table values */ Mul22(&tablesh_sup,&tablesl_sup,tbl1h_sup,tbl1m_sup,tbl2h_sup,tbl2m_sup); t8_sup = rm_sup + highPolyWithSquare_sup; t9_sup = rh_sup + t8_sup; t10_sup = tablesh_sup * t9_sup; Add12(t11_sup,t12_sup,tablesh_sup,t10_sup); t13_sup = t12_sup + tablesl_sup; Add12(polyTblhdb_sup.d,polyTblmdb_sup.d,t11_sup,t13_sup); /* Reconstruction: multiplication by 2^M */ /* Implement the multiplication by addition to overcome the problem of the non-representability of 2^1024 (M = 1024) This case is possible if polyTblhdb.d < 1 */ polyTblhdb_sup.i[HI] += M_sup << 20; if(polyTblmdb_sup.d!=0.0) /* predicted true, but it happens for x=-4.1588039009762204, thanks Morten */ polyTblmdb_sup.i[HI] += M_sup << 20; exph_sup = polyTblhdb_sup.d; expm_sup = polyTblmdb_sup.d; /* Subtraction of 1 Testing if the operation is necessary is more expensive than performing it in any case. We may cancellate at most 2 bits in the subtraction for arguments 1/4 <= x <= ln(2) (0.25 <= x <= 0.69) We must therefore use conditional Add12s Since we perform a subtraction, we may not have addition overflow towards +inf */ Add12Cond(t1_sup,t2_sup,-1,exph_sup); t3_sup = t2_sup + expm_sup; Add12Cond(expm1h_sup,expm1m_sup,t1_sup,t3_sup); /* Rounding test */ TEST_AND_COPY_RU(roundable,res_sup,expm1h_sup, expm1m_sup, ROUNDCSTCOMMONRD); if(roundable==0) { /* Rest of argument reduction for accurate phase */ Mul133(&msLog2Div2LMultKh_sup,&msLog2Div2LMultKm_sup,&msLog2Div2LMultKl_sup,kd_sup,msLog2Div2Lh,msLog2Div2Lm,msLog2Div2Ll); t1_sup = x_sup + msLog2Div2LMultKh_sup; Add12Cond(rh_sup,t2_sup,t1_sup,msLog2Div2LMultKm_sup); Add12Cond(rm_sup,rl_sup,t2_sup,msLog2Div2LMultKl_sup); /* Table reads for accurate phase */ tbl1l_sup = twoPowerIndex1[index1_sup].lo; tbl2l_sup = twoPowerIndex2[index2_sup].lo; /* Call accurate phase */ expm1_common_td(&expm1h_sup, &expm1m_sup, &expm1l_sup, rh_sup, rm_sup, rl_sup, tbl1h_sup, tbl1m_sup, tbl1l_sup, tbl2h_sup, tbl2m_sup, tbl2l_sup, M_sup); /* Final rounding */ RoundUpwards3(&res_sup,expm1h_sup, expm1m_sup, expm1l_sup); } /* Accurate phase launched */ } if (infDone==1) res_inf=restemp_inf; if (supDone==1) res_sup=restemp_sup; ASSIGN_LOW(res,res_inf); ASSIGN_UP(res,res_sup); return res; } #endif interval-3.2.0/src/crlibm/expm1.h0000644000000000000000000012174213316017127014740 0ustar 00000000000000/* * Correctly rounded expm1 = e^x - 1 * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" /* File generated by maple/expm1.mpl */ #define log2InvMult2L 5.90927888748119403317105025053024291992187500000000e+03 #define msLog2Div2Lh -1.69225385878892892145206050535932718048570677638054e-04 #define msLog2Div2Lm -5.66173538536694228129338642508144915789549786200850e-21 #define msLog2Div2Ll -1.39348350547270802387134479195513221596886344528448e-37 #define shiftConst 6.75539944105574400000000000000000000000000000000000e+15 #define INDEXMASK1 0x0000003f #define INDEXMASK2 0x00000fc0 #define RETURNXBOUND 0x3c900000 #define OVERFLOWBOUND 7.09782712893383973096206318587064743041992187500000e+02 #define LARGEST 1.79769313486231570814527423731704356798070567525845e+308 #define SMALLEST 4.94065645841246544176568792868221372365059802614325e-324 #define MINUSONEBOUND -3.74299477502370478987359092570841312408447265625000e+01 #define SIMPLEOVERFLOWBOUND 0x40862e42 #define DIRECTINTERVALBOUND 0x3fd00000 #define SPECIALINTERVALBOUND 0x3f300000 #define ROUNDCSTDIRECTRN 1.00392156862745109185069459291432461909707184007331e+00 #define ROUNDCSTDIRECTRD 2.16840434497100886801490560173988342285156250000000e-19 #define ROUNDCSTCOMMONRN 1.00392156862745109185069459291432461909707184007331e+00 #define ROUNDCSTCOMMONRD 2.16840434497100886801490560173988342285156250000000e-19 #define MINUSONEPLUSONEULP -9.99999999999999888977697537484345957636833190917969e-01 #define quickDirectpolyC3h 1.66666666666666657414808128123695496469736099243164e-01 #define quickDirectpolyC4h 4.16666666666666921092776476598373847082257270812988e-02 #define quickDirectpolyC5h 8.33333333340913022524443221072942833416163921356201e-03 #define quickDirectpolyC6h 1.38888888866754321368968128069809608859941363334656e-03 #define quickDirectpolyC7h 1.98412543160940484055984600608724122139392420649528e-04 #define quickDirectpolyC8h 2.48020519562457199031109411624385074901510961353779e-05 #define quickDirectpolyC9h 2.84660857362219107811367527216539485834800871089101e-06 #define accuDirectpolyC3h 1.66666666666666657414808128123695496469736099243164e-01 #define accuDirectpolyC3m 9.25185853854297065661561206416060845590588197735272e-18 #define accuDirectpolyC3l 5.13581650457284662711479178584444638962917803311780e-34 #define accuDirectpolyC4h 4.16666666666666643537020320309238741174340248107910e-02 #define accuDirectpolyC4m 2.31296463463574227896791413859298150278088197735272e-18 #define accuDirectpolyC5h 8.33333333333333321768510160154619370587170124053955e-03 #define accuDirectpolyC5m 1.15648231731787113948395706929649075139044098867636e-19 #define accuDirectpolyC6h 1.38888888888888894189432843262466121814213693141937e-03 #define accuDirectpolyC6m -5.30054395357292524960423423338339636695154423835845e-20 #define accuDirectpolyC7h 1.98412698412698412526317115478491359681356698274612e-04 #define accuDirectpolyC7m 1.72095583354814495137206233661964154177299630853468e-22 #define accuDirectpolyC8h 2.48015873015873015657896394348114199601695872843266e-05 #define accuDirectpolyC8m 2.14651941309384838916703253244235321323283349969089e-23 #define accuDirectpolyC9h 2.75573192239858925109505932704578867742384318262339e-06 #define accuDirectpolyC9m -1.85841997665354272936683956225603122653869677259213e-22 #define accuDirectpolyC10h 2.75573192239859041576536180170875489636728161713108e-07 #define accuDirectpolyC11h 2.50521083854417268413110797455750633488946732541081e-08 #define accuDirectpolyC12h 2.08767569858109971289062132052388037761758710075810e-09 #define accuDirectpolyC13h 1.60590438355780403477083534013894559194790545575415e-10 #define accuDirectpolyC14h 1.14709032708663011999233928519882120839606942652722e-11 #define accuDirectpolyC15h 7.64725827750169879636792489069881340263759583741887e-13 #define quickCommonpolyC3h 1.66666666696497350885763921723992098122835159301758e-01 #define quickCommonpolyC4h 4.16666666766102242180913606262038229033350944519043e-02 #define accuCommonpolyC3h 1.66666666666666657414808128123695496469736099243164e-01 #define accuCommonpolyC3m 9.25185853866467248091737476239823936927135463652392e-18 #define accuCommonpolyC4h 4.16666666666666643537020320309238741174340248107910e-02 #define accuCommonpolyC4m 2.31256737150511109641969514308685693497248293481702e-18 #define accuCommonpolyC5h 8.33333333333333321768510160154619370587170124053955e-03 #define accuCommonpolyC6h 1.38888888911084334119860894674047813168726861476898e-03 #define accuCommonpolyC7h 1.98412713635391310413452758965036082372535020112991e-04 typedef struct tPi_t_tag {double hi; double mi; double lo;} tPi_t; static const tPi_t twoPowerIndex1[64] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1hi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1mi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1lo[0] */ } , { 1.00016923970530213772178740327944979071617126464844e+00, /* twoPowerIndex1hi[1] */ 9.33618533547846199388179470637929281332443150415515e-17, /* twoPowerIndex1mi[1] */ 3.77297954885090084710073756456287936644477196404411e-33, /* twoPowerIndex1lo[1] */ } , { 1.00033850805268231809463941317517310380935668945312e+00, /* twoPowerIndex1hi[2] */ -5.14133393131895706530678267769194263660821897510018e-18, /* twoPowerIndex1mi[2] */ 3.65532984508913994275805274025238001612209382982528e-34, /* twoPowerIndex1lo[2] */ } , { 1.00050780504698755279946453811135143041610717773438e+00, /* twoPowerIndex1hi[3] */ 6.96242402202057255168575283120383384543281723609229e-17, /* twoPowerIndex1mi[3] */ 5.20646484360987194687938744912769762301408608274186e-34, /* twoPowerIndex1lo[3] */ } , { 1.00067713069306640782940576173132285475730895996094e+00, /* twoPowerIndex1hi[4] */ -5.11512329768566763581175858027414623025077801052578e-17, /* twoPowerIndex1mi[4] */ 6.98198098827029289611306311409722598417652045670746e-34, /* twoPowerIndex1lo[4] */ } , { 1.00084648499576744917760606767842546105384826660156e+00, /* twoPowerIndex1hi[5] */ 8.42299002458648658027371639395540881533737558365359e-17, /* twoPowerIndex1mi[5] */ 2.36970468083963275494383447607242933566525306383712e-33, /* twoPowerIndex1lo[5] */ } , { 1.00101586795994101919404783984646201133728027343750e+00, /* twoPowerIndex1hi[6] */ -2.82452207477616780689379931990767172214919031737312e-17, /* twoPowerIndex1mi[6] */ -1.95728551891328398835983018867545661396300096090192e-33, /* twoPowerIndex1lo[6] */ } , { 1.00118527959043746022871346212923526763916015625000e+00, /* twoPowerIndex1hi[7] */ -7.18042456559213166577815896739695813826899291527385e-17, /* twoPowerIndex1mi[7] */ -4.76259460142737667571053552520587169925041399888400e-33, /* twoPowerIndex1lo[7] */ } , { 1.00135471989210822485460994357708841562271118164062e+00, /* twoPowerIndex1hi[8] */ -1.89737284167929933536294189134998232481318340155287e-17, /* twoPowerIndex1mi[8] */ -1.14644761608474571162584330231223616391499645510675e-34, /* twoPowerIndex1lo[8] */ } , { 1.00152418886980565382316399336559697985649108886719e+00, /* twoPowerIndex1hi[9] */ 9.06044106726912172835402556659442028244667434824268e-17, /* twoPowerIndex1mi[9] */ -9.28795936877474030548429956901821606468166518236870e-34, /* twoPowerIndex1lo[9] */ } , { 1.00169368652838319810882694582687690854072570800781e+00, /* twoPowerIndex1hi[10] */ -7.17327634990031997530849131951948428542423257707819e-17, /* twoPowerIndex1mi[10] */ 6.07647560689104755979568262152596670382288431776872e-33, /* twoPowerIndex1lo[10] */ } , { 1.00186321287269430868605013529304414987564086914062e+00, /* twoPowerIndex1hi[11] */ -1.33071962467226606689858482393149015112554043251841e-17, /* twoPowerIndex1mi[11] */ -3.85443386097781554341108465500150047004226523597749e-34, /* twoPowerIndex1lo[11] */ } , { 1.00203276790759399084151937131537124514579772949219e+00, /* twoPowerIndex1hi[12] */ 2.57269259432211179649018725316354562817431777421067e-17, /* twoPowerIndex1mi[12] */ 6.79751255613789265201334995370535043187556454092516e-34, /* twoPowerIndex1lo[12] */ } , { 1.00220235163793791599573523853905498981475830078125e+00, /* twoPowerIndex1hi[13] */ -3.92993778548451720552933864302152846562830407163222e-17, /* twoPowerIndex1mi[13] */ 2.22740945016647607963332576015739728975193247400334e-33, /* twoPowerIndex1lo[13] */ } , { 1.00237196406858219965840817167190834879875183105469e+00, /* twoPowerIndex1hi[14] */ 8.46137724799471749932697856411684097253648908880386e-17, /* twoPowerIndex1mi[14] */ -1.15795350476069740873680647805085951983720786847012e-33, /* twoPowerIndex1lo[14] */ } , { 1.00254160520438451165148308064090088009834289550781e+00, /* twoPowerIndex1hi[15] */ -4.19488324163994025318330321149973224973566383682287e-17, /* twoPowerIndex1mi[15] */ -1.10867727371575753136248480661711257993643946476249e-33, /* twoPowerIndex1lo[15] */ } , { 1.00271127505020252179690487537300214171409606933594e+00, /* twoPowerIndex1hi[16] */ -3.63661592869226394431650732319448247819940912156384e-17, /* twoPowerIndex1mi[16] */ -6.58076018413558386665763067745208065096307047224855e-34, /* twoPowerIndex1lo[16] */ } , { 1.00288097361089523218424801598303020000457763671875e+00, /* twoPowerIndex1hi[17] */ -2.61094406324393831074545742903203024867557691172893e-17, /* twoPowerIndex1mi[17] */ 1.20560913995705683042979390390212408639703633013464e-33, /* twoPowerIndex1lo[17] */ } , { 1.00305070089132231103690173767972737550735473632812e+00, /* twoPowerIndex1hi[18] */ 1.75307847798233211014008193947934807324617806015147e-17, /* twoPowerIndex1mi[18] */ 1.13393213893456062969952574781413432615748154285102e-33, /* twoPowerIndex1lo[18] */ } , { 1.00322045689634431475667497579706832766532897949219e+00, /* twoPowerIndex1hi[19] */ 5.75392352562826744411122442879351687879645730521252e-17, /* twoPowerIndex1mi[19] */ -2.67723202763627633853056570968049475423332897231238e-33, /* twoPowerIndex1lo[19] */ } , { 1.00339024163082268792379636579426005482673645019531e+00, /* twoPowerIndex1hi[20] */ -8.68492200511795617368964392061338881522209699276521e-18, /* twoPowerIndex1mi[20] */ -3.48402050975972235345434529928044249018150775634918e-34, /* twoPowerIndex1lo[20] */ } , { 1.00356005509961931920770439319312572479248046875000e+00, /* twoPowerIndex1hi[21] */ 9.49003543098177759384527648244793376993805358019830e-17, /* twoPowerIndex1mi[21] */ -2.72838479693459377473949067074824993718971708464416e-34, /* twoPowerIndex1lo[21] */ } , { 1.00372989730759765159007201873464509844779968261719e+00, /* twoPowerIndex1hi[22] */ -8.71038060581842237129503222771273097866222639659196e-17, /* twoPowerIndex1mi[22] */ 1.08618280977421918449964280592134822915254002216492e-33, /* twoPowerIndex1lo[22] */ } , { 1.00389976825962090600796727812848985195159912109375e+00, /* twoPowerIndex1hi[23] */ 3.49589169585715450145113080496294928974704413200507e-17, /* twoPowerIndex1mi[23] */ -2.94144759791575889018758341844218078845293410867033e-33, /* twoPowerIndex1lo[23] */ } , { 1.00406966796055407975529760733479633927345275878906e+00, /* twoPowerIndex1hi[24] */ 9.75378754984024099793268477195846557070899843396028e-17, /* twoPowerIndex1mi[24] */ 5.64300142720863839874652371486135387544215443970822e-33, /* twoPowerIndex1lo[24] */ } , { 1.00423959641526283625978521740762516856193542480469e+00, /* twoPowerIndex1hi[25] */ -1.05762211962928569325595987354393790031696252155330e-16, /* twoPowerIndex1mi[25] */ 5.83707943855262433756426258532402998630656838432942e-33, /* twoPowerIndex1lo[25] */ } , { 1.00440955362861283894915231940103694796562194824219e+00, /* twoPowerIndex1hi[26] */ 4.20918873812712592966120368574870018412444102186114e-17, /* twoPowerIndex1mi[26] */ 2.17971061415864797757688538084764343153482363480001e-33, /* twoPowerIndex1lo[26] */ } , { 1.00457953960547174965256544965086504817008972167969e+00, /* twoPowerIndex1hi[27] */ -1.67001668575547876279593068362269006396955075031486e-17, /* twoPowerIndex1mi[27] */ 8.56552273127180632250100064178508499726804497630949e-34, /* twoPowerIndex1lo[27] */ } , { 1.00474955435070723019919114449294283986091613769531e+00, /* twoPowerIndex1hi[28] */ -1.62314635541245143576050143734168865049382925451905e-17, /* twoPowerIndex1mi[28] */ 9.28530603331304279248127378347521992965436217888846e-35, /* twoPowerIndex1lo[28] */ } , { 1.00491959786918805264122056541964411735534667968750e+00, /* twoPowerIndex1hi[29] */ 2.30285392780281171183781407072193459566423534757738e-17, /* twoPowerIndex1mi[29] */ -4.94345170697772961451844215454960159293576885861471e-34, /* twoPowerIndex1lo[29] */ } , { 1.00508967016578387720926457404857501387596130371094e+00, /* twoPowerIndex1hi[30] */ 1.64180469767730323539044065876968510741128671646342e-17, /* twoPowerIndex1mi[30] */ -1.40120338097898451052996285664279342840562084008057e-34, /* twoPowerIndex1lo[30] */ } , { 1.00525977124536503026774880709126591682434082031250e+00, /* twoPowerIndex1hi[31] */ 3.72669843182841367415839881731427710949489409371967e-17, /* twoPowerIndex1mi[31] */ -6.47401139805376556406832921347318553328966160972009e-34, /* twoPowerIndex1lo[31] */ } , { 1.00542990111280272635951860138447955250740051269531e+00, /* twoPowerIndex1hi[32] */ 9.49918653545503175702165599813853704096085691656846e-17, /* twoPowerIndex1mi[32] */ 2.69197614795285565383714012654266434015814803945559e-33, /* twoPowerIndex1lo[32] */ } , { 1.00560005977296929025044391892151907086372375488281e+00, /* twoPowerIndex1hi[33] */ -8.68093131444458156819420437418787120833640771986467e-17, /* twoPowerIndex1mi[33] */ 1.70120132411898592857823454488038166970266621441155e-33, /* twoPowerIndex1lo[33] */ } , { 1.00577024723073704670639472169568762183189392089844e+00, /* twoPowerIndex1hi[34] */ 4.00054749103011688253297776917861866454998331259826e-17, /* twoPowerIndex1mi[34] */ 1.31925963209617013098908877209722537258440391267352e-33, /* twoPowerIndex1lo[34] */ } , { 1.00594046349098009685008037195075303316116333007812e+00, /* twoPowerIndex1hi[35] */ 7.19049911150997399545071999536183023264065701084941e-17, /* twoPowerIndex1mi[35] */ 5.87388840736458866162752231275781178461761843642826e-33, /* twoPowerIndex1lo[35] */ } , { 1.00611070855857298589342008199309930205345153808594e+00, /* twoPowerIndex1hi[36] */ -1.39080686710657830063564897325456873924612265621065e-17, /* twoPowerIndex1mi[36] */ -1.04608842475341479042763417006066485614641577765254e-33, /* twoPowerIndex1lo[36] */ } , { 1.00628098243839092518214783922303467988967895507812e+00, /* twoPowerIndex1hi[37] */ -8.14020864257304964668281784838729787981918541118695e-17, /* twoPowerIndex1mi[37] */ 9.81687621053626949463979101287162593669867055078380e-34, /* twoPowerIndex1lo[37] */ } , { 1.00645128513531001424041733116609975695610046386719e+00, /* twoPowerIndex1hi[38] */ -5.76215104374953424938341851527793234314721266620465e-17, /* twoPowerIndex1mi[38] */ -2.57074696660737495074482007072094547944536206743811e-33, /* twoPowerIndex1lo[38] */ } , { 1.00662161665420724077080194547306746244430541992188e+00, /* twoPowerIndex1hi[39] */ 6.74527847731045679518854873240614524466814727371618e-17, /* twoPowerIndex1mi[39] */ 3.78807035520293397050945635744099720111701312971531e-33, /* twoPowerIndex1lo[39] */ } , { 1.00679197699996070269889969495125114917755126953125e+00, /* twoPowerIndex1hi[40] */ 1.89985572403462958330039110072328316553950667129559e-17, /* twoPowerIndex1mi[40] */ -9.63431595756658515104002497950853752466876076619761e-34, /* twoPowerIndex1lo[40] */ } , { 1.00696236617744894203951844247058033943176269531250e+00, /* twoPowerIndex1hi[41] */ -9.63743003231640715845365699595418727819327585110316e-17, /* twoPowerIndex1mi[41] */ 5.37739172125896523173793245498965828230574349410153e-34, /* twoPowerIndex1lo[41] */ } , { 1.00713278419155116694128082599490880966186523437500e+00, /* twoPowerIndex1hi[42] */ -1.25286544624539788678561179100718466970708089928402e-17, /* twoPowerIndex1mi[42] */ 6.73461401738595970431440883296934068477066941591536e-34, /* twoPowerIndex1lo[42] */ } , { 1.00730323104714791782043903367593884468078613281250e+00, /* twoPowerIndex1hi[43] */ 3.02057888784369419361601396858156577301726732087163e-17, /* twoPowerIndex1mi[43] */ 2.28748779695564659338938424768062274005093770790899e-33, /* twoPowerIndex1lo[43] */ } , { 1.00747370674912040122706002875929698348045349121094e+00, /* twoPowerIndex1hi[44] */ -4.86939425860856490657306074829518805252629724182687e-17, /* twoPowerIndex1mi[44] */ -2.15005825118530979132585793750524459885823808259600e-33, /* twoPowerIndex1lo[44] */ } , { 1.00764421130235026780042062455322593450546264648438e+00, /* twoPowerIndex1hi[45] */ 5.22402993768745316546273304631524097955173932918745e-17, /* twoPowerIndex1mi[45] */ 1.56859855755260687389551771821040360984576895950448e-33, /* twoPowerIndex1lo[45] */ } , { 1.00781474471172072249203210958512499928474426269531e+00, /* twoPowerIndex1hi[46] */ -9.36154355147845590745647945463041972879607082944076e-17, /* twoPowerIndex1mi[46] */ 2.73525232969860711971224663796949142049450209755900e-33, /* twoPowerIndex1lo[46] */ } , { 1.00798530698211497025340577238239347934722900390625e+00, /* twoPowerIndex1hi[47] */ -8.65251323306194956904999437269495581443314540350323e-17, /* twoPowerIndex1mi[47] */ 3.95202635576858744637745517221782298786195221857564e-33, /* twoPowerIndex1lo[47] */ } , { 1.00815589811841754830368245166027918457984924316406e+00, /* twoPowerIndex1hi[48] */ -3.25205875608430806088583499076669170064325943797327e-17, /* twoPowerIndex1mi[48] */ 2.46355206137317856028163445564386882918089954604456e-33, /* twoPowerIndex1lo[48] */ } , { 1.00832651812551388204042268625926226377487182617188e+00, /* twoPowerIndex1hi[49] */ -9.91723226806091428304981281566311898208154515630026e-17, /* twoPowerIndex1mi[49] */ -5.54888559019883709197982155449053331751526019176611e-33, /* twoPowerIndex1lo[49] */ } , { 1.00849716700828984095039686508243903517723083496094e+00, /* twoPowerIndex1hi[50] */ -7.13604740416252276802131825807759910735798752142063e-17, /* twoPowerIndex1mi[50] */ 4.98539917129953776836361552714923793985513981224277e-33, /* twoPowerIndex1lo[50] */ } , { 1.00866784477163240474340000218944624066352844238281e+00, /* twoPowerIndex1hi[51] */ -1.72686837122432199045769102324975071816159176955755e-17, /* twoPowerIndex1mi[51] */ 1.49699250027049460850618457278328039699137666243513e-33, /* twoPowerIndex1lo[51] */ } , { 1.00883855142042944130764681176515296101570129394531e+00, /* twoPowerIndex1hi[52] */ -6.61995469367394011396161169543794432105455894234207e-17, /* twoPowerIndex1mi[52] */ -1.37180394060118324236386341775148249159351409372011e-33, /* twoPowerIndex1lo[52] */ } , { 1.00900928695956926262056185805704444646835327148438e+00, /* twoPowerIndex1hi[53] */ 3.56545690151302037529536411250390721695546928174132e-17, /* twoPowerIndex1mi[53] */ -3.04973969952342772070810129193852120178103073824881e-33, /* twoPowerIndex1lo[53] */ } , { 1.00918005139394151292719925550045445561408996582031e+00, /* twoPowerIndex1hi[54] */ 3.71731001370881785990046067286312459291233468170260e-17, /* twoPowerIndex1mi[54] */ 2.33846700487585833881864340821781209486455210644683e-33, /* twoPowerIndex1lo[54] */ } , { 1.00935084472843628056182296859333291649818420410156e+00, /* twoPowerIndex1hi[55] */ 7.06257240682552768409771521622687712943771198652841e-17, /* twoPowerIndex1mi[55] */ -2.69254581845265407066861039619808678678301305791490e-33, /* twoPowerIndex1lo[55] */ } , { 1.00952166696794476408172158699017018079757690429688e+00, /* twoPowerIndex1hi[56] */ -1.43214123034288192889278157016818203958577074101904e-17, /* twoPowerIndex1mi[56] */ 1.18343254028162625925516501493235924385911429505127e-33, /* twoPowerIndex1lo[56] */ } , { 1.00969251811735860613339355040807276964187622070312e+00, /* twoPowerIndex1hi[57] */ 1.56681880131341096294393603553275561732689802958880e-17, /* twoPowerIndex1mi[57] */ -7.81531085085694011629938080711347719818453468652371e-34, /* twoPowerIndex1lo[57] */ } , { 1.00986339818157078163096684875199571251869201660156e+00, /* twoPowerIndex1hi[58] */ -1.10436957803936884179513517801130489140214758906396e-16, /* twoPowerIndex1mi[58] */ 2.26009746193166539328485913376118607218426838997178e-33, /* twoPowerIndex1lo[58] */ } , { 1.01003430716547448753317439695820212364196777343750e+00, /* twoPowerIndex1hi[59] */ -5.76731742716039801926309676866051407637690838590278e-17, /* twoPowerIndex1mi[59] */ -2.78217177127226696492717790709599913537289113429847e-33, /* twoPowerIndex1lo[59] */ } , { 1.01020524507396425306637866015080362558364868164062e+00, /* twoPowerIndex1hi[60] */ 4.83548497844038273903057565303994337100835235326315e-18, /* twoPowerIndex1mi[60] */ 2.61454310671247390892899439237254056446677108734060e-34, /* twoPowerIndex1lo[60] */ } , { 1.01037621191193527359075687854783609509468078613281e+00, /* twoPowerIndex1hi[61] */ 7.01512128971544209746870624992521939688820868468409e-17, /* twoPowerIndex1mi[61] */ -5.58161827166019262256128049263563333632096890407031e-33, /* twoPowerIndex1lo[61] */ } , { 1.01054720768428363264490599249256774783134460449219e+00, /* twoPowerIndex1hi[62] */ 7.16180287361957384315239192590148379997244337618299e-17, /* twoPowerIndex1mi[62] */ -2.02563561553844543425647289447795720504633264470840e-34, /* twoPowerIndex1lo[62] */ } , { 1.01071823239590607990123771742219105362892150878906e+00, /* twoPowerIndex1hi[63] */ 1.05046591340840499506734116899577087874840087102554e-16, /* twoPowerIndex1mi[63] */ 2.18415845005431430458109722226729544983351542501345e-33, /* twoPowerIndex1lo[63] */ } }; static const tPi_t twoPowerIndex2[64] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex2hi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex2mi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex2lo[0] */ } , { 1.01088928605170047525518839393043890595436096191406e+00, /* twoPowerIndex2hi[1] */ -1.52347786033685771762884896542837070154735103108242e-17, /* twoPowerIndex2mi[1] */ -1.20527773363982029579667170059568717373235495431222e-33, /* twoPowerIndex2lo[1] */ } , { 1.02189714865411662714222984504885971546173095703125e+00, /* twoPowerIndex2hi[2] */ 5.10922502897344389358977529484899213711118891193073e-17, /* twoPowerIndex2mi[2] */ 7.88422656496927442160138555121324022911581088833303e-34, /* twoPowerIndex2lo[2] */ } , { 1.03302487902122841489926940994337201118469238281250e+00, /* twoPowerIndex2hi[3] */ 7.60083887402708848935418174694583720224989620170520e-18, /* twoPowerIndex2mi[3] */ 4.17547660336499599627565312970423748685953776150432e-34, /* twoPowerIndex2lo[3] */ } , { 1.04427378242741375480306942336028441786766052246094e+00, /* twoPowerIndex2hi[4] */ 8.55188970553796489217080231819249267647451456689049e-17, /* twoPowerIndex2mi[4] */ -4.33079108057472301914865017639792677602990877842667e-33, /* twoPowerIndex2lo[4] */ } , { 1.05564517836055715704901558638084679841995239257812e+00, /* twoPowerIndex2hi[5] */ 1.75932573877209198413667791203269037000656546957040e-18, /* twoPowerIndex2mi[5] */ -1.30396724977978376996223394717384715710429730879060e-34, /* twoPowerIndex2lo[5] */ } , { 1.06714040067682369716806078940862789750099182128906e+00, /* twoPowerIndex2hi[6] */ -7.89985396684158212226333428391940791349522867645719e-17, /* twoPowerIndex2mi[6] */ 2.48773924323047906697979838020484860096229450391065e-33, /* twoPowerIndex2lo[6] */ } , { 1.07876079775711986030728439800441265106201171875000e+00, /* twoPowerIndex2hi[7] */ -6.65666043605659260344452997720816205593857378631714e-17, /* twoPowerIndex2mi[7] */ -3.65812580131923690564246115619834327696213789275798e-33, /* twoPowerIndex2lo[7] */ } , { 1.09050773266525768967483145388541743159294128417969e+00, /* twoPowerIndex2hi[8] */ -3.04678207981247114696551170541257032193091359539676e-17, /* twoPowerIndex2mi[8] */ 2.01705487848848619150139275849815038703452970938356e-33, /* twoPowerIndex2lo[8] */ } , { 1.10238258330784089089604549371870234608650207519531e+00, /* twoPowerIndex2hi[9] */ 5.26603687157069438656191942579725322612448063343618e-17, /* twoPowerIndex2mi[9] */ 6.45805397536721410708490440561131106837447579889036e-34, /* twoPowerIndex2lo[9] */ } , { 1.11438674259589243220602838846389204263687133789062e+00, /* twoPowerIndex2hi[10] */ 1.04102784568455709549461912557590544266030834754874e-16, /* twoPowerIndex2mi[10] */ 1.47570167344000313963428137759389241586071635800536e-33, /* twoPowerIndex2lo[10] */ } , { 1.12652161860824184813623105583246797323226928710938e+00, /* twoPowerIndex2hi[11] */ 5.16585675879545673703180814711785602957687143067887e-17, /* twoPowerIndex2mi[11] */ -5.65916686170716220063974592097473710424342945964456e-34, /* twoPowerIndex2lo[11] */ } , { 1.13878863475669156457570352358743548393249511718750e+00, /* twoPowerIndex2hi[12] */ 8.91281267602540777782023808215740339330966556723006e-17, /* twoPowerIndex2mi[12] */ -2.00741463283249448727846279877956608996968961458494e-33, /* twoPowerIndex2lo[12] */ } , { 1.15118922995298267331065744656370952725410461425781e+00, /* twoPowerIndex2hi[13] */ 3.25071021886382721197741051783883831627922464835734e-17, /* twoPowerIndex2mi[13] */ 8.89091931637927159755660842958283684863470887791663e-34, /* twoPowerIndex2lo[13] */ } , { 1.16372485877757747552152522985124960541725158691406e+00, /* twoPowerIndex2hi[14] */ 3.82920483692409349872159816102110059722238312159091e-17, /* twoPowerIndex2mi[14] */ 7.19709831987676327409679245188515478735702972651365e-34, /* twoPowerIndex2lo[14] */ } , { 1.17639699165028122074261318630306050181388854980469e+00, /* twoPowerIndex2hi[15] */ 5.55420325421807896276684328889766000203735373777665e-17, /* twoPowerIndex2mi[15] */ -1.48842929343368511961710849782815827921712348302943e-33, /* twoPowerIndex2lo[15] */ } , { 1.18920711500272102689734765590401366353034973144531e+00, /* twoPowerIndex2hi[16] */ 3.98201523146564611098029654755651628169309930562261e-17, /* twoPowerIndex2mi[16] */ 1.14195965688545340101163692105448367710482873511510e-33, /* twoPowerIndex2lo[16] */ } , { 1.20215673145270307564658196497475728392601013183594e+00, /* twoPowerIndex2hi[17] */ 6.64498149925230124489270286991048474954122885069094e-17, /* twoPowerIndex2mi[17] */ -3.85685255336907654452995968372311171004938395576078e-33, /* twoPowerIndex2lo[17] */ } , { 1.21524735998046895524282717815367504954338073730469e+00, /* twoPowerIndex2hi[18] */ -7.71263069268148813091257203929615917892526180720328e-17, /* twoPowerIndex2mi[18] */ 4.71720614288499816545262331753743129502653902881319e-33, /* twoPowerIndex2lo[18] */ } , { 1.22848053610687002468182527081808075308799743652344e+00, /* twoPowerIndex2hi[19] */ -1.89878163130252995311948719658078062677878185721429e-17, /* twoPowerIndex2mi[19] */ 6.18469453652103848424687212656185051850860290411013e-34, /* twoPowerIndex2lo[19] */ } , { 1.24185781207348400201340155035723000764846801757812e+00, /* twoPowerIndex2hi[20] */ 4.65802759183693679122616767654141683800114091774588e-17, /* twoPowerIndex2mi[20] */ -2.31439910378785985764079190411324307370918857557275e-33, /* twoPowerIndex2lo[20] */ } , { 1.25538075702469109629078047873917967081069946289062e+00, /* twoPowerIndex2hi[21] */ -6.71138982129687841852821870522008036246320680675952e-18, /* twoPowerIndex2mi[21] */ -5.76846264325028352862497671463784812858487529613818e-35, /* twoPowerIndex2lo[21] */ } , { 1.26905095719173321988648694969015195965766906738281e+00, /* twoPowerIndex2hi[22] */ 2.66793213134218609522998616502989391061315227839969e-18, /* twoPowerIndex2mi[22] */ -5.01723570938719050333027020376949013774930719140568e-35, /* twoPowerIndex2lo[22] */ } , { 1.28287001607877826359072059858590364456176757812500e+00, /* twoPowerIndex2hi[23] */ 1.71359491824356096814175768900864730928374054987756e-17, /* twoPowerIndex2mi[23] */ 7.25131491282819461838977871983760669047046080773478e-34, /* twoPowerIndex2lo[23] */ } , { 1.29683955465100964055125132290413603186607360839844e+00, /* twoPowerIndex2hi[24] */ 2.53825027948883149592910250791940344234383392801619e-17, /* twoPowerIndex2mi[24] */ 1.68678246461832500334243039646153124282288438904092e-34, /* twoPowerIndex2lo[24] */ } , { 1.31096121152476441373835314152529463171958923339844e+00, /* twoPowerIndex2hi[25] */ -7.18153613551945385697245613605196258733040544776187e-17, /* twoPowerIndex2mi[25] */ -2.12629266743969557140434977160228094057588798528197e-34, /* twoPowerIndex2lo[25] */ } , { 1.32523664315974132321684919588733464479446411132812e+00, /* twoPowerIndex2hi[26] */ -2.85873121003886137327027220806882812126373511580572e-17, /* twoPowerIndex2mi[26] */ 7.62021406397260431456821182703024347950927217409368e-34, /* twoPowerIndex2lo[26] */ } , { 1.33966752405330291608720472140703350305557250976562e+00, /* twoPowerIndex2hi[27] */ 8.92728259483173198426255486589831591472085466011828e-17, /* twoPowerIndex2mi[27] */ -7.69657983531899254540849298389093495155758992415150e-34, /* twoPowerIndex2lo[27] */ } , { 1.35425554693689265128853094211081042885780334472656e+00, /* twoPowerIndex2hi[28] */ 7.70094837980298946162338224151128414915778826123523e-17, /* twoPowerIndex2mi[28] */ -2.24074836437395028882100810844688282941385619430371e-33, /* twoPowerIndex2lo[28] */ } , { 1.36900242297459051599162194179370999336242675781250e+00, /* twoPowerIndex2hi[29] */ 9.59379791911884877255545693637832999511204427845953e-17, /* twoPowerIndex2mi[29] */ -4.88674958784947176959607858061848292445663702071206e-33, /* twoPowerIndex2lo[29] */ } , { 1.38390988196383202257777611521305516362190246582031e+00, /* twoPowerIndex2hi[30] */ -6.77051165879478628715737183479431151106043475381389e-17, /* twoPowerIndex2mi[30] */ 5.25954134785524271676320971772030766300829615286373e-34, /* twoPowerIndex2lo[30] */ } , { 1.39897967253831123635166022722842171788215637207031e+00, /* twoPowerIndex2hi[31] */ -9.61421320905132307233280072508933760749140842467170e-17, /* twoPowerIndex2mi[31] */ 3.97465190077505680357285219692652769985214754647576e-33, /* twoPowerIndex2lo[31] */ } , { 1.41421356237309514547462185873882845044136047363281e+00, /* twoPowerIndex2hi[32] */ -9.66729331345291345105469972976694765012981670542977e-17, /* twoPowerIndex2mi[32] */ 4.13867530869941356271900493210877889450985709540127e-33, /* twoPowerIndex2lo[32] */ } , { 1.42961333839197002326670826732879504561424255371094e+00, /* twoPowerIndex2hi[33] */ -1.20316424890536551791763281075597751007148682598677e-17, /* twoPowerIndex2mi[33] */ 3.96492532243389364766543780399018506300743370884771e-35, /* twoPowerIndex2lo[33] */ } , { 1.44518080697704665027458759141154587268829345703125e+00, /* twoPowerIndex2hi[34] */ -3.02375813499398731939978948265280760393682335269040e-17, /* twoPowerIndex2mi[34] */ -1.77301195820250091791088617662298487007284882395542e-33, /* twoPowerIndex2lo[34] */ } , { 1.46091779418064704465507475106278434395790100097656e+00, /* twoPowerIndex2hi[35] */ -5.60037718607521580013156831807759453639536208267684e-17, /* twoPowerIndex2mi[35] */ -4.80948804890004400970317146361816382779746350931714e-33, /* twoPowerIndex2lo[35] */ } , { 1.47682614593949934622685304930200800299644470214844e+00, /* twoPowerIndex2hi[36] */ -3.48399455689279579579151031868718147769491495422105e-17, /* twoPowerIndex2mi[36] */ -1.21157704523090580028169713170353136148082368354920e-34, /* twoPowerIndex2lo[36] */ } , { 1.49290772829126483500772337720263749361038208007812e+00, /* twoPowerIndex2hi[37] */ 1.41929201542840357707378184476885202767753055101956e-17, /* twoPowerIndex2mi[37] */ 2.77326329344780505247628358108799734324783290873618e-34, /* twoPowerIndex2lo[37] */ } , { 1.50916442759342284141155232646269723773002624511719e+00, /* twoPowerIndex2hi[38] */ -1.01645532775429503910501990740249618370059871055172e-16, /* twoPowerIndex2mi[38] */ 2.04191706967403438352422808603561166583202022922508e-34, /* twoPowerIndex2lo[38] */ } , { 1.52559815074453841710067081294255331158638000488281e+00, /* twoPowerIndex2hi[39] */ -1.10249417123425609363148008789604625195179292613569e-16, /* twoPowerIndex2mi[39] */ -2.99382882637137806007903782085057425945683820190483e-33, /* twoPowerIndex2lo[39] */ } , { 1.54221082540794074411394376511452719569206237792969e+00, /* twoPowerIndex2hi[40] */ 7.94983480969762085616103882937991564856794389991833e-17, /* twoPowerIndex2mi[40] */ -9.15995637410036729585390444224530830478731117122757e-34, /* twoPowerIndex2lo[40] */ } , { 1.55900440023783692922165755589958280324935913085938e+00, /* twoPowerIndex2hi[41] */ 3.78120705335752750188190562589679090842557793649900e-17, /* twoPowerIndex2mi[41] */ 5.94230221045385633407443935898656310894518533675204e-35, /* twoPowerIndex2lo[41] */ } , { 1.57598084510788649659218663146020844578742980957031e+00, /* twoPowerIndex2hi[42] */ -1.01369164712783039807957177429288269249745537889645e-17, /* twoPowerIndex2mi[42] */ 5.43913851556220712785038586461119929989856637311730e-34, /* twoPowerIndex2lo[42] */ } , { 1.59314215134226699888131406623870134353637695312500e+00, /* twoPowerIndex2hi[43] */ -1.00944065423119637216151952902063201612012779755882e-16, /* twoPowerIndex2mi[43] */ 4.60848399034962572477662350836868643017178368092553e-33, /* twoPowerIndex2lo[43] */ } , { 1.61049033194925428347232809755951166152954101562500e+00, /* twoPowerIndex2hi[44] */ 2.47071925697978878522451183466139791436957933053447e-17, /* twoPowerIndex2mi[44] */ 1.06968477888935897586507304780358756526593706030066e-33, /* twoPowerIndex2lo[44] */ } , { 1.62802742185734783397776936908485367894172668457031e+00, /* twoPowerIndex2hi[45] */ -6.71295508470708408629558620522800193343463268850872e-17, /* twoPowerIndex2mi[45] */ 1.86124288813399584090278118171650158752835667500490e-33, /* twoPowerIndex2lo[45] */ } , { 1.64575547815396494577555586147354915738105773925781e+00, /* twoPowerIndex2hi[46] */ -1.01256799136747726037875241569662212149731136230039e-16, /* twoPowerIndex2mi[46] */ -6.73838498803664271467304077725442401461793880458369e-34, /* twoPowerIndex2lo[46] */ } , { 1.66367658032673637613640948984539136290550231933594e+00, /* twoPowerIndex2hi[47] */ 5.89099269671309967045155789620226639428173542900082e-17, /* twoPowerIndex2mi[47] */ 2.37785299276765025315795732233641105960161859663372e-33, /* twoPowerIndex2lo[47] */ } , { 1.68179283050742900407215074665145948529243469238281e+00, /* twoPowerIndex2hi[48] */ 8.19901002058149652012724391042374107310082144797238e-17, /* twoPowerIndex2mi[48] */ 5.10351519472809316392686812760480457926425713861784e-33, /* twoPowerIndex2lo[48] */ } , { 1.70010635371852347752508194389520213007926940917969e+00, /* twoPowerIndex2hi[49] */ -8.02371937039770024588528464451482959960563128920877e-18, /* twoPowerIndex2mi[49] */ 4.50894675051846528463958043437010583905518288996850e-34, /* twoPowerIndex2lo[49] */ } , { 1.71861929812247793414314855908742174506187438964844e+00, /* twoPowerIndex2hi[50] */ -1.85138041826311098821086356969536380719870481925638e-17, /* twoPowerIndex2mi[50] */ 6.41562962530571009881963439719259893730039269925891e-34, /* twoPowerIndex2lo[50] */ } , { 1.73733383527370621735030908894259482622146606445312e+00, /* twoPowerIndex2hi[51] */ 3.16438929929295694659064288262436215220581330791541e-17, /* twoPowerIndex2mi[51] */ 2.46812086524635182684409036079744664142196277491485e-33, /* twoPowerIndex2lo[51] */ } , { 1.75625216037329945351075366488657891750335693359375e+00, /* twoPowerIndex2hi[52] */ 2.96014069544887330703087179323550026749650613893620e-17, /* twoPowerIndex2mi[52] */ 1.23348227448930022362949427574612725745479960698002e-33, /* twoPowerIndex2lo[52] */ } , { 1.77537649252652118825324123463360592722892761230469e+00, /* twoPowerIndex2hi[53] */ 6.42973179655657203395602172161574258202382771355994e-17, /* twoPowerIndex2mi[53] */ -3.05903038196122316059732104267589318807211463677414e-33, /* twoPowerIndex2lo[53] */ } , { 1.79470907500310716820024481421569362282752990722656e+00, /* twoPowerIndex2hi[54] */ 1.82274584279120867697625715862678123206602563412216e-17, /* twoPowerIndex2mi[54] */ 1.42176433874694971095041068746172287320972847635154e-33, /* twoPowerIndex2lo[54] */ } , { 1.81425217550039885594514998956583440303802490234375e+00, /* twoPowerIndex2hi[55] */ -9.96953153892034881983229632097342495877571562964276e-17, /* twoPowerIndex2mi[55] */ -5.86224914377491774994695195482808191103744720514440e-33, /* twoPowerIndex2lo[55] */ } , { 1.83400808640934243065601094713201746344566345214844e+00, /* twoPowerIndex2hi[56] */ 3.28310722424562720351405816760294702167288526703081e-17, /* twoPowerIndex2mi[56] */ -6.42508934795304248095271046696049734574532048424330e-34, /* twoPowerIndex2lo[56] */ } , { 1.85397912508338547077357816306175664067268371582031e+00, /* twoPowerIndex2hi[57] */ 9.76188749072759353840331670682321086158335176176729e-17, /* twoPowerIndex2mi[57] */ 4.61481577205566482307976345637533484680898060020057e-33, /* twoPowerIndex2lo[57] */ } , { 1.87416763411029996255763307999586686491966247558594e+00, /* twoPowerIndex2hi[58] */ -6.12276341300414256163658402373731493255704994623650e-17, /* twoPowerIndex2mi[58] */ 5.28588559402507397372575432425046614667899080733482e-33, /* twoPowerIndex2lo[58] */ } , { 1.89457598158696560730618330126162618398666381835938e+00, /* twoPowerIndex2hi[59] */ 3.40340353521652967060147928999507962708632290832738e-17, /* twoPowerIndex2mi[59] */ 1.72475099549343225430579028439403217279441019556785e-33, /* twoPowerIndex2lo[59] */ } , { 1.91520656139714740007207183225546032190322875976562e+00, /* twoPowerIndex2hi[60] */ -1.06199460561959626376283195555328606320260702029334e-16, /* twoPowerIndex2mi[60] */ -3.05776975679132548538006102719337626149343902119718e-33, /* twoPowerIndex2lo[60] */ } , { 1.93606179349229434727419629780342802405357360839844e+00, /* twoPowerIndex2hi[61] */ 1.03323859606763257447769151803649788699571393339738e-16, /* twoPowerIndex2mi[61] */ 6.05301367682062275405664830597304146844867569493449e-33, /* twoPowerIndex2lo[61] */ } , { 1.95714412417540017941064434126019477844238281250000e+00, /* twoPowerIndex2hi[62] */ 8.96076779103666776760155050762912042076490756639488e-17, /* twoPowerIndex2mi[62] */ -9.63267661361827588458686334472185443533033181828620e-34, /* twoPowerIndex2lo[62] */ } , { 1.97845602638795092786949680885300040245056152343750e+00, /* twoPowerIndex2hi[63] */ 4.03887531092781665749784154795462589642365074083484e-17, /* twoPowerIndex2mi[63] */ 3.58120371667786223934924900740488031476290303118010e-34, /* twoPowerIndex2lo[63] */ } }; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR0.gappa0000644000000000000000000005430413316017127020520 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: x * (1b0 + ((x^(1b1)) * (108172851219475575594385340192083b-109 + ((x^(1b1)) * (3042361440547750563592087693241b-105 + ((x^(1b1)) * (115899483449438116708269989305805b-111 + ((x^(1b1)) * (78876037347534273870913665352907b-111 + ((x^(1b1)) * (14520361420796082234834302007973b-109 + ((x^(1b1)) * (90100704200837228890721343577993b-112 + ((x^(1b1)) * (8050184333924753b-59 + ((x^(1b1)) * (3329579917524393b-58 + ((x^(1b1)) * (703398096605685b-56 + ((x^(1b1)) * (2418349647542263b-58 + ((x^(1b1)) * (4215384086352865b-59 + ((x^(1b1)) * (3716565942414711b-59 + ((x^(1b1)) * (3308858625299127b-59 + ((x^(1b1)) * (1485727445894643b-58 + ((x^(1b1)) * (1338544855889499b-58 + ((x^(1b1)) * (1262327254413885b-58 + ((x^(1b1)) * (7109335287797167b-61 + ((x^(1b1)) * 3595912496380613b-59)))))))))))))))))))))))))))))))))))) # The polynomial implemented is: x * (1b0 + ((x^(1b1)) * (108172851219475575594385340192083b-109 + ((x^(1b1)) * (3042361440547750563592087693241b-105 + ((x^(1b1)) * (115899483449438116708269989305805b-111 + ((x^(1b1)) * (78876037347534273870913665352907b-111 + ((x^(1b1)) * (14520361420796082234834302007973b-109 + ((x^(1b1)) * (90100704200837228890721343577993b-112 + ((x^(1b1)) * (8050184333924753b-59 + ((x^(1b1)) * (3329579917524393b-58 + ((x^(1b1)) * (703398096605685b-56 + ((x^(1b1)) * (2418349647542263b-58 + ((x^(1b1)) * (4215384086352865b-59 + ((x^(1b1)) * (3716565942414711b-59 + ((x^(1b1)) * (3308858625299127b-59 + ((x^(1b1)) * (1485727445894643b-58 + ((x^(1b1)) * (1338544855889499b-58 + ((x^(1b1)) * (1262327254413885b-58 + ((x^(1b1)) * (7109335287797167b-61 + ((x^(1b1)) * 3595912496380613b-59)))))))))))))))))))))))))))))))))))) # The domain is [1b-54;9007199254740983b-55] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 56 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_1h = double(1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00); p_coeff_3h = double(1.66666666666666657414808128123695496469736099243164062500000000000000000000000000e-01); p_coeff_3m = double(9.25185853854296757512770104458324356634117384146900539554358999794203555211424828e-18); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_5h = double(7.49999999999999972244424384371086489409208297729492187500000000000000000000000000e-02); p_coeff_5m = double(2.77555756157123848551244900139306363413139848179272961559149734966922551393508911e-18); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_7h = double(4.46428571428571438484134148438897682353854179382324218750000000000000000000000000e-02); p_coeff_7m = double(-9.91270564650888671257031422999640405542600950171395167431764861021292745135724545e-19); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_9h = double(3.03819444444444440589503386718206456862390041351318359375000000000000000000000000e-02); p_coeff_9m = double(3.85497067132392282371332994114988395042540962791093560324551248186253360472619534e-19); p_coeff_9hm = p_coeff_9h + p_coeff_9m; p_coeff_11h = double(2.23721590909090918553037141691675060428678989410400390625000000000000000000000000e-02); p_coeff_11m = double(-9.46970190235819944882493359250540536388374860744029243297958942093828227370977402e-19); p_coeff_11hm = p_coeff_11h + p_coeff_11m; p_coeff_13h = double(1.73527644230769238775646812200648128055036067962646484375000000000000000000000000e-02); p_coeff_13m = double(-6.73286913315360860061003796178520710524664576113391175476996508564297982957214117e-19); p_coeff_13hm = p_coeff_13h + p_coeff_13m; p_coeff_15h = double(1.39648437499999850813781065994589880574494600296020507812500000000000000000000000e-02); p_coeff_17h = double(1.15518008961409714141499449624461703933775424957275390625000000000000000000000000e-02); p_coeff_19h = double(9.76160952911427071132521859908592887222766876220703125000000000000000000000000000e-03); p_coeff_21h = double(8.39033581342360154642356917520373826846480369567871093750000000000000000000000000e-03); p_coeff_23h = double(7.31252573485535913022648202286291052587330341339111328125000000000000000000000000e-03); p_coeff_25h = double(6.44721419032266533644115469314783695153892040252685546875000000000000000000000000e-03); p_coeff_27h = double(5.73995473599474108350459999883241835050284862518310546875000000000000000000000000e-03); p_coeff_29h = double(5.15465255859299739671364193327462999150156974792480468750000000000000000000000000e-03); p_coeff_31h = double(4.64401037031901206542094939777598483487963676452636718750000000000000000000000000e-03); p_coeff_33h = double(4.37957744519422778606276835944299818947911262512207031250000000000000000000000000e-03); p_coeff_35h = double(3.08318270558301894476715965254243201343342661857604980468750000000000000000000000e-03); p_coeff_37h = double(6.23791382502981474333925149267088272608816623687744140625000000000000000000000000e-03); p_x_0_pow2hm = xh * xh; p_x_0_pow2h = double(p_x_0_pow2hm); p_x_0_pow2m = p_x_0_pow2hm - p_x_0_pow2h; p_t_1_0h = p_coeff_37h; p_t_2_0h = double(p_t_1_0h * p_x_0_pow2h); p_t_3_0h = double(p_coeff_35h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * p_x_0_pow2h); p_t_5_0h = double(p_coeff_33h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * p_x_0_pow2h); p_t_7_0hm = p_coeff_31h + p_t_6_0h; p_t_7_0h = double(p_t_7_0hm); p_t_7_0m = p_t_7_0hm - p_t_7_0h; p_t_8_0hm = mul_rel<102>(p_t_7_0hm,p_x_0_pow2hm); p_t_8_0h = double(p_t_8_0hm); p_t_8_0m = p_t_8_0hm - p_t_8_0h; p_t_9_0hm = add_rel<102>(p_coeff_29h,p_t_8_0hm); p_t_9_0h = double(p_t_9_0hm); p_t_9_0m = p_t_9_0hm - p_t_9_0h; p_t_10_0hm = mul_rel<102>(p_t_9_0hm,p_x_0_pow2hm); p_t_10_0h = double(p_t_10_0hm); p_t_10_0m = p_t_10_0hm - p_t_10_0h; p_t_11_0hm = add_rel<102>(p_coeff_27h,p_t_10_0hm); p_t_11_0h = double(p_t_11_0hm); p_t_11_0m = p_t_11_0hm - p_t_11_0h; p_t_12_0hm = mul_rel<102>(p_t_11_0hm,p_x_0_pow2hm); p_t_12_0h = double(p_t_12_0hm); p_t_12_0m = p_t_12_0hm - p_t_12_0h; p_t_13_0hm = add_rel<102>(p_coeff_25h,p_t_12_0hm); p_t_13_0h = double(p_t_13_0hm); p_t_13_0m = p_t_13_0hm - p_t_13_0h; p_t_14_0hm = mul_rel<102>(p_t_13_0hm,p_x_0_pow2hm); p_t_14_0h = double(p_t_14_0hm); p_t_14_0m = p_t_14_0hm - p_t_14_0h; p_t_15_0hm = add_rel<102>(p_coeff_23h,p_t_14_0hm); p_t_15_0h = double(p_t_15_0hm); p_t_15_0m = p_t_15_0hm - p_t_15_0h; p_t_16_0hm = mul_rel<102>(p_t_15_0hm,p_x_0_pow2hm); p_t_16_0h = double(p_t_16_0hm); p_t_16_0m = p_t_16_0hm - p_t_16_0h; p_t_17_0hm = add_rel<102>(p_coeff_21h,p_t_16_0hm); p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(p_t_17_0hm,p_x_0_pow2hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_19h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(p_t_19_0hm,p_x_0_pow2hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_17h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(p_t_21_0hm,p_x_0_pow2hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_15h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = fma_rel<100>(p_t_23_0hm,p_x_0_pow2hm,p_coeff_13hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = fma_rel<100>(p_t_24_0hm,p_x_0_pow2hm,p_coeff_11hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = fma_rel<100>(p_t_25_0hm,p_x_0_pow2hm,p_coeff_9hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = mul_rel<102>(p_t_26_0hm,p_x_0_pow2hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hml = add_rel<140>(p_coeff_7hm,p_t_27_0hm); p_t_28_0ml = p_t_28_0hml - p_t_28_0h; p_t_28_0m = double(p_t_28_0ml); p_t_28_0l = p_t_28_0ml - p_t_28_0m; p_t_28_0hm = p_t_28_0h + p_t_28_0m; overlap_p_t_28_0 = p_t_28_0m / p_t_28_0h; p_t_29_0hml = mul_rel<142>(p_x_0_pow2hm,p_t_28_0hml); p_t_29_0ml = p_t_29_0hml - p_t_29_0h; p_t_29_0m = double(p_t_29_0ml); p_t_29_0l = p_t_29_0ml - p_t_29_0m; p_t_29_0hm = p_t_29_0h + p_t_29_0m; overlap_p_t_29_0 = p_t_29_0m / p_t_29_0h; p_t_30_0hml = add_rel<144>(p_coeff_5hm,p_t_29_0hml); p_t_30_0ml = p_t_30_0hml - p_t_30_0h; p_t_30_0m = double(p_t_30_0ml); p_t_30_0l = p_t_30_0ml - p_t_30_0m; p_t_30_0hm = p_t_30_0h + p_t_30_0m; overlap_p_t_30_0 = p_t_30_0m / p_t_30_0h; p_t_31_0hml = mul_rel<133>(p_x_0_pow2hm,p_t_30_0hml); p_t_31_0ml = p_t_31_0hml - p_t_31_0h; p_t_31_0m = double(p_t_31_0ml); p_t_31_0l = p_t_31_0ml - p_t_31_0m; p_t_31_0hm = p_t_31_0h + p_t_31_0m; overlap_p_t_31_0 = p_t_31_0m / p_t_31_0h; p_t_32_0hml = add_rel<135>(p_coeff_3hm,p_t_31_0hml); p_t_32_0ml = p_t_32_0hml - p_t_32_0h; p_t_32_0m = double(p_t_32_0ml); p_t_32_0l = p_t_32_0ml - p_t_32_0m; p_t_32_0hm = p_t_32_0h + p_t_32_0m; overlap_p_t_32_0 = p_t_32_0m / p_t_32_0h; p_t_33_0hml = mul_rel<124>(p_x_0_pow2hm,p_t_32_0hml); p_t_33_0ml = p_t_33_0hml - p_t_33_0h; p_t_33_0m = double(p_t_33_0ml); p_t_33_0l = p_t_33_0ml - p_t_33_0m; p_t_33_0hm = p_t_33_0h + p_t_33_0m; overlap_p_t_33_0 = p_t_33_0m / p_t_33_0h; p_t_34_0hml = add_rel<127>(p_coeff_1h,p_t_33_0hml); p_t_34_0ml = p_t_34_0hml - p_t_34_0h; p_t_34_0m = double(p_t_34_0ml); p_t_34_0l = p_t_34_0ml - p_t_34_0m; p_t_34_0hm = p_t_34_0h + p_t_34_0m; overlap_p_t_34_0 = p_t_34_0m / p_t_34_0h; p_t_35_0hml = mul_rel<121>(xh,p_t_34_0hml); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_reshml = p_t_35_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_1 = p_coeff_1h; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_9 = p_coeff_9hm; Mp_coeff_11 = p_coeff_11hm; Mp_coeff_13 = p_coeff_13hm; Mp_coeff_15 = p_coeff_15h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_21 = p_coeff_21h; Mp_coeff_23 = p_coeff_23h; Mp_coeff_25 = p_coeff_25h; Mp_coeff_27 = p_coeff_27h; Mp_coeff_29 = p_coeff_29h; Mp_coeff_31 = p_coeff_31h; Mp_coeff_33 = p_coeff_33h; Mp_coeff_35 = p_coeff_35h; Mp_coeff_37 = p_coeff_37h; Mp_x_0_pow2 = Mx * Mx; Mp_t_1_0 = Mp_coeff_37; Mp_t_2_0 = Mp_t_1_0 * Mp_x_0_pow2; Mp_t_3_0 = Mp_coeff_35 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mp_x_0_pow2; Mp_t_5_0 = Mp_coeff_33 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mp_x_0_pow2; Mp_t_7_0 = Mp_coeff_31 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mp_x_0_pow2; Mp_t_9_0 = Mp_coeff_29 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mp_x_0_pow2; Mp_t_11_0 = Mp_coeff_27 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mp_x_0_pow2; Mp_t_13_0 = Mp_coeff_25 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mp_x_0_pow2; Mp_t_15_0 = Mp_coeff_23 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mp_x_0_pow2; Mp_t_17_0 = Mp_coeff_21 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mp_x_0_pow2; Mp_t_19_0 = Mp_coeff_19 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mp_x_0_pow2; Mp_t_21_0 = Mp_coeff_17 + Mp_t_20_0; Mp_t_22_0 = Mp_t_21_0 * Mp_x_0_pow2; Mp_t_23_0 = Mp_coeff_15 + Mp_t_22_0; Mp_t_24_0 = (Mp_t_23_0 * Mp_x_0_pow2) + Mp_coeff_13; Mp_t_25_0 = (Mp_t_24_0 * Mp_x_0_pow2) + Mp_coeff_11; Mp_t_26_0 = (Mp_t_25_0 * Mp_x_0_pow2) + Mp_coeff_9; Mp_t_27_0 = Mp_t_26_0 * Mp_x_0_pow2; Mp_t_28_0 = Mp_coeff_7 + Mp_t_27_0; Mp_t_29_0 = Mp_x_0_pow2 * Mp_t_28_0; Mp_t_30_0 = Mp_coeff_5 + Mp_t_29_0; Mp_t_31_0 = Mp_x_0_pow2 * Mp_t_30_0; Mp_t_32_0 = Mp_coeff_3 + Mp_t_31_0; Mp_t_33_0 = Mp_x_0_pow2 * Mp_t_32_0; Mp_t_34_0 = Mp_coeff_1 + Mp_t_33_0; Mp_t_35_0 = Mx * Mp_t_34_0; Mp_res = Mp_t_35_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [1b-54,9007199254740983b-55] /\ |overlap_p_t_28_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_28_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_29_0| in [1b-400,1b-41] # Verify the lower bound /\ |p_t_29_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_30_0| in [1b-400,1b-36] # Verify the lower bound /\ |p_t_30_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_31_0| in [1b-400,1b-32] # Verify the lower bound /\ |p_t_31_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_32_0| in [1b-400,1b-27] # Verify the lower bound /\ |p_t_32_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_33_0| in [1b-400,1b-23] # Verify the lower bound /\ |p_t_33_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_34_0| in [1b-400,1b-21] # Verify the lower bound /\ |p_t_34_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_35_0| in [1b-400,1b-16] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [-9007199254740983b-55,-1b-54] /\ |overlap_p_t_28_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_28_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_29_0| in [1b-400,1b-41] # Verify the lower bound /\ |p_t_29_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_30_0| in [1b-400,1b-36] # Verify the lower bound /\ |p_t_30_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_31_0| in [1b-400,1b-32] # Verify the lower bound /\ |p_t_31_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_32_0| in [1b-400,1b-27] # Verify the lower bound /\ |p_t_32_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_33_0| in [1b-400,1b-23] # Verify the lower bound /\ |p_t_33_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_34_0| in [1b-400,1b-21] # Verify the lower bound /\ |p_t_34_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_35_0| in [1b-400,1b-16] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_x_0_pow2h ~ p_x_0_pow2hm; p_t_7_0h ~ p_t_7_0hm; p_t_8_0h ~ p_t_8_0hm; p_t_9_0h ~ p_t_9_0hm; p_t_10_0h ~ p_t_10_0hm; p_t_11_0h ~ p_t_11_0hm; p_t_12_0h ~ p_t_12_0hm; p_t_13_0h ~ p_t_13_0hm; p_t_14_0h ~ p_t_14_0hm; p_t_15_0h ~ p_t_15_0hm; p_t_16_0h ~ p_t_16_0hm; p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0hm ~ p_t_28_0hml; p_t_28_0h ~ p_t_28_0hm; p_t_28_0h ~ p_t_28_0hml; p_t_28_0m -> p_t_28_0h * overlap_p_t_28_0; p_t_28_0l / p_t_28_0m -> - ((p_t_28_0m - p_t_28_0ml) / p_t_28_0ml) / (1 + ((p_t_28_0m - p_t_28_0ml) / p_t_28_0ml)); (p_t_28_0hm - p_t_28_0hml) / p_t_28_0hml -> - (p_t_28_0l / p_t_28_0m) * (1 / (1 / overlap_p_t_28_0 + 1 + (p_t_28_0l / p_t_28_0m))); p_t_28_0ml -> p_t_28_0hml / ((1 + ((p_t_28_0m - p_t_28_0ml) / p_t_28_0ml)) / overlap_p_t_28_0 + 1); (p_t_28_0h - p_t_28_0hm) / p_t_28_0hm -> - 1 / (1 / overlap_p_t_28_0 + 1); p_t_28_0h -> p_t_28_0hml / (overlap_p_t_28_0 / (1 + ((p_t_28_0m - p_t_28_0ml) / p_t_28_0ml)) + 1); p_t_29_0hm ~ p_t_29_0hml; p_t_29_0h ~ p_t_29_0hm; p_t_29_0h ~ p_t_29_0hml; p_t_29_0m -> p_t_29_0h * overlap_p_t_29_0; p_t_29_0l / p_t_29_0m -> - ((p_t_29_0m - p_t_29_0ml) / p_t_29_0ml) / (1 + ((p_t_29_0m - p_t_29_0ml) / p_t_29_0ml)); (p_t_29_0hm - p_t_29_0hml) / p_t_29_0hml -> - (p_t_29_0l / p_t_29_0m) * (1 / (1 / overlap_p_t_29_0 + 1 + (p_t_29_0l / p_t_29_0m))); p_t_29_0ml -> p_t_29_0hml / ((1 + ((p_t_29_0m - p_t_29_0ml) / p_t_29_0ml)) / overlap_p_t_29_0 + 1); (p_t_29_0h - p_t_29_0hm) / p_t_29_0hm -> - 1 / (1 / overlap_p_t_29_0 + 1); p_t_29_0h -> p_t_29_0hml / (overlap_p_t_29_0 / (1 + ((p_t_29_0m - p_t_29_0ml) / p_t_29_0ml)) + 1); p_t_30_0hm ~ p_t_30_0hml; p_t_30_0h ~ p_t_30_0hm; p_t_30_0h ~ p_t_30_0hml; p_t_30_0m -> p_t_30_0h * overlap_p_t_30_0; p_t_30_0l / p_t_30_0m -> - ((p_t_30_0m - p_t_30_0ml) / p_t_30_0ml) / (1 + ((p_t_30_0m - p_t_30_0ml) / p_t_30_0ml)); (p_t_30_0hm - p_t_30_0hml) / p_t_30_0hml -> - (p_t_30_0l / p_t_30_0m) * (1 / (1 / overlap_p_t_30_0 + 1 + (p_t_30_0l / p_t_30_0m))); p_t_30_0ml -> p_t_30_0hml / ((1 + ((p_t_30_0m - p_t_30_0ml) / p_t_30_0ml)) / overlap_p_t_30_0 + 1); (p_t_30_0h - p_t_30_0hm) / p_t_30_0hm -> - 1 / (1 / overlap_p_t_30_0 + 1); p_t_30_0h -> p_t_30_0hml / (overlap_p_t_30_0 / (1 + ((p_t_30_0m - p_t_30_0ml) / p_t_30_0ml)) + 1); p_t_31_0hm ~ p_t_31_0hml; p_t_31_0h ~ p_t_31_0hm; p_t_31_0h ~ p_t_31_0hml; p_t_31_0m -> p_t_31_0h * overlap_p_t_31_0; p_t_31_0l / p_t_31_0m -> - ((p_t_31_0m - p_t_31_0ml) / p_t_31_0ml) / (1 + ((p_t_31_0m - p_t_31_0ml) / p_t_31_0ml)); (p_t_31_0hm - p_t_31_0hml) / p_t_31_0hml -> - (p_t_31_0l / p_t_31_0m) * (1 / (1 / overlap_p_t_31_0 + 1 + (p_t_31_0l / p_t_31_0m))); p_t_31_0ml -> p_t_31_0hml / ((1 + ((p_t_31_0m - p_t_31_0ml) / p_t_31_0ml)) / overlap_p_t_31_0 + 1); (p_t_31_0h - p_t_31_0hm) / p_t_31_0hm -> - 1 / (1 / overlap_p_t_31_0 + 1); p_t_31_0h -> p_t_31_0hml / (overlap_p_t_31_0 / (1 + ((p_t_31_0m - p_t_31_0ml) / p_t_31_0ml)) + 1); p_t_32_0hm ~ p_t_32_0hml; p_t_32_0h ~ p_t_32_0hm; p_t_32_0h ~ p_t_32_0hml; p_t_32_0m -> p_t_32_0h * overlap_p_t_32_0; p_t_32_0l / p_t_32_0m -> - ((p_t_32_0m - p_t_32_0ml) / p_t_32_0ml) / (1 + ((p_t_32_0m - p_t_32_0ml) / p_t_32_0ml)); (p_t_32_0hm - p_t_32_0hml) / p_t_32_0hml -> - (p_t_32_0l / p_t_32_0m) * (1 / (1 / overlap_p_t_32_0 + 1 + (p_t_32_0l / p_t_32_0m))); p_t_32_0ml -> p_t_32_0hml / ((1 + ((p_t_32_0m - p_t_32_0ml) / p_t_32_0ml)) / overlap_p_t_32_0 + 1); (p_t_32_0h - p_t_32_0hm) / p_t_32_0hm -> - 1 / (1 / overlap_p_t_32_0 + 1); p_t_32_0h -> p_t_32_0hml / (overlap_p_t_32_0 / (1 + ((p_t_32_0m - p_t_32_0ml) / p_t_32_0ml)) + 1); p_t_33_0hm ~ p_t_33_0hml; p_t_33_0h ~ p_t_33_0hm; p_t_33_0h ~ p_t_33_0hml; p_t_33_0m -> p_t_33_0h * overlap_p_t_33_0; p_t_33_0l / p_t_33_0m -> - ((p_t_33_0m - p_t_33_0ml) / p_t_33_0ml) / (1 + ((p_t_33_0m - p_t_33_0ml) / p_t_33_0ml)); (p_t_33_0hm - p_t_33_0hml) / p_t_33_0hml -> - (p_t_33_0l / p_t_33_0m) * (1 / (1 / overlap_p_t_33_0 + 1 + (p_t_33_0l / p_t_33_0m))); p_t_33_0ml -> p_t_33_0hml / ((1 + ((p_t_33_0m - p_t_33_0ml) / p_t_33_0ml)) / overlap_p_t_33_0 + 1); (p_t_33_0h - p_t_33_0hm) / p_t_33_0hm -> - 1 / (1 / overlap_p_t_33_0 + 1); p_t_33_0h -> p_t_33_0hml / (overlap_p_t_33_0 / (1 + ((p_t_33_0m - p_t_33_0ml) / p_t_33_0ml)) + 1); p_t_34_0hm ~ p_t_34_0hml; p_t_34_0h ~ p_t_34_0hm; p_t_34_0h ~ p_t_34_0hml; p_t_34_0m -> p_t_34_0h * overlap_p_t_34_0; p_t_34_0l / p_t_34_0m -> - ((p_t_34_0m - p_t_34_0ml) / p_t_34_0ml) / (1 + ((p_t_34_0m - p_t_34_0ml) / p_t_34_0ml)); (p_t_34_0hm - p_t_34_0hml) / p_t_34_0hml -> - (p_t_34_0l / p_t_34_0m) * (1 / (1 / overlap_p_t_34_0 + 1 + (p_t_34_0l / p_t_34_0m))); p_t_34_0ml -> p_t_34_0hml / ((1 + ((p_t_34_0m - p_t_34_0ml) / p_t_34_0ml)) / overlap_p_t_34_0 + 1); (p_t_34_0h - p_t_34_0hm) / p_t_34_0hm -> - 1 / (1 / overlap_p_t_34_0 + 1); p_t_34_0h -> p_t_34_0hml / (overlap_p_t_34_0 / (1 + ((p_t_34_0m - p_t_34_0ml) / p_t_34_0ml)) + 1); p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_x_0_pow2hm ~ Mp_x_0_pow2; p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0hm ~ Mp_t_7_0; p_t_8_0hm ~ Mp_t_8_0; p_t_9_0hm ~ Mp_t_9_0; p_t_10_0hm ~ Mp_t_10_0; p_t_11_0hm ~ Mp_t_11_0; p_t_12_0hm ~ Mp_t_12_0; p_t_13_0hm ~ Mp_t_13_0; p_t_14_0hm ~ Mp_t_14_0; p_t_15_0hm ~ Mp_t_15_0; p_t_16_0hm ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hml ~ Mp_t_28_0; p_t_29_0hml ~ Mp_t_29_0; p_t_30_0hml ~ Mp_t_30_0; p_t_31_0hml ~ Mp_t_31_0; p_t_32_0hml ~ Mp_t_32_0; p_t_33_0hml ~ Mp_t_33_0; p_t_34_0hml ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_28_0hml in (0); $ p_t_28_0ml in (0); $ p_t_29_0hml in (0); $ p_t_29_0ml in (0); $ p_t_30_0hml in (0); $ p_t_30_0ml in (0); $ p_t_31_0hml in (0); $ p_t_31_0ml in (0); $ p_t_32_0hml in (0); $ p_t_32_0ml in (0); $ p_t_33_0hml in (0); $ p_t_33_0ml in (0); $ p_t_34_0hml in (0); $ p_t_34_0ml in (0); $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR1.gappa0000644000000000000000000004740013316017127020520 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 12733824903478660485213924945761441b-115 + (x * (21274243840621107493132068550861b-104 + (x * (56506575121178698033892645299217b-108 + (x * (162352694585912342011697266345865b-109 + (x * (108824425124571119884970372511875b-109 + (x * (130962285214586424233709645857015b-109 + (x * (64538322654437688214573659252359b-108 + (x * (19138493711791118275730909715341b-106 + (x * (86948317116031170147801372254985b-108 + (x * (2926340027982217b-53 + (x * (7079519916441877b-54 + (x * (4400722769684657b-53 + (x * (2753619111017419b-52 + (x * (1747593133357423b-51 + (x * (1117301179312929b-50 + (x * (2882758419021281b-51 + (x * (7485076380936111b-52 + (x * (4889438710496705b-51 + (x * (6420893266510167b-51 + (x * (8469313684169241b-51 + (x * (701323415166733b-47 + (x * (7696281875237263b-50 + (x * 5166029452007411b-49))))))))))))))))))))))))))))))))))))))))))) # The polynomial implemented is: 12733824903478660485213924945761441b-115 + (x * (21274243840621107493132068550861b-104 + (x * (56506575121178698033892645299217b-108 + (x * (162352694585912342011697266345865b-109 + (x * (108824425124571119884970372511875b-109 + (x * (130962285214586424233709645857015b-109 + (x * (64538322654437688214573659252359b-108 + (x * (19138493711791118275730909715341b-106 + (x * (86948317116031170147801372254985b-108 + (x * (2926340027982217b-53 + (x * (7079519916441877b-54 + (x * (4400722769684657b-53 + (x * (2753619111017419b-52 + (x * (1747593133357423b-51 + (x * (1117301179312929b-50 + (x * (2882758419021281b-51 + (x * (7485076380936111b-52 + (x * (4889438710496705b-51 + (x * (6420893266510167b-51 + (x * (8469313684169241b-51 + (x * (701323415166733b-47 + (x * (7696281875237263b-50 + (x * 5166029452007411b-49))))))))))))))))))))))))))))))))))))))))))) # The domain is [-466363011288839b-53;932726022577599b-54] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 63 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(3.06555683602418194144689778113388456404209136962890625000000000000000000000000000e-01); p_coeff_0m = double(1.38398751617026410180086928097698669616246328887899420551771401122209681489039212e-19); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.04890120337530645677759366662940010428428649902343750000000000000000000000000000e+00); p_coeff_1m = double(-1.03082627287649058162739898016810705246384011505786371110104937542928382754325867e-16); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(1.74124328129031780143520791170885786414146423339843750000000000000000000000000000e-01); p_coeff_2m = double(-1.22415542219236523063144722572481689558635471916500300770813680628634756430983543e-17); p_coeff_2hm = p_coeff_2h + p_coeff_2m; p_coeff_3h = double(2.50143932843971239510239001901936717331409454345703125000000000000000000000000000e-01); p_coeff_3m = double(-4.13151149720064821141736364751386140320745355927365902171111144980386598035693169e-18); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_4h = double(1.67670575222510526147701170884829480201005935668945312500000000000000000000000000e-01); p_coeff_4m = double(9.08471320692536034881317437634606200189439625594786317797080243963137036189436913e-18); p_coeff_4hm = p_coeff_4h + p_coeff_4m; p_coeff_5h = double(2.01779349344123004605933147104224190115928649902343750000000000000000000000000000e-01); p_coeff_5m = double(-2.81327768912778086871203966934740276353563377312707108335310124402894871309399605e-18); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_6h = double(1.98874061057130652185875874238263349980115890502929687500000000000000000000000000e-01); p_coeff_6m = double(4.84208641776008377910230190635861197948724910162295737015014651660749223083257675e-18); p_coeff_6hm = p_coeff_6h + p_coeff_6m; p_coeff_7h = double(2.35900148032034129297329627661383710801601409912109375000000000000000000000000000e-01); p_coeff_7m = double(-7.70265627820459694705350308676046582995139915634938421185040624550310894846916199e-18); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_8h = double(2.67930188076546671460675952403107658028602600097656250000000000000000000000000000e-01); p_coeff_8m = double(-1.74203278137786025999080009256505191287370077696727496685547009747097035869956017e-17); p_coeff_8hm = p_coeff_8h + p_coeff_8m; p_coeff_9h = double(3.24889007694808218396076426870422437787055969238281250000000000000000000000000000e-01); p_coeff_10h = double(3.92992300726306809099952488395501859486103057861328125000000000000000000000000000e-01); p_coeff_11h = double(4.88578374389609604300233058893354609608650207519531250000000000000000000000000000e-01); p_coeff_12h = double(6.11426267619878727188620359811466187238693237304687500000000000000000000000000000e-01); p_coeff_13h = double(7.76087253732093085289989176089875400066375732421875000000000000000000000000000000e-01); p_coeff_14h = double(9.92362795771243533238248346606269478797912597656250000000000000000000000000000000e-01); p_coeff_15h = double(1.28020190849177639691447438963223248720169067382812500000000000000000000000000000e+00); p_coeff_16h = double(1.66202082783864191206646410137182101607322692871093750000000000000000000000000000e+00); p_coeff_17h = double(2.17134697355479078240136914246249943971633911132812500000000000000000000000000000e+00); p_coeff_18h = double(2.85144941725608758176235824066679924726486206054687500000000000000000000000000000e+00); p_coeff_19h = double(3.76113082197504100534501958463806658983230590820312500000000000000000000000000000e+00); p_coeff_20h = double(4.98320258065187005058760405518114566802978515625000000000000000000000000000000000e+00); p_coeff_21h = double(6.83567147351494863727339179604314267635345458984375000000000000000000000000000000e+00); p_coeff_22h = double(9.17671174961649249723905086284503340721130371093750000000000000000000000000000000e+00); p_t_1_0h = p_coeff_22h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_21h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_20h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_19h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_18h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_17h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_16h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_15h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0hm = p_coeff_14h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(xh,p_t_17_0hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_13h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_12h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_11h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = mul_rel<102>(xh,p_t_23_0hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = add_rel<102>(p_coeff_10h,p_t_24_0hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = mul_rel<102>(xh,p_t_25_0hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = add_rel<102>(p_coeff_9h,p_t_26_0hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hm = fma_rel<100>(p_t_27_0hm,xh,p_coeff_8hm); p_t_28_0h = double(p_t_28_0hm); p_t_28_0m = p_t_28_0hm - p_t_28_0h; p_t_29_0hm = fma_rel<100>(p_t_28_0hm,xh,p_coeff_7hm); p_t_29_0h = double(p_t_29_0hm); p_t_29_0m = p_t_29_0hm - p_t_29_0h; p_t_30_0hm = fma_rel<100>(p_t_29_0hm,xh,p_coeff_6hm); p_t_30_0h = double(p_t_30_0hm); p_t_30_0m = p_t_30_0hm - p_t_30_0h; p_t_31_0hm = fma_rel<100>(p_t_30_0hm,xh,p_coeff_5hm); p_t_31_0h = double(p_t_31_0hm); p_t_31_0m = p_t_31_0hm - p_t_31_0h; p_t_32_0hm = fma_rel<100>(p_t_31_0hm,xh,p_coeff_4hm); p_t_32_0h = double(p_t_32_0hm); p_t_32_0m = p_t_32_0hm - p_t_32_0h; p_t_33_0hm = fma_rel<100>(p_t_32_0hm,xh,p_coeff_3hm); p_t_33_0h = double(p_t_33_0hm); p_t_33_0m = p_t_33_0hm - p_t_33_0h; p_t_34_0hm = mul_rel<102>(xh,p_t_33_0hm); p_t_34_0h = double(p_t_34_0hm); p_t_34_0m = p_t_34_0hm - p_t_34_0h; p_t_35_0hml = add_rel<140>(p_coeff_2hm,p_t_34_0hm); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_t_36_0hml = mul_rel<145>(xh,p_t_35_0hml); p_t_36_0ml = p_t_36_0hml - p_t_36_0h; p_t_36_0m = double(p_t_36_0ml); p_t_36_0l = p_t_36_0ml - p_t_36_0m; p_t_36_0hm = p_t_36_0h + p_t_36_0m; overlap_p_t_36_0 = p_t_36_0m / p_t_36_0h; p_t_37_0hml = add_rel<143>(p_coeff_1hm,p_t_36_0hml); p_t_37_0ml = p_t_37_0hml - p_t_37_0h; p_t_37_0m = double(p_t_37_0ml); p_t_37_0l = p_t_37_0ml - p_t_37_0m; p_t_37_0hm = p_t_37_0h + p_t_37_0m; overlap_p_t_37_0 = p_t_37_0m / p_t_37_0h; p_t_38_0hml = mul_rel<135>(xh,p_t_37_0hml); p_t_38_0ml = p_t_38_0hml - p_t_38_0h; p_t_38_0m = double(p_t_38_0ml); p_t_38_0l = p_t_38_0ml - p_t_38_0m; p_t_38_0hm = p_t_38_0h + p_t_38_0m; overlap_p_t_38_0 = p_t_38_0m / p_t_38_0h; p_t_39_0hml = add_rel<133>(p_coeff_0hm,p_t_38_0hml); p_t_39_0ml = p_t_39_0hml - p_t_39_0h; p_t_39_0m = double(p_t_39_0ml); p_t_39_0l = p_t_39_0ml - p_t_39_0m; p_t_39_0hm = p_t_39_0h + p_t_39_0m; overlap_p_t_39_0 = p_t_39_0m / p_t_39_0h; p_reshml = p_t_39_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2hm; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_4 = p_coeff_4hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_6 = p_coeff_6hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_8 = p_coeff_8hm; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_14 = p_coeff_14h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_16 = p_coeff_16h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_18 = p_coeff_18h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_20 = p_coeff_20h; Mp_coeff_21 = p_coeff_21h; Mp_coeff_22 = p_coeff_22h; Mp_t_1_0 = Mp_coeff_22; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_21 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_20 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_19 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_18 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_17 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_16 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_15 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_14 + Mp_t_16_0; Mp_t_18_0 = Mx * Mp_t_17_0; Mp_t_19_0 = Mp_coeff_13 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_t_21_0 = Mp_coeff_12 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_11 + Mp_t_22_0; Mp_t_24_0 = Mx * Mp_t_23_0; Mp_t_25_0 = Mp_coeff_10 + Mp_t_24_0; Mp_t_26_0 = Mx * Mp_t_25_0; Mp_t_27_0 = Mp_coeff_9 + Mp_t_26_0; Mp_t_28_0 = (Mp_t_27_0 * Mx) + Mp_coeff_8; Mp_t_29_0 = (Mp_t_28_0 * Mx) + Mp_coeff_7; Mp_t_30_0 = (Mp_t_29_0 * Mx) + Mp_coeff_6; Mp_t_31_0 = (Mp_t_30_0 * Mx) + Mp_coeff_5; Mp_t_32_0 = (Mp_t_31_0 * Mx) + Mp_coeff_4; Mp_t_33_0 = (Mp_t_32_0 * Mx) + Mp_coeff_3; Mp_t_34_0 = Mx * Mp_t_33_0; Mp_t_35_0 = Mp_coeff_2 + Mp_t_34_0; Mp_t_36_0 = Mx * Mp_t_35_0; Mp_t_37_0 = Mp_coeff_1 + Mp_t_36_0; Mp_t_38_0 = Mx * Mp_t_37_0; Mp_t_39_0 = Mp_coeff_0 + Mp_t_38_0; Mp_res = Mp_t_39_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [-466363011288839b-53,-466363011288839b-453] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [932726022577599b-454,932726022577599b-54] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0h ~ p_t_28_0hm; p_t_29_0h ~ p_t_29_0hm; p_t_30_0h ~ p_t_30_0hm; p_t_31_0h ~ p_t_31_0hm; p_t_32_0h ~ p_t_32_0hm; p_t_33_0h ~ p_t_33_0hm; p_t_34_0h ~ p_t_34_0hm; p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_t_36_0hm ~ p_t_36_0hml; p_t_36_0h ~ p_t_36_0hm; p_t_36_0h ~ p_t_36_0hml; p_t_36_0m -> p_t_36_0h * overlap_p_t_36_0; p_t_36_0l / p_t_36_0m -> - ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml) / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)); (p_t_36_0hm - p_t_36_0hml) / p_t_36_0hml -> - (p_t_36_0l / p_t_36_0m) * (1 / (1 / overlap_p_t_36_0 + 1 + (p_t_36_0l / p_t_36_0m))); p_t_36_0ml -> p_t_36_0hml / ((1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) / overlap_p_t_36_0 + 1); (p_t_36_0h - p_t_36_0hm) / p_t_36_0hm -> - 1 / (1 / overlap_p_t_36_0 + 1); p_t_36_0h -> p_t_36_0hml / (overlap_p_t_36_0 / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) + 1); p_t_37_0hm ~ p_t_37_0hml; p_t_37_0h ~ p_t_37_0hm; p_t_37_0h ~ p_t_37_0hml; p_t_37_0m -> p_t_37_0h * overlap_p_t_37_0; p_t_37_0l / p_t_37_0m -> - ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml) / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)); (p_t_37_0hm - p_t_37_0hml) / p_t_37_0hml -> - (p_t_37_0l / p_t_37_0m) * (1 / (1 / overlap_p_t_37_0 + 1 + (p_t_37_0l / p_t_37_0m))); p_t_37_0ml -> p_t_37_0hml / ((1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) / overlap_p_t_37_0 + 1); (p_t_37_0h - p_t_37_0hm) / p_t_37_0hm -> - 1 / (1 / overlap_p_t_37_0 + 1); p_t_37_0h -> p_t_37_0hml / (overlap_p_t_37_0 / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) + 1); p_t_38_0hm ~ p_t_38_0hml; p_t_38_0h ~ p_t_38_0hm; p_t_38_0h ~ p_t_38_0hml; p_t_38_0m -> p_t_38_0h * overlap_p_t_38_0; p_t_38_0l / p_t_38_0m -> - ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml) / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)); (p_t_38_0hm - p_t_38_0hml) / p_t_38_0hml -> - (p_t_38_0l / p_t_38_0m) * (1 / (1 / overlap_p_t_38_0 + 1 + (p_t_38_0l / p_t_38_0m))); p_t_38_0ml -> p_t_38_0hml / ((1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) / overlap_p_t_38_0 + 1); (p_t_38_0h - p_t_38_0hm) / p_t_38_0hm -> - 1 / (1 / overlap_p_t_38_0 + 1); p_t_38_0h -> p_t_38_0hml / (overlap_p_t_38_0 / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) + 1); p_t_39_0hm ~ p_t_39_0hml; p_t_39_0h ~ p_t_39_0hm; p_t_39_0h ~ p_t_39_0hml; p_t_39_0m -> p_t_39_0h * overlap_p_t_39_0; p_t_39_0l / p_t_39_0m -> - ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml) / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)); (p_t_39_0hm - p_t_39_0hml) / p_t_39_0hml -> - (p_t_39_0l / p_t_39_0m) * (1 / (1 / overlap_p_t_39_0 + 1 + (p_t_39_0l / p_t_39_0m))); p_t_39_0ml -> p_t_39_0hml / ((1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) / overlap_p_t_39_0 + 1); (p_t_39_0h - p_t_39_0hm) / p_t_39_0hm -> - 1 / (1 / overlap_p_t_39_0 + 1); p_t_39_0h -> p_t_39_0hml / (overlap_p_t_39_0 / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hm ~ Mp_t_28_0; p_t_29_0hm ~ Mp_t_29_0; p_t_30_0hm ~ Mp_t_30_0; p_t_31_0hm ~ Mp_t_31_0; p_t_32_0hm ~ Mp_t_32_0; p_t_33_0hm ~ Mp_t_33_0; p_t_34_0hm ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_t_36_0hml ~ Mp_t_36_0; p_t_37_0hml ~ Mp_t_37_0; p_t_38_0hml ~ Mp_t_38_0; p_t_39_0hml ~ Mp_t_39_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_t_36_0hml in (0); $ p_t_36_0ml in (0); $ p_t_37_0hml in (0); $ p_t_37_0ml in (0); $ p_t_38_0hml in (0); $ p_t_38_0ml in (0); $ p_t_39_0hml in (0); $ p_t_39_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR2.gappa0000644000000000000000000004740513316017127020526 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 537273513210223274716288889248434731b-120 + (x * (88240263986999722252297847012357b-106 + (x * (20526577571859871112569155652563b-106 + (x * (107789892750625855992013313785105b-108 + (x * (95062093602682177187811187465689b-108 + (x * (477193384067815679840324642654849b-110 + (x * (572921965627724688446677452418063b-110 + (x * (188719174585036872257517150346289b-108 + (x * (15724977217398503074240774828841b-104 + (x * (4815943101116825b-52 + (x * (3373125240821569b-51 + (x * (4808226395402763b-51 + (x * (3468851253814359b-50 + (x * (5061210136901323b-50 + (x * (7451575477138987b-50 + (x * (5529276895184587b-49 + (x * (8262038822452853b-49 + (x * (6210057040978841b-48 + (x * (4692590307258443b-47 + (x * (3562757466383109b-46 + (x * (2717503836213503b-45 + (x * (8416477620649297b-46 + (x * 396224776159005b-41))))))))))))))))))))))))))))))))))))))))))) # The polynomial implemented is: 537273513210223274716288889248434731b-120 + (x * (88240263986999722252297847012357b-106 + (x * (20526577571859871112569155652563b-106 + (x * (107789892750625855992013313785105b-108 + (x * (95062093602682177187811187465689b-108 + (x * (477193384067815679840324642654849b-110 + (x * (572921965627724688446677452418063b-110 + (x * (188719174585036872257517150346289b-108 + (x * (15724977217398503074240774828841b-104 + (x * (4815943101116825b-52 + (x * (3373125240821569b-51 + (x * (4808226395402763b-51 + (x * (3468851253814359b-50 + (x * (5061210136901323b-50 + (x * (7451575477138987b-50 + (x * (5529276895184587b-49 + (x * (8262038822452853b-49 + (x * (6210057040978841b-48 + (x * (4692590307258443b-47 + (x * (3562757466383109b-46 + (x * (2717503836213503b-45 + (x * (8416477620649297b-46 + (x * 396224776159005b-41))))))))))))))))))))))))))))))))))))))))))) # The domain is [-715705849514187b-54;178926462378499b-52] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 63 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(4.04199666960039116769820566332782618701457977294921875000000000000000000000000000e-01); p_coeff_0m = double(-6.46825370068901234687011200856515476665908008275043725957432344531028434175823350e-21); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.08764522696446319649510314775398001074790954589843750000000000000000000000000000e+00); p_coeff_1m = double(7.20122509204450857334003577729908463703780203035882678808121681868215091526508331e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(2.53009602569167157959384439891437068581581115722656250000000000000000000000000000e-01); p_coeff_2m = double(-2.62855515233500204494953653812414612827096270443634484781370019845780916512012482e-17); p_coeff_2hm = p_coeff_2h + p_coeff_2m; p_coeff_3h = double(3.32153251441150376699340540653793141245841979980468750000000000000000000000000000e-01); p_coeff_3m = double(-2.17141385535786665092496720426544052591009587195721927677105611564911669120192528e-17); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_4h = double(2.92932692232876656923679092869861051440238952636718750000000000000000000000000000e-01); p_coeff_4m = double(-2.54506532782342113657805222827712812531223364242776927013345300565561046823859215e-17); p_coeff_4hm = p_coeff_4h + p_coeff_4m; p_coeff_5h = double(3.67616411055874059421455513074761256575584411621093750000000000000000000000000000e-01); p_coeff_5m = double(-6.76970835849273256879417289105284614692988316998734608931354017613557516597211361e-18); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_6h = double(4.41363027759851866971274603201891295611858367919921875000000000000000000000000000e-01); p_coeff_6m = double(-2.90651996480231385490406350336172813253854649135862232844917940610685036517679691e-18); p_coeff_6hm = p_coeff_6h + p_coeff_6m; p_coeff_7h = double(5.81535855061384165942683921457501128315925598144531250000000000000000000000000000e-01); p_coeff_7m = double(2.15506151894707480118506866417280461854749969158187919426872269923478597775101662e-17); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_8h = double(7.75301235143548206352193119528237730264663696289062500000000000000000000000000000e-01); p_coeff_8m = double(-5.09980429509694427469186543286592667631136122693286116813737862685229629278182983e-17); p_coeff_8hm = p_coeff_8h + p_coeff_8m; p_coeff_9h = double(1.06935418322891551135001009242841973900794982910156250000000000000000000000000000e+00); p_coeff_10h = double(1.49796852292175275422891900234390050172805786132812500000000000000000000000000000e+00); p_coeff_11h = double(2.13528146071462776589555687678512185811996459960937500000000000000000000000000000e+00); p_coeff_12h = double(3.08095882478763538614430217421613633632659912109375000000000000000000000000000000e+00); p_coeff_13h = double(4.49525762116327154416239864076487720012664794921875000000000000000000000000000000e+00); p_coeff_14h = double(6.61832853156151212914437564904801547527313232421875000000000000000000000000000000e+00); p_coeff_15h = double(9.82196882969892293147040618350729346275329589843750000000000000000000000000000000e+00); p_coeff_16h = double(1.46763291696545170594845330924727022647857666015625000000000000000000000000000000e+01); p_coeff_17h = double(2.20625545956168913619421800831332802772521972656250000000000000000000000000000000e+01); p_coeff_18h = double(3.33428595472074320582578366156667470932006835937500000000000000000000000000000000e+01); p_coeff_19h = double(5.06298287402715487814930384047329425811767578125000000000000000000000000000000000e+01); p_coeff_20h = double(7.72361044088683854624832747504115104675292968750000000000000000000000000000000000e+01); p_coeff_21h = double(1.19605340680796203400859667453914880752563476562500000000000000000000000000000000e+02); p_coeff_22h = double(1.80182167313889749493682757019996643066406250000000000000000000000000000000000000e+02); p_t_1_0h = p_coeff_22h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_21h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_20h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_19h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_18h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_17h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_16h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_15h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0hm = p_coeff_14h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(xh,p_t_17_0hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_13h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_12h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_11h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = mul_rel<102>(xh,p_t_23_0hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = add_rel<102>(p_coeff_10h,p_t_24_0hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = mul_rel<102>(xh,p_t_25_0hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = add_rel<102>(p_coeff_9h,p_t_26_0hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hm = fma_rel<100>(p_t_27_0hm,xh,p_coeff_8hm); p_t_28_0h = double(p_t_28_0hm); p_t_28_0m = p_t_28_0hm - p_t_28_0h; p_t_29_0hm = fma_rel<100>(p_t_28_0hm,xh,p_coeff_7hm); p_t_29_0h = double(p_t_29_0hm); p_t_29_0m = p_t_29_0hm - p_t_29_0h; p_t_30_0hm = fma_rel<100>(p_t_29_0hm,xh,p_coeff_6hm); p_t_30_0h = double(p_t_30_0hm); p_t_30_0m = p_t_30_0hm - p_t_30_0h; p_t_31_0hm = fma_rel<100>(p_t_30_0hm,xh,p_coeff_5hm); p_t_31_0h = double(p_t_31_0hm); p_t_31_0m = p_t_31_0hm - p_t_31_0h; p_t_32_0hm = fma_rel<100>(p_t_31_0hm,xh,p_coeff_4hm); p_t_32_0h = double(p_t_32_0hm); p_t_32_0m = p_t_32_0hm - p_t_32_0h; p_t_33_0hm = fma_rel<100>(p_t_32_0hm,xh,p_coeff_3hm); p_t_33_0h = double(p_t_33_0hm); p_t_33_0m = p_t_33_0hm - p_t_33_0h; p_t_34_0hm = mul_rel<102>(xh,p_t_33_0hm); p_t_34_0h = double(p_t_34_0hm); p_t_34_0m = p_t_34_0hm - p_t_34_0h; p_t_35_0hml = add_rel<140>(p_coeff_2hm,p_t_34_0hm); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_t_36_0hml = mul_rel<145>(xh,p_t_35_0hml); p_t_36_0ml = p_t_36_0hml - p_t_36_0h; p_t_36_0m = double(p_t_36_0ml); p_t_36_0l = p_t_36_0ml - p_t_36_0m; p_t_36_0hm = p_t_36_0h + p_t_36_0m; overlap_p_t_36_0 = p_t_36_0m / p_t_36_0h; p_t_37_0hml = add_rel<143>(p_coeff_1hm,p_t_36_0hml); p_t_37_0ml = p_t_37_0hml - p_t_37_0h; p_t_37_0m = double(p_t_37_0ml); p_t_37_0l = p_t_37_0ml - p_t_37_0m; p_t_37_0hm = p_t_37_0h + p_t_37_0m; overlap_p_t_37_0 = p_t_37_0m / p_t_37_0h; p_t_38_0hml = mul_rel<135>(xh,p_t_37_0hml); p_t_38_0ml = p_t_38_0hml - p_t_38_0h; p_t_38_0m = double(p_t_38_0ml); p_t_38_0l = p_t_38_0ml - p_t_38_0m; p_t_38_0hm = p_t_38_0h + p_t_38_0m; overlap_p_t_38_0 = p_t_38_0m / p_t_38_0h; p_t_39_0hml = add_rel<133>(p_coeff_0hm,p_t_38_0hml); p_t_39_0ml = p_t_39_0hml - p_t_39_0h; p_t_39_0m = double(p_t_39_0ml); p_t_39_0l = p_t_39_0ml - p_t_39_0m; p_t_39_0hm = p_t_39_0h + p_t_39_0m; overlap_p_t_39_0 = p_t_39_0m / p_t_39_0h; p_reshml = p_t_39_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2hm; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_4 = p_coeff_4hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_6 = p_coeff_6hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_8 = p_coeff_8hm; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_14 = p_coeff_14h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_16 = p_coeff_16h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_18 = p_coeff_18h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_20 = p_coeff_20h; Mp_coeff_21 = p_coeff_21h; Mp_coeff_22 = p_coeff_22h; Mp_t_1_0 = Mp_coeff_22; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_21 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_20 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_19 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_18 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_17 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_16 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_15 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_14 + Mp_t_16_0; Mp_t_18_0 = Mx * Mp_t_17_0; Mp_t_19_0 = Mp_coeff_13 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_t_21_0 = Mp_coeff_12 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_11 + Mp_t_22_0; Mp_t_24_0 = Mx * Mp_t_23_0; Mp_t_25_0 = Mp_coeff_10 + Mp_t_24_0; Mp_t_26_0 = Mx * Mp_t_25_0; Mp_t_27_0 = Mp_coeff_9 + Mp_t_26_0; Mp_t_28_0 = (Mp_t_27_0 * Mx) + Mp_coeff_8; Mp_t_29_0 = (Mp_t_28_0 * Mx) + Mp_coeff_7; Mp_t_30_0 = (Mp_t_29_0 * Mx) + Mp_coeff_6; Mp_t_31_0 = (Mp_t_30_0 * Mx) + Mp_coeff_5; Mp_t_32_0 = (Mp_t_31_0 * Mx) + Mp_coeff_4; Mp_t_33_0 = (Mp_t_32_0 * Mx) + Mp_coeff_3; Mp_t_34_0 = Mx * Mp_t_33_0; Mp_t_35_0 = Mp_coeff_2 + Mp_t_34_0; Mp_t_36_0 = Mx * Mp_t_35_0; Mp_t_37_0 = Mp_coeff_1 + Mp_t_36_0; Mp_t_38_0 = Mx * Mp_t_37_0; Mp_t_39_0 = Mp_coeff_0 + Mp_t_38_0; Mp_res = Mp_t_39_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [-715705849514187b-54,-715705849514187b-454] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [178926462378499b-452,178926462378499b-52] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0h ~ p_t_28_0hm; p_t_29_0h ~ p_t_29_0hm; p_t_30_0h ~ p_t_30_0hm; p_t_31_0h ~ p_t_31_0hm; p_t_32_0h ~ p_t_32_0hm; p_t_33_0h ~ p_t_33_0hm; p_t_34_0h ~ p_t_34_0hm; p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_t_36_0hm ~ p_t_36_0hml; p_t_36_0h ~ p_t_36_0hm; p_t_36_0h ~ p_t_36_0hml; p_t_36_0m -> p_t_36_0h * overlap_p_t_36_0; p_t_36_0l / p_t_36_0m -> - ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml) / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)); (p_t_36_0hm - p_t_36_0hml) / p_t_36_0hml -> - (p_t_36_0l / p_t_36_0m) * (1 / (1 / overlap_p_t_36_0 + 1 + (p_t_36_0l / p_t_36_0m))); p_t_36_0ml -> p_t_36_0hml / ((1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) / overlap_p_t_36_0 + 1); (p_t_36_0h - p_t_36_0hm) / p_t_36_0hm -> - 1 / (1 / overlap_p_t_36_0 + 1); p_t_36_0h -> p_t_36_0hml / (overlap_p_t_36_0 / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) + 1); p_t_37_0hm ~ p_t_37_0hml; p_t_37_0h ~ p_t_37_0hm; p_t_37_0h ~ p_t_37_0hml; p_t_37_0m -> p_t_37_0h * overlap_p_t_37_0; p_t_37_0l / p_t_37_0m -> - ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml) / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)); (p_t_37_0hm - p_t_37_0hml) / p_t_37_0hml -> - (p_t_37_0l / p_t_37_0m) * (1 / (1 / overlap_p_t_37_0 + 1 + (p_t_37_0l / p_t_37_0m))); p_t_37_0ml -> p_t_37_0hml / ((1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) / overlap_p_t_37_0 + 1); (p_t_37_0h - p_t_37_0hm) / p_t_37_0hm -> - 1 / (1 / overlap_p_t_37_0 + 1); p_t_37_0h -> p_t_37_0hml / (overlap_p_t_37_0 / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) + 1); p_t_38_0hm ~ p_t_38_0hml; p_t_38_0h ~ p_t_38_0hm; p_t_38_0h ~ p_t_38_0hml; p_t_38_0m -> p_t_38_0h * overlap_p_t_38_0; p_t_38_0l / p_t_38_0m -> - ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml) / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)); (p_t_38_0hm - p_t_38_0hml) / p_t_38_0hml -> - (p_t_38_0l / p_t_38_0m) * (1 / (1 / overlap_p_t_38_0 + 1 + (p_t_38_0l / p_t_38_0m))); p_t_38_0ml -> p_t_38_0hml / ((1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) / overlap_p_t_38_0 + 1); (p_t_38_0h - p_t_38_0hm) / p_t_38_0hm -> - 1 / (1 / overlap_p_t_38_0 + 1); p_t_38_0h -> p_t_38_0hml / (overlap_p_t_38_0 / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) + 1); p_t_39_0hm ~ p_t_39_0hml; p_t_39_0h ~ p_t_39_0hm; p_t_39_0h ~ p_t_39_0hml; p_t_39_0m -> p_t_39_0h * overlap_p_t_39_0; p_t_39_0l / p_t_39_0m -> - ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml) / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)); (p_t_39_0hm - p_t_39_0hml) / p_t_39_0hml -> - (p_t_39_0l / p_t_39_0m) * (1 / (1 / overlap_p_t_39_0 + 1 + (p_t_39_0l / p_t_39_0m))); p_t_39_0ml -> p_t_39_0hml / ((1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) / overlap_p_t_39_0 + 1); (p_t_39_0h - p_t_39_0hm) / p_t_39_0hm -> - 1 / (1 / overlap_p_t_39_0 + 1); p_t_39_0h -> p_t_39_0hml / (overlap_p_t_39_0 / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hm ~ Mp_t_28_0; p_t_29_0hm ~ Mp_t_29_0; p_t_30_0hm ~ Mp_t_30_0; p_t_31_0hm ~ Mp_t_31_0; p_t_32_0hm ~ Mp_t_32_0; p_t_33_0hm ~ Mp_t_33_0; p_t_34_0hm ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_t_36_0hml ~ Mp_t_36_0; p_t_37_0hml ~ Mp_t_37_0; p_t_38_0hml ~ Mp_t_38_0; p_t_39_0hml ~ Mp_t_39_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_t_36_0hml in (0); $ p_t_36_0ml in (0); $ p_t_37_0hml in (0); $ p_t_37_0ml in (0); $ p_t_38_0hml in (0); $ p_t_38_0ml in (0); $ p_t_39_0hml in (0); $ p_t_39_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR3.gappa0000644000000000000000000004737613316017127020536 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 630003272697881842134216252575451b-110 + (x * (91721878242709939892136825593527b-106 + (x * (218764722243419548644270705008141b-109 + (x * (143378738160791311151825186528399b-108 + (x * (306937566524655010129262065785625b-109 + (x * (105290255794522793027813910838891b-107 + (x * (292962667643541176300211307509459b-108 + (x * (54339736079161771142781818307313b-105 + (x * (20685535281765286913304275534467b-103 + (x * (7188477576369723b-51 + (x * (2865361488246401b-49 + (x * (2321271569119023b-48 + (x * (7618929984112671b-49 + (x * (6320068526567569b-48 + (x * (5290960389084703b-47 + (x * (8929200830189797b-47 + (x * (3793264268211083b-45 + (x * (6484707195893555b-45 + (x * (1393124273330901b-42 + (x * (4811689001485343b-43 + (x * (1043673078480581b-40 + (x * (7315064190991621b-42 + (x * 6179384798482871b-41))))))))))))))))))))))))))))))))))))))))))) # The polynomial implemented is: 630003272697881842134216252575451b-110 + (x * (91721878242709939892136825593527b-106 + (x * (218764722243419548644270705008141b-109 + (x * (143378738160791311151825186528399b-108 + (x * (306937566524655010129262065785625b-109 + (x * (105290255794522793027813910838891b-107 + (x * (292962667643541176300211307509459b-108 + (x * (54339736079161771142781818307313b-105 + (x * (20685535281765286913304275534467b-103 + (x * (7188477576369723b-51 + (x * (2865361488246401b-49 + (x * (2321271569119023b-48 + (x * (7618929984112671b-49 + (x * (6320068526567569b-48 + (x * (5290960389084703b-47 + (x * (8929200830189797b-47 + (x * (3793264268211083b-45 + (x * (6484707195893555b-45 + (x * (1393124273330901b-42 + (x * (4811689001485343b-43 + (x * (1043673078480581b-40 + (x * (7315064190991621b-42 + (x * 6179384798482871b-41))))))))))))))))))))))))))))))))))))))))))) # The domain is [-603367941593347b-54;301683970796841b-53] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 63 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(4.85336867180323261461438733022077940404415130615234375000000000000000000000000000e-01); p_coeff_0m = double(2.48711731548431450339898686061161136444646421020973452165048200868113781325519085e-18); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.13055943592368102201817237073555588722229003906250000000000000000000000000000000e+00); p_coeff_1m = double(8.33253077521152707672020411779329031688034814541986283753516318029141984879970551e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(3.37060423475326498277127029723487794399261474609375000000000000000000000000000000e-01); p_coeff_2m = double(-1.06567668725757610844479862637418971752325776427227331522029629695680341683328152e-17); p_coeff_2hm = p_coeff_2h + p_coeff_2m; p_coeff_3h = double(4.41819848339719767338351630314718931913375854492187500000000000000000000000000000e-01); p_coeff_3m = double(1.00442163349492148002936541754087371062381994416120786772772532913222676143050194e-17); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_4h = double(4.72912200341745858622743980959057807922363281250000000000000000000000000000000000e-01); p_coeff_4m = double(4.32579192702017095690398912101462577298397752038590716172627992364141391590237617e-18); p_coeff_4hm = p_coeff_4h + p_coeff_4m; p_coeff_5h = double(6.48901300757961929654982213833136484026908874511718750000000000000000000000000000e-01); p_coeff_5m = double(5.53173550473638312502352924376368778723557407693469517573348070982319768518209457e-17); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_6h = double(9.02760918723618410730580308154458180069923400878906250000000000000000000000000000e-01); p_coeff_6m = double(1.83127184204758972652773042458306136013081307308989972848500826785311801359057426e-17); p_coeff_6hm = p_coeff_6h + p_coeff_6m; p_coeff_7h = double(1.33957791852745100591448590421350672841072082519531250000000000000000000000000000e+00); p_coeff_7m = double(-8.08660441258249393782142982707336982340679568071958871477988850529072806239128113e-17); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_8h = double(2.03975126091931757699171612330246716737747192382812500000000000000000000000000000e+00); p_coeff_8m = double(1.39326386720348649025304457272644525059897659732127683795965822355356067419052124e-16); p_coeff_8hm = p_coeff_8h + p_coeff_8m; p_coeff_9h = double(3.19232532691492343346340021525975316762924194335937500000000000000000000000000000e+00); p_coeff_10h = double(5.08990447700057480062696413369849324226379394531250000000000000000000000000000000e+00); p_coeff_11h = double(8.24681325581985547046315332408994436264038085937500000000000000000000000000000000e+00); p_coeff_12h = double(1.35339383861901847438957702252082526683807373046875000000000000000000000000000000e+01); p_coeff_13h = double(2.24533939052931295066173333907499909400939941406250000000000000000000000000000000e+01); p_coeff_14h = double(3.75945346965856899146274372469633817672729492187500000000000000000000000000000000e+01); p_coeff_15h = double(6.34457878603441614018265681806951761245727539062500000000000000000000000000000000e+01); p_coeff_16h = double(1.07811054823829493898301734589040279388427734375000000000000000000000000000000000e+02); p_coeff_17h = double(1.84306463662936579339657328091561794281005859375000000000000000000000000000000000e+02); p_coeff_18h = double(3.16759786376428792209480889141559600830078125000000000000000000000000000000000000e+02); p_coeff_19h = double(5.47025706678748861122585367411375045776367187500000000000000000000000000000000000e+02); p_coeff_20h = double(9.49215135261129944410640746355056762695312500000000000000000000000000000000000000e+02); p_coeff_21h = double(1.66325303120893772756971884518861770629882812500000000000000000000000000000000000e+03); p_coeff_22h = double(2.81005886721817250872845761477947235107421875000000000000000000000000000000000000e+03); p_t_1_0h = p_coeff_22h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_21h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_20h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_19h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_18h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_17h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_16h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_15h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0hm = p_coeff_14h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(xh,p_t_17_0hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_13h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_12h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_11h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = mul_rel<102>(xh,p_t_23_0hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = add_rel<102>(p_coeff_10h,p_t_24_0hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = mul_rel<102>(xh,p_t_25_0hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = add_rel<102>(p_coeff_9h,p_t_26_0hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hm = fma_rel<100>(p_t_27_0hm,xh,p_coeff_8hm); p_t_28_0h = double(p_t_28_0hm); p_t_28_0m = p_t_28_0hm - p_t_28_0h; p_t_29_0hm = fma_rel<100>(p_t_28_0hm,xh,p_coeff_7hm); p_t_29_0h = double(p_t_29_0hm); p_t_29_0m = p_t_29_0hm - p_t_29_0h; p_t_30_0hm = fma_rel<100>(p_t_29_0hm,xh,p_coeff_6hm); p_t_30_0h = double(p_t_30_0hm); p_t_30_0m = p_t_30_0hm - p_t_30_0h; p_t_31_0hm = fma_rel<100>(p_t_30_0hm,xh,p_coeff_5hm); p_t_31_0h = double(p_t_31_0hm); p_t_31_0m = p_t_31_0hm - p_t_31_0h; p_t_32_0hm = fma_rel<100>(p_t_31_0hm,xh,p_coeff_4hm); p_t_32_0h = double(p_t_32_0hm); p_t_32_0m = p_t_32_0hm - p_t_32_0h; p_t_33_0hm = fma_rel<100>(p_t_32_0hm,xh,p_coeff_3hm); p_t_33_0h = double(p_t_33_0hm); p_t_33_0m = p_t_33_0hm - p_t_33_0h; p_t_34_0hm = mul_rel<102>(xh,p_t_33_0hm); p_t_34_0h = double(p_t_34_0hm); p_t_34_0m = p_t_34_0hm - p_t_34_0h; p_t_35_0hml = add_rel<140>(p_coeff_2hm,p_t_34_0hm); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_t_36_0hml = mul_rel<145>(xh,p_t_35_0hml); p_t_36_0ml = p_t_36_0hml - p_t_36_0h; p_t_36_0m = double(p_t_36_0ml); p_t_36_0l = p_t_36_0ml - p_t_36_0m; p_t_36_0hm = p_t_36_0h + p_t_36_0m; overlap_p_t_36_0 = p_t_36_0m / p_t_36_0h; p_t_37_0hml = add_rel<143>(p_coeff_1hm,p_t_36_0hml); p_t_37_0ml = p_t_37_0hml - p_t_37_0h; p_t_37_0m = double(p_t_37_0ml); p_t_37_0l = p_t_37_0ml - p_t_37_0m; p_t_37_0hm = p_t_37_0h + p_t_37_0m; overlap_p_t_37_0 = p_t_37_0m / p_t_37_0h; p_t_38_0hml = mul_rel<135>(xh,p_t_37_0hml); p_t_38_0ml = p_t_38_0hml - p_t_38_0h; p_t_38_0m = double(p_t_38_0ml); p_t_38_0l = p_t_38_0ml - p_t_38_0m; p_t_38_0hm = p_t_38_0h + p_t_38_0m; overlap_p_t_38_0 = p_t_38_0m / p_t_38_0h; p_t_39_0hml = add_rel<133>(p_coeff_0hm,p_t_38_0hml); p_t_39_0ml = p_t_39_0hml - p_t_39_0h; p_t_39_0m = double(p_t_39_0ml); p_t_39_0l = p_t_39_0ml - p_t_39_0m; p_t_39_0hm = p_t_39_0h + p_t_39_0m; overlap_p_t_39_0 = p_t_39_0m / p_t_39_0h; p_reshml = p_t_39_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2hm; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_4 = p_coeff_4hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_6 = p_coeff_6hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_8 = p_coeff_8hm; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_14 = p_coeff_14h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_16 = p_coeff_16h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_18 = p_coeff_18h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_20 = p_coeff_20h; Mp_coeff_21 = p_coeff_21h; Mp_coeff_22 = p_coeff_22h; Mp_t_1_0 = Mp_coeff_22; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_21 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_20 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_19 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_18 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_17 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_16 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_15 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_14 + Mp_t_16_0; Mp_t_18_0 = Mx * Mp_t_17_0; Mp_t_19_0 = Mp_coeff_13 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_t_21_0 = Mp_coeff_12 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_11 + Mp_t_22_0; Mp_t_24_0 = Mx * Mp_t_23_0; Mp_t_25_0 = Mp_coeff_10 + Mp_t_24_0; Mp_t_26_0 = Mx * Mp_t_25_0; Mp_t_27_0 = Mp_coeff_9 + Mp_t_26_0; Mp_t_28_0 = (Mp_t_27_0 * Mx) + Mp_coeff_8; Mp_t_29_0 = (Mp_t_28_0 * Mx) + Mp_coeff_7; Mp_t_30_0 = (Mp_t_29_0 * Mx) + Mp_coeff_6; Mp_t_31_0 = (Mp_t_30_0 * Mx) + Mp_coeff_5; Mp_t_32_0 = (Mp_t_31_0 * Mx) + Mp_coeff_4; Mp_t_33_0 = (Mp_t_32_0 * Mx) + Mp_coeff_3; Mp_t_34_0 = Mx * Mp_t_33_0; Mp_t_35_0 = Mp_coeff_2 + Mp_t_34_0; Mp_t_36_0 = Mx * Mp_t_35_0; Mp_t_37_0 = Mp_coeff_1 + Mp_t_36_0; Mp_t_38_0 = Mx * Mp_t_37_0; Mp_t_39_0 = Mp_coeff_0 + Mp_t_38_0; Mp_res = Mp_t_39_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [-603367941593347b-54,-603367941593347b-454] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [301683970796841b-453,301683970796841b-53] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0h ~ p_t_28_0hm; p_t_29_0h ~ p_t_29_0hm; p_t_30_0h ~ p_t_30_0hm; p_t_31_0h ~ p_t_31_0hm; p_t_32_0h ~ p_t_32_0hm; p_t_33_0h ~ p_t_33_0hm; p_t_34_0h ~ p_t_34_0hm; p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_t_36_0hm ~ p_t_36_0hml; p_t_36_0h ~ p_t_36_0hm; p_t_36_0h ~ p_t_36_0hml; p_t_36_0m -> p_t_36_0h * overlap_p_t_36_0; p_t_36_0l / p_t_36_0m -> - ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml) / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)); (p_t_36_0hm - p_t_36_0hml) / p_t_36_0hml -> - (p_t_36_0l / p_t_36_0m) * (1 / (1 / overlap_p_t_36_0 + 1 + (p_t_36_0l / p_t_36_0m))); p_t_36_0ml -> p_t_36_0hml / ((1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) / overlap_p_t_36_0 + 1); (p_t_36_0h - p_t_36_0hm) / p_t_36_0hm -> - 1 / (1 / overlap_p_t_36_0 + 1); p_t_36_0h -> p_t_36_0hml / (overlap_p_t_36_0 / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) + 1); p_t_37_0hm ~ p_t_37_0hml; p_t_37_0h ~ p_t_37_0hm; p_t_37_0h ~ p_t_37_0hml; p_t_37_0m -> p_t_37_0h * overlap_p_t_37_0; p_t_37_0l / p_t_37_0m -> - ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml) / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)); (p_t_37_0hm - p_t_37_0hml) / p_t_37_0hml -> - (p_t_37_0l / p_t_37_0m) * (1 / (1 / overlap_p_t_37_0 + 1 + (p_t_37_0l / p_t_37_0m))); p_t_37_0ml -> p_t_37_0hml / ((1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) / overlap_p_t_37_0 + 1); (p_t_37_0h - p_t_37_0hm) / p_t_37_0hm -> - 1 / (1 / overlap_p_t_37_0 + 1); p_t_37_0h -> p_t_37_0hml / (overlap_p_t_37_0 / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) + 1); p_t_38_0hm ~ p_t_38_0hml; p_t_38_0h ~ p_t_38_0hm; p_t_38_0h ~ p_t_38_0hml; p_t_38_0m -> p_t_38_0h * overlap_p_t_38_0; p_t_38_0l / p_t_38_0m -> - ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml) / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)); (p_t_38_0hm - p_t_38_0hml) / p_t_38_0hml -> - (p_t_38_0l / p_t_38_0m) * (1 / (1 / overlap_p_t_38_0 + 1 + (p_t_38_0l / p_t_38_0m))); p_t_38_0ml -> p_t_38_0hml / ((1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) / overlap_p_t_38_0 + 1); (p_t_38_0h - p_t_38_0hm) / p_t_38_0hm -> - 1 / (1 / overlap_p_t_38_0 + 1); p_t_38_0h -> p_t_38_0hml / (overlap_p_t_38_0 / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) + 1); p_t_39_0hm ~ p_t_39_0hml; p_t_39_0h ~ p_t_39_0hm; p_t_39_0h ~ p_t_39_0hml; p_t_39_0m -> p_t_39_0h * overlap_p_t_39_0; p_t_39_0l / p_t_39_0m -> - ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml) / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)); (p_t_39_0hm - p_t_39_0hml) / p_t_39_0hml -> - (p_t_39_0l / p_t_39_0m) * (1 / (1 / overlap_p_t_39_0 + 1 + (p_t_39_0l / p_t_39_0m))); p_t_39_0ml -> p_t_39_0hml / ((1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) / overlap_p_t_39_0 + 1); (p_t_39_0h - p_t_39_0hm) / p_t_39_0hm -> - 1 / (1 / overlap_p_t_39_0 + 1); p_t_39_0h -> p_t_39_0hml / (overlap_p_t_39_0 / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hm ~ Mp_t_28_0; p_t_29_0hm ~ Mp_t_29_0; p_t_30_0hm ~ Mp_t_30_0; p_t_31_0hm ~ Mp_t_31_0; p_t_32_0hm ~ Mp_t_32_0; p_t_33_0hm ~ Mp_t_33_0; p_t_34_0hm ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_t_36_0hml ~ Mp_t_36_0; p_t_37_0hml ~ Mp_t_37_0; p_t_38_0hml ~ Mp_t_38_0; p_t_39_0hml ~ Mp_t_39_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_t_36_0hml in (0); $ p_t_36_0ml in (0); $ p_t_37_0hml in (0); $ p_t_37_0ml in (0); $ p_t_38_0hml in (0); $ p_t_38_0ml in (0); $ p_t_39_0hml in (0); $ p_t_39_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR4.gappa0000644000000000000000000004736713316017127020537 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 23179288235074235572414273684753507b-115 + (x * (3060396379323915655525965395989715b-111 + (x * (140743048026270511662877904535769b-108 + (x * (192160797867958272369452195721767b-108 + (x * (60484226630360230815207732200825b-106 + (x * (92348318688015868651166719352511b-106 + (x * (36688451231400427366893071297149b-104 + (x * (61518808568240203990282236793039b-104 + (x * (13291614381561738069979153918799b-101 + (x * (2617096155665713b-48 + (x * (591488490579095b-45 + (x * (2173007049277499b-46 + (x * (8087008738508987b-47 + (x * (1901529448151669b-44 + (x * (902491660970179b-42 + (x * (863474430653389b-41 + (x * (6654746176145717b-43 + (x * (6449723213208583b-42 + (x * (6284418716064433b-41 + (x * (3077265176489673b-39 + (x * (3027664741461211b-38 + (x * (370529235053615b-34 + (x * 5644104751496821b-37))))))))))))))))))))))))))))))))))))))))))) # The polynomial implemented is: 23179288235074235572414273684753507b-115 + (x * (3060396379323915655525965395989715b-111 + (x * (140743048026270511662877904535769b-108 + (x * (192160797867958272369452195721767b-108 + (x * (60484226630360230815207732200825b-106 + (x * (92348318688015868651166719352511b-106 + (x * (36688451231400427366893071297149b-104 + (x * (61518808568240203990282236793039b-104 + (x * (13291614381561738069979153918799b-101 + (x * (2617096155665713b-48 + (x * (591488490579095b-45 + (x * (2173007049277499b-46 + (x * (8087008738508987b-47 + (x * (1901529448151669b-44 + (x * (902491660970179b-42 + (x * (863474430653389b-41 + (x * (6654746176145717b-43 + (x * (6449723213208583b-42 + (x * (6284418716064433b-41 + (x * (3077265176489673b-39 + (x * (3027664741461211b-38 + (x * (370529235053615b-34 + (x * 5644104751496821b-37))))))))))))))))))))))))))))))))))))))))))) # The domain is [-66447228468955b-51;265788913875259b-53] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 63 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(5.58021066268902909968119274708442389965057373046875000000000000000000000000000000e-01); p_coeff_0m = double(9.14056635248981946291334736807400951779846267656755277007663007537985322414897382e-20); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.17882180572684136521388609253335744142532348632812500000000000000000000000000000e+00); p_coeff_1m = double(2.57506761959083747975269601591872190204330911429892510960959484123122820165008307e-18); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(4.33698001053000381510571514809271320700645446777343750000000000000000000000000000e-01); p_coeff_2m = double(-1.13987489167043526825762332057111190978471845558278249810335580605169525370001793e-17); p_coeff_2hm = p_coeff_2h + p_coeff_2m; p_coeff_3h = double(5.92141175601989977472783266421174630522727966308593750000000000000000000000000000e-01); p_coeff_3m = double(1.51434599074934130528344780896022003291074232766760462864930047999223461374640465e-17); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_4h = double(7.45525652675293803994804875401314347982406616210937500000000000000000000000000000e-01); p_coeff_4m = double(-4.95666529120828261720386639182573717908098482969568576717023233868530951440334320e-17); p_coeff_4hm = p_coeff_4h + p_coeff_4m; p_coeff_5h = double(1.13828091056041680317889586149249225854873657226562500000000000000000000000000000e+00); p_coeff_5m = double(6.30476130024642952826684347359752494928069360322596403900519135277136228978633881e-17); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_6h = double(1.80888030309746783430568939365912228822708129882812500000000000000000000000000000e+00); p_coeff_6m = double(6.53471855925770582546264336577217040248932212759963578108113324560690671205520630e-17); p_coeff_6hm = p_coeff_6h + p_coeff_6m; p_coeff_7h = double(3.03311143845375674743536364985629916191101074218750000000000000000000000000000000e+00); p_coeff_7m = double(-2.14585117370534459252749227343052173552538040022033549725222201232099905610084534e-16); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_8h = double(5.24261747644370590393236852833069860935211181640625000000000000000000000000000000e+00); p_coeff_8m = double(-5.46512862978737750269761176067830595023185492192796530730447557289153337478637695e-17); p_coeff_8hm = p_coeff_8h + p_coeff_8m; p_coeff_9h = double(9.29779331096978367554584110621362924575805664062500000000000000000000000000000000e+00); p_coeff_10h = double(1.68111140106672962701850337907671928405761718750000000000000000000000000000000000e+01); p_coeff_11h = double(3.08802874723923395094971056096255779266357421875000000000000000000000000000000000e+01); p_coeff_12h = double(5.74616531317601229034153220709413290023803710937500000000000000000000000000000000e+01); p_coeff_13h = double(1.08089434897446437844337197020649909973144531250000000000000000000000000000000000e+02); p_coeff_14h = double(2.05202846011656902192044071853160858154296875000000000000000000000000000000000000e+02); p_coeff_15h = double(3.92662709897826516680652275681495666503906250000000000000000000000000000000000000e+02); p_coeff_16h = double(7.56557048606022931380721274763345718383789062500000000000000000000000000000000000e+02); p_coeff_17h = double(1.46649727257876816111092921346426010131835937500000000000000000000000000000000000e+03); p_coeff_18h = double(2.85782276299161503629875369369983673095703125000000000000000000000000000000000000e+03); p_coeff_19h = double(5.59751274793538505036849528551101684570312500000000000000000000000000000000000000e+03); p_coeff_20h = double(1.10145801644146959006320685148239135742187500000000000000000000000000000000000000e+04); p_coeff_21h = double(2.15676400725272833369672298431396484375000000000000000000000000000000000000000000e+04); p_coeff_22h = double(4.10662669419021476642228662967681884765625000000000000000000000000000000000000000e+04); p_t_1_0h = p_coeff_22h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_21h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_20h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_19h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_18h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_17h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_16h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_15h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0hm = p_coeff_14h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(xh,p_t_17_0hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_13h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_12h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_11h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = mul_rel<102>(xh,p_t_23_0hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = add_rel<102>(p_coeff_10h,p_t_24_0hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = mul_rel<102>(xh,p_t_25_0hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = add_rel<102>(p_coeff_9h,p_t_26_0hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hm = fma_rel<100>(p_t_27_0hm,xh,p_coeff_8hm); p_t_28_0h = double(p_t_28_0hm); p_t_28_0m = p_t_28_0hm - p_t_28_0h; p_t_29_0hm = fma_rel<100>(p_t_28_0hm,xh,p_coeff_7hm); p_t_29_0h = double(p_t_29_0hm); p_t_29_0m = p_t_29_0hm - p_t_29_0h; p_t_30_0hm = fma_rel<100>(p_t_29_0hm,xh,p_coeff_6hm); p_t_30_0h = double(p_t_30_0hm); p_t_30_0m = p_t_30_0hm - p_t_30_0h; p_t_31_0hm = fma_rel<100>(p_t_30_0hm,xh,p_coeff_5hm); p_t_31_0h = double(p_t_31_0hm); p_t_31_0m = p_t_31_0hm - p_t_31_0h; p_t_32_0hm = fma_rel<100>(p_t_31_0hm,xh,p_coeff_4hm); p_t_32_0h = double(p_t_32_0hm); p_t_32_0m = p_t_32_0hm - p_t_32_0h; p_t_33_0hm = fma_rel<100>(p_t_32_0hm,xh,p_coeff_3hm); p_t_33_0h = double(p_t_33_0hm); p_t_33_0m = p_t_33_0hm - p_t_33_0h; p_t_34_0hm = mul_rel<102>(xh,p_t_33_0hm); p_t_34_0h = double(p_t_34_0hm); p_t_34_0m = p_t_34_0hm - p_t_34_0h; p_t_35_0hml = add_rel<140>(p_coeff_2hm,p_t_34_0hm); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_t_36_0hml = mul_rel<145>(xh,p_t_35_0hml); p_t_36_0ml = p_t_36_0hml - p_t_36_0h; p_t_36_0m = double(p_t_36_0ml); p_t_36_0l = p_t_36_0ml - p_t_36_0m; p_t_36_0hm = p_t_36_0h + p_t_36_0m; overlap_p_t_36_0 = p_t_36_0m / p_t_36_0h; p_t_37_0hml = add_rel<143>(p_coeff_1hm,p_t_36_0hml); p_t_37_0ml = p_t_37_0hml - p_t_37_0h; p_t_37_0m = double(p_t_37_0ml); p_t_37_0l = p_t_37_0ml - p_t_37_0m; p_t_37_0hm = p_t_37_0h + p_t_37_0m; overlap_p_t_37_0 = p_t_37_0m / p_t_37_0h; p_t_38_0hml = mul_rel<135>(xh,p_t_37_0hml); p_t_38_0ml = p_t_38_0hml - p_t_38_0h; p_t_38_0m = double(p_t_38_0ml); p_t_38_0l = p_t_38_0ml - p_t_38_0m; p_t_38_0hm = p_t_38_0h + p_t_38_0m; overlap_p_t_38_0 = p_t_38_0m / p_t_38_0h; p_t_39_0hml = add_rel<133>(p_coeff_0hm,p_t_38_0hml); p_t_39_0ml = p_t_39_0hml - p_t_39_0h; p_t_39_0m = double(p_t_39_0ml); p_t_39_0l = p_t_39_0ml - p_t_39_0m; p_t_39_0hm = p_t_39_0h + p_t_39_0m; overlap_p_t_39_0 = p_t_39_0m / p_t_39_0h; p_reshml = p_t_39_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2hm; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_4 = p_coeff_4hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_6 = p_coeff_6hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_8 = p_coeff_8hm; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_14 = p_coeff_14h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_16 = p_coeff_16h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_18 = p_coeff_18h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_20 = p_coeff_20h; Mp_coeff_21 = p_coeff_21h; Mp_coeff_22 = p_coeff_22h; Mp_t_1_0 = Mp_coeff_22; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_21 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_20 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_19 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_18 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_17 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_16 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_15 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_14 + Mp_t_16_0; Mp_t_18_0 = Mx * Mp_t_17_0; Mp_t_19_0 = Mp_coeff_13 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_t_21_0 = Mp_coeff_12 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_11 + Mp_t_22_0; Mp_t_24_0 = Mx * Mp_t_23_0; Mp_t_25_0 = Mp_coeff_10 + Mp_t_24_0; Mp_t_26_0 = Mx * Mp_t_25_0; Mp_t_27_0 = Mp_coeff_9 + Mp_t_26_0; Mp_t_28_0 = (Mp_t_27_0 * Mx) + Mp_coeff_8; Mp_t_29_0 = (Mp_t_28_0 * Mx) + Mp_coeff_7; Mp_t_30_0 = (Mp_t_29_0 * Mx) + Mp_coeff_6; Mp_t_31_0 = (Mp_t_30_0 * Mx) + Mp_coeff_5; Mp_t_32_0 = (Mp_t_31_0 * Mx) + Mp_coeff_4; Mp_t_33_0 = (Mp_t_32_0 * Mx) + Mp_coeff_3; Mp_t_34_0 = Mx * Mp_t_33_0; Mp_t_35_0 = Mp_coeff_2 + Mp_t_34_0; Mp_t_36_0 = Mx * Mp_t_35_0; Mp_t_37_0 = Mp_coeff_1 + Mp_t_36_0; Mp_t_38_0 = Mx * Mp_t_37_0; Mp_t_39_0 = Mp_coeff_0 + Mp_t_38_0; Mp_res = Mp_t_39_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [-66447228468955b-51,-66447228468955b-451] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [265788913875259b-453,265788913875259b-53] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0h ~ p_t_28_0hm; p_t_29_0h ~ p_t_29_0hm; p_t_30_0h ~ p_t_30_0hm; p_t_31_0h ~ p_t_31_0hm; p_t_32_0h ~ p_t_32_0hm; p_t_33_0h ~ p_t_33_0hm; p_t_34_0h ~ p_t_34_0hm; p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_t_36_0hm ~ p_t_36_0hml; p_t_36_0h ~ p_t_36_0hm; p_t_36_0h ~ p_t_36_0hml; p_t_36_0m -> p_t_36_0h * overlap_p_t_36_0; p_t_36_0l / p_t_36_0m -> - ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml) / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)); (p_t_36_0hm - p_t_36_0hml) / p_t_36_0hml -> - (p_t_36_0l / p_t_36_0m) * (1 / (1 / overlap_p_t_36_0 + 1 + (p_t_36_0l / p_t_36_0m))); p_t_36_0ml -> p_t_36_0hml / ((1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) / overlap_p_t_36_0 + 1); (p_t_36_0h - p_t_36_0hm) / p_t_36_0hm -> - 1 / (1 / overlap_p_t_36_0 + 1); p_t_36_0h -> p_t_36_0hml / (overlap_p_t_36_0 / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) + 1); p_t_37_0hm ~ p_t_37_0hml; p_t_37_0h ~ p_t_37_0hm; p_t_37_0h ~ p_t_37_0hml; p_t_37_0m -> p_t_37_0h * overlap_p_t_37_0; p_t_37_0l / p_t_37_0m -> - ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml) / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)); (p_t_37_0hm - p_t_37_0hml) / p_t_37_0hml -> - (p_t_37_0l / p_t_37_0m) * (1 / (1 / overlap_p_t_37_0 + 1 + (p_t_37_0l / p_t_37_0m))); p_t_37_0ml -> p_t_37_0hml / ((1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) / overlap_p_t_37_0 + 1); (p_t_37_0h - p_t_37_0hm) / p_t_37_0hm -> - 1 / (1 / overlap_p_t_37_0 + 1); p_t_37_0h -> p_t_37_0hml / (overlap_p_t_37_0 / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) + 1); p_t_38_0hm ~ p_t_38_0hml; p_t_38_0h ~ p_t_38_0hm; p_t_38_0h ~ p_t_38_0hml; p_t_38_0m -> p_t_38_0h * overlap_p_t_38_0; p_t_38_0l / p_t_38_0m -> - ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml) / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)); (p_t_38_0hm - p_t_38_0hml) / p_t_38_0hml -> - (p_t_38_0l / p_t_38_0m) * (1 / (1 / overlap_p_t_38_0 + 1 + (p_t_38_0l / p_t_38_0m))); p_t_38_0ml -> p_t_38_0hml / ((1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) / overlap_p_t_38_0 + 1); (p_t_38_0h - p_t_38_0hm) / p_t_38_0hm -> - 1 / (1 / overlap_p_t_38_0 + 1); p_t_38_0h -> p_t_38_0hml / (overlap_p_t_38_0 / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) + 1); p_t_39_0hm ~ p_t_39_0hml; p_t_39_0h ~ p_t_39_0hm; p_t_39_0h ~ p_t_39_0hml; p_t_39_0m -> p_t_39_0h * overlap_p_t_39_0; p_t_39_0l / p_t_39_0m -> - ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml) / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)); (p_t_39_0hm - p_t_39_0hml) / p_t_39_0hml -> - (p_t_39_0l / p_t_39_0m) * (1 / (1 / overlap_p_t_39_0 + 1 + (p_t_39_0l / p_t_39_0m))); p_t_39_0ml -> p_t_39_0hml / ((1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) / overlap_p_t_39_0 + 1); (p_t_39_0h - p_t_39_0hm) / p_t_39_0hm -> - 1 / (1 / overlap_p_t_39_0 + 1); p_t_39_0h -> p_t_39_0hml / (overlap_p_t_39_0 / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hm ~ Mp_t_28_0; p_t_29_0hm ~ Mp_t_29_0; p_t_30_0hm ~ Mp_t_30_0; p_t_31_0hm ~ Mp_t_31_0; p_t_32_0hm ~ Mp_t_32_0; p_t_33_0hm ~ Mp_t_33_0; p_t_34_0hm ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_t_36_0hml ~ Mp_t_36_0; p_t_37_0hml ~ Mp_t_37_0; p_t_38_0hml ~ Mp_t_38_0; p_t_39_0hml ~ Mp_t_39_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_t_36_0hml in (0); $ p_t_36_0ml in (0); $ p_t_37_0hml in (0); $ p_t_37_0ml in (0); $ p_t_38_0hml in (0); $ p_t_38_0ml in (0); $ p_t_39_0hml in (0); $ p_t_39_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR5.gappa0000644000000000000000000004737613316017127020540 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 207936752306311063879596363241397575b-118 + (x * (200188677279957379313404027895927b-107 + (x * (44618069117890863136015301040417b-106 + (x * (260684645695147510943269794340145b-108 + (x * (381061457037558230442783063668111b-108 + (x * (81771898601459245984531837067169b-105 + (x * (74010517123253970985200791902569b-104 + (x * (140730399485913888056405477478093b-104 + (x * (69075144564109197184455554933769b-102 + (x * (1930159181128091b-46 + (x * (495367769220905b-43 + (x * (8265972462160073b-46 + (x * (8733056710727285b-45 + (x * (4663575235242669b-43 + (x * (2513454672531187b-41 + (x * (1365405966868523b-39 + (x * (5974899153588327b-40 + (x * (3287993622923969b-38 + (x * (7276245728935959b-38 + (x * (8086590392420483b-37 + (x * (2257198020248361b-34 + (x * (5210712187241083b-34 + (x * 5860188613098115b-33))))))))))))))))))))))))))))))))))))))))))) # The polynomial implemented is: 207936752306311063879596363241397575b-118 + (x * (200188677279957379313404027895927b-107 + (x * (44618069117890863136015301040417b-106 + (x * (260684645695147510943269794340145b-108 + (x * (381061457037558230442783063668111b-108 + (x * (81771898601459245984531837067169b-105 + (x * (74010517123253970985200791902569b-104 + (x * (140730399485913888056405477478093b-104 + (x * (69075144564109197184455554933769b-102 + (x * (1930159181128091b-46 + (x * (495367769220905b-43 + (x * (8265972462160073b-46 + (x * (8733056710727285b-45 + (x * (4663575235242669b-43 + (x * (2513454672531187b-41 + (x * (1365405966868523b-39 + (x * (5974899153588327b-40 + (x * (3287993622923969b-38 + (x * (7276245728935959b-38 + (x * (8086590392420483b-37 + (x * (2257198020248361b-34 + (x * (5210712187241083b-34 + (x * 5860188613098115b-33))))))))))))))))))))))))))))))))))))))))))) # The domain is [-120145772825149b-52;60072886412803b-51] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 63 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(6.25736902820868912122875826753443107008934020996093750000000000000000000000000000e-01); p_coeff_0m = double(1.03044861946200352361105560063972534424839340803290894401332555840866689322865568e-20); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.23375797792237640315704538807040080428123474121093750000000000000000000000000000e+00); p_coeff_1m = double(-1.56943153280384722085732805658465945105123195556662968330741136924189049750566483e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(5.49960162399266483390647408668883144855499267578125000000000000000000000000000000e-01); p_coeff_2m = double(4.77724544586887245869366226653936105958167895554379589473370515406713820993900299e-17); p_coeff_2hm = p_coeff_2h + p_coeff_2m; p_coeff_3h = double(8.03296584298018756520320948766311630606651306152343750000000000000000000000000000e-01); p_coeff_3m = double(8.24298592592304193429233278946371287822415169276122487440616737330856267362833023e-18); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_4h = double(1.17423627321674173273891028657089918851852416992187500000000000000000000000000000e+00); p_coeff_4m = double(6.51885136427795249608596859127055587343811181939758764292136561380175407975912094e-18); p_coeff_4hm = p_coeff_4h + p_coeff_4m; p_coeff_5h = double(2.01583293601212298895575258939061313867568969726562500000000000000000000000000000e+00); p_coeff_5m = double(-1.74898605368430358273924263609101302050140983100449953990818130478146485984325409e-16); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_6h = double(3.64900022085783248826373892370611429214477539062500000000000000000000000000000000e+00); p_coeff_6m = double(1.43304714197470670030886399120078425706334125872346008101487768726656213402748108e-16); p_coeff_6hm = p_coeff_6h + p_coeff_6m; p_coeff_7h = double(6.93854439566079062018388867727480828762054443359375000000000000000000000000000000e+00); p_coeff_7m = double(-3.60750117305009285790273957823616258349535174413877380850124154676450416445732117e-16); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_8h = double(1.36226702672788579917551032849587500095367431640625000000000000000000000000000000e+01); p_coeff_8m = double(5.62980642478103599614115253967152086402971956392848884576096679666079580783843994e-16); p_coeff_8hm = p_coeff_8h + p_coeff_8m; p_coeff_9h = double(2.74292117002245703361040796153247356414794921875000000000000000000000000000000000e+01); p_coeff_10h = double(5.63167951919359666135278530418872833251953125000000000000000000000000000000000000e+01); p_coeff_11h = double(1.17466533739617389642262423876672983169555664062500000000000000000000000000000000e+02); p_coeff_12h = double(2.48208400271530678082854137755930423736572265625000000000000000000000000000000000e+02); p_coeff_13h = double(5.30187120971580611694662366062402725219726562500000000000000000000000000000000000e+02); p_coeff_14h = double(1.14298685390676246242946945130825042724609375000000000000000000000000000000000000e+03); p_coeff_15h = double(2.48365898527212812041398137807846069335937500000000000000000000000000000000000000e+03); p_coeff_16h = double(5.43413912381613681645831093192100524902343750000000000000000000000000000000000000e+03); p_coeff_17h = double(1.19616511180501001945231109857559204101562500000000000000000000000000000000000000e+04); p_coeff_18h = double(2.64708277570606114750262349843978881835937500000000000000000000000000000000000000e+04); p_coeff_19h = double(5.88376889385143513209186494350433349609375000000000000000000000000000000000000000e+04); p_coeff_20h = double(1.31386216977166535798460245132446289062500000000000000000000000000000000000000000e+05); p_coeff_21h = double(3.03303368112601048778742551803588867187500000000000000000000000000000000000000000e+05); p_coeff_22h = double(6.82215743360355845652520656585693359375000000000000000000000000000000000000000000e+05); p_t_1_0h = p_coeff_22h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_21h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_20h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_19h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_18h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_17h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_16h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_15h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0hm = p_coeff_14h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(xh,p_t_17_0hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_13h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_12h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_11h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = mul_rel<102>(xh,p_t_23_0hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = add_rel<102>(p_coeff_10h,p_t_24_0hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = mul_rel<102>(xh,p_t_25_0hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = add_rel<102>(p_coeff_9h,p_t_26_0hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hm = fma_rel<100>(p_t_27_0hm,xh,p_coeff_8hm); p_t_28_0h = double(p_t_28_0hm); p_t_28_0m = p_t_28_0hm - p_t_28_0h; p_t_29_0hm = fma_rel<100>(p_t_28_0hm,xh,p_coeff_7hm); p_t_29_0h = double(p_t_29_0hm); p_t_29_0m = p_t_29_0hm - p_t_29_0h; p_t_30_0hm = fma_rel<100>(p_t_29_0hm,xh,p_coeff_6hm); p_t_30_0h = double(p_t_30_0hm); p_t_30_0m = p_t_30_0hm - p_t_30_0h; p_t_31_0hm = fma_rel<100>(p_t_30_0hm,xh,p_coeff_5hm); p_t_31_0h = double(p_t_31_0hm); p_t_31_0m = p_t_31_0hm - p_t_31_0h; p_t_32_0hm = fma_rel<100>(p_t_31_0hm,xh,p_coeff_4hm); p_t_32_0h = double(p_t_32_0hm); p_t_32_0m = p_t_32_0hm - p_t_32_0h; p_t_33_0hm = fma_rel<100>(p_t_32_0hm,xh,p_coeff_3hm); p_t_33_0h = double(p_t_33_0hm); p_t_33_0m = p_t_33_0hm - p_t_33_0h; p_t_34_0hm = mul_rel<102>(xh,p_t_33_0hm); p_t_34_0h = double(p_t_34_0hm); p_t_34_0m = p_t_34_0hm - p_t_34_0h; p_t_35_0hml = add_rel<140>(p_coeff_2hm,p_t_34_0hm); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_t_36_0hml = mul_rel<145>(xh,p_t_35_0hml); p_t_36_0ml = p_t_36_0hml - p_t_36_0h; p_t_36_0m = double(p_t_36_0ml); p_t_36_0l = p_t_36_0ml - p_t_36_0m; p_t_36_0hm = p_t_36_0h + p_t_36_0m; overlap_p_t_36_0 = p_t_36_0m / p_t_36_0h; p_t_37_0hml = add_rel<143>(p_coeff_1hm,p_t_36_0hml); p_t_37_0ml = p_t_37_0hml - p_t_37_0h; p_t_37_0m = double(p_t_37_0ml); p_t_37_0l = p_t_37_0ml - p_t_37_0m; p_t_37_0hm = p_t_37_0h + p_t_37_0m; overlap_p_t_37_0 = p_t_37_0m / p_t_37_0h; p_t_38_0hml = mul_rel<135>(xh,p_t_37_0hml); p_t_38_0ml = p_t_38_0hml - p_t_38_0h; p_t_38_0m = double(p_t_38_0ml); p_t_38_0l = p_t_38_0ml - p_t_38_0m; p_t_38_0hm = p_t_38_0h + p_t_38_0m; overlap_p_t_38_0 = p_t_38_0m / p_t_38_0h; p_t_39_0hml = add_rel<133>(p_coeff_0hm,p_t_38_0hml); p_t_39_0ml = p_t_39_0hml - p_t_39_0h; p_t_39_0m = double(p_t_39_0ml); p_t_39_0l = p_t_39_0ml - p_t_39_0m; p_t_39_0hm = p_t_39_0h + p_t_39_0m; overlap_p_t_39_0 = p_t_39_0m / p_t_39_0h; p_reshml = p_t_39_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2hm; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_4 = p_coeff_4hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_6 = p_coeff_6hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_8 = p_coeff_8hm; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_14 = p_coeff_14h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_16 = p_coeff_16h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_18 = p_coeff_18h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_20 = p_coeff_20h; Mp_coeff_21 = p_coeff_21h; Mp_coeff_22 = p_coeff_22h; Mp_t_1_0 = Mp_coeff_22; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_21 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_20 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_19 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_18 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_17 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_16 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_15 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_14 + Mp_t_16_0; Mp_t_18_0 = Mx * Mp_t_17_0; Mp_t_19_0 = Mp_coeff_13 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_t_21_0 = Mp_coeff_12 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_11 + Mp_t_22_0; Mp_t_24_0 = Mx * Mp_t_23_0; Mp_t_25_0 = Mp_coeff_10 + Mp_t_24_0; Mp_t_26_0 = Mx * Mp_t_25_0; Mp_t_27_0 = Mp_coeff_9 + Mp_t_26_0; Mp_t_28_0 = (Mp_t_27_0 * Mx) + Mp_coeff_8; Mp_t_29_0 = (Mp_t_28_0 * Mx) + Mp_coeff_7; Mp_t_30_0 = (Mp_t_29_0 * Mx) + Mp_coeff_6; Mp_t_31_0 = (Mp_t_30_0 * Mx) + Mp_coeff_5; Mp_t_32_0 = (Mp_t_31_0 * Mx) + Mp_coeff_4; Mp_t_33_0 = (Mp_t_32_0 * Mx) + Mp_coeff_3; Mp_t_34_0 = Mx * Mp_t_33_0; Mp_t_35_0 = Mp_coeff_2 + Mp_t_34_0; Mp_t_36_0 = Mx * Mp_t_35_0; Mp_t_37_0 = Mp_coeff_1 + Mp_t_36_0; Mp_t_38_0 = Mx * Mp_t_37_0; Mp_t_39_0 = Mp_coeff_0 + Mp_t_38_0; Mp_res = Mp_t_39_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [-120145772825149b-52,-120145772825149b-452] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [60072886412803b-451,60072886412803b-51] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0h ~ p_t_28_0hm; p_t_29_0h ~ p_t_29_0hm; p_t_30_0h ~ p_t_30_0hm; p_t_31_0h ~ p_t_31_0hm; p_t_32_0h ~ p_t_32_0hm; p_t_33_0h ~ p_t_33_0hm; p_t_34_0h ~ p_t_34_0hm; p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_t_36_0hm ~ p_t_36_0hml; p_t_36_0h ~ p_t_36_0hm; p_t_36_0h ~ p_t_36_0hml; p_t_36_0m -> p_t_36_0h * overlap_p_t_36_0; p_t_36_0l / p_t_36_0m -> - ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml) / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)); (p_t_36_0hm - p_t_36_0hml) / p_t_36_0hml -> - (p_t_36_0l / p_t_36_0m) * (1 / (1 / overlap_p_t_36_0 + 1 + (p_t_36_0l / p_t_36_0m))); p_t_36_0ml -> p_t_36_0hml / ((1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) / overlap_p_t_36_0 + 1); (p_t_36_0h - p_t_36_0hm) / p_t_36_0hm -> - 1 / (1 / overlap_p_t_36_0 + 1); p_t_36_0h -> p_t_36_0hml / (overlap_p_t_36_0 / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) + 1); p_t_37_0hm ~ p_t_37_0hml; p_t_37_0h ~ p_t_37_0hm; p_t_37_0h ~ p_t_37_0hml; p_t_37_0m -> p_t_37_0h * overlap_p_t_37_0; p_t_37_0l / p_t_37_0m -> - ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml) / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)); (p_t_37_0hm - p_t_37_0hml) / p_t_37_0hml -> - (p_t_37_0l / p_t_37_0m) * (1 / (1 / overlap_p_t_37_0 + 1 + (p_t_37_0l / p_t_37_0m))); p_t_37_0ml -> p_t_37_0hml / ((1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) / overlap_p_t_37_0 + 1); (p_t_37_0h - p_t_37_0hm) / p_t_37_0hm -> - 1 / (1 / overlap_p_t_37_0 + 1); p_t_37_0h -> p_t_37_0hml / (overlap_p_t_37_0 / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) + 1); p_t_38_0hm ~ p_t_38_0hml; p_t_38_0h ~ p_t_38_0hm; p_t_38_0h ~ p_t_38_0hml; p_t_38_0m -> p_t_38_0h * overlap_p_t_38_0; p_t_38_0l / p_t_38_0m -> - ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml) / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)); (p_t_38_0hm - p_t_38_0hml) / p_t_38_0hml -> - (p_t_38_0l / p_t_38_0m) * (1 / (1 / overlap_p_t_38_0 + 1 + (p_t_38_0l / p_t_38_0m))); p_t_38_0ml -> p_t_38_0hml / ((1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) / overlap_p_t_38_0 + 1); (p_t_38_0h - p_t_38_0hm) / p_t_38_0hm -> - 1 / (1 / overlap_p_t_38_0 + 1); p_t_38_0h -> p_t_38_0hml / (overlap_p_t_38_0 / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) + 1); p_t_39_0hm ~ p_t_39_0hml; p_t_39_0h ~ p_t_39_0hm; p_t_39_0h ~ p_t_39_0hml; p_t_39_0m -> p_t_39_0h * overlap_p_t_39_0; p_t_39_0l / p_t_39_0m -> - ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml) / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)); (p_t_39_0hm - p_t_39_0hml) / p_t_39_0hml -> - (p_t_39_0l / p_t_39_0m) * (1 / (1 / overlap_p_t_39_0 + 1 + (p_t_39_0l / p_t_39_0m))); p_t_39_0ml -> p_t_39_0hml / ((1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) / overlap_p_t_39_0 + 1); (p_t_39_0h - p_t_39_0hm) / p_t_39_0hm -> - 1 / (1 / overlap_p_t_39_0 + 1); p_t_39_0h -> p_t_39_0hml / (overlap_p_t_39_0 / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hm ~ Mp_t_28_0; p_t_29_0hm ~ Mp_t_29_0; p_t_30_0hm ~ Mp_t_30_0; p_t_31_0hm ~ Mp_t_31_0; p_t_32_0hm ~ Mp_t_32_0; p_t_33_0hm ~ Mp_t_33_0; p_t_34_0hm ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_t_36_0hml ~ Mp_t_36_0; p_t_37_0hml ~ Mp_t_37_0; p_t_38_0hml ~ Mp_t_38_0; p_t_39_0hml ~ Mp_t_39_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_t_36_0hml in (0); $ p_t_36_0ml in (0); $ p_t_37_0hml in (0); $ p_t_37_0ml in (0); $ p_t_38_0hml in (0); $ p_t_38_0ml in (0); $ p_t_39_0hml in (0); $ p_t_39_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR6.gappa0000644000000000000000000004736013316017127020532 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 1792581242326710567212291806223253b-111 + (x * (52617200066848308332099303297945b-105 + (x * (902150187593629183958092782443033b-110 + (x * (44965428859892640751057159071087b-105 + (x * (4752633902292393250779852752339b-101 + (x * (148125601965768399364062017841291b-105 + (x * (153165790916719773608400395315619b-104 + (x * (41511842370824976233500266801317b-101 + (x * (23248649506122112562773990099117b-99 + (x * (370572309710903b-42 + (x * (6944699428013305b-45 + (x * (4131783695767297b-43 + (x * (2490319441786495b-41 + (x * (3034706834572899b-40 + (x * (933084968080141b-37 + (x * (2313432583692069b-37 + (x * (5775407383919483b-37 + (x * (906590116929055b-33 + (x * (2289170179319731b-33 + (x * (2903438112538227b-32 + (x * (7396622347274281b-32 + (x * (4823126988259909b-30 + (x * 6227373019952893b-29))))))))))))))))))))))))))))))))))))))))))) # The polynomial implemented is: 1792581242326710567212291806223253b-111 + (x * (52617200066848308332099303297945b-105 + (x * (902150187593629183958092782443033b-110 + (x * (44965428859892640751057159071087b-105 + (x * (4752633902292393250779852752339b-101 + (x * (148125601965768399364062017841291b-105 + (x * (153165790916719773608400395315619b-104 + (x * (41511842370824976233500266801317b-101 + (x * (23248649506122112562773990099117b-99 + (x * (370572309710903b-42 + (x * (6944699428013305b-45 + (x * (4131783695767297b-43 + (x * (2490319441786495b-41 + (x * (3034706834572899b-40 + (x * (933084968080141b-37 + (x * (2313432583692069b-37 + (x * (5775407383919483b-37 + (x * (906590116929055b-33 + (x * (2289170179319731b-33 + (x * (2903438112538227b-32 + (x * (7396622347274281b-32 + (x * (4823126988259909b-30 + (x * 6227373019952893b-29))))))))))))))))))))))))))))))))))))))))))) # The domain is [-110485440722351b-52;55242720361239b-51] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 63 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(6.90477178468776764397318856936180964112281799316406250000000000000000000000000000e-01); p_coeff_0m = double(3.39466231816613032388245073452427079551490712938188829689289960356290976051241159e-18); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.29711412734153253012436834978871047496795654296875000000000000000000000000000000e+00); p_coeff_1m = double(-4.91536443957924304285159601199758593586250555616465329755726543226046487689018250e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(6.94991224248453054457286270917393267154693603515625000000000000000000000000000000e-01); p_coeff_2m = double(4.14055567174545404801311585696815622965502227300336503257316422832445823587477207e-18); p_coeff_2hm = p_coeff_2h + p_coeff_2m; p_coeff_3h = double(1.10848340356455987709693999931914731860160827636718750000000000000000000000000000e+00); p_coeff_3m = double(4.16266958244922006708243033738862584564114206709881105261672473716316744685173035e-17); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_4h = double(1.87458354117322345544494055502582341432571411132812500000000000000000000000000000e+00); p_coeff_4m = double(1.01371418047977543599188915056692109774560397669751488081146817421540617942810059e-16); p_coeff_4hm = p_coeff_4h + p_coeff_4m; p_coeff_5h = double(3.65157801416010441286630339163821190595626831054687500000000000000000000000000000e+00); p_coeff_5m = double(1.26536476346012852031977695308463633490816727090143289924384362166165374219417572e-16); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_6h = double(7.55165652946598697781155351549386978149414062500000000000000000000000000000000000e+00); p_coeff_6m = double(-2.14190464475496048348382959343551268818198527301224776131505223020212724804878235e-16); p_coeff_6hm = p_coeff_6h + p_coeff_6m; p_coeff_7h = double(1.63735347750204702776954945875331759452819824218750000000000000000000000000000000e+01); p_coeff_7m = double(1.51055732062479748503833695277300766424363764363347772956558401347137987613677979e-15); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_8h = double(3.66799013891310394797073968220502138137817382812500000000000000000000000000000000e+01); p_coeff_8m = double(-1.96467879903428952233615671924270070336884016354295212636316136922687292098999023e-15); p_coeff_8hm = p_coeff_8h + p_coeff_8m; p_coeff_9h = double(8.42583880764557306974893435835838317871093750000000000000000000000000000000000000e+01); p_coeff_10h = double(1.97380229224487067085647140629589557647705078125000000000000000000000000000000000e+02); p_coeff_11h = double(4.69729422521515630251087713986635208129882812500000000000000000000000000000000000e+02); p_coeff_12h = double(1.13246616901346669692429713904857635498046875000000000000000000000000000000000000e+03); p_coeff_13h = double(2.76004978747814584494335576891899108886718750000000000000000000000000000000000000e+03); p_coeff_14h = double(6.78908667818280082428827881813049316406250000000000000000000000000000000000000000e+03); p_coeff_15h = double(1.68324374222143451333977282047271728515625000000000000000000000000000000000000000e+04); p_coeff_16h = double(4.20216193300401428132317960262298583984375000000000000000000000000000000000000000e+04); p_coeff_17h = double(1.05540980227414402179419994354248046875000000000000000000000000000000000000000000e+05); p_coeff_18h = double(2.66494483142128563486039638519287109375000000000000000000000000000000000000000000e+05); p_coeff_19h = double(6.76009364551451755687594413757324218750000000000000000000000000000000000000000000e+05); p_coeff_20h = double(1.72216034198046685196459293365478515625000000000000000000000000000000000000000000e+06); p_coeff_21h = double(4.49188704440361727029085159301757812500000000000000000000000000000000000000000000e+06); p_coeff_22h = double(1.15993861480669919401407241821289062500000000000000000000000000000000000000000000e+07); p_t_1_0h = p_coeff_22h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_21h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_20h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_19h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_18h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_17h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_16h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_15h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0hm = p_coeff_14h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(xh,p_t_17_0hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_13h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_12h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_11h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = mul_rel<102>(xh,p_t_23_0hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = add_rel<102>(p_coeff_10h,p_t_24_0hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = mul_rel<102>(xh,p_t_25_0hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = add_rel<102>(p_coeff_9h,p_t_26_0hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hm = fma_rel<100>(p_t_27_0hm,xh,p_coeff_8hm); p_t_28_0h = double(p_t_28_0hm); p_t_28_0m = p_t_28_0hm - p_t_28_0h; p_t_29_0hm = fma_rel<100>(p_t_28_0hm,xh,p_coeff_7hm); p_t_29_0h = double(p_t_29_0hm); p_t_29_0m = p_t_29_0hm - p_t_29_0h; p_t_30_0hm = fma_rel<100>(p_t_29_0hm,xh,p_coeff_6hm); p_t_30_0h = double(p_t_30_0hm); p_t_30_0m = p_t_30_0hm - p_t_30_0h; p_t_31_0hm = fma_rel<100>(p_t_30_0hm,xh,p_coeff_5hm); p_t_31_0h = double(p_t_31_0hm); p_t_31_0m = p_t_31_0hm - p_t_31_0h; p_t_32_0hm = fma_rel<100>(p_t_31_0hm,xh,p_coeff_4hm); p_t_32_0h = double(p_t_32_0hm); p_t_32_0m = p_t_32_0hm - p_t_32_0h; p_t_33_0hm = fma_rel<100>(p_t_32_0hm,xh,p_coeff_3hm); p_t_33_0h = double(p_t_33_0hm); p_t_33_0m = p_t_33_0hm - p_t_33_0h; p_t_34_0hm = mul_rel<102>(xh,p_t_33_0hm); p_t_34_0h = double(p_t_34_0hm); p_t_34_0m = p_t_34_0hm - p_t_34_0h; p_t_35_0hml = add_rel<140>(p_coeff_2hm,p_t_34_0hm); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_t_36_0hml = mul_rel<145>(xh,p_t_35_0hml); p_t_36_0ml = p_t_36_0hml - p_t_36_0h; p_t_36_0m = double(p_t_36_0ml); p_t_36_0l = p_t_36_0ml - p_t_36_0m; p_t_36_0hm = p_t_36_0h + p_t_36_0m; overlap_p_t_36_0 = p_t_36_0m / p_t_36_0h; p_t_37_0hml = add_rel<143>(p_coeff_1hm,p_t_36_0hml); p_t_37_0ml = p_t_37_0hml - p_t_37_0h; p_t_37_0m = double(p_t_37_0ml); p_t_37_0l = p_t_37_0ml - p_t_37_0m; p_t_37_0hm = p_t_37_0h + p_t_37_0m; overlap_p_t_37_0 = p_t_37_0m / p_t_37_0h; p_t_38_0hml = mul_rel<135>(xh,p_t_37_0hml); p_t_38_0ml = p_t_38_0hml - p_t_38_0h; p_t_38_0m = double(p_t_38_0ml); p_t_38_0l = p_t_38_0ml - p_t_38_0m; p_t_38_0hm = p_t_38_0h + p_t_38_0m; overlap_p_t_38_0 = p_t_38_0m / p_t_38_0h; p_t_39_0hml = add_rel<133>(p_coeff_0hm,p_t_38_0hml); p_t_39_0ml = p_t_39_0hml - p_t_39_0h; p_t_39_0m = double(p_t_39_0ml); p_t_39_0l = p_t_39_0ml - p_t_39_0m; p_t_39_0hm = p_t_39_0h + p_t_39_0m; overlap_p_t_39_0 = p_t_39_0m / p_t_39_0h; p_reshml = p_t_39_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2hm; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_4 = p_coeff_4hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_6 = p_coeff_6hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_8 = p_coeff_8hm; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_14 = p_coeff_14h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_16 = p_coeff_16h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_18 = p_coeff_18h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_20 = p_coeff_20h; Mp_coeff_21 = p_coeff_21h; Mp_coeff_22 = p_coeff_22h; Mp_t_1_0 = Mp_coeff_22; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_21 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_20 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_19 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_18 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_17 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_16 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_15 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_14 + Mp_t_16_0; Mp_t_18_0 = Mx * Mp_t_17_0; Mp_t_19_0 = Mp_coeff_13 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_t_21_0 = Mp_coeff_12 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_11 + Mp_t_22_0; Mp_t_24_0 = Mx * Mp_t_23_0; Mp_t_25_0 = Mp_coeff_10 + Mp_t_24_0; Mp_t_26_0 = Mx * Mp_t_25_0; Mp_t_27_0 = Mp_coeff_9 + Mp_t_26_0; Mp_t_28_0 = (Mp_t_27_0 * Mx) + Mp_coeff_8; Mp_t_29_0 = (Mp_t_28_0 * Mx) + Mp_coeff_7; Mp_t_30_0 = (Mp_t_29_0 * Mx) + Mp_coeff_6; Mp_t_31_0 = (Mp_t_30_0 * Mx) + Mp_coeff_5; Mp_t_32_0 = (Mp_t_31_0 * Mx) + Mp_coeff_4; Mp_t_33_0 = (Mp_t_32_0 * Mx) + Mp_coeff_3; Mp_t_34_0 = Mx * Mp_t_33_0; Mp_t_35_0 = Mp_coeff_2 + Mp_t_34_0; Mp_t_36_0 = Mx * Mp_t_35_0; Mp_t_37_0 = Mp_coeff_1 + Mp_t_36_0; Mp_t_38_0 = Mx * Mp_t_37_0; Mp_t_39_0 = Mp_coeff_0 + Mp_t_38_0; Mp_res = Mp_t_39_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [-110485440722351b-52,-110485440722351b-452] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [55242720361239b-451,55242720361239b-51] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0h ~ p_t_28_0hm; p_t_29_0h ~ p_t_29_0hm; p_t_30_0h ~ p_t_30_0hm; p_t_31_0h ~ p_t_31_0hm; p_t_32_0h ~ p_t_32_0hm; p_t_33_0h ~ p_t_33_0hm; p_t_34_0h ~ p_t_34_0hm; p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_t_36_0hm ~ p_t_36_0hml; p_t_36_0h ~ p_t_36_0hm; p_t_36_0h ~ p_t_36_0hml; p_t_36_0m -> p_t_36_0h * overlap_p_t_36_0; p_t_36_0l / p_t_36_0m -> - ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml) / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)); (p_t_36_0hm - p_t_36_0hml) / p_t_36_0hml -> - (p_t_36_0l / p_t_36_0m) * (1 / (1 / overlap_p_t_36_0 + 1 + (p_t_36_0l / p_t_36_0m))); p_t_36_0ml -> p_t_36_0hml / ((1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) / overlap_p_t_36_0 + 1); (p_t_36_0h - p_t_36_0hm) / p_t_36_0hm -> - 1 / (1 / overlap_p_t_36_0 + 1); p_t_36_0h -> p_t_36_0hml / (overlap_p_t_36_0 / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) + 1); p_t_37_0hm ~ p_t_37_0hml; p_t_37_0h ~ p_t_37_0hm; p_t_37_0h ~ p_t_37_0hml; p_t_37_0m -> p_t_37_0h * overlap_p_t_37_0; p_t_37_0l / p_t_37_0m -> - ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml) / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)); (p_t_37_0hm - p_t_37_0hml) / p_t_37_0hml -> - (p_t_37_0l / p_t_37_0m) * (1 / (1 / overlap_p_t_37_0 + 1 + (p_t_37_0l / p_t_37_0m))); p_t_37_0ml -> p_t_37_0hml / ((1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) / overlap_p_t_37_0 + 1); (p_t_37_0h - p_t_37_0hm) / p_t_37_0hm -> - 1 / (1 / overlap_p_t_37_0 + 1); p_t_37_0h -> p_t_37_0hml / (overlap_p_t_37_0 / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) + 1); p_t_38_0hm ~ p_t_38_0hml; p_t_38_0h ~ p_t_38_0hm; p_t_38_0h ~ p_t_38_0hml; p_t_38_0m -> p_t_38_0h * overlap_p_t_38_0; p_t_38_0l / p_t_38_0m -> - ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml) / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)); (p_t_38_0hm - p_t_38_0hml) / p_t_38_0hml -> - (p_t_38_0l / p_t_38_0m) * (1 / (1 / overlap_p_t_38_0 + 1 + (p_t_38_0l / p_t_38_0m))); p_t_38_0ml -> p_t_38_0hml / ((1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) / overlap_p_t_38_0 + 1); (p_t_38_0h - p_t_38_0hm) / p_t_38_0hm -> - 1 / (1 / overlap_p_t_38_0 + 1); p_t_38_0h -> p_t_38_0hml / (overlap_p_t_38_0 / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) + 1); p_t_39_0hm ~ p_t_39_0hml; p_t_39_0h ~ p_t_39_0hm; p_t_39_0h ~ p_t_39_0hml; p_t_39_0m -> p_t_39_0h * overlap_p_t_39_0; p_t_39_0l / p_t_39_0m -> - ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml) / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)); (p_t_39_0hm - p_t_39_0hml) / p_t_39_0hml -> - (p_t_39_0l / p_t_39_0m) * (1 / (1 / overlap_p_t_39_0 + 1 + (p_t_39_0l / p_t_39_0m))); p_t_39_0ml -> p_t_39_0hml / ((1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) / overlap_p_t_39_0 + 1); (p_t_39_0h - p_t_39_0hm) / p_t_39_0hm -> - 1 / (1 / overlap_p_t_39_0 + 1); p_t_39_0h -> p_t_39_0hml / (overlap_p_t_39_0 / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hm ~ Mp_t_28_0; p_t_29_0hm ~ Mp_t_29_0; p_t_30_0hm ~ Mp_t_30_0; p_t_31_0hm ~ Mp_t_31_0; p_t_32_0hm ~ Mp_t_32_0; p_t_33_0hm ~ Mp_t_33_0; p_t_34_0hm ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_t_36_0hml ~ Mp_t_36_0; p_t_37_0hml ~ Mp_t_37_0; p_t_38_0hml ~ Mp_t_38_0; p_t_39_0hml ~ Mp_t_39_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_t_36_0hml in (0); $ p_t_36_0ml in (0); $ p_t_37_0hml in (0); $ p_t_37_0ml in (0); $ p_t_38_0hml in (0); $ p_t_38_0ml in (0); $ p_t_39_0hml in (0); $ p_t_39_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR7.gappa0000644000000000000000000004737113316017127020535 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 15651770362713997207607972106972745b-114 + (x * (3476698806776688943652103662933b-101 + (x * (17894972500311187082269807705171b-104 + (x * (126976607296441025269345153102591b-106 + (x * (249107378895562413495151944042799b-106 + (x * (139053951649796304768149995225589b-104 + (x * (165428664168251249501887921888847b-103 + (x * (206167601873884163281098618631159b-102 + (x * (66386611260133347295510390653099b-99 + (x * (2433556521489987b-43 + (x * (409716955440671b-39 + (x * (2242518346998655b-40 + (x * (3108616106416871b-39 + (x * (4356285307071455b-38 + (x * (6161286268548935b-37 + (x * (8783550111623067b-36 + (x * (788026560267325b-31 + (x * (1138037795125313b-30 + (x * (3304615966282565b-30 + (x * (602367826671283b-26 + (x * (1765006192104851b-26 + (x * (1337636086941861b-24 + (x * 986777691264547b-22))))))))))))))))))))))))))))))))))))))))))) # The polynomial implemented is: 15651770362713997207607972106972745b-114 + (x * (3476698806776688943652103662933b-101 + (x * (17894972500311187082269807705171b-104 + (x * (126976607296441025269345153102591b-106 + (x * (249107378895562413495151944042799b-106 + (x * (139053951649796304768149995225589b-104 + (x * (165428664168251249501887921888847b-103 + (x * (206167601873884163281098618631159b-102 + (x * (66386611260133347295510390653099b-99 + (x * (2433556521489987b-43 + (x * (409716955440671b-39 + (x * (2242518346998655b-40 + (x * (3108616106416871b-39 + (x * (4356285307071455b-38 + (x * (6161286268548935b-37 + (x * (8783550111623067b-36 + (x * (788026560267325b-31 + (x * (1138037795125313b-30 + (x * (3304615966282565b-30 + (x * (602367826671283b-26 + (x * (1765006192104851b-26 + (x * (1337636086941861b-24 + (x * 986777691264547b-22))))))))))))))))))))))))))))))))))))))))))) # The domain is [-205674681606191b-53;205674681606835b-53] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 63 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(7.53605330605588874526290510402759537100791931152343750000000000000000000000000000e-01); p_coeff_0m = double(-6.86303578932659590324882262388685086010663787564085999357010869914574868744239211e-20); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.37131588394733516800272354885237291455268859863281250000000000000000000000000000e+00); p_coeff_1m = double(5.85729819349925155946752593741546617096794483808830378279708384070545434951782227e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(8.82290262843787198576706032326910644769668579101562500000000000000000000000000000e-01); p_coeff_2m = double(5.16377114572074856584788281695076928068533622922381409736658497422467917203903198e-17); p_coeff_2hm = p_coeff_2h + p_coeff_2m; p_coeff_3h = double(1.56510752146505316417801623174455016851425170898437500000000000000000000000000000e+00); p_coeff_3m = double(-4.39163602371923391288987498767894166026634554891340533888666186612681485712528229e-17); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_4h = double(3.07048550644979600932060748164076358079910278320312500000000000000000000000000000e+00); p_coeff_4m = double(-1.10182145686314872930592860300828689006905830376995686359364867712429258972406387e-16); p_coeff_4hm = p_coeff_4h + p_coeff_4m; p_coeff_5h = double(6.85588913581356962367863161489367485046386718750000000000000000000000000000000000e+00); p_coeff_5m = double(4.35622325486244782178679451752414705321823684735019210911843856592895463109016418e-16); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_6h = double(1.63125257206586802283254655776545405387878417968750000000000000000000000000000000e+01); p_coeff_6m = double(-1.42810985056358952027816317128163090933704222357941704402151117392349988222122192e-16); p_coeff_6hm = p_coeff_6h + p_coeff_6m; p_coeff_7h = double(4.06593902603693564401510229799896478652954101562500000000000000000000000000000000e+01); p_coeff_7m = double(1.26451118649566617072575681437226509832616233499485991487176761438604444265365601e-15); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_8h = double(1.04739604506448415577324340119957923889160156250000000000000000000000000000000000e+02); p_coeff_8m = double(-4.21355762035756719251654947961735015460869348269401513107368373312056064605712891e-16); p_coeff_8hm = p_coeff_8h + p_coeff_8m; p_coeff_9h = double(2.76663345345012544385099317878484725952148437500000000000000000000000000000000000e+02); p_coeff_10h = double(7.45270800399650397594086825847625732421875000000000000000000000000000000000000000e+02); p_coeff_11h = double(2.03955855522386173106497153639793395996093750000000000000000000000000000000000000e+03); p_coeff_12h = double(5.65453975726426688197534531354904174804687500000000000000000000000000000000000000e+03); p_coeff_13h = double(1.58480736247709683084394782781600952148437500000000000000000000000000000000000000e+04); p_coeff_14h = double(4.48292577388124118442647159099578857421875000000000000000000000000000000000000000e+04); p_coeff_15h = double(1.27817476628451069700531661510467529296875000000000000000000000000000000000000000e+05); p_coeff_16h = double(3.66953462486772332340478897094726562500000000000000000000000000000000000000000000e+05); p_coeff_17h = double(1.05988028936582896858453750610351562500000000000000000000000000000000000000000000e+06); p_coeff_18h = double(3.07766344983369577676057815551757812500000000000000000000000000000000000000000000e+06); p_coeff_19h = double(8.97598008321647346019744873046875000000000000000000000000000000000000000000000000e+06); p_coeff_20h = double(2.63006417766936272382736206054687500000000000000000000000000000000000000000000000e+07); p_coeff_21h = double(7.97293238009131550788879394531250000000000000000000000000000000000000000000000000e+07); p_coeff_22h = double(2.35266135040413618087768554687500000000000000000000000000000000000000000000000000e+08); p_t_1_0h = p_coeff_22h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_21h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_20h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_19h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_18h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_17h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_16h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_15h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0hm = p_coeff_14h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(xh,p_t_17_0hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_13h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_12h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_11h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = mul_rel<102>(xh,p_t_23_0hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = add_rel<102>(p_coeff_10h,p_t_24_0hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = mul_rel<102>(xh,p_t_25_0hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = add_rel<102>(p_coeff_9h,p_t_26_0hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hm = fma_rel<100>(p_t_27_0hm,xh,p_coeff_8hm); p_t_28_0h = double(p_t_28_0hm); p_t_28_0m = p_t_28_0hm - p_t_28_0h; p_t_29_0hm = fma_rel<100>(p_t_28_0hm,xh,p_coeff_7hm); p_t_29_0h = double(p_t_29_0hm); p_t_29_0m = p_t_29_0hm - p_t_29_0h; p_t_30_0hm = fma_rel<100>(p_t_29_0hm,xh,p_coeff_6hm); p_t_30_0h = double(p_t_30_0hm); p_t_30_0m = p_t_30_0hm - p_t_30_0h; p_t_31_0hm = fma_rel<100>(p_t_30_0hm,xh,p_coeff_5hm); p_t_31_0h = double(p_t_31_0hm); p_t_31_0m = p_t_31_0hm - p_t_31_0h; p_t_32_0hm = fma_rel<100>(p_t_31_0hm,xh,p_coeff_4hm); p_t_32_0h = double(p_t_32_0hm); p_t_32_0m = p_t_32_0hm - p_t_32_0h; p_t_33_0hm = fma_rel<100>(p_t_32_0hm,xh,p_coeff_3hm); p_t_33_0h = double(p_t_33_0hm); p_t_33_0m = p_t_33_0hm - p_t_33_0h; p_t_34_0hm = mul_rel<102>(xh,p_t_33_0hm); p_t_34_0h = double(p_t_34_0hm); p_t_34_0m = p_t_34_0hm - p_t_34_0h; p_t_35_0hml = add_rel<140>(p_coeff_2hm,p_t_34_0hm); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_t_36_0hml = mul_rel<145>(xh,p_t_35_0hml); p_t_36_0ml = p_t_36_0hml - p_t_36_0h; p_t_36_0m = double(p_t_36_0ml); p_t_36_0l = p_t_36_0ml - p_t_36_0m; p_t_36_0hm = p_t_36_0h + p_t_36_0m; overlap_p_t_36_0 = p_t_36_0m / p_t_36_0h; p_t_37_0hml = add_rel<143>(p_coeff_1hm,p_t_36_0hml); p_t_37_0ml = p_t_37_0hml - p_t_37_0h; p_t_37_0m = double(p_t_37_0ml); p_t_37_0l = p_t_37_0ml - p_t_37_0m; p_t_37_0hm = p_t_37_0h + p_t_37_0m; overlap_p_t_37_0 = p_t_37_0m / p_t_37_0h; p_t_38_0hml = mul_rel<135>(xh,p_t_37_0hml); p_t_38_0ml = p_t_38_0hml - p_t_38_0h; p_t_38_0m = double(p_t_38_0ml); p_t_38_0l = p_t_38_0ml - p_t_38_0m; p_t_38_0hm = p_t_38_0h + p_t_38_0m; overlap_p_t_38_0 = p_t_38_0m / p_t_38_0h; p_t_39_0hml = add_rel<133>(p_coeff_0hm,p_t_38_0hml); p_t_39_0ml = p_t_39_0hml - p_t_39_0h; p_t_39_0m = double(p_t_39_0ml); p_t_39_0l = p_t_39_0ml - p_t_39_0m; p_t_39_0hm = p_t_39_0h + p_t_39_0m; overlap_p_t_39_0 = p_t_39_0m / p_t_39_0h; p_reshml = p_t_39_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2hm; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_4 = p_coeff_4hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_6 = p_coeff_6hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_8 = p_coeff_8hm; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_14 = p_coeff_14h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_16 = p_coeff_16h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_18 = p_coeff_18h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_20 = p_coeff_20h; Mp_coeff_21 = p_coeff_21h; Mp_coeff_22 = p_coeff_22h; Mp_t_1_0 = Mp_coeff_22; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_21 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_20 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_19 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_18 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_17 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_16 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_15 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_14 + Mp_t_16_0; Mp_t_18_0 = Mx * Mp_t_17_0; Mp_t_19_0 = Mp_coeff_13 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_t_21_0 = Mp_coeff_12 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_11 + Mp_t_22_0; Mp_t_24_0 = Mx * Mp_t_23_0; Mp_t_25_0 = Mp_coeff_10 + Mp_t_24_0; Mp_t_26_0 = Mx * Mp_t_25_0; Mp_t_27_0 = Mp_coeff_9 + Mp_t_26_0; Mp_t_28_0 = (Mp_t_27_0 * Mx) + Mp_coeff_8; Mp_t_29_0 = (Mp_t_28_0 * Mx) + Mp_coeff_7; Mp_t_30_0 = (Mp_t_29_0 * Mx) + Mp_coeff_6; Mp_t_31_0 = (Mp_t_30_0 * Mx) + Mp_coeff_5; Mp_t_32_0 = (Mp_t_31_0 * Mx) + Mp_coeff_4; Mp_t_33_0 = (Mp_t_32_0 * Mx) + Mp_coeff_3; Mp_t_34_0 = Mx * Mp_t_33_0; Mp_t_35_0 = Mp_coeff_2 + Mp_t_34_0; Mp_t_36_0 = Mx * Mp_t_35_0; Mp_t_37_0 = Mp_coeff_1 + Mp_t_36_0; Mp_t_38_0 = Mx * Mp_t_37_0; Mp_t_39_0 = Mp_coeff_0 + Mp_t_38_0; Mp_res = Mp_t_39_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [-205674681606191b-53,-205674681606191b-453] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [205674681606835b-453,205674681606835b-53] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0h ~ p_t_28_0hm; p_t_29_0h ~ p_t_29_0hm; p_t_30_0h ~ p_t_30_0hm; p_t_31_0h ~ p_t_31_0hm; p_t_32_0h ~ p_t_32_0hm; p_t_33_0h ~ p_t_33_0hm; p_t_34_0h ~ p_t_34_0hm; p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_t_36_0hm ~ p_t_36_0hml; p_t_36_0h ~ p_t_36_0hm; p_t_36_0h ~ p_t_36_0hml; p_t_36_0m -> p_t_36_0h * overlap_p_t_36_0; p_t_36_0l / p_t_36_0m -> - ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml) / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)); (p_t_36_0hm - p_t_36_0hml) / p_t_36_0hml -> - (p_t_36_0l / p_t_36_0m) * (1 / (1 / overlap_p_t_36_0 + 1 + (p_t_36_0l / p_t_36_0m))); p_t_36_0ml -> p_t_36_0hml / ((1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) / overlap_p_t_36_0 + 1); (p_t_36_0h - p_t_36_0hm) / p_t_36_0hm -> - 1 / (1 / overlap_p_t_36_0 + 1); p_t_36_0h -> p_t_36_0hml / (overlap_p_t_36_0 / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) + 1); p_t_37_0hm ~ p_t_37_0hml; p_t_37_0h ~ p_t_37_0hm; p_t_37_0h ~ p_t_37_0hml; p_t_37_0m -> p_t_37_0h * overlap_p_t_37_0; p_t_37_0l / p_t_37_0m -> - ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml) / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)); (p_t_37_0hm - p_t_37_0hml) / p_t_37_0hml -> - (p_t_37_0l / p_t_37_0m) * (1 / (1 / overlap_p_t_37_0 + 1 + (p_t_37_0l / p_t_37_0m))); p_t_37_0ml -> p_t_37_0hml / ((1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) / overlap_p_t_37_0 + 1); (p_t_37_0h - p_t_37_0hm) / p_t_37_0hm -> - 1 / (1 / overlap_p_t_37_0 + 1); p_t_37_0h -> p_t_37_0hml / (overlap_p_t_37_0 / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) + 1); p_t_38_0hm ~ p_t_38_0hml; p_t_38_0h ~ p_t_38_0hm; p_t_38_0h ~ p_t_38_0hml; p_t_38_0m -> p_t_38_0h * overlap_p_t_38_0; p_t_38_0l / p_t_38_0m -> - ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml) / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)); (p_t_38_0hm - p_t_38_0hml) / p_t_38_0hml -> - (p_t_38_0l / p_t_38_0m) * (1 / (1 / overlap_p_t_38_0 + 1 + (p_t_38_0l / p_t_38_0m))); p_t_38_0ml -> p_t_38_0hml / ((1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) / overlap_p_t_38_0 + 1); (p_t_38_0h - p_t_38_0hm) / p_t_38_0hm -> - 1 / (1 / overlap_p_t_38_0 + 1); p_t_38_0h -> p_t_38_0hml / (overlap_p_t_38_0 / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) + 1); p_t_39_0hm ~ p_t_39_0hml; p_t_39_0h ~ p_t_39_0hm; p_t_39_0h ~ p_t_39_0hml; p_t_39_0m -> p_t_39_0h * overlap_p_t_39_0; p_t_39_0l / p_t_39_0m -> - ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml) / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)); (p_t_39_0hm - p_t_39_0hml) / p_t_39_0hml -> - (p_t_39_0l / p_t_39_0m) * (1 / (1 / overlap_p_t_39_0 + 1 + (p_t_39_0l / p_t_39_0m))); p_t_39_0ml -> p_t_39_0hml / ((1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) / overlap_p_t_39_0 + 1); (p_t_39_0h - p_t_39_0hm) / p_t_39_0hm -> - 1 / (1 / overlap_p_t_39_0 + 1); p_t_39_0h -> p_t_39_0hml / (overlap_p_t_39_0 / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hm ~ Mp_t_28_0; p_t_29_0hm ~ Mp_t_29_0; p_t_30_0hm ~ Mp_t_30_0; p_t_31_0hm ~ Mp_t_31_0; p_t_32_0hm ~ Mp_t_32_0; p_t_33_0hm ~ Mp_t_33_0; p_t_34_0hm ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_t_36_0hml ~ Mp_t_36_0; p_t_37_0hml ~ Mp_t_37_0; p_t_38_0hml ~ Mp_t_38_0; p_t_39_0hml ~ Mp_t_39_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_t_36_0hml in (0); $ p_t_36_0ml in (0); $ p_t_37_0hml in (0); $ p_t_37_0ml in (0); $ p_t_38_0hml in (0); $ p_t_38_0ml in (0); $ p_t_39_0hml in (0); $ p_t_39_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR8.gappa0000644000000000000000000004736013316017127020534 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 271231531131291488500256432295155355b-118 + (x * (59219663444275665418148029933093b-105 + (x * (91951771149333176184232653360269b-106 + (x * (92423083901517259878576132800551b-105 + (x * (106023148728483104576104226688181b-104 + (x * (2198352805121143801422469570143153b-107 + (x * (95066434162584819377607079588059b-101 + (x * (34442113666568245424103461394667b-98 + (x * (25796159680640669851948010272065b-96 + (x * (8798088372766967b-43 + (x * (215344979201967b-36 + (x * (5483368112016911b-39 + (x * (4420325172995913b-37 + (x * (450290687498503b-32 + (x * (5925847171037497b-34 + (x * (4912853910106897b-32 + (x * (8202403581885303b-31 + (x * (6888828459746951b-29 + (x * (5816597361461873b-27 + (x * (2466185133128319b-24 + (x * (8404734260175089b-24 + (x * (7429764157461459b-22 + (x * 1594661061408329b-18))))))))))))))))))))))))))))))))))))))))))) # The polynomial implemented is: 271231531131291488500256432295155355b-118 + (x * (59219663444275665418148029933093b-105 + (x * (91951771149333176184232653360269b-106 + (x * (92423083901517259878576132800551b-105 + (x * (106023148728483104576104226688181b-104 + (x * (2198352805121143801422469570143153b-107 + (x * (95066434162584819377607079588059b-101 + (x * (34442113666568245424103461394667b-98 + (x * (25796159680640669851948010272065b-96 + (x * (8798088372766967b-43 + (x * (215344979201967b-36 + (x * (5483368112016911b-39 + (x * (4420325172995913b-37 + (x * (450290687498503b-32 + (x * (5925847171037497b-34 + (x * (4912853910106897b-32 + (x * (8202403581885303b-31 + (x * (6888828459746951b-29 + (x * (5816597361461873b-27 + (x * (2466185133128319b-24 + (x * (8404734260175089b-24 + (x * (7429764157461459b-22 + (x * 1594661061408329b-18))))))))))))))))))))))))))))))))))))))))))) # The domain is [-96586942132361b-52;6036683883289b-48] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 63 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(8.16207699480864135033186812506755813956260681152343750000000000000000000000000000e-01); p_coeff_0m = double(1.10010191397663675140086054218782967355131241568134164879148861881930088202352636e-20); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.45987741598546749699494284868706017732620239257812500000000000000000000000000000e+00); p_coeff_1m = double(1.03784174873658842691949705484313598874177727812186111666648002938018180429935455e-16); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(1.13339308477403566399743795045651495456695556640625000000000000000000000000000000e+00); p_coeff_2m = double(6.19984751477578508212901866489819694255822369395765580879498202193644829094409943e-17); p_coeff_2hm = p_coeff_2h + p_coeff_2m; p_coeff_3h = double(2.27840492593338828086757530400063842535018920898437500000000000000000000000000000e+00); p_coeff_3m = double(1.29623917002581965214107410636027293901696556366158474826733026930014602839946747e-16); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_4h = double(5.22734481752082214001120519242249429225921630859375000000000000000000000000000000e+00); p_coeff_4m = double(-3.48196612292005370465186545711763157537164151090688934964134659821866080164909363e-16); p_coeff_4hm = p_coeff_4h + p_coeff_4m; p_coeff_5h = double(1.35483951862735629845246876357123255729675292968750000000000000000000000000000000e+01); p_coeff_5m = double(-4.53291289318611746967298644014774748053833951222640202827207644986629020422697067e-17); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_6h = double(3.74970966548151878328098973724991083145141601562500000000000000000000000000000000e+01); p_coeff_6m = double(3.16809448186690022670167104047109366061463187579094746837427010177634656429290771e-15); p_coeff_6hm = p_coeff_6h + p_coeff_6m; p_coeff_7h = double(1.08680147858936038574029225856065750122070312500000000000000000000000000000000000e+02); p_coeff_7m = double(-6.36137089188991992639408248982314785589906210028221522634339635260403156280517578e-15); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_8h = double(3.25593310030335430838022148236632347106933593750000000000000000000000000000000000e+02); p_coeff_8m = double(1.91287227671501587672951512619431386699611966073497626439348096027970314025878906e-14); p_coeff_8hm = p_coeff_8h + p_coeff_8m; p_coeff_9h = double(1.00022684509519501716567901894450187683105468750000000000000000000000000000000000e+03); p_coeff_10h = double(3.13368188220144656952470541000366210937500000000000000000000000000000000000000000e+03); p_coeff_11h = double(9.97418849150001005909871309995651245117187500000000000000000000000000000000000000e+03); p_coeff_12h = double(3.21620985996262825210578739643096923828125000000000000000000000000000000000000000e+04); p_coeff_13h = double(1.04841470601619919762015342712402343750000000000000000000000000000000000000000000e+05); p_coeff_14h = double(3.44929702756780723575502634048461914062500000000000000000000000000000000000000000e+05); p_coeff_15h = double(1.14386293806761899031698703765869140625000000000000000000000000000000000000000000e+06); p_coeff_16h = double(3.81954181095832167193293571472167968750000000000000000000000000000000000000000000e+06); p_coeff_17h = double(1.28314429144318234175443649291992187500000000000000000000000000000000000000000000e+07); p_coeff_18h = double(4.33370274414261654019355773925781250000000000000000000000000000000000000000000000e+07); p_coeff_19h = double(1.46996088810462892055511474609375000000000000000000000000000000000000000000000000e+08); p_coeff_20h = double(5.00961200009291708469390869140625000000000000000000000000000000000000000000000000e+08); p_coeff_21h = double(1.77139381348167872428894042968750000000000000000000000000000000000000000000000000e+09); p_coeff_22h = double(6.08314919055301284790039062500000000000000000000000000000000000000000000000000000e+09); p_t_1_0h = p_coeff_22h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_21h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_20h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_19h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_18h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_17h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_16h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_15h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0hm = p_coeff_14h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(xh,p_t_17_0hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_13h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_12h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_11h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = mul_rel<102>(xh,p_t_23_0hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = add_rel<102>(p_coeff_10h,p_t_24_0hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = mul_rel<102>(xh,p_t_25_0hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = add_rel<102>(p_coeff_9h,p_t_26_0hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hm = fma_rel<100>(p_t_27_0hm,xh,p_coeff_8hm); p_t_28_0h = double(p_t_28_0hm); p_t_28_0m = p_t_28_0hm - p_t_28_0h; p_t_29_0hm = fma_rel<100>(p_t_28_0hm,xh,p_coeff_7hm); p_t_29_0h = double(p_t_29_0hm); p_t_29_0m = p_t_29_0hm - p_t_29_0h; p_t_30_0hm = fma_rel<100>(p_t_29_0hm,xh,p_coeff_6hm); p_t_30_0h = double(p_t_30_0hm); p_t_30_0m = p_t_30_0hm - p_t_30_0h; p_t_31_0hm = fma_rel<100>(p_t_30_0hm,xh,p_coeff_5hm); p_t_31_0h = double(p_t_31_0hm); p_t_31_0m = p_t_31_0hm - p_t_31_0h; p_t_32_0hm = fma_rel<100>(p_t_31_0hm,xh,p_coeff_4hm); p_t_32_0h = double(p_t_32_0hm); p_t_32_0m = p_t_32_0hm - p_t_32_0h; p_t_33_0hm = fma_rel<100>(p_t_32_0hm,xh,p_coeff_3hm); p_t_33_0h = double(p_t_33_0hm); p_t_33_0m = p_t_33_0hm - p_t_33_0h; p_t_34_0hm = mul_rel<102>(xh,p_t_33_0hm); p_t_34_0h = double(p_t_34_0hm); p_t_34_0m = p_t_34_0hm - p_t_34_0h; p_t_35_0hml = add_rel<140>(p_coeff_2hm,p_t_34_0hm); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_t_36_0hml = mul_rel<145>(xh,p_t_35_0hml); p_t_36_0ml = p_t_36_0hml - p_t_36_0h; p_t_36_0m = double(p_t_36_0ml); p_t_36_0l = p_t_36_0ml - p_t_36_0m; p_t_36_0hm = p_t_36_0h + p_t_36_0m; overlap_p_t_36_0 = p_t_36_0m / p_t_36_0h; p_t_37_0hml = add_rel<143>(p_coeff_1hm,p_t_36_0hml); p_t_37_0ml = p_t_37_0hml - p_t_37_0h; p_t_37_0m = double(p_t_37_0ml); p_t_37_0l = p_t_37_0ml - p_t_37_0m; p_t_37_0hm = p_t_37_0h + p_t_37_0m; overlap_p_t_37_0 = p_t_37_0m / p_t_37_0h; p_t_38_0hml = mul_rel<135>(xh,p_t_37_0hml); p_t_38_0ml = p_t_38_0hml - p_t_38_0h; p_t_38_0m = double(p_t_38_0ml); p_t_38_0l = p_t_38_0ml - p_t_38_0m; p_t_38_0hm = p_t_38_0h + p_t_38_0m; overlap_p_t_38_0 = p_t_38_0m / p_t_38_0h; p_t_39_0hml = add_rel<133>(p_coeff_0hm,p_t_38_0hml); p_t_39_0ml = p_t_39_0hml - p_t_39_0h; p_t_39_0m = double(p_t_39_0ml); p_t_39_0l = p_t_39_0ml - p_t_39_0m; p_t_39_0hm = p_t_39_0h + p_t_39_0m; overlap_p_t_39_0 = p_t_39_0m / p_t_39_0h; p_reshml = p_t_39_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2hm; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_4 = p_coeff_4hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_6 = p_coeff_6hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_8 = p_coeff_8hm; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_14 = p_coeff_14h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_16 = p_coeff_16h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_18 = p_coeff_18h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_20 = p_coeff_20h; Mp_coeff_21 = p_coeff_21h; Mp_coeff_22 = p_coeff_22h; Mp_t_1_0 = Mp_coeff_22; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_21 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_20 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_19 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_18 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_17 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_16 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_15 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_14 + Mp_t_16_0; Mp_t_18_0 = Mx * Mp_t_17_0; Mp_t_19_0 = Mp_coeff_13 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_t_21_0 = Mp_coeff_12 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_11 + Mp_t_22_0; Mp_t_24_0 = Mx * Mp_t_23_0; Mp_t_25_0 = Mp_coeff_10 + Mp_t_24_0; Mp_t_26_0 = Mx * Mp_t_25_0; Mp_t_27_0 = Mp_coeff_9 + Mp_t_26_0; Mp_t_28_0 = (Mp_t_27_0 * Mx) + Mp_coeff_8; Mp_t_29_0 = (Mp_t_28_0 * Mx) + Mp_coeff_7; Mp_t_30_0 = (Mp_t_29_0 * Mx) + Mp_coeff_6; Mp_t_31_0 = (Mp_t_30_0 * Mx) + Mp_coeff_5; Mp_t_32_0 = (Mp_t_31_0 * Mx) + Mp_coeff_4; Mp_t_33_0 = (Mp_t_32_0 * Mx) + Mp_coeff_3; Mp_t_34_0 = Mx * Mp_t_33_0; Mp_t_35_0 = Mp_coeff_2 + Mp_t_34_0; Mp_t_36_0 = Mx * Mp_t_35_0; Mp_t_37_0 = Mp_coeff_1 + Mp_t_36_0; Mp_t_38_0 = Mx * Mp_t_37_0; Mp_t_39_0 = Mp_coeff_0 + Mp_t_38_0; Mp_res = Mp_t_39_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [-96586942132361b-52,-96586942132361b-452] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [6036683883289b-448,6036683883289b-48] /\ |overlap_p_t_35_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_36_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_36_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_37_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_37_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_38_0| in [1b-400,1b-30] # Verify the lower bound /\ |p_t_38_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_39_0| in [1b-400,1b-25] # Verify the lower bound /\ |p_t_39_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0h ~ p_t_28_0hm; p_t_29_0h ~ p_t_29_0hm; p_t_30_0h ~ p_t_30_0hm; p_t_31_0h ~ p_t_31_0hm; p_t_32_0h ~ p_t_32_0hm; p_t_33_0h ~ p_t_33_0hm; p_t_34_0h ~ p_t_34_0hm; p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_t_36_0hm ~ p_t_36_0hml; p_t_36_0h ~ p_t_36_0hm; p_t_36_0h ~ p_t_36_0hml; p_t_36_0m -> p_t_36_0h * overlap_p_t_36_0; p_t_36_0l / p_t_36_0m -> - ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml) / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)); (p_t_36_0hm - p_t_36_0hml) / p_t_36_0hml -> - (p_t_36_0l / p_t_36_0m) * (1 / (1 / overlap_p_t_36_0 + 1 + (p_t_36_0l / p_t_36_0m))); p_t_36_0ml -> p_t_36_0hml / ((1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) / overlap_p_t_36_0 + 1); (p_t_36_0h - p_t_36_0hm) / p_t_36_0hm -> - 1 / (1 / overlap_p_t_36_0 + 1); p_t_36_0h -> p_t_36_0hml / (overlap_p_t_36_0 / (1 + ((p_t_36_0m - p_t_36_0ml) / p_t_36_0ml)) + 1); p_t_37_0hm ~ p_t_37_0hml; p_t_37_0h ~ p_t_37_0hm; p_t_37_0h ~ p_t_37_0hml; p_t_37_0m -> p_t_37_0h * overlap_p_t_37_0; p_t_37_0l / p_t_37_0m -> - ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml) / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)); (p_t_37_0hm - p_t_37_0hml) / p_t_37_0hml -> - (p_t_37_0l / p_t_37_0m) * (1 / (1 / overlap_p_t_37_0 + 1 + (p_t_37_0l / p_t_37_0m))); p_t_37_0ml -> p_t_37_0hml / ((1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) / overlap_p_t_37_0 + 1); (p_t_37_0h - p_t_37_0hm) / p_t_37_0hm -> - 1 / (1 / overlap_p_t_37_0 + 1); p_t_37_0h -> p_t_37_0hml / (overlap_p_t_37_0 / (1 + ((p_t_37_0m - p_t_37_0ml) / p_t_37_0ml)) + 1); p_t_38_0hm ~ p_t_38_0hml; p_t_38_0h ~ p_t_38_0hm; p_t_38_0h ~ p_t_38_0hml; p_t_38_0m -> p_t_38_0h * overlap_p_t_38_0; p_t_38_0l / p_t_38_0m -> - ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml) / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)); (p_t_38_0hm - p_t_38_0hml) / p_t_38_0hml -> - (p_t_38_0l / p_t_38_0m) * (1 / (1 / overlap_p_t_38_0 + 1 + (p_t_38_0l / p_t_38_0m))); p_t_38_0ml -> p_t_38_0hml / ((1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) / overlap_p_t_38_0 + 1); (p_t_38_0h - p_t_38_0hm) / p_t_38_0hm -> - 1 / (1 / overlap_p_t_38_0 + 1); p_t_38_0h -> p_t_38_0hml / (overlap_p_t_38_0 / (1 + ((p_t_38_0m - p_t_38_0ml) / p_t_38_0ml)) + 1); p_t_39_0hm ~ p_t_39_0hml; p_t_39_0h ~ p_t_39_0hm; p_t_39_0h ~ p_t_39_0hml; p_t_39_0m -> p_t_39_0h * overlap_p_t_39_0; p_t_39_0l / p_t_39_0m -> - ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml) / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)); (p_t_39_0hm - p_t_39_0hml) / p_t_39_0hml -> - (p_t_39_0l / p_t_39_0m) * (1 / (1 / overlap_p_t_39_0 + 1 + (p_t_39_0l / p_t_39_0m))); p_t_39_0ml -> p_t_39_0hml / ((1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) / overlap_p_t_39_0 + 1); (p_t_39_0h - p_t_39_0hm) / p_t_39_0hm -> - 1 / (1 / overlap_p_t_39_0 + 1); p_t_39_0h -> p_t_39_0hml / (overlap_p_t_39_0 / (1 + ((p_t_39_0m - p_t_39_0ml) / p_t_39_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hm ~ Mp_t_28_0; p_t_29_0hm ~ Mp_t_29_0; p_t_30_0hm ~ Mp_t_30_0; p_t_31_0hm ~ Mp_t_31_0; p_t_32_0hm ~ Mp_t_32_0; p_t_33_0hm ~ Mp_t_33_0; p_t_34_0hm ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_t_36_0hml ~ Mp_t_36_0; p_t_37_0hml ~ Mp_t_37_0; p_t_38_0hml ~ Mp_t_38_0; p_t_39_0hml ~ Mp_t_39_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_t_36_0hml in (0); $ p_t_36_0ml in (0); $ p_t_37_0hml in (0); $ p_t_37_0ml in (0); $ p_t_38_0hml in (0); $ p_t_38_0ml in (0); $ p_t_39_0hml in (0); $ p_t_39_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinAccuR9.gappa0000644000000000000000000004107113316017127020526 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 10495927159903232351211685275788667b-113 + (x * ((-114617556493442511624717420939755b-110) + (x * (27305479231796324762706248415393b-110 + (x * ((-69064186447523516588334408074399b-113) + (x * (100011328992979175025945315294869b-115 + (x * ((-78413912811472400588428747081623b-116) + (x * (16197729753218861570784898965837b-115 + (x * ((-55561816015974041716967640671199b-118) + (x * (1359649836545143b-64 + (x * ((-4899041428846357b-67) + (x * (8978414956877191b-69 + (x * ((-4171527322798521b-69) + (x * (1960809304100323b-69 + (x * ((-3723031201800671b-71) + (x * (7128608706414571b-73 + (x * ((-6874476813806547b-74) + (x * (6671643449666827b-75 + (x * ((-3255007506604485b-75) + (x * (6385219779544523b-77 + (x * ((-802479419572625b-75) + (x * 6343351034255153b-79))))))))))))))))))))))))))))))))))))))) # The polynomial implemented is: 10495927159903232351211685275788667b-113 + (x * ((-114617556493442511624717420939755b-110) + (x * (27305479231796324762706248415393b-110 + (x * ((-69064186447523516588334408074399b-113) + (x * (100011328992979175025945315294869b-115 + (x * ((-78413912811472400588428747081623b-116) + (x * (16197729753218861570784898965837b-115 + (x * ((-55561816015974041716967640671199b-118) + (x * (1359649836545143b-64 + (x * ((-4899041428846357b-67) + (x * (8978414956877191b-69 + (x * ((-4171527322798521b-69) + (x * (1960809304100323b-69 + (x * ((-3723031201800671b-71) + (x * (7128608706414571b-73 + (x * ((-6874476813806547b-74) + (x * (6671643449666827b-75 + (x * ((-3255007506604485b-75) + (x * (6385219779544523b-77 + (x * ((-802479419572625b-75) + (x * 6343351034255153b-79))))))))))))))))))))))))))))))))))))))) # The domain is [-140737488356209b-50;1125899906835577b-53] # The free variable x is a double precision number, the result p_res* is stored on a triple-double number. # The code produces 57 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(1.01072102056824553173441927356179803609848022460937500000000000000000000000000000e+00); p_coeff_0m = double(1.39129934510313097947345056199237890632902839379463674068793110905062349047511816e-20); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(-8.82981536812866424357437722392205614596605300903320312500000000000000000000000000e-02); p_coeff_1m = double(2.41792724167186006978828150786347532734726726246399404474107797113902051933109760e-18); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(2.10353760393441266418612656252662418410181999206542968750000000000000000000000000e-02); p_coeff_2m = double(1.08336737333055412851633739558643005025128690376628494418387305131545872427523136e-18); p_coeff_2hm = p_coeff_2h + p_coeff_2m; p_coeff_3h = double(-6.65063923820143239329372164547748980112373828887939453125000000000000000000000000e-03); p_coeff_3m = double(-3.26520170221686406454105223534078119197675928213141878161951403569673857418820262e-19); p_coeff_3hm = p_coeff_3h + p_coeff_3m; p_coeff_4h = double(2.40768516606927433787443959545271354727447032928466796875000000000000000000000000e-03); p_coeff_4m = double(-1.97265146971483602383336920707508202998297784121844945705998020102356349525507540e-19); p_coeff_4hm = p_coeff_4h + p_coeff_4m; p_coeff_5h = double(-9.43873142126153748948658162021274620201438665390014648437500000000000000000000000e-04); p_coeff_5m = double(-1.00627526920533400945274389592272919368733418903938436114037235924456581415142864e-20); p_coeff_5hm = p_coeff_5h + p_coeff_5m; p_coeff_6h = double(3.89946159535203471478703729502512942417524755001068115234375000000000000000000000e-04); p_coeff_6m = double(-1.68716106145871574328060887792714981312318371720271803146373734705321112414821982e-21); p_coeff_6hm = p_coeff_6h + p_coeff_6m; p_coeff_7h = double(-1.67200258171404256496775375673280450428137555718421936035156250000000000000000000e-04); p_coeff_7m = double(1.19784970040097203700724589956273625590162416200800595011445592863452702658833005e-20); p_coeff_7hm = p_coeff_7h + p_coeff_7m; p_coeff_8h = double(7.37067653300902520495385683574340873747132718563079833984375000000000000000000000e-05); p_coeff_9h = double(-3.31971960015731878111157338029357788400375284254550933837890625000000000000000000e-05); p_coeff_10h = double(1.52100265651915579552836896293221968790021492168307304382324218750000000000000000e-05); p_coeff_11h = double(-7.06684216556374468498364499469133193088055122643709182739257812500000000000000000e-06); p_coeff_12h = double(3.32174016771150049044582924784307920162973459810018539428710937500000000000000000e-06); p_coeff_13h = double(-1.57676504579047108034364592377141178758392925374209880828857421875000000000000000e-06); p_coeff_14h = double(7.54770805302124936124669781628560016883966454770416021347045898437500000000000000e-07); p_coeff_15h = double(-3.63931772276869473623270951831432107326236291555687785148620605468750000000000000e-07); p_coeff_16h = double(1.76596931693785619791949872102454488498324280953966081142425537109375000000000000e-07); p_coeff_17h = double(-8.61593313016896376739609539688324879591618810081854462623596191406250000000000000e-08); p_coeff_18h = double(4.22538400682347749169000988064132107169257324130740016698837280273437500000000000e-08); p_coeff_19h = double(-2.12414533709850257115170054159070112120843987213447690010070800781250000000000000e-08); p_coeff_20h = double(1.04941939883081181921218176284101020190320241454173810780048370361328125000000000e-08); p_t_1_0h = p_coeff_20h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_19h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_18h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_17h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_16h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_15h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_14h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_13h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0hm = p_coeff_12h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(xh,p_t_17_0hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_11h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_t_21_0hm = add_rel<102>(p_coeff_10h,p_t_20_0hm); p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_9h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_t_24_0hm = mul_rel<102>(xh,p_t_23_0hm); p_t_24_0h = double(p_t_24_0hm); p_t_24_0m = p_t_24_0hm - p_t_24_0h; p_t_25_0hm = add_rel<102>(p_coeff_8h,p_t_24_0hm); p_t_25_0h = double(p_t_25_0hm); p_t_25_0m = p_t_25_0hm - p_t_25_0h; p_t_26_0hm = fma_rel<100>(p_t_25_0hm,xh,p_coeff_7hm); p_t_26_0h = double(p_t_26_0hm); p_t_26_0m = p_t_26_0hm - p_t_26_0h; p_t_27_0hm = fma_rel<100>(p_t_26_0hm,xh,p_coeff_6hm); p_t_27_0h = double(p_t_27_0hm); p_t_27_0m = p_t_27_0hm - p_t_27_0h; p_t_28_0hm = fma_rel<100>(p_t_27_0hm,xh,p_coeff_5hm); p_t_28_0h = double(p_t_28_0hm); p_t_28_0m = p_t_28_0hm - p_t_28_0h; p_t_29_0hm = fma_rel<100>(p_t_28_0hm,xh,p_coeff_4hm); p_t_29_0h = double(p_t_29_0hm); p_t_29_0m = p_t_29_0hm - p_t_29_0h; p_t_30_0hm = fma_rel<100>(p_t_29_0hm,xh,p_coeff_3hm); p_t_30_0h = double(p_t_30_0hm); p_t_30_0m = p_t_30_0hm - p_t_30_0h; p_t_31_0hm = fma_rel<100>(p_t_30_0hm,xh,p_coeff_2hm); p_t_31_0h = double(p_t_31_0hm); p_t_31_0m = p_t_31_0hm - p_t_31_0h; p_t_32_0hm = mul_rel<102>(xh,p_t_31_0hm); p_t_32_0h = double(p_t_32_0hm); p_t_32_0m = p_t_32_0hm - p_t_32_0h; p_t_33_0hml = add_rel<140>(p_coeff_1hm,p_t_32_0hm); p_t_33_0ml = p_t_33_0hml - p_t_33_0h; p_t_33_0m = double(p_t_33_0ml); p_t_33_0l = p_t_33_0ml - p_t_33_0m; p_t_33_0hm = p_t_33_0h + p_t_33_0m; overlap_p_t_33_0 = p_t_33_0m / p_t_33_0h; p_t_34_0hml = mul_rel<145>(xh,p_t_33_0hml); p_t_34_0ml = p_t_34_0hml - p_t_34_0h; p_t_34_0m = double(p_t_34_0ml); p_t_34_0l = p_t_34_0ml - p_t_34_0m; p_t_34_0hm = p_t_34_0h + p_t_34_0m; overlap_p_t_34_0 = p_t_34_0m / p_t_34_0h; p_t_35_0hml = add_rel<143>(p_coeff_0hm,p_t_34_0hml); p_t_35_0ml = p_t_35_0hml - p_t_35_0h; p_t_35_0m = double(p_t_35_0ml); p_t_35_0l = p_t_35_0ml - p_t_35_0m; p_t_35_0hm = p_t_35_0h + p_t_35_0m; overlap_p_t_35_0 = p_t_35_0m / p_t_35_0h; p_reshml = p_t_35_0hml; p_resml = p_reshml - p_resh; p_resm = double(p_resml); p_resl = p_resml - p_resm; p_reshm = p_resh + p_resm; overlap_p_res = p_resm / p_resh; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2hm; Mp_coeff_3 = p_coeff_3hm; Mp_coeff_4 = p_coeff_4hm; Mp_coeff_5 = p_coeff_5hm; Mp_coeff_6 = p_coeff_6hm; Mp_coeff_7 = p_coeff_7hm; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_14 = p_coeff_14h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_16 = p_coeff_16h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_18 = p_coeff_18h; Mp_coeff_19 = p_coeff_19h; Mp_coeff_20 = p_coeff_20h; Mp_t_1_0 = Mp_coeff_20; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_19 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_18 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_17 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_16 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_15 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_14 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_13 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_12 + Mp_t_16_0; Mp_t_18_0 = Mx * Mp_t_17_0; Mp_t_19_0 = Mp_coeff_11 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_t_21_0 = Mp_coeff_10 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_9 + Mp_t_22_0; Mp_t_24_0 = Mx * Mp_t_23_0; Mp_t_25_0 = Mp_coeff_8 + Mp_t_24_0; Mp_t_26_0 = (Mp_t_25_0 * Mx) + Mp_coeff_7; Mp_t_27_0 = (Mp_t_26_0 * Mx) + Mp_coeff_6; Mp_t_28_0 = (Mp_t_27_0 * Mx) + Mp_coeff_5; Mp_t_29_0 = (Mp_t_28_0 * Mx) + Mp_coeff_4; Mp_t_30_0 = (Mp_t_29_0 * Mx) + Mp_coeff_3; Mp_t_31_0 = (Mp_t_30_0 * Mx) + Mp_coeff_2; Mp_t_32_0 = Mx * Mp_t_31_0; Mp_t_33_0 = Mp_coeff_1 + Mp_t_32_0; Mp_t_34_0 = Mx * Mp_t_33_0; Mp_t_35_0 = Mp_coeff_0 + Mp_t_34_0; Mp_res = Mp_t_35_0; # Definition of the relative arithmetical error epsilon = (p_reshml - Mp_res) / Mp_res; # Implication to prove {(( x in [-140737488356209b-50,-140737488356209b-450] /\ |overlap_p_t_33_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_33_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_34_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_34_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_35_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] ) \/ ( x in [1125899906835577b-453,1125899906835577b-53] /\ |overlap_p_t_33_0| in [1b-400,1b-45] # Verify the lower bound /\ |p_t_33_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_34_0| in [1b-400,1b-40] # Verify the lower bound /\ |p_t_34_0ml| in [1b-1021,1b1023] /\ |overlap_p_t_35_0| in [1b-400,1b-35] # Verify the lower bound /\ |p_t_35_0ml| in [1b-1021,1b1023] /\ |overlap_p_res| in [1b-400,1b-52] # Verify the lower bound /\ |p_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; p_t_24_0h ~ p_t_24_0hm; p_t_25_0h ~ p_t_25_0hm; p_t_26_0h ~ p_t_26_0hm; p_t_27_0h ~ p_t_27_0hm; p_t_28_0h ~ p_t_28_0hm; p_t_29_0h ~ p_t_29_0hm; p_t_30_0h ~ p_t_30_0hm; p_t_31_0h ~ p_t_31_0hm; p_t_32_0h ~ p_t_32_0hm; p_t_33_0hm ~ p_t_33_0hml; p_t_33_0h ~ p_t_33_0hm; p_t_33_0h ~ p_t_33_0hml; p_t_33_0m -> p_t_33_0h * overlap_p_t_33_0; p_t_33_0l / p_t_33_0m -> - ((p_t_33_0m - p_t_33_0ml) / p_t_33_0ml) / (1 + ((p_t_33_0m - p_t_33_0ml) / p_t_33_0ml)); (p_t_33_0hm - p_t_33_0hml) / p_t_33_0hml -> - (p_t_33_0l / p_t_33_0m) * (1 / (1 / overlap_p_t_33_0 + 1 + (p_t_33_0l / p_t_33_0m))); p_t_33_0ml -> p_t_33_0hml / ((1 + ((p_t_33_0m - p_t_33_0ml) / p_t_33_0ml)) / overlap_p_t_33_0 + 1); (p_t_33_0h - p_t_33_0hm) / p_t_33_0hm -> - 1 / (1 / overlap_p_t_33_0 + 1); p_t_33_0h -> p_t_33_0hml / (overlap_p_t_33_0 / (1 + ((p_t_33_0m - p_t_33_0ml) / p_t_33_0ml)) + 1); p_t_34_0hm ~ p_t_34_0hml; p_t_34_0h ~ p_t_34_0hm; p_t_34_0h ~ p_t_34_0hml; p_t_34_0m -> p_t_34_0h * overlap_p_t_34_0; p_t_34_0l / p_t_34_0m -> - ((p_t_34_0m - p_t_34_0ml) / p_t_34_0ml) / (1 + ((p_t_34_0m - p_t_34_0ml) / p_t_34_0ml)); (p_t_34_0hm - p_t_34_0hml) / p_t_34_0hml -> - (p_t_34_0l / p_t_34_0m) * (1 / (1 / overlap_p_t_34_0 + 1 + (p_t_34_0l / p_t_34_0m))); p_t_34_0ml -> p_t_34_0hml / ((1 + ((p_t_34_0m - p_t_34_0ml) / p_t_34_0ml)) / overlap_p_t_34_0 + 1); (p_t_34_0h - p_t_34_0hm) / p_t_34_0hm -> - 1 / (1 / overlap_p_t_34_0 + 1); p_t_34_0h -> p_t_34_0hml / (overlap_p_t_34_0 / (1 + ((p_t_34_0m - p_t_34_0ml) / p_t_34_0ml)) + 1); p_t_35_0hm ~ p_t_35_0hml; p_t_35_0h ~ p_t_35_0hm; p_t_35_0h ~ p_t_35_0hml; p_t_35_0m -> p_t_35_0h * overlap_p_t_35_0; p_t_35_0l / p_t_35_0m -> - ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml) / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)); (p_t_35_0hm - p_t_35_0hml) / p_t_35_0hml -> - (p_t_35_0l / p_t_35_0m) * (1 / (1 / overlap_p_t_35_0 + 1 + (p_t_35_0l / p_t_35_0m))); p_t_35_0ml -> p_t_35_0hml / ((1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) / overlap_p_t_35_0 + 1); (p_t_35_0h - p_t_35_0hm) / p_t_35_0hm -> - 1 / (1 / overlap_p_t_35_0 + 1); p_t_35_0h -> p_t_35_0hml / (overlap_p_t_35_0 / (1 + ((p_t_35_0m - p_t_35_0ml) / p_t_35_0ml)) + 1); p_reshm ~ p_reshml; p_resh ~ p_reshm; p_resh ~ p_reshml; p_resm -> p_resh * overlap_p_res; p_resl / p_resm -> - ((p_resm - p_resml) / p_resml) / (1 + ((p_resm - p_resml) / p_resml)); (p_reshm - p_reshml) / p_reshml -> - (p_resl / p_resm) * (1 / (1 / overlap_p_res + 1 + (p_resl / p_resm))); p_resml -> p_reshml / ((1 + ((p_resm - p_resml) / p_resml)) / overlap_p_res + 1); (p_resh - p_reshm) / p_reshm -> - 1 / (1 / overlap_p_res + 1); p_resh -> p_reshml / (overlap_p_res / (1 + ((p_resm - p_resml) / p_resml)) + 1); # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_t_24_0hm ~ Mp_t_24_0; p_t_25_0hm ~ Mp_t_25_0; p_t_26_0hm ~ Mp_t_26_0; p_t_27_0hm ~ Mp_t_27_0; p_t_28_0hm ~ Mp_t_28_0; p_t_29_0hm ~ Mp_t_29_0; p_t_30_0hm ~ Mp_t_30_0; p_t_31_0hm ~ Mp_t_31_0; p_t_32_0hm ~ Mp_t_32_0; p_t_33_0hml ~ Mp_t_33_0; p_t_34_0hml ~ Mp_t_34_0; p_t_35_0hml ~ Mp_t_35_0; p_reshml ~ Mp_res; # Dichotomies for triple-double decomposition $ p_t_33_0hml in (0); $ p_t_33_0ml in (0); $ p_t_34_0hml in (0); $ p_t_34_0ml in (0); $ p_t_35_0hml in (0); $ p_t_35_0ml in (0); $ p_reshml in (0); $ p_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR0.gappa0000644000000000000000000001515713316017127020724 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: x * (1b0 + ((x^(1b1)) * (6004799503160663b-55 + ((x^(1b1)) * (2702159776421267b-55 + ((x^(1b1)) * (6433713754276237b-57 + ((x^(1b1)) * (273656221440481b-53 + ((x^(1b1)) * (1612086811548785b-56 + ((x^(1b1)) * (2500589232146671b-57 + ((x^(1b1)) * (1008591508159575b-56 + ((x^(1b1)) * (6411982820477177b-59 + ((x^(1b1)) * 7401443504515565b-59)))))))))))))))))) # The polynomial implemented is: x * (1b0 + ((x^(1b1)) * (6004799503160663b-55 + ((x^(1b1)) * (2702159776421267b-55 + ((x^(1b1)) * (6433713754276237b-57 + ((x^(1b1)) * (273656221440481b-53 + ((x^(1b1)) * (1612086811548785b-56 + ((x^(1b1)) * (2500589232146671b-57 + ((x^(1b1)) * (1008591508159575b-56 + ((x^(1b1)) * (6411982820477177b-59 + ((x^(1b1)) * 7401443504515565b-59)))))))))))))))))) # The domain is [1b-54;9007199254740983b-55] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 32 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_1h = double(1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00); p_coeff_3h = double(1.66666666666666712925959359381522517651319503784179687500000000000000000000000000e-01); p_coeff_5h = double(7.49999999999713951037705328417359851300716400146484375000000000000000000000000000e-02); p_coeff_7h = double(4.46428571490314687886247213555179769173264503479003906250000000000000000000000000e-02); p_coeff_9h = double(3.03819437875142428495678359468001872301101684570312500000000000000000000000000000e-02); p_coeff_11h = double(2.23721986984502102524530187110940460115671157836914062500000000000000000000000000e-02); p_coeff_13h = double(1.73513233791185925158906400156411109492182731628417968750000000000000000000000000e-02); p_coeff_15h = double(1.39970189350021451124561622236797120422124862670898437500000000000000000000000000e-02); p_coeff_17h = double(1.11230171262417399519195626567125145811587572097778320312500000000000000000000000e-02); p_coeff_19h = double(1.28394578033992016324882357025671808514744043350219726562500000000000000000000000e-02); p_x_0_pow2hm = xh * xh; p_x_0_pow2h = double(p_x_0_pow2hm); p_x_0_pow2m = p_x_0_pow2hm - p_x_0_pow2h; p_t_1_0h = p_coeff_19h; p_t_2_0h = double(p_t_1_0h * p_x_0_pow2h); p_t_3_0h = double(p_coeff_17h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * p_x_0_pow2h); p_t_5_0h = double(p_coeff_15h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * p_x_0_pow2h); p_t_7_0h = double(p_coeff_13h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * p_x_0_pow2h); p_t_9_0h = double(p_coeff_11h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * p_x_0_pow2h); p_t_11_0h = double(p_coeff_9h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * p_x_0_pow2h); p_t_13_0h = double(p_coeff_7h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * p_x_0_pow2h); p_t_15_0h = double(p_coeff_5h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * p_x_0_pow2h); p_t_17_0hm = p_coeff_3h + p_t_16_0h; p_t_17_0h = double(p_t_17_0hm); p_t_17_0m = p_t_17_0hm - p_t_17_0h; p_t_18_0hm = mul_rel<102>(p_t_17_0hm,p_x_0_pow2hm); p_t_18_0h = double(p_t_18_0hm); p_t_18_0m = p_t_18_0hm - p_t_18_0h; p_t_19_0hm = add_rel<102>(p_coeff_1h,p_t_18_0hm); p_t_19_0h = double(p_t_19_0hm); p_t_19_0m = p_t_19_0hm - p_t_19_0h; p_t_20_0hm = mul_rel<102>(xh,p_t_19_0hm); p_t_20_0h = double(p_t_20_0hm); p_t_20_0m = p_t_20_0hm - p_t_20_0h; p_reshm = p_t_20_0hm; p_resh = p_t_20_0h; p_resm = p_t_20_0m; # Mathematical equivalents Mx = x; Mp_coeff_1 = p_coeff_1h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_13 = p_coeff_13h; Mp_coeff_15 = p_coeff_15h; Mp_coeff_17 = p_coeff_17h; Mp_coeff_19 = p_coeff_19h; Mp_x_0_pow2 = Mx * Mx; Mp_t_1_0 = Mp_coeff_19; Mp_t_2_0 = Mp_t_1_0 * Mp_x_0_pow2; Mp_t_3_0 = Mp_coeff_17 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mp_x_0_pow2; Mp_t_5_0 = Mp_coeff_15 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mp_x_0_pow2; Mp_t_7_0 = Mp_coeff_13 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mp_x_0_pow2; Mp_t_9_0 = Mp_coeff_11 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mp_x_0_pow2; Mp_t_11_0 = Mp_coeff_9 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mp_x_0_pow2; Mp_t_13_0 = Mp_coeff_7 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mp_x_0_pow2; Mp_t_15_0 = Mp_coeff_5 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mp_x_0_pow2; Mp_t_17_0 = Mp_coeff_3 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mp_x_0_pow2; Mp_t_19_0 = Mp_coeff_1 + Mp_t_18_0; Mp_t_20_0 = Mx * Mp_t_19_0; Mp_res = Mp_t_20_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [1b-54,9007199254740983b-55] ) \/ ( x in [-9007199254740983b-55,-1b-54] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_x_0_pow2h ~ p_x_0_pow2hm; p_t_17_0h ~ p_t_17_0hm; p_t_18_0h ~ p_t_18_0hm; p_t_19_0h ~ p_t_19_0hm; p_t_20_0h ~ p_t_20_0hm; # Meta-Hints for Horner scheme p_x_0_pow2hm ~ Mp_x_0_pow2; p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0hm ~ Mp_t_17_0; p_t_18_0hm ~ Mp_t_18_0; p_t_19_0hm ~ Mp_t_19_0; p_t_20_0hm ~ Mp_t_20_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR1.gappa0000644000000000000000000001654313316017127020725 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 3183456225869665121297930434727189b-113 + (x * (85096975362484429898305796608495b-106 + (x * (1568372518556091b-53 + (x * (2253096245490285b-53 + (x * (1510242280185791b-53 + (x * (3634933609551149b-54 + (x * (7165193180030863b-55 + (x * (8499199876434095b-55 + (x * (1206650223448851b-52 + (x * (2926133895132309b-53 + (x * (13826886836375b-45 + (x * (8924243571351707b-54 + (x * 5562679466946017b-53))))))))))))))))))))))) # The polynomial implemented is: 3183456225869665121297930434727189b-113 + (x * (85096975362484429898305796608495b-106 + (x * (1568372518556091b-53 + (x * (2253096245490285b-53 + (x * (1510242280185791b-53 + (x * (3634933609551149b-54 + (x * (7165193180030863b-55 + (x * (8499199876434095b-55 + (x * (1206650223448851b-52 + (x * (2926133895132309b-53 + (x * (13826886836375b-45 + (x * (8924243571351707b-54 + (x * 5562679466946017b-53))))))))))))))))))))))) # The domain is [-466363011288839b-53;932726022577599b-54] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 37 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(3.06555683602418194144689778113388456404209136962890625000000000000000000000000000e-01); p_coeff_0m = double(1.37864228855288786229514205458277346294726855883500333047053665325165638932958245e-19); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.04890120337530645677759366662940010428428649902343750000000000000000000000000000e+00); p_coeff_1m = double(-1.03997489957388085277493589447823941146606896923035995294881672634801361709833145e-16); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(1.74124328129031780143520791170885786414146423339843750000000000000000000000000000e-01); p_coeff_3h = double(2.50143932843980842939402009506011381745338439941406250000000000000000000000000000e-01); p_coeff_4h = double(1.67670575222466200493443011509953066706657409667968750000000000000000000000000000e-01); p_coeff_5h = double(2.01779349315375722273557812513899989426136016845703125000000000000000000000000000e-01); p_coeff_6h = double(1.98874061108935212827120153633586596697568893432617187500000000000000000000000000e-01); p_coeff_7h = double(2.35900184842710441968094414733059238642454147338867187500000000000000000000000000e-01); p_coeff_8h = double(2.67930172148400869147621961019467562437057495117187500000000000000000000000000000e-01); p_coeff_9h = double(3.24866122351198272077965611970284953713417053222656250000000000000000000000000000e-01); p_coeff_10h = double(3.92983759990528369598905555903911590576171875000000000000000000000000000000000000e-01); p_coeff_11h = double(4.95395034513885057503301823089714162051677703857421875000000000000000000000000000e-01); p_coeff_12h = double(6.17581482281306048953695153613807633519172668457031250000000000000000000000000000e-01); p_t_1_0h = p_coeff_12h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_11h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_10h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_9h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_8h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_7h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_6h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_5h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0h = double(p_coeff_4h + p_t_16_0h); p_t_18_0h = double(p_t_17_0h * xh); p_t_19_0h = double(p_coeff_3h + p_t_18_0h); p_t_20_0h = double(p_t_19_0h * xh); p_t_21_0hm = p_coeff_2h + p_t_20_0h; p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = fma_rel<100>(p_t_21_0hm,xh,p_coeff_1hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = fma_rel<100>(p_t_22_0hm,xh,p_coeff_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_reshm = p_t_23_0hm; p_resh = p_t_23_0h; p_resm = p_t_23_0m; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_4 = p_coeff_4h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_6 = p_coeff_6h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_t_1_0 = Mp_coeff_12; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_11 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_10 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_9 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_8 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_7 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_6 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_5 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_4 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mx; Mp_t_19_0 = Mp_coeff_3 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mx; Mp_t_21_0 = Mp_coeff_2 + Mp_t_20_0; Mp_t_22_0 = (Mp_t_21_0 * Mx) + Mp_coeff_1; Mp_t_23_0 = (Mp_t_22_0 * Mx) + Mp_coeff_0; Mp_res = Mp_t_23_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [-466363011288839b-53,-466363011288839b-453] ) \/ ( x in [932726022577599b-454,932726022577599b-54] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0h ~ Mp_t_17_0; p_t_18_0h ~ Mp_t_18_0; p_t_19_0h ~ Mp_t_19_0; p_t_20_0h ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR2.gappa0000644000000000000000000001655313316017127020727 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 268636756605111637357595545192172111b-119 + (x * (44120131993499861117550393673295b-105 + (x * (2278907903703317b-53 + (x * (5983541037681123b-54 + (x * (2638503127167829b-53 + (x * (6622388527030519b-54 + (x * (7950889475864811b-54 + (x * (5238009708732451b-53 + (x * (3491644690235915b-52 + (x * (4815737384658755b-52 + (x * (3373487667168671b-51 + (x * (1215099289485353b-49 + (x * 6911419428626897b-51))))))))))))))))))))))) # The polynomial implemented is: 268636756605111637357595545192172111b-119 + (x * (44120131993499861117550393673295b-105 + (x * (2278907903703317b-53 + (x * (5983541037681123b-54 + (x * (2638503127167829b-53 + (x * (6622388527030519b-54 + (x * (7950889475864811b-54 + (x * (5238009708732451b-53 + (x * (3491644690235915b-52 + (x * (4815737384658755b-52 + (x * (3373487667168671b-51 + (x * (1215099289485353b-49 + (x * 6911419428626897b-51))))))))))))))))))))))) # The domain is [-715705849514187b-54;178926462378499b-52] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 37 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(4.04199666960039116769820566332782618701457977294921875000000000000000000000000000e-01); p_coeff_0m = double(-7.29414577305862355348006038497258990002592122212580672446953500287492033749003895e-21); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.08764522696446319649510314775398001074790954589843750000000000000000000000000000e+00); p_coeff_1m = double(7.18002807945845121967809924279486007735232949667977808694274699519155547022819519e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(2.53009602569167157959384439891437068581581115722656250000000000000000000000000000e-01); p_coeff_3h = double(3.32153251441154206968775497443857602775096893310546875000000000000000000000000000e-01); p_coeff_4h = double(2.92932692232720115477206945797661319375038146972656250000000000000000000000000000e-01); p_coeff_5h = double(3.67616411036137902268450261544785462319850921630859375000000000000000000000000000e-01); p_coeff_6h = double(4.41363028117747802081538566199014894664287567138671875000000000000000000000000000e-01); p_coeff_7h = double(5.81535898184487698436839764326578006148338317871093750000000000000000000000000000e-01); p_coeff_8h = double(7.75300865782017067928677533927839249372482299804687500000000000000000000000000000e-01); p_coeff_9h = double(1.06930850499925678143142704357160255312919616699218750000000000000000000000000000e+00); p_coeff_10h = double(1.49812947255186612594002326659392565488815307617187500000000000000000000000000000e+00); p_coeff_11h = double(2.15844993342769164712535712169483304023742675781250000000000000000000000000000000e+00); p_coeff_12h = double(3.06928679300128992579743680835235863924026489257812500000000000000000000000000000e+00); p_t_1_0h = p_coeff_12h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_11h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_10h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_9h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_8h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_7h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_6h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_5h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0h = double(p_coeff_4h + p_t_16_0h); p_t_18_0h = double(p_t_17_0h * xh); p_t_19_0h = double(p_coeff_3h + p_t_18_0h); p_t_20_0h = double(p_t_19_0h * xh); p_t_21_0hm = p_coeff_2h + p_t_20_0h; p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = fma_rel<100>(p_t_21_0hm,xh,p_coeff_1hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = fma_rel<100>(p_t_22_0hm,xh,p_coeff_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_reshm = p_t_23_0hm; p_resh = p_t_23_0h; p_resm = p_t_23_0m; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_4 = p_coeff_4h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_6 = p_coeff_6h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_t_1_0 = Mp_coeff_12; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_11 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_10 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_9 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_8 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_7 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_6 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_5 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_4 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mx; Mp_t_19_0 = Mp_coeff_3 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mx; Mp_t_21_0 = Mp_coeff_2 + Mp_t_20_0; Mp_t_22_0 = (Mp_t_21_0 * Mx) + Mp_coeff_1; Mp_t_23_0 = (Mp_t_22_0 * Mx) + Mp_coeff_0; Mp_res = Mp_t_23_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [-715705849514187b-54,-715705849514187b-454] ) \/ ( x in [178926462378499b-452,178926462378499b-52] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0h ~ Mp_t_17_0; p_t_18_0h ~ Mp_t_18_0; p_t_19_0h ~ Mp_t_19_0; p_t_20_0h ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR3.gappa0000644000000000000000000001654213316017127020726 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 630003272697881842133904116649941b-110 + (x * (22930469560677484970259027045179b-104 + (x * (758992598782411b-51 + (x * (7959118817390667b-54 + (x * (1064903604618827b-51 + (x * (5844783312361271b-53 + (x * (8131347476778009b-53 + (x * (1508230740643617b-50 + (x * (2296555345676609b-50 + (x * (7188218310357077b-51 + (x * (5730917143769297b-50 + (x * (4688813330751791b-49 + (x * 7638382581357819b-49))))))))))))))))))))))) # The polynomial implemented is: 630003272697881842133904116649941b-110 + (x * (22930469560677484970259027045179b-104 + (x * (758992598782411b-51 + (x * (7959118817390667b-54 + (x * (1064903604618827b-51 + (x * (5844783312361271b-53 + (x * (8131347476778009b-53 + (x * (1508230740643617b-50 + (x * (2296555345676609b-50 + (x * (7188218310357077b-51 + (x * (5730917143769297b-50 + (x * (4688813330751791b-49 + (x * 7638382581357819b-49))))))))))))))))))))))) # The domain is [-603367941593347b-54;301683970796841b-53] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 37 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(4.85336867180323261461438733022077940404415130615234375000000000000000000000000000e-01); p_coeff_0m = double(2.48687685471405101032185714779683260767432502103446885499682394993214984424412251e-18); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.13055943592368102201817237073555588722229003906250000000000000000000000000000000e+00); p_coeff_1m = double(8.31884808460703843039094509953103826114589262451931572783792034897487610578536987e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(3.37060423475326498277127029723487794399261474609375000000000000000000000000000000e-01); p_coeff_3h = double(4.41819848339723264540879199557821266353130340576171875000000000000000000000000000e-01); p_coeff_4h = double(4.72912200341658373048403518623672425746917724609375000000000000000000000000000000e-01); p_coeff_5h = double(6.48901300732837138518505071260733529925346374511718750000000000000000000000000000e-01); p_coeff_6h = double(9.02760918994661598624418274994241073727607727050781250000000000000000000000000000e-01); p_coeff_7h = double(1.33957799576799718721531462506391108036041259765625000000000000000000000000000000e+00); p_coeff_8h = double(2.03975089767692541187216193065978586673736572265625000000000000000000000000000000e+00); p_coeff_9h = double(3.19221018967622649498139253410045057535171508789062500000000000000000000000000000e+00); p_coeff_10h = double(5.09007693218536960699793780804611742496490478515625000000000000000000000000000000e+00); p_coeff_11h = double(8.32900562875201266876956651685759425163269042968750000000000000000000000000000000e+00); p_coeff_12h = double(1.35684931403507018643495030119083821773529052734375000000000000000000000000000000e+01); p_t_1_0h = p_coeff_12h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_11h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_10h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_9h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_8h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_7h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_6h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_5h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0h = double(p_coeff_4h + p_t_16_0h); p_t_18_0h = double(p_t_17_0h * xh); p_t_19_0h = double(p_coeff_3h + p_t_18_0h); p_t_20_0h = double(p_t_19_0h * xh); p_t_21_0hm = p_coeff_2h + p_t_20_0h; p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = fma_rel<100>(p_t_21_0hm,xh,p_coeff_1hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = fma_rel<100>(p_t_22_0hm,xh,p_coeff_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_reshm = p_t_23_0hm; p_resh = p_t_23_0h; p_resm = p_t_23_0m; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_4 = p_coeff_4h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_6 = p_coeff_6h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_t_1_0 = Mp_coeff_12; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_11 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_10 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_9 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_8 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_7 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_6 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_5 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_4 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mx; Mp_t_19_0 = Mp_coeff_3 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mx; Mp_t_21_0 = Mp_coeff_2 + Mp_t_20_0; Mp_t_22_0 = (Mp_t_21_0 * Mx) + Mp_coeff_1; Mp_t_23_0 = (Mp_t_22_0 * Mx) + Mp_coeff_0; Mp_res = Mp_t_23_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [-603367941593347b-54,-603367941593347b-454] ) \/ ( x in [301683970796841b-453,301683970796841b-53] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0h ~ Mp_t_17_0; p_t_18_0h ~ Mp_t_18_0; p_t_19_0h ~ Mp_t_19_0; p_t_20_0h ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR4.gappa0000644000000000000000000001654113316017127020726 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 2897411029384279446550734201912699b-112 + (x * (1530198189661957827573916764927897b-110 + (x * (3906404311867243b-53 + (x * (2666766777791871b-52 + (x * (3357549051583063b-52 + (x * (2563180742222195b-51 + (x * (3977769854047b-41 + (x * (6829960164420871b-51 + (x * (5902661651242291b-50 + (x * (2617002045792421b-48 + (x * (4732026594888409b-48 + (x * (2194629853394353b-46 + (x * 4057612944155747b-46))))))))))))))))))))))) # The polynomial implemented is: 2897411029384279446550734201912699b-112 + (x * (1530198189661957827573916764927897b-110 + (x * (3906404311867243b-53 + (x * (2666766777791871b-52 + (x * (3357549051583063b-52 + (x * (2563180742222195b-51 + (x * (3977769854047b-41 + (x * (6829960164420871b-51 + (x * (5902661651242291b-50 + (x * (2617002045792421b-48 + (x * (4732026594888409b-48 + (x * (2194629853394353b-46 + (x * 4057612944155747b-46))))))))))))))))))))))) # The domain is [-66447228468955b-51;265788913875259b-53] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 37 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(5.58021066268902909968119274708442389965057373046875000000000000000000000000000000e-01); p_coeff_0m = double(9.12034392087434999453497016043152989309974709890359127750780743326686206273734570e-20); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.17882180572684136521388609253335744142532348632812500000000000000000000000000000e+00); p_coeff_1m = double(2.42941652280796864299660766500640409154688815034626482580737416583360754884779453e-18); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(4.33698001053000381510571514809271320700645446777343750000000000000000000000000000e-01); p_coeff_3h = double(5.92141175601994751431789154594298452138900756835937500000000000000000000000000000e-01); p_coeff_4h = double(7.45525652675174788086565058620180934667587280273437500000000000000000000000000000e-01); p_coeff_5h = double(1.13828091051635160724231354834046214818954467773437500000000000000000000000000000e+00); p_coeff_6h = double(1.80888030356391027453355491161346435546875000000000000000000000000000000000000000e+00); p_coeff_7h = double(3.03311161272506835118178969423752278089523315429687500000000000000000000000000000e+00); p_coeff_8h = double(5.24261669742490976631188459577970206737518310546875000000000000000000000000000000e+00); p_coeff_9h = double(9.29745896553562900521683332044631242752075195312500000000000000000000000000000000e+00); p_coeff_10h = double(1.68115356121078072249019896844401955604553222656250000000000000000000000000000000e+01); p_coeff_11h = double(3.11875660002322234731764183379709720611572265625000000000000000000000000000000000e+01); p_coeff_12h = double(5.76621480399203818478781613521277904510498046875000000000000000000000000000000000e+01); p_t_1_0h = p_coeff_12h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_11h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_10h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_9h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_8h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_7h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_6h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_5h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0h = double(p_coeff_4h + p_t_16_0h); p_t_18_0h = double(p_t_17_0h * xh); p_t_19_0h = double(p_coeff_3h + p_t_18_0h); p_t_20_0h = double(p_t_19_0h * xh); p_t_21_0hm = p_coeff_2h + p_t_20_0h; p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = fma_rel<100>(p_t_21_0hm,xh,p_coeff_1hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = fma_rel<100>(p_t_22_0hm,xh,p_coeff_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_reshm = p_t_23_0hm; p_resh = p_t_23_0h; p_resm = p_t_23_0m; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_4 = p_coeff_4h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_6 = p_coeff_6h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_t_1_0 = Mp_coeff_12; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_11 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_10 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_9 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_8 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_7 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_6 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_5 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_4 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mx; Mp_t_19_0 = Mp_coeff_3 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mx; Mp_t_21_0 = Mp_coeff_2 + Mp_t_20_0; Mp_t_22_0 = (Mp_t_21_0 * Mx) + Mp_coeff_1; Mp_t_23_0 = (Mp_t_22_0 * Mx) + Mp_coeff_0; Mp_res = Mp_t_23_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [-66447228468955b-51,-66447228468955b-451] ) \/ ( x in [265788913875259b-453,265788913875259b-53] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0h ~ Mp_t_17_0; p_t_18_0h ~ Mp_t_18_0; p_t_19_0h ~ Mp_t_19_0; p_t_20_0h ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR5.gappa0000644000000000000000000001654613316017127020734 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 51984188076577765969954972216329553b-116 + (x * (400377354559914758555498144461373b-108 + (x * (1238400191224977b-51 + (x * (7235452395425177b-53 + (x * (2644145021253385b-51 + (x * (2269626114756713b-50 + (x * (4108409004761789b-50 + (x * (7812107017201229b-50 + (x * (7668886762282561b-49 + (x * (7720327329412313b-48 + (x * (990526711637311b-44 + (x * (8352794841960659b-46 + (x * 2243673169183011b-43))))))))))))))))))))))) # The polynomial implemented is: 51984188076577765969954972216329553b-116 + (x * (400377354559914758555498144461373b-108 + (x * (1238400191224977b-51 + (x * (7235452395425177b-53 + (x * (2644145021253385b-51 + (x * (2269626114756713b-50 + (x * (4108409004761789b-50 + (x * (7812107017201229b-50 + (x * (7668886762282561b-49 + (x * (7720327329412313b-48 + (x * (990526711637311b-44 + (x * (8352794841960659b-46 + (x * 2243673169183011b-43))))))))))))))))))))))) # The domain is [-120145772825149b-52;60072886412803b-51] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 37 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(6.25736902820868912122875826753443107008934020996093750000000000000000000000000000e-01); p_coeff_0m = double(1.09771341515678393197247834713042073087550408801910172083143857335585380496922880e-20); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.23375797792237640315704538807040080428123474121093750000000000000000000000000000e+00); p_coeff_1m = double(-1.59140559577392273960428308971385735880640476257478696520131222769123269245028496e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(5.49960162399266483390647408668883144855499267578125000000000000000000000000000000e-01); p_coeff_3h = double(8.03296584298027416259913024987326934933662414550781250000000000000000000000000000e-01); p_coeff_4h = double(1.17423627321739276752055047836620360612869262695312500000000000000000000000000000e+00); p_coeff_5h = double(2.01583293591475243289323771023191511631011962890625000000000000000000000000000000e+00); p_coeff_6h = double(3.64900021733109003463368935626931488513946533203125000000000000000000000000000000e+00); p_coeff_7h = double(6.93854486506604661855135418591089546680450439453125000000000000000000000000000000e+00); p_coeff_8h = double(1.36226794507666699729497850057668983936309814453125000000000000000000000000000000e+01); p_coeff_9h = double(2.74281125080204652988413727143779397010803222656250000000000000000000000000000000e+01); p_coeff_10h = double(5.63049247624184658889134880155324935913085937500000000000000000000000000000000000e+01); p_coeff_11h = double(1.18700353964991606403600599151104688644409179687500000000000000000000000000000000e+02); p_coeff_12h = double(2.55076107485252919104823376983404159545898437500000000000000000000000000000000000e+02); p_t_1_0h = p_coeff_12h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_11h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_10h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_9h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_8h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_7h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_6h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_5h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0h = double(p_coeff_4h + p_t_16_0h); p_t_18_0h = double(p_t_17_0h * xh); p_t_19_0h = double(p_coeff_3h + p_t_18_0h); p_t_20_0h = double(p_t_19_0h * xh); p_t_21_0hm = p_coeff_2h + p_t_20_0h; p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = fma_rel<100>(p_t_21_0hm,xh,p_coeff_1hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = fma_rel<100>(p_t_22_0hm,xh,p_coeff_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_reshm = p_t_23_0hm; p_resh = p_t_23_0h; p_resm = p_t_23_0m; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_4 = p_coeff_4h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_6 = p_coeff_6h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_t_1_0 = Mp_coeff_12; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_11 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_10 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_9 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_8 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_7 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_6 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_5 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_4 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mx; Mp_t_19_0 = Mp_coeff_3 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mx; Mp_t_21_0 = Mp_coeff_2 + Mp_t_20_0; Mp_t_22_0 = (Mp_t_21_0 * Mx) + Mp_coeff_1; Mp_t_23_0 = (Mp_t_22_0 * Mx) + Mp_coeff_0; Mp_res = Mp_t_23_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [-120145772825149b-52,-120145772825149b-452] ) \/ ( x in [60072886412803b-451,60072886412803b-51] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0h ~ Mp_t_17_0; p_t_18_0h ~ Mp_t_18_0; p_t_19_0h ~ Mp_t_19_0; p_t_20_0h ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR6.gappa0000644000000000000000000001653413316017127020732 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 224072655290838820901547103663141b-108 + (x * (52617200066848308315160320054687b-105 + (x * (1564981109275549b-51 + (x * (4992165443239819b-52 + (x * (8442373737503053b-52 + (x * (1027827836419783b-48 + (x * (132850146592389b-44 + (x * (4608740736026111b-48 + (x * (2581118930247463b-46 + (x * (5928868654976949b-46 + (x * (108504530938057b-39 + (x * (522450050528739b-40 + (x * 5043156194756227b-42))))))))))))))))))))))) # The polynomial implemented is: 224072655290838820901547103663141b-108 + (x * (52617200066848308315160320054687b-105 + (x * (1564981109275549b-51 + (x * (4992165443239819b-52 + (x * (8442373737503053b-52 + (x * (1027827836419783b-48 + (x * (132850146592389b-44 + (x * (4608740736026111b-48 + (x * (2581118930247463b-46 + (x * (5928868654976949b-46 + (x * (108504530938057b-39 + (x * (522450050528739b-40 + (x * 5043156194756227b-42))))))))))))))))))))))) # The domain is [-110485440722351b-52;55242720361239b-51] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 37 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(6.90477178468776764397318856936180964112281799316406250000000000000000000000000000e-01); p_coeff_0m = double(3.39469506786599975391257859730058491397981612722623695477253136232320684939622879e-18); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.29711412734153253012436834978871047496795654296875000000000000000000000000000000e+00); p_coeff_1m = double(-4.95712225725049321877947559927504147795821978121980078135777603165479376912117004e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(6.94991224248453054457286270917393267154693603515625000000000000000000000000000000e-01); p_coeff_3h = double(1.10848340356457941702217340207425877451896667480468750000000000000000000000000000e+00); p_coeff_4h = double(1.87458354117332537391860114439623430371284484863281250000000000000000000000000000e+00); p_coeff_5h = double(3.65157801390048675216348783578723669052124023437500000000000000000000000000000000e+00); p_coeff_6h = double(7.55165652847091450894367881119251251220703125000000000000000000000000000000000000e+00); p_coeff_7h = double(1.63735362549250531571942701702937483787536621093750000000000000000000000000000000e+01); p_coeff_8h = double(3.66799061204043113093575811944901943206787109375000000000000000000000000000000000e+01); p_coeff_9h = double(8.42542910813925374213795294053852558135986328125000000000000000000000000000000000e+01); p_coeff_10h = double(1.97368592013039233279414474964141845703125000000000000000000000000000000000000000e+02); p_coeff_11h = double(4.75165552896886765665840357542037963867187500000000000000000000000000000000000000e+02); p_coeff_12h = double(1.14668095983602756859909277409315109252929687500000000000000000000000000000000000e+03); p_t_1_0h = p_coeff_12h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_11h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_10h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_9h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_8h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_7h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_6h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_5h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0h = double(p_coeff_4h + p_t_16_0h); p_t_18_0h = double(p_t_17_0h * xh); p_t_19_0h = double(p_coeff_3h + p_t_18_0h); p_t_20_0h = double(p_t_19_0h * xh); p_t_21_0hm = p_coeff_2h + p_t_20_0h; p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = fma_rel<100>(p_t_21_0hm,xh,p_coeff_1hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = fma_rel<100>(p_t_22_0hm,xh,p_coeff_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_reshm = p_t_23_0hm; p_resh = p_t_23_0h; p_resm = p_t_23_0m; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_4 = p_coeff_4h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_6 = p_coeff_6h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_t_1_0 = Mp_coeff_12; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_11 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_10 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_9 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_8 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_7 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_6 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_5 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_4 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mx; Mp_t_19_0 = Mp_coeff_3 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mx; Mp_t_21_0 = Mp_coeff_2 + Mp_t_20_0; Mp_t_22_0 = (Mp_t_21_0 * Mx) + Mp_coeff_1; Mp_t_23_0 = (Mp_t_22_0 * Mx) + Mp_coeff_0; Mp_res = Mp_t_23_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [-110485440722351b-52,-110485440722351b-452] ) \/ ( x in [55242720361239b-451,55242720361239b-51] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0h ~ Mp_t_17_0; p_t_18_0h ~ Mp_t_18_0; p_t_19_0h ~ Mp_t_19_0; p_t_20_0h ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR7.gappa0000644000000000000000000001654713316017127020737 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 31303540725427994415236316926498277b-115 + (x * (55627180908427023057028403875349b-105 + (x * (3973482098975897b-52 + (x * (7048617650465021b-52 + (x * (6914118691349309b-51 + (x * (3859522469193581b-49 + (x * (4591567794769115b-48 + (x * (357643827686125b-43 + (x * (3685198568657065b-45 + (x * (4866801803033539b-44 + (x * (1638677454183417b-41 + (x * (4544581697576865b-41 + (x * 6325975157511843b-40))))))))))))))))))))))) # The polynomial implemented is: 31303540725427994415236316926498277b-115 + (x * (55627180908427023057028403875349b-105 + (x * (3973482098975897b-52 + (x * (7048617650465021b-52 + (x * (6914118691349309b-51 + (x * (3859522469193581b-49 + (x * (4591567794769115b-48 + (x * (357643827686125b-43 + (x * (3685198568657065b-45 + (x * (4866801803033539b-44 + (x * (1638677454183417b-41 + (x * (4544581697576865b-41 + (x * 6325975157511843b-40))))))))))))))))))))))) # The domain is [-205674681606191b-53;205674681606835b-53] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 37 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(7.53605330605588874526290510402759537100791931152343750000000000000000000000000000e-01); p_coeff_0m = double(-6.81399026788433814240085924387948818667013384621768622671778015131849315366707742e-20); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.37131588394733516800272354885237291455268859863281250000000000000000000000000000e+00); p_coeff_1m = double(5.75522635997281408409017033924079017806689197384387157718776961701223626732826233e-17); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(8.82290262843787198576706032326910644769668579101562500000000000000000000000000000e-01); p_coeff_3h = double(1.56510752146510800919543271447764709591865539550781250000000000000000000000000000e+00); p_coeff_4h = double(3.07048550645086359978108703217003494501113891601562500000000000000000000000000000e+00); p_coeff_5h = double(6.85588913497096008597964100772514939308166503906250000000000000000000000000000000e+00); p_coeff_6h = double(1.63125257116160859993669873801991343498229980468750000000000000000000000000000000e+01); p_coeff_7h = double(4.06593958002900990322814323008060455322265625000000000000000000000000000000000000e+01); p_coeff_8h = double(1.04739642911711854367240448482334613800048828125000000000000000000000000000000000e+02); p_coeff_9h = double(2.76645653402371124229830456897616386413574218750000000000000000000000000000000000e+02); p_coeff_10h = double(7.45184231247284060373203828930854797363281250000000000000000000000000000000000000e+02); p_coeff_11h = double(2.06663648786018939063069410622119903564453125000000000000000000000000000000000000e+03); p_coeff_12h = double(5.75344088930418638483388349413871765136718750000000000000000000000000000000000000e+03); p_t_1_0h = p_coeff_12h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_11h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_10h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_9h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_8h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_7h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_6h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_5h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0h = double(p_coeff_4h + p_t_16_0h); p_t_18_0h = double(p_t_17_0h * xh); p_t_19_0h = double(p_coeff_3h + p_t_18_0h); p_t_20_0h = double(p_t_19_0h * xh); p_t_21_0hm = p_coeff_2h + p_t_20_0h; p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = fma_rel<100>(p_t_21_0hm,xh,p_coeff_1hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = fma_rel<100>(p_t_22_0hm,xh,p_coeff_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_reshm = p_t_23_0hm; p_resh = p_t_23_0h; p_resm = p_t_23_0m; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_4 = p_coeff_4h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_6 = p_coeff_6h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_t_1_0 = Mp_coeff_12; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_11 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_10 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_9 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_8 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_7 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_6 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_5 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_4 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mx; Mp_t_19_0 = Mp_coeff_3 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mx; Mp_t_21_0 = Mp_coeff_2 + Mp_t_20_0; Mp_t_22_0 = (Mp_t_21_0 * Mx) + Mp_coeff_1; Mp_t_23_0 = (Mp_t_22_0 * Mx) + Mp_coeff_0; Mp_res = Mp_t_23_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [-205674681606191b-53,-205674681606191b-453] ) \/ ( x in [205674681606835b-453,205674681606835b-53] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0h ~ Mp_t_17_0; p_t_18_0h ~ Mp_t_18_0; p_t_19_0h ~ Mp_t_19_0; p_t_20_0h ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR8.gappa0000644000000000000000000001653713316017127020737 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 33903941391411436062548621898578847b-115 + (x * (118439326888551330576771230425869b-106 + (x * (1276087168563161b-50 + (x * (2565255893858397b-50 + (x * (5885467043083027b-50 + (x * (7627068437138929b-49 + (x * (5277247200778677b-47 + (x * (3823843648895481b-45 + (x * (5727900287195667b-44 + (x * (549830323588319b-39 + (x * (6890204176375445b-41 + (x * (5570398459840501b-39 + (x * 1124915619397507b-35))))))))))))))))))))))) # The polynomial implemented is: 33903941391411436062548621898578847b-115 + (x * (118439326888551330576771230425869b-106 + (x * (1276087168563161b-50 + (x * (2565255893858397b-50 + (x * (5885467043083027b-50 + (x * (7627068437138929b-49 + (x * (5277247200778677b-47 + (x * (3823843648895481b-45 + (x * (5727900287195667b-44 + (x * (549830323588319b-39 + (x * (6890204176375445b-41 + (x * (5570398459840501b-39 + (x * 1124915619397507b-35))))))))))))))))))))))) # The domain is [-96586942132361b-52;6036683883289b-48] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 37 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(8.16207699480864135033186812506755813956260681152343750000000000000000000000000000e-01); p_coeff_0m = double(1.13998759014226814082709277093003596330685011160153518976201336698750310461036861e-20); p_coeff_0hm = p_coeff_0h + p_coeff_0m; p_coeff_1h = double(1.45987741598546749699494284868706017732620239257812500000000000000000000000000000e+00); p_coeff_1m = double(1.00585284375539824516783136958955684505754068277117579954804682529356796294450760e-16); p_coeff_1hm = p_coeff_1h + p_coeff_1m; p_coeff_2h = double(1.13339308477403566399743795045651495456695556640625000000000000000000000000000000e+00); p_coeff_3h = double(2.27840492593358323603069948148913681507110595703125000000000000000000000000000000e+00); p_coeff_4h = double(5.22734481752265178755578745040111243724822998046875000000000000000000000000000000e+00); p_coeff_5h = double(1.35483951828855158083797505241818726062774658203125000000000000000000000000000000e+01); p_coeff_6h = double(3.74970966332361186346133763436228036880493164062500000000000000000000000000000000e+01); p_coeff_7h = double(1.08680173096203162685924326069653034210205078125000000000000000000000000000000000e+02); p_coeff_8h = double(3.25593435218005822662235004827380180358886718750000000000000000000000000000000000e+02); p_coeff_9h = double(1.00013553235534163832198828458786010742187500000000000000000000000000000000000000e+03); p_coeff_10h = double(3.13330209627358499346883036196231842041015625000000000000000000000000000000000000e+03); p_coeff_11h = double(1.01324957719780304614687338471412658691406250000000000000000000000000000000000000e+04); p_coeff_12h = double(3.27393534650766232516616582870483398437500000000000000000000000000000000000000000e+04); p_t_1_0h = p_coeff_12h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_11h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_10h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_9h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_8h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_7h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_6h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_5h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0h = double(p_coeff_4h + p_t_16_0h); p_t_18_0h = double(p_t_17_0h * xh); p_t_19_0h = double(p_coeff_3h + p_t_18_0h); p_t_20_0h = double(p_t_19_0h * xh); p_t_21_0hm = p_coeff_2h + p_t_20_0h; p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = fma_rel<100>(p_t_21_0hm,xh,p_coeff_1hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = fma_rel<100>(p_t_22_0hm,xh,p_coeff_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_reshm = p_t_23_0hm; p_resh = p_t_23_0h; p_resm = p_t_23_0m; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0hm; Mp_coeff_1 = p_coeff_1hm; Mp_coeff_2 = p_coeff_2h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_4 = p_coeff_4h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_6 = p_coeff_6h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_coeff_12 = p_coeff_12h; Mp_t_1_0 = Mp_coeff_12; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_11 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_10 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_9 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_8 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_7 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_6 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_5 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_4 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mx; Mp_t_19_0 = Mp_coeff_3 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mx; Mp_t_21_0 = Mp_coeff_2 + Mp_t_20_0; Mp_t_22_0 = (Mp_t_21_0 * Mx) + Mp_coeff_1; Mp_t_23_0 = (Mp_t_22_0 * Mx) + Mp_coeff_0; Mp_res = Mp_t_23_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [-96586942132361b-52,-96586942132361b-452] ) \/ ( x in [6036683883289b-448,6036683883289b-48] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0h ~ Mp_t_17_0; p_t_18_0h ~ Mp_t_18_0; p_t_19_0h ~ Mp_t_19_0; p_t_20_0h ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/asin/asinQuickR9.gappa0000644000000000000000000001545713316017127020740 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 2275941405803339b-51 + (x * ((-6362552512264725b-56) + (x * (3031517174156445b-57 + (x * ((-1916916249275531b-58) + (x * (2775872004195495b-60 + (x * ((-8705693150762623b-63) + (x * (3596618703231213b-63 + (x * ((-3084299124302975b-64) + (x * (1359599812531581b-64 + (x * ((-4899514141103273b-67) + (x * (566891145413529b-65 + (x * (-8316266913880567b-70)))))))))))))))))))))) # The polynomial implemented is: 2275941405803339b-51 + (x * ((-6362552512264725b-56) + (x * (3031517174156445b-57 + (x * ((-1916916249275531b-58) + (x * (2775872004195495b-60 + (x * ((-8705693150762623b-63) + (x * (3596618703231213b-63 + (x * ((-3084299124302975b-64) + (x * (1359599812531581b-64 + (x * ((-4899514141103273b-67) + (x * (566891145413529b-65 + (x * (-8316266913880567b-70)))))))))))))))))))))) # The domain is [-140737488356209b-50;1125899906835577b-53] # The free variable x is a double precision number, the result p_res* is stored on a double-double number. # The code produces 36 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code p_coeff_0h = double(1.01072102056824553173441927356179803609848022460937500000000000000000000000000000e+00); p_coeff_1h = double(-8.82981536812866424357437722392205614596605300903320312500000000000000000000000000e-02); p_coeff_2h = double(2.10353760393442237863759203264635289087891578674316406250000000000000000000000000e-02); p_coeff_3h = double(-6.65063923819934552095212154654291225597262382507324218750000000000000000000000000e-03); p_coeff_4h = double(2.40768516599235756631136595729003602173179388046264648437500000000000000000000000e-03); p_coeff_5h = double(-9.43873142704901193882072174545783127541653811931610107421875000000000000000000000e-04); p_coeff_6h = double(3.89946181164527888064752492169873221428133547306060791015625000000000000000000000e-04); p_coeff_7h = double(-1.67200190558221219085804909454395783541258424520492553710937500000000000000000000e-04); p_coeff_8h = double(7.37040535228812338126858083597880977322347462177276611328125000000000000000000000e-05); p_coeff_9h = double(-3.32003992244226181431050737291599261880037374794483184814453125000000000000000000e-05); p_coeff_10h = double(1.53656152855036036170705004977321550541091710329055786132812500000000000000000000e-05); p_coeff_11h = double(-7.04415207421768136802344914548790200115035986527800559997558593750000000000000000e-06); p_t_1_0h = p_coeff_11h; p_t_2_0h = double(p_t_1_0h * xh); p_t_3_0h = double(p_coeff_10h + p_t_2_0h); p_t_4_0h = double(p_t_3_0h * xh); p_t_5_0h = double(p_coeff_9h + p_t_4_0h); p_t_6_0h = double(p_t_5_0h * xh); p_t_7_0h = double(p_coeff_8h + p_t_6_0h); p_t_8_0h = double(p_t_7_0h * xh); p_t_9_0h = double(p_coeff_7h + p_t_8_0h); p_t_10_0h = double(p_t_9_0h * xh); p_t_11_0h = double(p_coeff_6h + p_t_10_0h); p_t_12_0h = double(p_t_11_0h * xh); p_t_13_0h = double(p_coeff_5h + p_t_12_0h); p_t_14_0h = double(p_t_13_0h * xh); p_t_15_0h = double(p_coeff_4h + p_t_14_0h); p_t_16_0h = double(p_t_15_0h * xh); p_t_17_0h = double(p_coeff_3h + p_t_16_0h); p_t_18_0h = double(p_t_17_0h * xh); p_t_19_0h = double(p_coeff_2h + p_t_18_0h); p_t_20_0h = double(p_t_19_0h * xh); p_t_21_0hm = p_coeff_1h + p_t_20_0h; p_t_21_0h = double(p_t_21_0hm); p_t_21_0m = p_t_21_0hm - p_t_21_0h; p_t_22_0hm = mul_rel<102>(xh,p_t_21_0hm); p_t_22_0h = double(p_t_22_0hm); p_t_22_0m = p_t_22_0hm - p_t_22_0h; p_t_23_0hm = add_rel<102>(p_coeff_0h,p_t_22_0hm); p_t_23_0h = double(p_t_23_0hm); p_t_23_0m = p_t_23_0hm - p_t_23_0h; p_reshm = p_t_23_0hm; p_resh = p_t_23_0h; p_resm = p_t_23_0m; # Mathematical equivalents Mx = x; Mp_coeff_0 = p_coeff_0h; Mp_coeff_1 = p_coeff_1h; Mp_coeff_2 = p_coeff_2h; Mp_coeff_3 = p_coeff_3h; Mp_coeff_4 = p_coeff_4h; Mp_coeff_5 = p_coeff_5h; Mp_coeff_6 = p_coeff_6h; Mp_coeff_7 = p_coeff_7h; Mp_coeff_8 = p_coeff_8h; Mp_coeff_9 = p_coeff_9h; Mp_coeff_10 = p_coeff_10h; Mp_coeff_11 = p_coeff_11h; Mp_t_1_0 = Mp_coeff_11; Mp_t_2_0 = Mp_t_1_0 * Mx; Mp_t_3_0 = Mp_coeff_10 + Mp_t_2_0; Mp_t_4_0 = Mp_t_3_0 * Mx; Mp_t_5_0 = Mp_coeff_9 + Mp_t_4_0; Mp_t_6_0 = Mp_t_5_0 * Mx; Mp_t_7_0 = Mp_coeff_8 + Mp_t_6_0; Mp_t_8_0 = Mp_t_7_0 * Mx; Mp_t_9_0 = Mp_coeff_7 + Mp_t_8_0; Mp_t_10_0 = Mp_t_9_0 * Mx; Mp_t_11_0 = Mp_coeff_6 + Mp_t_10_0; Mp_t_12_0 = Mp_t_11_0 * Mx; Mp_t_13_0 = Mp_coeff_5 + Mp_t_12_0; Mp_t_14_0 = Mp_t_13_0 * Mx; Mp_t_15_0 = Mp_coeff_4 + Mp_t_14_0; Mp_t_16_0 = Mp_t_15_0 * Mx; Mp_t_17_0 = Mp_coeff_3 + Mp_t_16_0; Mp_t_18_0 = Mp_t_17_0 * Mx; Mp_t_19_0 = Mp_coeff_2 + Mp_t_18_0; Mp_t_20_0 = Mp_t_19_0 * Mx; Mp_t_21_0 = Mp_coeff_1 + Mp_t_20_0; Mp_t_22_0 = Mx * Mp_t_21_0; Mp_t_23_0 = Mp_coeff_0 + Mp_t_22_0; Mp_res = Mp_t_23_0; # Definition of the relative arithmetical error epsilon = (p_reshm - Mp_res) / Mp_res; # Implication to prove {(( x in [-140737488356209b-50,-140737488356209b-450] ) \/ ( x in [1125899906835577b-453,1125899906835577b-53] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition p_t_21_0h ~ p_t_21_0hm; p_t_22_0h ~ p_t_22_0hm; p_t_23_0h ~ p_t_23_0hm; # Meta-Hints for Horner scheme p_t_1_0h ~ Mp_t_1_0; p_t_2_0h ~ Mp_t_2_0; p_t_3_0h ~ Mp_t_3_0; p_t_4_0h ~ Mp_t_4_0; p_t_5_0h ~ Mp_t_5_0; p_t_6_0h ~ Mp_t_6_0; p_t_7_0h ~ Mp_t_7_0; p_t_8_0h ~ Mp_t_8_0; p_t_9_0h ~ Mp_t_9_0; p_t_10_0h ~ Mp_t_10_0; p_t_11_0h ~ Mp_t_11_0; p_t_12_0h ~ Mp_t_12_0; p_t_13_0h ~ Mp_t_13_0; p_t_14_0h ~ Mp_t_14_0; p_t_15_0h ~ Mp_t_15_0; p_t_16_0h ~ Mp_t_16_0; p_t_17_0h ~ Mp_t_17_0; p_t_18_0h ~ Mp_t_18_0; p_t_19_0h ~ Mp_t_19_0; p_t_20_0h ~ Mp_t_20_0; p_t_21_0hm ~ Mp_t_21_0; p_t_22_0hm ~ Mp_t_22_0; p_t_23_0hm ~ Mp_t_23_0; p_reshm ~ Mp_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/exp-td/exp-td-accurate1.gappa0000644000000000000000000001045513316017127022105 0ustar 00000000000000# Gappa proof for the relative error of a polynomial approximation of exp(rh)-1 # abs(rh) \leq 2^(-12) # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Rounding operators and sequences definition @double = float; @Add22 = add_rel<102>; @Mul22 = mul_rel<102>; @Mul23 = mul_rel<149>; # Instantiating of constants accPolyC7 = double(_accPolyC7); accPolyC6 = double(_accPolyC6); accPolyC5 = double(_accPolyC5); accPolyC4h = double(_accPolyC4h); accPolyC4l = double(_accPolyC4l); accPolyC3h = double(_accPolyC3h); accPolyC3l = double(_accPolyC3l); AccPolyC4hl = accPolyC4h + accPolyC4l; AccPolyC3hl = accPolyC3h + accPolyC3l; #Translation of the C code highPoly double= accPolyC5 + rh * (accPolyC6 + rh * accPolyC7); T1hl = rh * highPoly; T2hl = Add22(AccPolyC4hl,T1hl); T3hl = Mul22(rh,T2hl); T4hl = Add22(AccPolyC3hl,T3hl); RhSquarehl = rh * rh; RhCubehml = Mul23(rh,RhSquarehl); RhSquareHalfhl = 0.5 * RhSquarehl; LowPolyhml = rh + RhSquareHalfhl; HighPolyMulthml = mul_rel<148>(T4hl,RhCubehml); Phml = add_rel<145>(LowPolyhml,HighPolyMulthml); #Mathematical definitions corresponding to the code MHighPoly = accPolyC5 + rh * (accPolyC6 + rh * accPolyC7); MT1 = rh * MHighPoly; MT2 = AccPolyC4hl + MT1; MT3 = rh * MT2; MT4 = AccPolyC3hl + MT3; MRhSquare = rh * rh; MRhCube = rh * MRhSquare; MRhSquareHalf = 0.5 * MRhSquare; MLowPoly = rh + MRhSquareHalf; MHighPolyMult = MT4 * MRhCube; MP = MLowPoly + MHighPolyMult; #Definition of the errors epsilonApprox = (MP - MExpM1) / MExpM1; epsilonApproxRh = (Phml - MExpM1) / MExpM1; epsilon1 = (highPoly - MHighPoly) / MHighPoly; epsilon2 = (T1hl - MT1) / MT1; epsilon3 = (T2hl - MT2) / MT2; epsilon4 = (T3hl - MT3) / MT3; epsilon5 = (T4hl - MT4) / MT4; epsilon6 = (RhSquarehl - MRhSquare) / MRhSquare; epsilon7 = (RhCubehml - MRhCube) / MRhCube; epsilon8 = (RhSquareHalfhl - MRhSquareHalf) / MRhSquareHalf; epsilon9 = (LowPolyhml - MLowPoly) / MLowPoly; epsilon10 = (HighPolyMulthml - MHighPolyMult) / MHighPolyMult; epsilon11 = (Phml - MP) / MP; epsilon12 = ((LowPolyhml + HighPolyMulthml) - MP)/MP; epsilon13 = (Phml - (LowPolyhml + HighPolyMulthml)) / (LowPolyhml + HighPolyMulthml); # Additional mathematical definitions (values divided by rh) MRhHalf = rh * 0.5; #Logical implication to prove { ( rh in [-_rhmax,-1b-800] /\ epsilonApprox in [-_epsilonApproxAccurate, _epsilonApproxAccurate] -> epsilonApproxRh in [-1b-112,1b-112] /\ Phml in [-1b-12,-1b-820] ) /\ ( rh in [1b-800,_rhmax] /\ epsilonApprox in [-_epsilonApproxAccurate, _epsilonApproxAccurate] -> epsilonApproxRh in [-1b-112,1b-112] /\ Phml in [1b-820,1b-12] ) /\ ( rh in [-1b-30,-1b-800] /\ epsilonApprox in [-_epsilonApproxSpecial, _epsilonApproxSpecial] -> epsilonApproxRh in [-1b-144,1b-144] /\ Phml in [-1b-29,-1b-820] ) /\ ( rh in [1b-800,1b-30] /\ epsilonApprox in [-_epsilonApproxSpecial, _epsilonApproxSpecial] -> epsilonApproxRh in [-1b-144,1b-144] /\ Phml in [-1b-820,1b-29] ) } #Hints for composing the errors in the different levels epsilonApproxRh -> epsilon11 + epsilonApprox + epsilon11 * epsilonApprox; epsilon11 -> epsilon12 + epsilon13 + epsilon12 * epsilon13; epsilon12 -> (epsilon9 + epsilon9 * MRhHalf + epsilon10 * MRhSquare * MT4) / (1 + MRhHalf + MRhSquare * MT4); #Hints for convincing Gappa that some terms do not cross zero MLowPoly -> rh * (1 + MRhHalf); interval-3.2.0/src/crlibm/gappa/exp-td/exp-td-accurate2.gappa0000644000000000000000000001051513316017127022103 0ustar 00000000000000# Gappa proof for the relative error of the approximation of (exp(rh)-1)*(exp(rm)-1)*(exp(rl)-1) # abs(rh) \leq 2^(-12) using the proof for the approximation of exp(rh)-1 # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Rounding operators and sequences definition @double = float; @Add22 = add_rel<102>; @Mul22 = mul_rel<102>; @Mul23 = mul_rel<149>; #Different approximations of Rhml and definition of pl Rhml = rh + rm + rl; Rml = rm + rl; pl = double(Phml - Phm); #Translation of the C code RmlMultPhl = Mul22(Rml,Phm); Qhl = Add22(Rml,RmlMultPhl); FullPolyhml = add_rel<142>(Qhl,Phml); #Additional mathematical definitions MExpRmM1PExpRlM1 = MExpRmM1 + MExpRlM1; MExpRmM1MultExpRlM1 = MExpRmM1 * MExpRlM1; #Mathematical definitions corresponding to the code MExpRmM1PExpRlM1MultExpRhM1 = MExpRmM1PExpRlM1 * MExpRhM1; MExpLowerM1 = MExpRmM1PExpRlM1 + MExpRmM1PExpRlM1MultExpRhM1; MExpRhmlM1 = (MExpLowerM1 + MExpRhM1) + MExpRmM1MultExpRlM1; #Definition of the errors epsilonApproxRh = (Phml - MExpRhM1) / MExpRhM1; epsilonApproxRm = (rm - MExpRmM1) / MExpRmM1; epsilonApproxRl = (rl - MExpRlM1) / MExpRlM1; epsilonApproxPhm = (Phm - Phml) / Phml; deltaApproxExpRhml = FullPolyhml - MExpRhmlM1; delta1 = Phml - MExpRhM1; delta2 = FullPolyhml - (Qhl + Phml); delta3 = Qhl - MExpLowerM1; delta4 = Qhl - (Rml + RmlMultPhl); delta5 = Rml - MExpRmM1PExpRlM1; delta6 = RmlMultPhl - MExpRmM1PExpRlM1MultExpRhM1; delta7 = RmlMultPhl - (Rml * Phm); delta8 = (Rml * Phm) - MExpRmM1PExpRlM1MultExpRhM1; delta9 = Phm - MExpRhM1; epsilon1 = (FullPolyhml - (Qhl + Phml)) / (Qhl + Phml); epsilon2 = (Qhl - (Rml + RmlMultPhl)) / (Rml + RmlMultPhl); epsilon3 = (RmlMultPhl - (Rml * Phm)) / (Rml * Phm); #Logical implication to prove { ( epsilonApproxRh in [-1b-112,1b-112] /\ epsilonApproxRm in [-_epsilonApproxRmAccurate,_epsilonApproxRmAccurate] /\ epsilonApproxRl in [-_epsilonApproxRlAccurate,_epsilonApproxRlAccurate] /\ ( rh in [-_rhmax,-1b-800] \/ rh in [1b-800,_rhmax] ) /\ ( rm in [-_rmmax,-1b-800] \/ rm in [1b-800,_rmmax] ) /\ ( rl in [-_rlmax,-1b-800] \/ rl in [1b-800,_rlmax] ) /\ ( Phml in [-1b-12,-1b-820] \/ Phml in [1b-820,1b-12] ) /\ epsilonApproxPhm in [-1b-91,1b-91] -> deltaApproxExpRhml in [-1b-122,1b-122] /\ FullPolyhml in [-1b-11,1b-11] ) /\ ( epsilonApproxRh in [-1b-144,1b-144] /\ epsilonApproxRm in [0,0] /\ epsilonApproxRl in [0,0] /\ ( rh in [-1b-30,-1b-800] \/ rh in [1b-800,1b-30] ) /\ rm in [0,0] /\ rl in [0,0] /\ ( Phml in [-1b-29,-1b-820] \/ Phml in [1b-820,1b-29] ) /\ epsilonApproxPhm in [-1b-91,1b-91] -> deltaApproxExpRhml in [-1b-170,1b-170] /\ FullPolyhml in [-1b-28,1b-28] ) } #Hints for composing the errors in the different levels deltaApproxExpRhml -> delta1 + delta2 + delta3 - MExpRmM1MultExpRlM1; delta1 -> epsilonApproxRh * MExpRhM1; delta2 -> epsilon1 * (Qhl + Phml); delta4 -> epsilon2 * (Rml + RmlMultPhl); delta3 -> delta4 + delta5 + delta6; delta7 -> epsilon3 * (Rml * Phm); delta6 -> delta7 + delta8; delta9 -> epsilonApproxPhm * Phml + delta1; delta8 -> delta5 * MExpRhM1 + delta9 * MExpRmM1PExpRlM1 + delta5 * delta9; #Hints for computing the absolute mathematical values for the arithmetical ones MExpRhM1 -> Phml * (1 / (1 + epsilonApproxRh)); MExpRmM1 -> rm * (1 / (1 + epsilonApproxRm)); MExpRlM1 -> rl * (1 / (1 + epsilonApproxRl)); Phm -> Phml + epsilonApproxPhm * Phml; Phml - Phm -> -epsilonApproxPhm * Phml;interval-3.2.0/src/crlibm/gappa/exp-td/exp-td-accurate3.gappa0000644000000000000000000000416613316017127022111 0ustar 00000000000000# Gappa proof for the relative error of a polynomial approximation of exp(r) # abs(r) \leq 2^(-12), # integrating the final adding step, the errors made in the polynomial approximation # and the argument reduction error # # THIS IS THE SIMPLE CASE WHERE THERE IS NO GAPPING EFFECT TO PROVE # # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #Translation of the C code PolyAddOnehml = add_rel<138>(1,FullPolyhml); #Mathematical definitions corresponding to the code MExpRhml = 1 + MExpRhmlM1; #Definition of the errors deltaApproxExpRhml = FullPolyhml - MExpRhmlM1; epsilonArgRed = (MExpRhml - MExpR) / MExpR; epsilon = (PolyAddOnehml - MExpR) / MExpR; epsilon1 = (PolyAddOnehml - MExpRhml) / MExpRhml; #Logical implication to prove { deltaApproxExpRhml in [-1b-122,1b-122] /\ FullPolyhml in [-1b-11,1b-11] /\ epsilonArgRed in [-1b-141,1b-141] -> epsilon in [-1b-121,1b-121] } #Hints for composing the errors in the different levels epsilon -> epsilonArgRed + epsilon1 + epsilonArgRed * epsilon1; #Hints for computing the absolute mathematical values for the arithmetical ones MExpRhmlM1 -> FullPolyhml - deltaApproxExpRhml; interval-3.2.0/src/crlibm/gappa/exp-td/exp-td-accurate4.gappa0000644000000000000000000000421513316017127022105 0ustar 00000000000000# Gappa proof for the relative error of a polynomial approximation of exp(r) # abs(r) \leq 2^(-12), # integrating the final adding step, the errors made in the polynomial approximation # and the argument reduction error # # THIS IS THE DIFFICULT CASE WHERE WE MUST SHOW THE EXACTNESS OF THE LAST ADD # # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #Translation of the C code PolyAddOnehml = 1 + FullPolyhml; # MUST SHOW THIS EXACTNESS ON PAPER #Mathematical definitions corresponding to the code MExpRhml = 1 + MExpRhmlM1; #Definition of the errors deltaApproxExpRhml = FullPolyhml - MExpRhmlM1; epsilonArgRed = (MExpRhml - MExpR) / MExpR; epsilon = (PolyAddOnehml - MExpR) / MExpR; epsilon1 = (PolyAddOnehml - MExpRhml) / MExpRhml; #Logical implication to prove { deltaApproxExpRhml in [-1b-170,1b-170] /\ FullPolyhml in [-1b-28,1b-28] /\ epsilonArgRed in [0,0] -> epsilon in [-1b-169,1b-169] } #Hints for composing the errors in the different levels epsilon -> epsilonArgRed + epsilon1 + epsilonArgRed * epsilon1; #Hints for computing the absolute mathematical values for the arithmetical ones MExpRhmlM1 -> FullPolyhml - deltaApproxExpRhml; interval-3.2.0/src/crlibm/gappa/exp-td/exp-td-proof.sh0000755000000000000000000000260613316017127020706 0ustar 00000000000000#/bin/bash # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA GAPPA=~/gappa/src/gappa sed -f ../maple/TEMPEXP/exp-td-accurate.sed exp-td-accurate1.gappa | $GAPPA sed -f ../maple/TEMPEXP/exp-td-accurate.sed exp-td-accurate2.gappa | $GAPPA sed -f ../maple/TEMPEXP/exp-td-accurate.sed exp-td-accurate3.gappa | $GAPPA sed -f ../maple/TEMPEXP/exp-td-accurate.sed exp-td-accurate4.gappa | $GAPPA interval-3.2.0/src/crlibm/gappa/log-de/README0000644000000000000000000000255613316017127016655 0ustar 00000000000000 There are (too) many proof files for log-de. Those with "acc" in the filename concern the accurate step (double-double-extended computation). The others concern the quick phase (double-extended computation, with Estrin polynomial evaluation). The most interesting files are the latter. There are three files: log-de-index1N-E0N.gappa covers all the table index values, except 0. log-de-index0-E1N.gappa covers the index 0 and all the exponents, except 0. log-de-index0-E0.gappa covers the case where both the index and the exponent are zero. The hints given to Gappa need to be different in the three cases. Basically, as soon as either the exponent or the index is different from zero, Gappa computes the relative error by dividing an absolute error by the max value of the function, which is sufficiently large. In these cases, Estrin evaluation is just as easy as Horner to handle. However, in the case where both index and exponent are zero (this correspond to the interval where the logarithm goes through zero) we have to compute directly the relative error of the Estrin evaluation. The same holds for log-de-acc, but without the Estrin bravery. Note that some of these files forget the case z=0. It is easy the prove by hand that the Estrin evaluation, in this case, returns logir+E*log2 (with roundings on logir, log2, the + and the *), which is accurate enough. interval-3.2.0/src/crlibm/gappa/log-de/log-de-acc-index0-E0.gappa0000644000000000000000000001116613316017127022326 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Usage: This files builds an error computation for one index value #only. To get a complete proof you need to run it through gappa for all #the possible values of the constants. # Running the ../maple/log-de.mpl Maple script # should create the required sed files and give the command to run. # Example sed -f ../maple/TEMPLOG/polynomials.sed -f ../maple/TEMPLOG/log-de_1.sed ../gappa/log-de-accurate.gappa | ~/gappa/src/gappa # Remove the following line when editing this file, to get back the warnings (all the current ones are harmless) #@ -Wno-hint-difference -Wno-null-denominator # Remark: asking for warnings resuires at least 512MB of memory #This is to prevent another warning which might let you think Gappa failed when it eventually succeeds. #@ -Wno-dichotomy-failure # Rounding operators and sequences definition @IEEEdouble = float; @IEEEext = float; @Add22ext = add_rel<124>; @Mul22ext = mul_rel<124>; E=0; # polynomial coefficients, computed by Maple c14 = IEEEext(_c14h); c13 = IEEEext(_c13h); c12 = IEEEext(_c12h); c11 = IEEEext(_c11h); c10 = IEEEext(_c10h); c9 = IEEEext(_c9h); c8 = IEEEext(_c8h); c7h = IEEEext(_c7h); c7l = IEEEext(_c7l); c7=c7h+c7l; c6h = IEEEext(_c6h); c6l = IEEEext(_c6l); c6=c6h+c6l; c5h = IEEEext(_c5h); c5l = IEEEext(_c5l); c5=c5h+c5l; c4h = IEEEext(_c4h); c4l = IEEEext(_c4l); c4=c4h+c4l; c3h = IEEEext(_c3h); c3l = IEEEext(_c3l); c3=c3h+c3l; c2h = IEEEext(_c2h); c2l = IEEEext(_c2l); c2=c2h+c2l; c1h = IEEEext(_c1h); c1l = IEEEext(_c1l); c1=c1h+c1l; log2h = IEEEext(_log2h); log2l = IEEEext(_log2l); log2=log2h+log2l; logirh = IEEEext(_logirh); logirl = IEEEext(_logirl); logir=logirh+logirl; # Transcription of C code t13 IEEEext= c13 + z*c14; t12 IEEEext= c12 + z*t13; t11 IEEEext= c11 + z*t12; t10 IEEEext= c10 + z*t11; t9 IEEEext= c9 + z*t10; t8 IEEEext= c8 + z*t9; #Mul12ext(&p7h, &p7l, z, t8); p7=z*t8; #Add22ext(&t7h, &t7l, p7h,p7l, c7h,c7l); t7=Add22ext(c7,p7); #FMA22ext(&t6h, &t6l, z,0, t7h,t7l, c6h,c6l); p6=Mul22ext(z,t7); t6=Add22ext(c6,p6); #FMA22ext(&t5h, &t5l, z,0, t6h,t6l, c5h,c5l); p5=Mul22ext(z,t6); t5=Add22ext(c5,p5); #FMA22ext(&t4h, &t4l, z,0, t5h,t5l, c4h,c4l); p4=Mul22ext(z,t5); t4=Add22ext(c4,p4); #FMA22ext(&t3h, &t3l, z,0, t4h,t4l, c3h,c3l); p3=Mul22ext(z,t4); t3=Add22ext(c3,p3); #FMA22ext(&t2h, &t2l, z,0, t3h,t3l, c2h,c2l); p2=Mul22ext(z,t3); t2=Add22ext(c2,p2); #FMA22ext(&t1h, &t1l, z,0, t2h,t2l, c1h,c1l); p1=Mul22ext(z,t2); t1=Add22ext(c1,p1); #FMA22ext(&t0h, &t0l, z,0, t1h,t1l, argredtable[index].logirh, argredtable[index].logirl); p0=Mul22ext(z,t1); # Addition of 0 is exact t0=p0; #Mul22ext(&eh, &el, log2h,log2l, E, 0); #Mul by 0 is exact e=log2*E; #Add22ext(prh, prl, eh,el, t0h,t0l); #Then, e is also equal to 0 so the last addition is exact again logz=e+t0; #---------- What this code is supposed to approximate # Exact mathematical definition of the log Mlogz = Log1pz; PolyLog1pz = z*(c1+z*(c2+z*(c3+z*(c4+z*(c5+z*(c6+z*(c7+z*(c8+z*(c9+z*(c10+z*(c11+z*(c12+z*(c13+z*c14))))))))))))); epsilon = (logz - Mlogz)/Mlogz; epspoly=(p0-Log1pz)/Log1pz; epsolyRound=(p0-PolyLog1pz)/PolyLog1pz; epspolyApprox=(PolyLog1pz - Log1pz)/Log1pz; { |z| in [1b-200, _zabsmax] /\ log2 - Mlog2 in [-1b-129, 1b-129] /\ (PolyLog1pz - Log1pz)/Log1pz in [-_epsilonApproxAccurate, _epsilonApproxAccurate] /\ (PolyLog1pz - Log1pz) in [-_deltaApproxAccurate, _deltaApproxAccurate] -> epsilon in [-1b-119,1b-119] } epspoly -> epsolyRound + epspolyApprox + epsolyRound*epspolyApprox; Log1pz -> PolyLog1pz - (PolyLog1pz-Log1pz); epsilon-> epspoly; interval-3.2.0/src/crlibm/gappa/log-de/log-de-acc-index0-E1N.gappa0000644000000000000000000001225513316017127022445 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Usage: This files builds an error computation for one index value #only. To get a complete proof you need to run it through gappa for all #the possible values of the constants. # Running the ../maple/log-de.mpl Maple script # should create the required sed files and give the command to run. # Example sed -f ../maple/TEMPLOG/polynomials.sed -f ../maple/TEMPLOG/log-de_1.sed ../gappa/log-de-accurate.gappa | ~/gappa/src/gappa # Remove the following line when editing this file, to get back the warnings (all the current ones are harmless) #@ -Wno-hint-difference -Wno-null-denominator # Remark: asking for warnings resuires at least 512MB of memory #This is to prevent another warning which might let you think Gappa failed when it eventually succeeds. #@ -Wno-dichotomy-failure # Rounding operators and sequences definition @IEEEdouble = float; @IEEEext = float; @Add22ext = add_rel<124>; @Mul22ext = mul_rel<124>; # This is to tell Gappa that E is an integer. E=int(dummyE); # polynomial coefficients, computed by Maple c14 = IEEEext(_c14h); c13 = IEEEext(_c13h); c12 = IEEEext(_c12h); c11 = IEEEext(_c11h); c10 = IEEEext(_c10h); c9 = IEEEext(_c9h); c8 = IEEEext(_c8h); c7h = IEEEext(_c7h); c7l = IEEEext(_c7l); c7=c7h+c7l; c6h = IEEEext(_c6h); c6l = IEEEext(_c6l); c6=c6h+c6l; c5h = IEEEext(_c5h); c5l = IEEEext(_c5l); c5=c5h+c5l; c4h = IEEEext(_c4h); c4l = IEEEext(_c4l); c4=c4h+c4l; c3h = IEEEext(_c3h); c3l = IEEEext(_c3l); c3=c3h+c3l; c2h = IEEEext(_c2h); c2l = IEEEext(_c2l); c2=c2h+c2l; c1h = IEEEext(_c1h); c1l = IEEEext(_c1l); c1=c1h+c1l; log2h = IEEEext(_log2h); log2l = IEEEext(_log2l); log2=log2h+log2l; logirh = IEEEext(_logirh); logirl = IEEEext(_logirl); logir=logirh+logirl; # Transcription of C code t13 IEEEext= c13 + z*c14; t12 IEEEext= c12 + z*t13; t11 IEEEext= c11 + z*t12; t10 IEEEext= c10 + z*t11; t9 IEEEext= c9 + z*t10; t8 IEEEext= c8 + z*t9; #Mul12ext(&p7h, &p7l, z, t8); p7=z*t8; #Add22ext(&t7h, &t7l, p7h,p7l, c7h,c7l); t7=Add22ext(c7,p7); #FMA22ext(&t6h, &t6l, z,0, t7h,t7l, c6h,c6l); p6=Mul22ext(z,t7); t6=Add22ext(c6,p6); #FMA22ext(&t5h, &t5l, z,0, t6h,t6l, c5h,c5l); p5=Mul22ext(z,t6); t5=Add22ext(c5,p5); #FMA22ext(&t4h, &t4l, z,0, t5h,t5l, c4h,c4l); p4=Mul22ext(z,t5); t4=Add22ext(c4,p4); #FMA22ext(&t3h, &t3l, z,0, t4h,t4l, c3h,c3l); p3=Mul22ext(z,t4); t3=Add22ext(c3,p3); #FMA22ext(&t2h, &t2l, z,0, t3h,t3l, c2h,c2l); p2=Mul22ext(z,t3); t2=Add22ext(c2,p2); #FMA22ext(&t1h, &t1l, z,0, t2h,t2l, c1h,c1l); p1=Mul22ext(z,t2); t1=Add22ext(c1,p1); #FMA22ext(&t0h, &t0l, z,0, t1h,t1l, argredtable[index].logirh, argredtable[index].logirl); p0=Mul22ext(z,t1); # Addition of 0 is exact t0=logir+p0; #Mul22ext(&eh, &el, log2h,log2l, E, 0); e=Mul22ext(log2,E); #Add22ext(prh, prl, eh,el, t0h,t0l); logz=Add22ext(e,t0); #---------- What this code is supposed to approximate # Exact mathematical definition of the log Mlogz = E*Mlog2 + (Mlogir + Log1pz); PolyLog1pz = z*(c1+z*(c2+z*(c3+z*(c4+z*(c5+z*(c6+z*(c7+z*(c8+z*(c9+z*(c10+z*(c11+z*(c12+z*(c13+z*c14))))))))))))); epsilon = (logz - Mlogz)/Mlogz; # Auxiliary epsilons Alogz = e + (logir+p0); # exact, before approximating by the Add22 eps1 = (Alogz - Mlogz)/Mlogz; eps2 = (logz - Alogz)/Alogz; epspoly=(p0-Log1pz)/Log1pz; epsolyRound=(p0-PolyLog1pz)/PolyLog1pz; epspolyApprox=(PolyLog1pz - Log1pz)/Log1pz; { |E| in [1,1024] /\ |z| in [1b-200, _zabsmax] /\ log2 - Mlog2 in [-1b-129, 1b-129] /\ logir - Mlogir in [-1b-129, 1b-129] /\ (PolyLog1pz - Log1pz)/Log1pz in [-_epsilonApproxAccurate, _epsilonApproxAccurate] /\ (PolyLog1pz - Log1pz) in [-_deltaApproxAccurate, _deltaApproxAccurate] -> epsilon in [-1b-119,1b-119] } epspoly -> epsolyRound + epspolyApprox + epsolyRound*epspolyApprox; Log1pz -> PolyLog1pz - (PolyLog1pz-Log1pz); #(Alogz2-Mlogz)/Mlogz -> ( (e + (logir +p0)) - (E*Mlog2 + (Mlogir + Log1pz)) ) / Mlogz; (Alogz-Mlogz)/Mlogz -> ( (e - Mlog2*E) + (logir-Mlogir) + Log1pz*((p0 - Log1pz)/Log1pz) ) / Mlogz; Mlog2 -> log2 - (log2-Mlog2); Mlogir -> logir - (logir - Mlogir); e-E*Mlog2 -> (e-E*log2) + (E*(log2-Mlog2)) ; epsilon-> eps1 + eps2 + eps1*eps2; epsilon $ E; interval-3.2.0/src/crlibm/gappa/log-de/log-de-acc-index1N-E0.gappa0000644000000000000000000001243713316017127022447 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # This file works for the case E=0 and logir!=0 # sed -f ../maple/TEMPLOG/polynomials.sed -f ../maple/TEMPLOG/log-de_1.sed ../gappa/log-de-acc-logirN-E0.gappa | ~/gappa/src/gappa # Usage: This files builds an error computation for one index value #only. To get a complete proof you need to run it through gappa for all #the possible values of the constants. # Running the ../maple/log-de.mpl Maple script # should create the required sed files and give the command to run. # Example sed -f ../maple/TEMPLOG/polynomials.sed -f ../maple/TEMPLOG/log-de_1.sed ../gappa/log-de-accurate.gappa | ~/gappa/src/gappa # Remove the following line when editing this file, to get back the warnings (all the current ones are harmless) #@ -Wno-hint-difference -Wno-null-denominator # Remark: asking for warnings resuires at least 512MB of memory #This is to prevent another warning which might let you think Gappa failed when it eventually succeeds. #@ -Wno-dichotomy-failure # Rounding operators and sequences definition @IEEEdouble = float; @IEEEext = float; @Add22ext = add_rel<124>; @Mul22ext = mul_rel<124>; E=0; # polynomial coefficients, computed by Maple c14 = IEEEext(_c14h); c13 = IEEEext(_c13h); c12 = IEEEext(_c12h); c11 = IEEEext(_c11h); c10 = IEEEext(_c10h); c9 = IEEEext(_c9h); c8 = IEEEext(_c8h); c7h = IEEEext(_c7h); c7l = IEEEext(_c7l); c7=c7h+c7l; c6h = IEEEext(_c6h); c6l = IEEEext(_c6l); c6=c6h+c6l; c5h = IEEEext(_c5h); c5l = IEEEext(_c5l); c5=c5h+c5l; c4h = IEEEext(_c4h); c4l = IEEEext(_c4l); c4=c4h+c4l; c3h = IEEEext(_c3h); c3l = IEEEext(_c3l); c3=c3h+c3l; c2h = IEEEext(_c2h); c2l = IEEEext(_c2l); c2=c2h+c2l; c1h = IEEEext(_c1h); c1l = IEEEext(_c1l); c1=c1h+c1l; log2h = IEEEext(_log2h); log2l = IEEEext(_log2l); log2=log2h+log2l; logirh = IEEEext(_logirh); logirl = IEEEext(_logirl); logir=logirh+logirl; # Transcription of C code t13 IEEEext= c13 + z*c14; t12 IEEEext= c12 + z*t13; t11 IEEEext= c11 + z*t12; t10 IEEEext= c10 + z*t11; t9 IEEEext= c9 + z*t10; t8 IEEEext= c8 + z*t9; #Mul12ext(&p7h, &p7l, z, t8); p7=z*t8; #Add22ext(&t7h, &t7l, p7h,p7l, c7h,c7l); t7=Add22ext(c7,p7); #FMA22ext(&t6h, &t6l, z,0, t7h,t7l, c6h,c6l); p6=Mul22ext(z,t7); t6=Add22ext(c6,p6); #FMA22ext(&t5h, &t5l, z,0, t6h,t6l, c5h,c5l); p5=Mul22ext(z,t6); t5=Add22ext(c5,p5); #FMA22ext(&t4h, &t4l, z,0, t5h,t5l, c4h,c4l); p4=Mul22ext(z,t5); t4=Add22ext(c4,p4); #FMA22ext(&t3h, &t3l, z,0, t4h,t4l, c3h,c3l); p3=Mul22ext(z,t4); t3=Add22ext(c3,p3); #FMA22ext(&t2h, &t2l, z,0, t3h,t3l, c2h,c2l); p2=Mul22ext(z,t3); t2=Add22ext(c2,p2); #FMA22ext(&t1h, &t1l, z,0, t2h,t2l, c1h,c1l); p1=Mul22ext(z,t2); t1=Add22ext(c1,p1); #FMA22ext(&t0h, &t0l, z,0, t1h,t1l, argredtable[index].logirh, argredtable[index].logirl); p0=Mul22ext(z,t1); t0=Add22ext(logir,p0); #Mul22ext(&eh, &el, log2h,log2l, E, 0); #Mul22 is exact when multipluing by 0 e=log2*E; #Add22ext(prh, prl, eh,el, t0h,t0l); # Same for Add22 logz=e+t0; #---------- What this code is supposed to approximate # Exact mathematical definition of the log Mlogz = E*Mlog2 + (Mlogir + Log1pz); PolyLog1pz = z*(c1+z*(c2+z*(c3+z*(c4+z*(c5+z*(c6+z*(c7+z*(c8+z*(c9+z*(c10+z*(c11+z*(c12+z*(c13+z*c14))))))))))))); epsilon = (logz - Mlogz)/Mlogz; # Auxiliary epsilons Alogz = e + (logir+p0); # exact, before approximating by the Add22 eps1 = (Alogz - Mlogz)/Mlogz; eps2 = (logz - Alogz)/Alogz; epspoly=(p0-Log1pz)/Log1pz; epsolyRound=(p0-PolyLog1pz)/PolyLog1pz; epspolyApprox=(PolyLog1pz - Log1pz)/Log1pz; { |z| in [1b-200, _zabsmax] /\ log2 - Mlog2 in [-1b-129, 1b-129] /\ logir - Mlogir in [-1b-129, 1b-129] /\ (PolyLog1pz - Log1pz)/Log1pz in [-_epsilonApproxAccurate, _epsilonApproxAccurate] /\ (PolyLog1pz - Log1pz) in [-_deltaApproxAccurate, _deltaApproxAccurate] -> epsilon in [-1b-119,1b-119] } epspoly -> epsolyRound + epspolyApprox + epsolyRound*epspolyApprox; Log1pz -> PolyLog1pz - (PolyLog1pz-Log1pz); #(Alogz2-Mlogz)/Mlogz -> ( (e + (logir +p0)) - (E*Mlog2 + (Mlogir + Log1pz)) ) / Mlogz; (Alogz-Mlogz)/Mlogz -> ( (e - Mlog2*E) + (logir-Mlogir) + Log1pz*((p0 - Log1pz)/Log1pz) ) / Mlogz; Mlog2 -> log2 - (log2-Mlog2); Mlogir -> logir - (logir - Mlogir); e-E*Mlog2 -> (e-E*log2) + (E*(log2-Mlog2)) ; epsilon-> eps1 + eps2 + eps1*eps2; interval-3.2.0/src/crlibm/gappa/log-de/log-de-acc-index1N-E1N.gappa0000644000000000000000000001223713316017127022564 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Usage: This files builds an error computation for one index value #only. To get a complete proof you need to run it through gappa for all #the possible values of the constants. # Running the ../maple/log-de.mpl Maple script # should create the required sed files and give the command to run. # Example sed -f ../maple/TEMPLOG/polynomials.sed -f ../maple/TEMPLOG/log-de_1.sed ../gappa/log-de-accurate.gappa | ~/gappa/src/gappa # Remove the following line when editing this file, to get back the warnings (all the current ones are harmless) #@ -Wno-hint-difference -Wno-null-denominator # Remark: asking for warnings resuires at least 512MB of memory #This is to prevent another warning which might let you think Gappa failed when it eventually succeeds. #@ -Wno-dichotomy-failure # Rounding operators and sequences definition @IEEEdouble = float; @IEEEext = float; @Add22ext = add_rel<124>; @Mul22ext = mul_rel<124>; # This is to tell Gappa that E is an integer. E=int(dummyE); # polynomial coefficients, computed by Maple c14 = IEEEext(_c14h); c13 = IEEEext(_c13h); c12 = IEEEext(_c12h); c11 = IEEEext(_c11h); c10 = IEEEext(_c10h); c9 = IEEEext(_c9h); c8 = IEEEext(_c8h); c7h = IEEEext(_c7h); c7l = IEEEext(_c7l); c7=c7h+c7l; c6h = IEEEext(_c6h); c6l = IEEEext(_c6l); c6=c6h+c6l; c5h = IEEEext(_c5h); c5l = IEEEext(_c5l); c5=c5h+c5l; c4h = IEEEext(_c4h); c4l = IEEEext(_c4l); c4=c4h+c4l; c3h = IEEEext(_c3h); c3l = IEEEext(_c3l); c3=c3h+c3l; c2h = IEEEext(_c2h); c2l = IEEEext(_c2l); c2=c2h+c2l; c1h = IEEEext(_c1h); c1l = IEEEext(_c1l); c1=c1h+c1l; log2h = IEEEext(_log2h); log2l = IEEEext(_log2l); log2=log2h+log2l; logirh = IEEEext(_logirh); logirl = IEEEext(_logirl); logir=logirh+logirl; # Transcription of C code t13 IEEEext= c13 + z*c14; t12 IEEEext= c12 + z*t13; t11 IEEEext= c11 + z*t12; t10 IEEEext= c10 + z*t11; t9 IEEEext= c9 + z*t10; t8 IEEEext= c8 + z*t9; #Mul12ext(&p7h, &p7l, z, t8); p7=z*t8; #Add22ext(&t7h, &t7l, p7h,p7l, c7h,c7l); t7=Add22ext(c7,p7); #FMA22ext(&t6h, &t6l, z,0, t7h,t7l, c6h,c6l); p6=Mul22ext(z,t7); t6=Add22ext(c6,p6); #FMA22ext(&t5h, &t5l, z,0, t6h,t6l, c5h,c5l); p5=Mul22ext(z,t6); t5=Add22ext(c5,p5); #FMA22ext(&t4h, &t4l, z,0, t5h,t5l, c4h,c4l); p4=Mul22ext(z,t5); t4=Add22ext(c4,p4); #FMA22ext(&t3h, &t3l, z,0, t4h,t4l, c3h,c3l); p3=Mul22ext(z,t4); t3=Add22ext(c3,p3); #FMA22ext(&t2h, &t2l, z,0, t3h,t3l, c2h,c2l); p2=Mul22ext(z,t3); t2=Add22ext(c2,p2); #FMA22ext(&t1h, &t1l, z,0, t2h,t2l, c1h,c1l); p1=Mul22ext(z,t2); t1=Add22ext(c1,p1); #FMA22ext(&t0h, &t0l, z,0, t1h,t1l, argredtable[index].logirh, argredtable[index].logirl); p0=Mul22ext(z,t1); t0=Add22ext(logir,p0); #Mul22ext(&eh, &el, log2h,log2l, E, 0); e=Mul22ext(log2,E); #Add22ext(prh, prl, eh,el, t0h,t0l); logz=Add22ext(e,t0); #---------- What this code is supposed to approximate # Exact mathematical definition of the log Mlogz = E*Mlog2 + (Mlogir + Log1pz); PolyLog1pz = z*(c1+z*(c2+z*(c3+z*(c4+z*(c5+z*(c6+z*(c7+z*(c8+z*(c9+z*(c10+z*(c11+z*(c12+z*(c13+z*c14))))))))))))); epsilon = (logz - Mlogz)/Mlogz; # Auxiliary epsilons Alogz = e + (logir+p0); # exact, before approximating by the Add22 eps1 = (Alogz - Mlogz)/Mlogz; eps2 = (logz - Alogz)/Alogz; epspoly=(p0-Log1pz)/Log1pz; epsolyRound=(p0-PolyLog1pz)/PolyLog1pz; epspolyApprox=(PolyLog1pz - Log1pz)/Log1pz; { |E| in [1,1024] /\ |z| in [1b-200, _zabsmax] /\ log2 - Mlog2 in [-1b-129, 1b-129] /\ logir - Mlogir in [-1b-129, 1b-129] /\ (PolyLog1pz - Log1pz)/Log1pz in [-_epsilonApproxAccurate, _epsilonApproxAccurate] /\ (PolyLog1pz - Log1pz) in [-_deltaApproxAccurate, _deltaApproxAccurate] -> epsilon in [-1b-119,1b-119] } epspoly -> epsolyRound + epspolyApprox + epsolyRound*epspolyApprox; Log1pz -> PolyLog1pz - (PolyLog1pz-Log1pz); #(Alogz2-Mlogz)/Mlogz -> ( (e + (logir +p0)) - (E*Mlog2 + (Mlogir + Log1pz)) ) / Mlogz; (Alogz-Mlogz)/Mlogz -> ( (e - Mlog2*E) + (logir-Mlogir) + Log1pz*((p0 - Log1pz)/Log1pz) ) / Mlogz; Mlog2 -> log2 - (log2-Mlog2); Mlogir -> logir - (logir - Mlogir); e-E*Mlog2 -> (e-E*log2) + (E*(log2-Mlog2)) ; epsilon-> eps1 + eps2 + eps1*eps2; epsilon $ E; interval-3.2.0/src/crlibm/gappa/log-de/log-de-index0-E0.gappa0000644000000000000000000002445413316017127021606 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Usage: This files builds an error computation for the case when both the # index and the exponent are zero. # sed -f ../maple/TEMPLOG/polynomials.sed -f ../maple/TEMPLOG/log-de_0.sed ../gappa/log-de-index0-E0.gappa | $GAPPA # NOTATION CONVENTION # Variables that will be replaced with Maple-computed constants begin with an underscore # Variables that correspond to double-precision variables in the code begin with a small letter # variable eps_xxx denote the relative rounding error of the last machine operation that computes xxx # Remove the following line when editing this file, to get back the warnings (all the current ones are harmless) #@ -Wno-hint-difference -Wno-null-denominator # Remark: asking for warnings resuires at least 512MB of memory @IEEEdouble = float; @IEEEext = float; # polynomial coefficients, computed by Maple #c1 = IEEEext(_c1); c2 = IEEEext(_c2); c3 = IEEEext(_c3); c4 = IEEEext(_c4); c5 = IEEEext(_c5); c6 = IEEEext(_c6); c7 = IEEEext(_c7); log2h = IEEEext(_log2h); log2l = IEEEext(_log2l); #r = IEEEext(_rval); #logirh = IEEEext(_logirh); #logirl = IEEEext(_logirl); # Transcription of the code, NOT using FMA # We have removed logirh and Elog2 z2 IEEEext= z*z; p67 IEEEext= c6 + z*c7; p45 IEEEext= c4 + z*c5; p23 IEEEext= c2 + z*c3; #p01 IEEEext= z; z4 IEEEext= z2*z2; p47 IEEEext= p45 + z2*p67; p03 IEEEext= z + z2*p23; # suppressed by hand the exact additions of 0 logz IEEEext= p03 + z4*p47; #---------- What this code is supposed to approximate # Exact mathematical definition of the log Mlogz = Log1pz; ############# Now come auxiliary definitions # Give the polynomial in Estrin form (no need to transcribe the intermediate steps) # Since the argument reduction is exact, Mz = z. Mz2 = z*z; Mz4 = Mz2*Mz2; Mz3 = z*z*z; Mz5 = z*z*z*z*z; Mz6 = z*z*z*z*z*z; eps_z2 = (z2 - z*z)/(z*z); eps_z4 = (z4 - z2*z2)/(z2*z2); t3 = IEEEext(z*c3); t5 = IEEEext(z*c5); t7 = IEEEext(z*c7); t23 = IEEEext(z2*p23); t47 = IEEEext(z4*p47); t67 = IEEEext(z2*p67); eps_t3 = (t3 - z*c3)/(z*c3); eps_t5 = (t5 - z*c5)/(z*c5); eps_t7 = (t7 - z*c7)/(z*c7); eps_t23 = (t23 - z2*p23)/(z2*p23); eps_t67 = (t67 - z2*p67)/(z2*p67); eps_t47 = (t47 - z4*p47)/(z4*p47); eps_p03 = (p03 - (z+t23)) / (z+t23); eps_p23 = (p23 - (c2 + t3)) / (c2 + t3); eps_p45 = (p45 - (c4 + t5)) / (c4 + t5); eps_p67 = (p67 - (c6 + t7)) / (c6 + t7); eps_p47 = (p47 - (p45 + t67)) / (p45 + t67); eps_logz = (logz - (p03 + t47))/(p03 + t47); # The following are just for lightening notations eps2_z4 = (1+eps_z2)*(1+eps_z2)*(1+eps_z4)-1; eps2_p67 = (1+eps_z2)*(1+eps_p67) -1; eps2_p47 = (1+eps2_z4)*(1+eps_p47) -1; PolyLog1pz = z + Mz2*(c2+z*c3) + Mz4*( (c4+z*c5) + Mz2*(c6+z*c7) ); epsilon = (logz - Mlogz)/Mlogz; epsilon_approx = (PolyLog1pz - Log1pz)/Log1pz; epsilon_round = (logz-PolyLog1pz)/PolyLog1pz; # The theorem. Remark that the case z=0 has to be proven by hand (fortunately it is easy) { (z in [1b-200, _zabsmax] \/ z in [-_zabsmax, -1b-200]) /\ epsilon_approx in [-_epsilonApproxQuick, _epsilonApproxQuick] /\ (PolyLog1pz - Log1pz) in [-_deltaApproxQuick, _deltaApproxQuick] -> epsilon in [-1b-63, 1b-63] } epsilon -> epsilon_approx + epsilon_round + epsilon_approx*epsilon_round; #We need to factor z by using : (logz-PolyLog1pz)/PolyLog1pz -> ((logz/z) - PolyLog1pz/z) / (PolyLog1pz/z); # Here the denominator will be bound properly: PolyLog1pz/z -> 1 + z*(c2+z*c3) + z*z*z*( (c4+z*c5) + z*z*(c6+z*c7) ) ; # so all we have is to cancel as much as possible from the numerator. # As all the polynomials come close to zero, we do this by forcing appearance of rel error # (1) logz = IEEEext(p03 + t47). Since p03+t47 comes close to zero, force appearance of relative error logz/z -> (1+ (IEEEext(p03 + t47) - (p03 + t47))/(p03 + t47) ) * ((p03 + t47)/z) ; # ------------------rel error----------------- --closer to PolyLog1pz/z--- # Now if we try to print out the rel error above, it is undefined. # This is because Gappa is not able to prove that p03+t47 does not contain 0. # So the first job is to get a better enclosure of p03+t47, without 0. # First get a good enclosure on p03 (so that it does not contain zero): same process as (1) p03 -> (1+ eps_p03) * (z+t23); # Again, the relative error above exists only if z+t23 does not contain 0 z+t23-> z*(1+t23/z); # now we force the relative error of the rounding of t23 t23/z -> eps_t23 * ((z2/z)*p23) + (z2/z)*p23; z2/z -> ( (z2 - z*z)/(z*z) ) * z + z; # that's eps_z2 # Now p03 is OK, but p03 + t47 still contains 0: rewrite it, first by rewriting t47: t47 -> (1 + eps_t47) * (z4*p47) ; # now we may rewrite p03+t47, with the purpose to factor z p03+t47 -> z*( (1+eps_p03)*(1+t23/z) + (1+eps_t47)*(z4*p47/z)); # remains to bound z4*p47/z, a piece of cake (we even recycle z2/z) z4*p47/z -> (1 + (IEEEext(z2*z2) - z2*z2)/(z2*z2)) * p47*z2*(z2/z) ; # At this point the relative error in (1) exists at last. Beside we have almost built a good approx of: (p03+t47)/z -> (1+eps_p03)*(1+t23/z) + (1+eps_t47)*(z4*p47/z) ; # The previous gives a bound of 2^-8 for the approximation error. Let us refine it. # Replacing the terms with the best expression we have for them gives: (logz-PolyLog1pz)/PolyLog1pz -> ( (1+ eps_logz)*( (1+eps_p03)*(1+t23/z) + (1+eps_t47)*(z4*p47/z) ) - (1 + z*(c2+z*c3) + z*z*z*( (c4+z*c5) + z*z*(c6+z*c7) )) ) / (PolyLog1pz/z); # We develop and simplify the logz/z part of the expression in Maple using expand(). Need to set: interface(prettyprint=0); #expand( (1+ eps_logz)*( (1+eps_p03)*(1+t23/z) + (1+eps_t47)*(z4*p47/z) )); # Then we may cancel the 1s. # Then we regroup the next significant terms: t23/z - z*(c2+z*c3), and # (also add parentheses around (z4*p47/z) and (t23/z) so that the remainder is bound properly using previous hints) (logz-PolyLog1pz)/PolyLog1pz -> ( (t23/z - z*(c2+z*c3)) +((z4*p47/z) - z*z*z*( (c4+z*c5) + z*z*(c6+z*c7))) + (eps_p03 + eps_p03*(t23/z) + + (z4*p47/z)*eps_t47+eps_logz+eps_logz*(t23/z) + eps_logz*eps_p03 + eps_logz*eps_p03*(t23/z) + eps_logz*(z4*p47/z) + eps_logz*(z4*p47/z)*eps_t47 ) ) / (PolyLog1pz/z); # A quick check gives a bound of 2^-62 for the third term (sum of epsilons), which is OK for now. # Now let us work on this next significant term, starting with the expression we already have for t23/z: t23/z - z*(c2+z*c3) -> eps_t23 * ((z2/z)*p23) + ( (z2/z)*p23 - z*(c2+z*c3)) ; # ----------small------- # insert rel error of p23, and replace z2/z with the hint already given, then simplify and look for the most significant term : # expand((eps_z2 * z + z) * (1+eps_p23)*(c2+t3) - z*(c2+z*c3)); (z2/z)*p23 - z*(c2+z*c3) -> (z*t3 - z*z*c3) + eps_z2*z*c2 + eps_z2*z*t3 + eps_z2*z*eps_p23*c2 + eps_z2*z*eps_p23*t3 + z*eps_p23*c2 + z*eps_p23*t3 ; (z*t3 - z*z*c3) -> z*(z*c3*eps_t3); # At this point we have a bound of 2^-71 for t23/z - z*(c2+z*c3), perfect. # Let us attack (z4*p47/z) - z*z*z*( (c4+z*c5) + z*z*(c6+z*c7)) (currently 2^-25 -- interval arithmetic on z^3) # Rewrite z4 as z2*z2*(1+eps_z4), then inside this rewrite z2 as z*z*(1+eps_z2). z4/z -> z*z*z + z*z*z*((1+eps_z2)*(1+eps_z2)*(1+eps_z4) -1); #OK # Also rewrite p47 all the way down : we get # p47 -> (1+eps_p47)*(p45 + (1+eps_t67)*(z2*p67)); # p45 -> (1+eps_p45)*(c4+(1+eps_t5)*(z*c5)); # z2*p67 -> (1+eps_z2)*z*z*(1+eps_p67)*(c6+(1+eps_t7)*(c7*z)); # Putting together: (z4*p47/z) - z*z*z*( (c4+z*c5) + z*z*(c6+z*c7)) -> z*z*z*( (1+eps2_p47)*(((1+eps_p45)*(c4+(1+eps_t5)*(z*c5))) + (1+eps_t67)*(z*z*(1+eps2_p67)*(c6+(1+eps_t7)*c7*z))) - c4 - z*c5 - z*z*(c6+z*c7)) ; # This last hint is computed by one expand() and one collect(,z) in maple (1+eps2_p47)*(((1+eps_p45)*(c4+(1+eps_t5)*(z*c5))) + (1+eps_t67)*(z*z*(1+eps2_p67)*(c6+(1+eps_t7)*c7*z))) - c4 - z*c5 - z*z*(c6+z*c7) -> (eps2_z4*c7*eps_t7+eps2_z4*eps2_p67*c7+c7*eps_t7+eps2_z4*c7+eps2_p67*c7+eps2_p67*c7*eps_t7+eps2_z4*eps2_p67*c7*eps_t7+eps_t67* c7+eps_p47*c7+eps_t67*c7*eps_t7+eps_p47*c7*eps_t7+eps_p47*eps_t67*c7+eps2_z4*eps_p47*c7+eps2_z4*eps_t67*c7+eps_t67*eps2_p67*c7 +eps_p47*eps2_p67*c7+eps_p47*eps_t67*c7*eps_t7+eps2_z4*eps_p47*c7*eps_t7+eps2_z4*eps_p47*eps_t67*c7+eps2_z4*eps_t67*c7*eps_t7+ eps_t67*eps2_p67*c7*eps_t7+eps2_z4*eps_p47*eps2_p67*c7+eps_p47*eps2_p67*c7*eps_t7+eps_p47*eps_t67*eps2_p67*c7+eps2_z4*eps_t67* eps2_p67*c7+eps2_z4*eps_p47*eps_t67*c7*eps_t7+eps2_z4*eps_p47*eps2_p67*c7*eps_t7+eps2_z4*eps_p47*eps_t67*eps2_p67*c7+eps2_z4* eps_p47*eps_t67*eps2_p67*c7*eps_t7+eps_p47*eps_t67*eps2_p67*c7*eps_t7+eps2_z4*eps_t67*eps2_p67*c7*eps_t7)*Mz3+(eps_t67* eps2_p67*c6+eps_p47*eps2_p67*c6+eps_p47*c6+eps2_z4*eps_p47*c6+eps_p47*eps_t67*eps2_p67*c6+eps_t67*c6+eps2_z4*eps_p47*eps2_p67* c6+eps2_p67*c6+eps2_z4*eps_t67*eps2_p67*c6+eps2_z4*eps_p47*eps_t67*eps2_p67*c6+eps2_z4*eps_t67*c6+eps2_z4*eps_p47*eps_t67*c6+ eps2_z4*c6+eps2_z4*eps2_p67*c6+eps_p47*eps_t67*c6)*Mz2+(eps2_z4*eps_p47*eps_p45*c5+c5*eps_t5+eps2_z4*eps_p45*c5*eps_t5+eps_p47 *c5+eps_p45*c5+eps_p47*eps_p45*c5+eps_p45*c5*eps_t5+eps_p47*eps_p45*c5*eps_t5+eps_p47*c5*eps_t5+eps2_z4*eps_p47*c5+eps2_z4* eps_p45*c5+eps2_z4*eps_p47*eps_p45*c5*eps_t5+eps2_z4*eps_p47*c5*eps_t5+eps2_z4*c5*eps_t5+eps2_z4*c5)*z+eps_p47*c4+eps2_z4* eps_p45*c4+eps2_z4*eps_p47*c4+eps2_z4*c4+eps_p47*eps_p45*c4+eps2_z4*eps_p47*eps_p45*c4+eps_p45*c4 ; interval-3.2.0/src/crlibm/gappa/log-de/log-de-index0-E1N.gappa0000644000000000000000000000717013316017127021721 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # This file is exactly log-de-logirN-E0N.gappa, with the case E=0 removed in the theorem. # It is useful only to allow for a full automated proof. # Remove the following line when editing this file, to get back the warnings (all the current ones are harmless) #@ -Wno-hint-difference -Wno-null-denominator # Remark: asking for warnings resuires at least 512MB of memory #This is to prevent another warning which might let you think Gappa failed when it eventually succeeds. #@ -Wno-dichotomy-failure @IEEEdouble = float; @IEEEext = float; # This is to tell Gappa that E is an integer. E=int(dummyE); # polynomial coefficients, computed by Maple #c1 = IEEEext(_c1); # Since c1=1, it does not appear in the C code anymode c2 = IEEEext(_c2); c3 = IEEEext(_c3); c4 = IEEEext(_c4); c5 = IEEEext(_c5); c6 = IEEEext(_c6); c7 = IEEEext(_c7); # other constants, also from Maple log2h = IEEEext(_log2h); log2l = IEEEext(_log2l); #table values r = IEEEext(_rval); logirh = IEEEext(_logirh); logirl = IEEEext(_logirl); # Transcription of the code, NOT using FMA z2 IEEEext= z*z; p67 IEEEext= c6 + z*c7; p45 IEEEext= c4 + z*c5; p23 IEEEext= c2 + z*c3; p01 IEEEext= logirh + z; z4 IEEEext= z2*z2; p47 IEEEext= p45 + z2*p67; p03 IEEEext= p01 + z2*p23; p07 IEEEext= p03 + z4*p47; logz IEEEext= p07 + E*log2h; #---------- What this code is supposed to approximate # Exact mathematical definition of the log Mlogz = Log1pz + Logir + E*Mlog2; ############# Now come auxiliary definitions Log2hl = log2h + log2l; Logirhl = logirh + logirl; # Give the polynomial in Estrin form (no need to transcribe the intermediate steps) # Since the argument reduction is exact, Mz = z. Mz2 = z*z; Mz4 = Mz2*Mz2; P07 = ( (logirh+z) + Mz2*(c2+z*c3) ) + Mz4*( (c4+z*c5) + Mz2*(c6+z*c7) ); Alogz = P07 + E*Mlog2; PolyLog1pz = z + Mz2*(c2+z*c3) + Mz4*( (c4+z*c5) + Mz2*(c6+z*c7) ); epsilon = (logz - Mlogz)/Mlogz; { |E| in [1,1024] /\ |z| in [1b-200, _zabsmax] /\ Log2hl - Mlog2 in [-1b-129, 1b-129] /\ Logirhl - Logir in [-1b-129, 1b-129] /\ (PolyLog1pz - Log1pz) in [-_deltaApproxQuick, _deltaApproxQuick] -> epsilon in [-1b-63, 1b-63] } logz ~ Alogz; Alogz ~ Mlogz; # Trivialities which cannot be expressed using ~ logirh - Logir -> (logirh +logirl -Logir) - logirl; log2h-Mlog2 -> ((log2h + log2l) - Mlog2) - log2l; Mlog2 -> (log2h + log2l) - ((log2h + log2l) - Mlog2); Logir -> logirh + ((logirl - (logirh +logirl -Logir))); Mlogz -> Alogz - (Alogz-Mlogz); Alogz - Mlogz -> (logirh-Logir) + (PolyLog1pz - Log1pz); epsilon $ E; epsilon $ z; interval-3.2.0/src/crlibm/gappa/log-de/log-de-index1N-E0N.gappa0000644000000000000000000001077113316017127022040 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Usage: This files builds an error computation for all possible #exponent values, but for one index value only. To get a complete #proof you need to run it through gappa for all the possible values of #the constants. However, it doesn't work for the index value 0: use #file log-de-logir0-E0 instead # Running the ../maple/log-de.mpl Maple script # should create the required sed files and give the command to run. # Example sed -f ../maple/TEMPLOG/polynomials.sed -f ../maple/TEMPLOG/log-de_1.sed ../gappa/log-de.gappa | ~/gappa/src/gappa # NOTATION CONVENTION # Variables that will be replaced with Maple-computed constants begin with an underscore # Variables that correspond to double-precision variables in the code begin with a small letter # Other variables begin with a capital letter. # Remove the following line when editing this file, to get back the warnings (all the current ones are harmless) #@ -Wno-hint-difference -Wno-null-denominator # Remark: asking for warnings resuires at least 512MB of memory #This is to prevent another warning which might let you think Gappa failed when it eventually succeeds. #@ -Wno-dichotomy-failure @IEEEdouble = float; @IEEEext = float; # This is to tell Gappa that E is an integer. E=int(dummyE); # polynomial coefficients, computed by Maple #c1 = IEEEext(_c1); # Since c1=1, it does not appear in the C code anymode c2 = IEEEext(_c2); c3 = IEEEext(_c3); c4 = IEEEext(_c4); c5 = IEEEext(_c5); c6 = IEEEext(_c6); c7 = IEEEext(_c7); # other constants, also from Maple log2h = IEEEext(_log2h); log2l = IEEEext(_log2l); #table values r = IEEEext(_rval); logirh = IEEEext(_logirh); logirl = IEEEext(_logirl); # Transcription of the code, NOT using FMA z2 IEEEext= z*z; p67 IEEEext= c6 + z*c7; p45 IEEEext= c4 + z*c5; p23 IEEEext= c2 + z*c3; p01 IEEEext= logirh + z; z4 IEEEext= z2*z2; p47 IEEEext= p45 + z2*p67; p03 IEEEext= p01 + z2*p23; p07 IEEEext= p03 + z4*p47; logz IEEEext= p07 + E*log2h; #---------- What this code is supposed to approximate # Exact mathematical definition of the log Mlogz = Log1pz + Logir + E*Mlog2; ############# Now come auxiliary definitions Log2hl = log2h + log2l; Logirhl = logirh + logirl; # Give the polynomial in Estrin form (no need to transcribe the intermediate steps) # Since the argument reduction is exact, Mz = z. Mz2 = z*z; Mz4 = Mz2*Mz2; P07 = ( (logirh+z) + Mz2*(c2+z*c3) ) + Mz4*( (c4+z*c5) + Mz2*(c6+z*c7) ); Alogz = P07 + E*Mlog2; PolyLog1pz = z + Mz2*(c2+z*c3) + Mz4*( (c4+z*c5) + Mz2*(c6+z*c7) ); epsilon = (logz - Mlogz)/Mlogz; { ( |E| in [1,1024] /\ |z| in [1b-200, _zabsmax] /\ Log2hl - Mlog2 in [-1b-129, 1b-129] /\ Logirhl - Logir in [-1b-129, 1b-129] /\ (PolyLog1pz - Log1pz) in [-_deltaApproxQuick, _deltaApproxQuick] -> epsilon in [-1b-63, 1b-63] ) /\ ( E in [0,0] /\ z in [-_zabsmax, _zabsmax] /\ Log2hl - Mlog2 in [-1b-129, 1b-129] /\ Logirhl - Logir in [-1b-129, 1b-129] /\ (PolyLog1pz - Log1pz) in [-_deltaApproxQuick, _deltaApproxQuick] -> epsilon in [-1b-63, 1b-63] ) } logz ~ Alogz; Alogz ~ Mlogz; # Trivialities which cannot be expressed using ~ logirh - Logir -> (logirh +logirl -Logir) - logirl; log2h-Mlog2 -> ((log2h + log2l) - Mlog2) - log2l; Mlog2 -> (log2h + log2l) - ((log2h + log2l) - Mlog2); Logir -> logirh + ((logirl - (logirh +logirl -Logir))); Mlogz -> Alogz - (Alogz-Mlogz); Alogz - Mlogz -> (logirh-Logir) + (PolyLog1pz - Log1pz); epsilon $ E; epsilon $ z; interval-3.2.0/src/crlibm/gappa/log-td/log-td-E0-logir0.gappa0000644000000000000000000001203713316017127021643 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA c3 = (_c3); c4 = (_c4); c5 = (_c5); c6 = (_c6); c7 = (_c7); E = 0; #MAPLE zh = (Z); zl = Z - zh; #MAPLE polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); ZhSquarehl = zh * zh; #MAPLE zhSquareh = (ZhSquarehl); zhSquarel = (ZhSquarehl - zhSquareh); zhSquareHalfh = zhSquareh * (-0.5); #MAPLE zhSquareHalfl = zhSquarel * (-0.5); #MAPLE ZhSquareHalfhl = ZhSquarehl * (-0.5); #MAPLE ZhCube = (zh * zhSquareh); polyUpper = polyHorner * ZhCube; temp = (zh * zl); T1hl = polyUpper - temp; #MAPLE t1h = (T1hl); t1l = (T1hl - t1h); T2 = Z + ZhSquareHalfhl; #MAPLE t2h = (T2hl); t2l = (T2hl - t2h); PE = T2hl + T1hl; #MAPLE ph = (Phl); pl = (Phl - ph); #We can simplify the computations in the function in this case as we know that #all operations (add, mult) on 0 (as a double double) are exact. Loghm = Phl; #MAPLE logh = (Loghm); logm = (Loghm - logh); #Mathematical definition of the logarithm and the polynomial Phigher = (c3 + Z * (c4 + Z * (c5 + Z * (c6 + Z * c7)))); #MAPLE ZZZ = Z*Z*Z; #MAPLE ZZZPhigher = ZZZ * Phigher; #MAPLE HZZ = (-0.5*Z*Z); #MAPLE ZpHZZ = Z + HZZ; #MAPLE P = ZpHZZ + ZZZPhigher; #MAPLE #We apply the same simplification on the mathematical definition of the log Log = Log1pZ; #MAPLE #Additional useful definitions ZZ = Z*Z; #MAPLE ZZZPhigherPzhzl = ZZZPhigher - zh * zl; #MAPLE HZ = -0.5*Z; #MAPLE Flzhzl = temp; #MAPLE { (T2hl - T2) / T2 in [-1b-103,1b-103] /\ (Phl - PE) / PE in [-1b-103,1b-103] /\ Z in [_zmin,_zmax] /\ (P - Log1pZ) / Log1pZ in [-_epsilonApproxQuick,_epsilonApproxQuick] /\ ((logh + logm) - Loghm) / Loghm in [-1b-106,1b-106] -> ((logh + logm) - Log) / Log in [-5b-65,5b-65] } T2hl - T2 -> ((T2hl - T2) / T2) * T2; T2hl -> (T2hl - T2) + T2; Phl - PE -> ((Phl - PE) / PE) * PE; Phl -> (Phl - PE) + PE; (ZhSquarehl - ZZ) / ZZ -> 2 * ((zh - Z) / Z) + ((zh - Z) / Z) * ((zh - Z) / Z); (zhSquareh - ZZ) / ZZ -> ((ZhSquarehl - ZZ) / ZZ) + ((zhSquareh - ZhSquarehl) / ZZ); (zhSquareh - ZhSquarehl) / ZZ -> ((zhSquareh - ZhSquarehl) / ZhSquarehl) * (ZhSquarehl / ZZ); ZhSquarehl / ZZ -> ((ZhSquarehl - ZZ) / ZZ) + 1; (ZhCube - ZZZ) / ZZZ -> (((zh * zhSquareh) - ZZZ) / ZZZ) + ((ZhCube - (zh * zhSquareh)) / ZZZ); ((zh * zhSquareh) - ZZZ) / ZZZ -> (1 + ((zh - Z) / Z)) * (1 + ((zhSquareh - ZZ) / ZZ)) - 1; ((ZhCube - (zh * zhSquareh)) / ZZZ) -> ((ZhCube - (zh * zhSquareh)) / (zh * zhSquareh)) * (((zh - Z) / Z) + 1) * (((zhSquareh - ZZ) / ZZ) + 1); polyHorner / Phigher -> ((polyHorner - Phigher) / Phigher) + 1; (polyUpper - ZZZPhigher) / ZZZPhigher -> ((polyHorner - Phigher) / Phigher) + ((ZhCube - ZZZ) / ZZZ) * (polyHorner / Phigher) + + ((polyUpper - (polyHorner * ZhCube)) / (polyHorner * ZhCube)) * (polyHorner / Phigher) + + ((ZhCube - ZZZ) / ZZZ) * ((polyUpper - (polyHorner * ZhCube)) / (polyHorner * ZhCube)) * (polyHorner / Phigher); ((ZhSquareHalfhl - (zh * zl)) - HZZ) / HZZ -> - ((zh - Z) / Z) * ((zh - Z) / Z); (ZhSquareHalfhl - HZZ) / HZZ -> (ZhSquarehl - ZZ) / ZZ; ((T2hl - (zh * zl)) - ZpHZZ) / ZpHZZ -> ((HZ * (((ZhSquareHalfhl - (zh * zl)) - HZZ) / HZZ)) + ((T2hl - T2) / T2) + (HZ * ((T2hl - T2) / T2)) + (HZ * ((ZhSquareHalfhl - HZZ) / HZZ) * ((T2hl - T2) / T2))) / (1 + HZ); (PE - P) / P -> (((1 + HZ) * (((T2hl - (zh * zl)) - ZpHZZ) / ZpHZZ)) + ((1 + ((zh - Z) / Z)) * (Z * ((zh - Z) / Z)) * ((Flzhzl - (zh * zl)) / (zh * zl))) + (ZZ * Phigher * ((polyUpper - ZZZPhigher) / ZZZPhigher))) / (1 + HZ + ZZ * Phigher); (Phl - P) / P -> ((PE - P) / P) + ((((PE - P) / P) + 1) * ((Phl - PE) / PE)); (Loghm - Log) / Log -> ((Loghm - P) / P) + ((P - Log) / Log) + ((Loghm - P) / P) * ((P - Log) / Log); (((logh + logm) - Log) / Log) -> (((logh + logm) - Loghm) / Loghm) + ((Loghm - Log) / Log) + (((logh + logm) - Loghm) / Loghm) * ((Loghm - Log) / Log); interval-3.2.0/src/crlibm/gappa/log-td/log-td-E0.gappa0000644000000000000000000001122113316017127020443 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA c3 = (_c3); c4 = (_c4); c5 = (_c5); c6 = (_c6); c7 = (_c7); E = 0; #MAPLE logih = (_logih); logim = (_logim); logil = (_logil); zh = (Z); zl = Z - zh; #MAPLE polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); ZhSquarehl = zh * zh; #MAPLE zhSquareh = (ZhSquarehl); zhSquarel = (ZhSquarehl - zhSquareh); zhSquareHalfh = zhSquareh * (-0.5); #MAPLE zhSquareHalfl = zhSquarel * (-0.5); #MAPLE ZhSquareHalfhl = ZhSquarehl * (-0.5); #MAPLE polyUpper = polyHorner * (zh * zhSquareh); temp = (zh * zl); T1hl = polyUpper - temp; #MAPLE t1h = (T1hl); t1l = (T1hl - t1h); T2 = Z + ZhSquareHalfhl; #MAPLE t2h = (T2hl); t2l = (T2hl - t2h); PE = T2hl + T1hl; #MAPLE ph = (Phl); pl = (Phl - ph); #Useful additional definitions Log2hm = log2h + log2m; #MAPLE Logihm = logih + logim; #MAPLE #End additional LogTabPoly = Logihm + Phl; #MAPLE logTabPolyh = (LogTabPolyhl); logTabPolyl = (LogTabPolyhl - logTabPolyh); #We know that the addition of E * log2hm = 0 and logTabPolyhl is exact #Thus we simplify the proof at this level Loghm = LogTabPolyhl; #MAPLE logh = (Loghm); logm = (Loghm - logh); #Mathematical definition of the logarithm and the polynomial Phigher = (c3 + Z * (c4 + Z * (c5 + Z * (c6 + Z * c7)))); #MAPLE ZZZ = Z*Z*Z; #MAPLE ZZZPhigher = ZZZ * Phigher; #MAPLE HZZ = (-0.5*Z*Z); #MAPLE ZpHZZ = Z + HZZ; #MAPLE P = ZpHZZ + ZZZPhigher; #MAPLE Log1pZpTab = Log1pZ + Logir; #MAPLE #We apply the same simplification to the mathematical definition of the logarithm Log = Log1pZpTab; #MAPLE # Useful additional definitions HZZsimp = HZZ + (zh * zl); #MAPLE ZpHZZsimp = Z + HZZsimp; #MAPLE ZZZPhigherPzhzl = ZZZPhigher - zh * zl; #MAPLE zhCube = zh * zhSquareh; #MAPLE delta1 = T2hl - T2; #MAPLE delta2 = polyUpper - (polyHorner * zhCube); #MAPLE delta3 = zhCube - ZZZ; #MAPLE delta4 = Phl - PE; #MAPLE delta6 = P - Log1pZ; #MAPLE delta7 = LogTabPolyhl - LogTabPoly; #MAPLE # End additional { (T2hl - T2) / T2 in [-1b-103,1b-103] /\ (Phl - PE) / PE in [-1b-103,1b-103] /\ (LogTabPolyhl - LogTabPoly) / LogTabPoly in [-1b-103,1b-103] /\ (Log2hm - Log2) / Log2 in [-1b-84,1b-84] /\ (Logihm - Logir) / Logir in [-1b-106,1b-106] /\ Z in [_zmin,_zmax] /\ (P - Log1pZ) / Log1pZ in [-_epsilonApproxQuick,_epsilonApproxQuick] /\ ((logh + logm) - Loghm) / Loghm in [-1b-106,1b-106] -> ((logh + logm) - Log) / Log in [-5b-65,5b-65] } T2hl - T2 -> ((T2hl - T2) / T2) * T2; T2hl -> (T2hl - T2) + T2; Phl - PE -> ((Phl - PE) / PE) * PE; Phl -> (Phl - PE) + PE; LogTabPolyhl -> (LogTabPolyhl - LogTabPoly) + LogTabPoly; Loghm -> (Loghm - LogE) + LogE; Log2 -> Log2hm * (1 / (((Log2hm - Log2) / Log2) + 1)); Logir -> Logihm * (1 / (((Logihm - Logir) / Logir) + 1)); HZZsimp -> (-0.5 * zh * zh) - (0.5 * zl * zl); T2hl - ZpHZZsimp -> (0.5 * zl * zl) + delta1; zhCube - ZZZ -> (Z * (zhSquareh - Z * Z)) - (zl * zhSquareh); polyUpper - ZZZPhigher -> ZZZ * (polyHorner - Phigher) + polyHorner * delta3 + delta2; ZpHZZ + ZZZPhigher -> ZpHZZsimp + ZZZPhigherPzhzl; Phl - P -> (T2hl - ZpHZZsimp) + (T1hl - ZZZPhigherPzhzl) + delta4; Log1pZ -> P * (1 / (((P - Log1pZ) / Log1pZ) + 1)); P - Log1pZ -> ((P - Log1pZ) / Log1pZ) * Log1pZ; Phl - Log1pZ -> (Phl - P) + delta6; LogTabPolyhl - Log1pZpTab -> (Logihm - Logir) + (Phl - Log1pZ) + delta7; (logh + logm) - Loghm -> (((logh + logm) - Loghm) / Loghm) * Loghm; (logh + logm) - Log -> ((logh + logm) - Loghm) + (Loghm - Log);interval-3.2.0/src/crlibm/gappa/log-td/log-td-accurate-E0-logir0.gappa0000644000000000000000000002450713316017127023435 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA accPolyC14 = (_accPolyC14); accPolyC13 = (_accPolyC13); accPolyC12 = (_accPolyC12); accPolyC11 = (_accPolyC11); accPolyC10 = (_accPolyC10); accPolyC9h = (_accPolyC9h); accPolyC9l = (_accPolyC9l); AccPolyC9hl = accPolyC9h + accPolyC9l; #MAPLE accPolyC8h = (_accPolyC8h); accPolyC8l = (_accPolyC8l); AccPolyC8hl = accPolyC8h + accPolyC8l; #MAPLE accPolyC7h = (_accPolyC7h); accPolyC7l = (_accPolyC7l); AccPolyC7hl = accPolyC7h + accPolyC7l; #MAPLE accPolyC6h = (_accPolyC6h); accPolyC6l = (_accPolyC6l); AccPolyC6hl = accPolyC6h + accPolyC6l; #MAPLE accPolyC5h = (_accPolyC5h); accPolyC5l = (_accPolyC5l); AccPolyC5hl = accPolyC5h + accPolyC5l; #MAPLE accPolyC4h = (_accPolyC4h); accPolyC4l = (_accPolyC4l); AccPolyC4hl = accPolyC4h + accPolyC4l; #MAPLE accPolyC3h = (_accPolyC3h); accPolyC3l = (_accPolyC3l); AccPolyC3hl = accPolyC3h + accPolyC3l; #MAPLE E = 0; #MAPLE zh = (Z); zl = Z - zh; #MAPLE highPoly = accPolyC10 + zh * (accPolyC11 + zh * (accPolyC12 + zh * (accPolyC13 + zh * accPolyC14))); T1hl = zh * highPoly; #MAPLE T2 = AccPolyC9hl + T1hl; #MAPLE T3 = Z * T2hl; #MAPLE T4 = AccPolyC8hl + T3hl; #MAPLE T5 = Z * T4hl; #MAPLE T6 = AccPolyC7hl + T5hl; #MAPLE T7 = Z * T6hl; #MAPLE T8 = AccPolyC6hl + T7hl; #MAPLE T9 = Z * T8hl; #MAPLE T10 = AccPolyC5hl + T9hl; #MAPLE T11 = Z * T10hl; #MAPLE T12 = AccPolyC4hl + T11hl; #MAPLE T13 = Z * T12hl; #MAPLE T14 = AccPolyC3hl + T13hl; #MAPLE ZSquare = Z * Z; #MAPLE ZCube = Z * ZSquarehml; #MAPLE HigherPolyMultZ = T14hl * ZCubehml; #MAPLE ZSquareHalfhml = -0.5 * ZSquarehml; #MAPLE PolyWithSquare = ZSquareHalfhml + HigherPolyMultZhml; #MAPLE Poly = Z + PolyWithSquarehml; #MAPLE #We can simplify the proof in this case since we know that adding a triple double which is #equal to 0 exactly is exact. Loghml = Polyhml; #MAPLE #Mathematical definition of the logarithm MHighPoly = accPolyC10 + Z * (accPolyC11 + Z * (accPolyC12 + Z * (accPolyC13 + Z * accPolyC14))); #MAPLE MT1 = Z * MHighPoly; #MAPLE MT2 = AccPolyC9hl + MT1; #MAPLE MT3 = Z * MT2; #MAPLE MT4 = AccPolyC8hl + MT3; #MAPLE MT5 = Z * MT4; #MAPLE MT6 = AccPolyC7hl + MT5; #MAPLE MT7 = Z * MT6; #MAPLE MT8 = AccPolyC6hl + MT7; #MAPLE MT9 = Z * MT8; #MAPLE MT10 = AccPolyC5hl + MT9; #MAPLE MT11 = Z * MT10; #MAPLE MT12 = AccPolyC4hl + MT11; #MAPLE MT13 = Z * MT12; #MAPLE MT14 = AccPolyC3hl + MT13; #MAPLE MZSquare = Z * Z; #MAPLE MZCube = Z * MZSquare; #MAPLE MHigherPolyMultZ = MT14 * MZCube; #MAPLE MZSquareHalf = -0.5 * MZSquare; #MAPLE MPolyWithSquare = MZSquareHalf + MHigherPolyMultZ; #MAPLE MPoly = Z + MPolyWithSquare; #MAPLE #We apply the same simplification here MLog = MLog1pZ; #MAPLE #Useful additional definitions epsilon1 = (highPoly - MHighPoly) / MHighPoly; #MAPLE epsilon2 = (T1hl - MT1) / MT1; #MAPLE epsilon3 = (T2hl - MT2) / MT2; #MAPLE epsilon4 = (T3hl - MT3) / MT3; #MAPLE epsilon5 = (T4hl - MT4) / MT4; #MAPLE epsilon6 = (T5hl - MT5) / MT5; #MAPLE epsilon7 = (T6hl - MT6) / MT6; #MAPLE epsilon8 = (T7hl - MT7) / MT7; #MAPLE epsilon9 = (T8hl - MT8) / MT8; #MAPLE epsilon10 = (T9hl - MT9) / MT9; #MAPLE epsilon11 = (T10hl - MT10) / MT10; #MAPLE epsilon12 = (T11hl - MT11) / MT11; #MAPLE epsilon13 = (T12hl - MT12) / MT12; #MAPLE epsilon14 = (T13hl - MT13) / MT13; #MAPLE epsilon15 = (T14hl - MT14) / MT14; #MAPLE epsilon16 = (ZCubehml - MZCube) / MZCube; #MAPLE epsilon17 = (HigherPolyMultZhml - MHigherPolyMultZ) / MHigherPolyMultZ; #MAPLE epsilon18 = (ZSquareHalfhml - MZSquareHalf) / MZSquareHalf; #MAPLE epsilon19 = (PolyWithSquarehml - MPolyWithSquare) / MPolyWithSquare; #MAPLE epsilon20 = (Polyhml - MLog1pZ) / MLog1pZ; #MAPLE epsilon21 = (PolyWithSquare - MPolyWithSquare) / MPolyWithSquare; #MAPLE epsilon22 = (Polyhml - MPoly) / MPoly; #MAPLE epsilon23 = (Poly - MPoly) / MPoly; #MAPLE aux1 = -0.5 * Z + MZSquare * MT14; #MAPLE #End additional definitions { ( (T2hl - T2) / T2 in [-1b-103,1b-103] /\ (T3hl - T3) / T3 in [-1b-102,1b-102] /\ (T4hl - T4) / T4 in [-1b-103,1b-103] /\ (T5hl - T5) / T5 in [-1b-102,1b-102] /\ (T6hl - T6) / T6 in [-1b-103,1b-103] /\ (T7hl - T7) / T7 in [-1b-102,1b-102] /\ (T8hl - T8) / T8 in [-1b-103,1b-103] /\ (T9hl - T9) / T9 in [-1b-102,1b-102] /\ (T10hl - T10) / T10 in [-1b-103,1b-103] /\ (T11hl - T11) / T11 in [-1b-102,1b-102] /\ (T12hl - T12) / T12 in [-1b-103,1b-103] /\ (T13hl - T13) / T13 in [-1b-102,1b-102] /\ (T14hl - T14) / T14 in [-1b-103,1b-103] /\ (ZSquarehml - ZSquare) / ZSquare in [-1b-149,1b-149] /\ (ZCubehml - ZCube) / ZCube in [-1b-144,1b-144] /\ (HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ in [-1b-141,1b-141] /\ (PolyWithSquarehml - PolyWithSquare) / PolyWithSquare in [-1b-137,1b-137] /\ (Polyhml - Poly) / Poly in [-1b-134,1b-134] /\ (MPoly - MLog1pZ) / MLog1pZ in [-_epsilonApproxAccurate,_epsilonApproxAccurate] /\ Z in [1b-900,_zmax] /\ ((logh + logm + logl) - Loghml) / Loghml in [-1b-159,1b-159] -> ((logh + logm + logl) - MLog) / MLog in [-5735b-132,5735b-132] ) /\ ( (T2hl - T2) / T2 in [-1b-103,1b-103] /\ (T3hl - T3) / T3 in [-1b-102,1b-102] /\ (T4hl - T4) / T4 in [-1b-103,1b-103] /\ (T5hl - T5) / T5 in [-1b-102,1b-102] /\ (T6hl - T6) / T6 in [-1b-103,1b-103] /\ (T7hl - T7) / T7 in [-1b-102,1b-102] /\ (T8hl - T8) / T8 in [-1b-103,1b-103] /\ (T9hl - T9) / T9 in [-1b-102,1b-102] /\ (T10hl - T10) / T10 in [-1b-103,1b-103] /\ (T11hl - T11) / T11 in [-1b-102,1b-102] /\ (T12hl - T12) / T12 in [-1b-103,1b-103] /\ (T13hl - T13) / T13 in [-1b-102,1b-102] /\ (T14hl - T14) / T14 in [-1b-103,1b-103] /\ (ZSquarehml - ZSquare) / ZSquare in [-1b-149,1b-149] /\ (ZCubehml - ZCube) / ZCube in [-1b-144,1b-144] /\ (HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ in [-1b-141,1b-141] /\ (PolyWithSquarehml - PolyWithSquare) / PolyWithSquare in [-1b-137,1b-137] /\ (Polyhml - Poly) / Poly in [-1b-134,1b-134] /\ (MPoly - MLog1pZ) / MLog1pZ in [-_epsilonApproxAccurate,_epsilonApproxAccurate] /\ Z in [_zmin,-1b-900] /\ ((logh + logm + logl) - Loghml) / Loghml in [-1b-159,1b-159] -> ((logh + logm + logl) - MLog) / MLog in [-5735b-132,5735b-132] ) } ((logh + logm + logl) - MLog) / MLog -> ((Loghml - MLog) / MLog) + ((((logh + logm + logl) - Loghml) / Loghml) * (((Loghml - MLog) / MLog) + 1)); T2hl -> (T2 * ((T2hl - T2) / T2)) + T2; T3hl -> (T3 * ((T3hl - T3) / T3)) + T3; T4hl -> (T4 * ((T4hl - T4) / T4)) + T4; T5hl -> (T5 * ((T5hl - T5) / T5)) + T5; T6hl -> (T6 * ((T6hl - T6) / T6)) + T6; T7hl -> (T7 * ((T7hl - T7) / T7)) + T7; T8hl -> (T8 * ((T8hl - T8) / T8)) + T8; T9hl -> (T9 * ((T9hl - T9) / T9)) + T9; T10hl -> (T10 * ((T10hl - T10) / T10)) + T10; T11hl -> (T11 * ((T11hl - T11) / T11)) + T11; T12hl -> (T12 * ((T12hl - T12) / T12)) + T12; T13hl -> (T13 * ((T13hl - T13) / T13)) + T13; T14hl -> (T14 * ((T14hl - T14) / T14)) + T14; ZSquarehml -> (ZSquare * ((ZSquarehml - ZSquare) / ZSquare)) + ZSquare; ZCubehml -> (ZCube * ((ZCubehml - ZCube) / ZCube)) + ZCube; HigherPolyMultZhml -> (HigherPolyMultZ * ((HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ)) + HigherPolyMultZ; PolyWithSquarehml -> (PolyWithSquare * ((PolyWithSquarehml - PolyWithSquare) / PolyWithSquare)) + PolyWithSquare; Polyhml -> (Poly * ((Polyhml - Poly) / Poly)) + Poly; epsilon2 -> epsilon1 + (((zh - Z) / Z) * (epsilon1 + 1)); epsilon3 -> ((epsilon2 * MT1) / (AccPolyC9hl + MT1)) + (((AccPolyC9hl + T1hl) / (AccPolyC9hl + MT1)) * ((T2hl - T2) / T2)); epsilon4 -> epsilon3 + (((T3hl - T3) / T3) * (epsilon3 + 1)); epsilon5 -> ((epsilon4 * MT3) / (AccPolyC8hl + MT3)) + (((AccPolyC8hl + T3hl) / (AccPolyC8hl + MT3)) * ((T4hl - T4) / T4)); epsilon6 -> epsilon5 + (((T5hl - T5) / T5) * (epsilon5 + 1)); epsilon7 -> ((epsilon6 * MT5) / (AccPolyC7hl + MT5)) + (((AccPolyC7hl + T5hl) / (AccPolyC7hl + MT5)) * ((T6hl - T6) / T6)); epsilon8 -> epsilon7 + (((T7hl - T7) / T7) * (epsilon7 + 1)); epsilon9 -> ((epsilon8 * MT7) / (AccPolyC6hl + MT7)) + (((AccPolyC6hl + T7hl) / (AccPolyC6hl + MT7)) * ((T8hl - T8) / T8)); epsilon10 -> epsilon9 + (((T9hl - T9) / T9) * (epsilon9 + 1)); epsilon11 -> ((epsilon10 * MT9) / (AccPolyC5hl + MT9)) + (((AccPolyC5hl + T9hl) / (AccPolyC5hl + MT9)) * ((T10hl - T10) / T10)); epsilon12 -> epsilon11 + (((T11hl - T11) / T11) * (epsilon11 + 1)); epsilon13 -> ((epsilon12 * MT11) / (AccPolyC4hl + MT11)) + (((AccPolyC4hl + T11hl) / (AccPolyC4hl + MT11)) * ((T12hl - T12) / T12)); epsilon14 -> epsilon13 + (((T13hl - T13) / T13) * (epsilon13 + 1)); epsilon15 -> ((epsilon14 * MT13) / (AccPolyC3hl + MT13)) + (((AccPolyC3hl + T13hl) / (AccPolyC3hl + MT13)) * ((T14hl - T14) / T14)); epsilon16 -> ((ZSquarehml - MZSquare) / MZSquare) + (((ZCubehml - ZCube) / ZCube) * (((ZSquarehml - MZSquare) / MZSquare) + 1)); epsilon17 -> epsilon15 + epsilon16 + epsilon15 * epsilon16 + ((HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ) * (1 + epsilon15 + epsilon16 + epsilon15 * epsilon16); epsilon18 -> (ZSquarehml - MZSquare) / MZSquare; epsilon19 -> epsilon21 + (1 + epsilon21) * ((PolyWithSquarehml - PolyWithSquare) / PolyWithSquare); epsilon20 -> (((Polyhml - MPoly) / MPoly) + ((MPoly - MLog1pZ) / MLog1pZ)) + (((Polyhml - MPoly) / MPoly) * ((MPoly - MLog1pZ) / MLog1pZ)); epsilon21 -> ((-0.5 * epsilon18) + (Z * MT14 * epsilon17)) / (-0.5 + (Z * MT14)); epsilon22 -> epsilon23 + (((Polyhml - Poly) / Poly) * (1+ epsilon23)); epsilon23 -> epsilon19 * (aux1 / (1 + aux1)); interval-3.2.0/src/crlibm/gappa/log-td/log-td-accurate-E0.gappa0000644000000000000000000002111613316017127022234 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA logih = (_logih); logim = (_logim); logil = (_logil); Logihml = logih + logim + logil; #MAPLE accPolyC14 = (_accPolyC14); accPolyC13 = (_accPolyC13); accPolyC12 = (_accPolyC12); accPolyC11 = (_accPolyC11); accPolyC10 = (_accPolyC10); accPolyC9h = (_accPolyC9h); accPolyC9l = (_accPolyC9l); AccPolyC9hl = accPolyC9h + accPolyC9l; #MAPLE accPolyC8h = (_accPolyC8h); accPolyC8l = (_accPolyC8l); AccPolyC8hl = accPolyC8h + accPolyC8l; #MAPLE accPolyC7h = (_accPolyC7h); accPolyC7l = (_accPolyC7l); AccPolyC7hl = accPolyC7h + accPolyC7l; #MAPLE accPolyC6h = (_accPolyC6h); accPolyC6l = (_accPolyC6l); AccPolyC6hl = accPolyC6h + accPolyC6l; #MAPLE accPolyC5h = (_accPolyC5h); accPolyC5l = (_accPolyC5l); AccPolyC5hl = accPolyC5h + accPolyC5l; #MAPLE accPolyC4h = (_accPolyC4h); accPolyC4l = (_accPolyC4l); AccPolyC4hl = accPolyC4h + accPolyC4l; #MAPLE accPolyC3h = (_accPolyC3h); accPolyC3l = (_accPolyC3l); AccPolyC3hl = accPolyC3h + accPolyC3l; #MAPLE E = 0; #MAPLE zh = (Z); zl = Z - zh; #MAPLE highPoly = accPolyC10 + zh * (accPolyC11 + zh * (accPolyC12 + zh * (accPolyC13 + zh * accPolyC14))); T1hl = zh * highPoly; #MAPLE T2 = AccPolyC9hl + T1hl; #MAPLE T3 = Z * T2hl; #MAPLE T4 = AccPolyC8hl + T3hl; #MAPLE T5 = Z * T4hl; #MAPLE T6 = AccPolyC7hl + T5hl; #MAPLE T7 = Z * T6hl; #MAPLE T8 = AccPolyC6hl + T7hl; #MAPLE T9 = Z * T8hl; #MAPLE T10 = AccPolyC5hl + T9hl; #MAPLE T11 = Z * T10hl; #MAPLE T12 = AccPolyC4hl + T11hl; #MAPLE T13 = Z * T12hl; #MAPLE T14 = AccPolyC3hl + T13hl; #MAPLE ZSquare = Z * Z; #MAPLE ZCube = Z * ZSquarehml; #MAPLE HigherPolyMultZ = T14hl * ZCubehml; #MAPLE ZSquareHalfhml = -0.5 * ZSquarehml; #MAPLE PolyWithSquare = ZSquareHalfhml + HigherPolyMultZhml; #MAPLE Poly = Z + PolyWithSquarehml; #MAPLE Logy = Logihml + Polyhml; #MAPLE #We can simplify the proof in this case since we know that adding a triple double which is #equal to 0 exactly is exact. Loghml = Logyhml; #MAPLE #Mathematical definition of the logarithm MHighPoly = accPolyC10 + Z * (accPolyC11 + Z * (accPolyC12 + Z * (accPolyC13 + Z * accPolyC14))); #MAPLE MT1 = Z * MHighPoly; #MAPLE MT2 = AccPolyC9hl + MT1; #MAPLE MT3 = Z * MT2; #MAPLE MT4 = AccPolyC8hl + MT3; #MAPLE MT5 = Z * MT4; #MAPLE MT6 = AccPolyC7hl + MT5; #MAPLE MT7 = Z * MT6; #MAPLE MT8 = AccPolyC6hl + MT7; #MAPLE MT9 = Z * MT8; #MAPLE MT10 = AccPolyC5hl + MT9; #MAPLE MT11 = Z * MT10; #MAPLE MT12 = AccPolyC4hl + MT11; #MAPLE MT13 = Z * MT12; #MAPLE MT14 = AccPolyC3hl + MT13; #MAPLE MZSquare = Z * Z; #MAPLE MZCube = Z * MZSquare; #MAPLE MHigherPolyMultZ = MT14 * MZCube; #MAPLE MZSquareHalf = -0.5 * MZSquare; #MAPLE MPolyWithSquare = MZSquareHalf + MHigherPolyMultZ; #MAPLE MPoly = Z + MPolyWithSquare; #MAPLE MLogy = MLogi + MLog1pZ; #MAPLE #We apply the same simplification here MLog = MLogy; #MAPLE #Useful additional definitions delta1 = highPoly - MHighPoly; #MAPLE delta2 = T1hl - MT1; #MAPLE delta3 = T2hl - MT2; #MAPLE delta4 = T3hl - MT3; #MAPLE delta5 = T4hl - MT4; #MAPLE delta6 = T5hl - MT5; #MAPLE delta7 = T6hl - MT6; #MAPLE delta8 = T7hl - MT7; #MAPLE delta9 = T8hl - MT8; #MAPLE delta10 = T9hl - MT9; #MAPLE delta11 = T10hl - MT10; #MAPLE delta12 = T11hl - MT11; #MAPLE delta13 = T12hl - MT12; #MAPLE delta14 = T13hl - MT13; #MAPLE delta15 = T14hl - MT14; #MAPLE delta16 = ZSquarehml - MZSquare; #MAPLE delta17 = ZCubehml - MZCube; #MAPLE delta18 = HigherPolyMultZhml - MHigherPolyMultZ; #MAPLE delta19 = ZSquareHalfhml - MZSquareHalf; #MAPLE delta20 = PolyWithSquarehml - MPolyWithSquare; #MAPLE delta21 = Polyhml - MPoly; #MAPLE delta22 = Logyhml - MLogy; #MAPLE delta24 = Loghml - MLog; #MAPLE delta25 = Logihml - MLogi; #MAPLE delta26 = Polyhml - MLog1pZ; #MAPLE #End additional definitions { (T2hl - T2) / T2 in [-1b-103,1b-103] /\ (T3hl - T3) / T3 in [-1b-102,1b-102] /\ (T4hl - T4) / T4 in [-1b-103,1b-103] /\ (T5hl - T5) / T5 in [-1b-102,1b-102] /\ (T6hl - T6) / T6 in [-1b-103,1b-103] /\ (T7hl - T7) / T7 in [-1b-102,1b-102] /\ (T8hl - T8) / T8 in [-1b-103,1b-103] /\ (T9hl - T9) / T9 in [-1b-102,1b-102] /\ (T10hl - T10) / T10 in [-1b-103,1b-103] /\ (T11hl - T11) / T11 in [-1b-102,1b-102] /\ (T12hl - T12) / T12 in [-1b-103,1b-103] /\ (T13hl - T13) / T13 in [-1b-102,1b-102] /\ (T14hl - T14) / T14 in [-1b-103,1b-103] /\ (ZSquarehml - ZSquare) / ZSquare in [-1b-149,1b-149] /\ (ZCubehml - ZCube) / ZCube in [-1b-144,1b-144] /\ (HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ in [-1b-141,1b-141] /\ (PolyWithSquarehml - PolyWithSquare) / PolyWithSquare in [-1b-137,1b-137] /\ (Polyhml - Poly) / Poly in [-1b-134,1b-134] /\ (Logyhml - Logy) / Logy in [-1b-128,1b-128] /\ (Logihml - MLogi) / MLogi in [-1b-159,1b-159] /\ (MPoly - MLog1pZ) / MLog1pZ in [-_epsilonApproxAccurate,_epsilonApproxAccurate] /\ Z in [_zmin,_zmax] /\ ((logh + logm + logl) - Loghml) / Loghml in [-1b-159,1b-159] -> ((logh + logm + logl) - MLog) / MLog in [-5735b-132,5735b-132] } MLog1pZ -> MPoly * (1 / (((MPoly - MLog1pZ) / MLog1pZ) + 1)); MLog2 -> Log2hml * (1 / (((Log2hml - MLog2) / MLog2) + 1)); MLogi -> Logihml * (1 / (((Logihml - MLogi) / MLogi) + 1)); T2hl -> (T2 * ((T2hl - T2) / T2)) + T2; T3hl -> (T3 * ((T3hl - T3) / T3)) + T3; T4hl -> (T4 * ((T4hl - T4) / T4)) + T4; T5hl -> (T5 * ((T5hl - T5) / T5)) + T5; T6hl -> (T6 * ((T6hl - T6) / T6)) + T6; T7hl -> (T7 * ((T7hl - T7) / T7)) + T7; T8hl -> (T8 * ((T8hl - T8) / T8)) + T8; T9hl -> (T9 * ((T9hl - T9) / T9)) + T9; T10hl -> (T10 * ((T10hl - T10) / T10)) + T10; T11hl -> (T11 * ((T11hl - T11) / T11)) + T11; T12hl -> (T12 * ((T12hl - T12) / T12)) + T12; T13hl -> (T13 * ((T13hl - T13) / T13)) + T13; T14hl -> (T14 * ((T14hl - T14) / T14)) + T14; ZSquarehml -> (ZSquare * ((ZSquarehml - ZSquare) / ZSquare)) + ZSquare; ZCubehml -> (ZCube * ((ZCubehml - ZCube) / ZCube)) + ZCube; HigherPolyMultZhml -> (HigherPolyMultZ * ((HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ)) + HigherPolyMultZ; PolyWithSquarehml -> (PolyWithSquare * ((PolyWithSquarehml - PolyWithSquare) / PolyWithSquare)) + PolyWithSquare; Polyhml -> (Poly * ((Polyhml - Poly) / Poly)) + Poly; Logyhml -> (Logy * ((Logyhml - Logy) / Logy)) + Logy; delta3 -> delta2 + (T2 * ((T2hl - T2) / T2)); delta4 -> Z * delta3 + T3 * ((T3hl - T3) / T3); delta5 -> delta4 + (T4 * ((T4hl - T4) / T4)); delta6 -> Z * delta5 + T5 * ((T5hl - T5) / T5); delta7 -> delta6 + (T6 * ((T6hl - T6) / T6)); delta8 -> Z * delta7 + T7 * ((T7hl - T7) / T7); delta9 -> delta8 + (T8 * ((T8hl - T8) / T8)); delta10 -> Z * delta9 + T9 * ((T9hl - T9) / T9); delta11 -> delta10 + (T10 * ((T10hl - T10) / T10)); delta12 -> Z * delta11 + T11 * ((T11hl - T11) / T11); delta13 -> delta12 + (T12 * ((T12hl - T12) / T12)); delta14 -> Z * delta13 + T13 * ((T13hl - T13) / T13); delta15 -> delta14 + (T14 * ((T14hl - T14) / T14)); delta16 -> Z*Z*((ZSquarehml - ZSquare) / ZSquare); delta17 -> Z * delta16 + ZCube * ((ZCubehml - ZCube) / ZCube); delta18 -> delta15 * delta17 + delta15 * MZCube + delta17 * MT14 + HigherPolyMultZ * ((HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ); delta20 -> delta19 + delta18 + PolyWithSquare * ((PolyWithSquarehml - PolyWithSquare) / PolyWithSquare); delta21 -> delta20 + Poly * ((Polyhml - Poly) / Poly); delta22 -> delta25 + delta26 + Logy * ((Logyhml - Logy) / Logy); delta26 -> delta21 + MLog1pZ * ((MPoly - MLog1pZ) / MLog1pZ); ((logh + logm + logl) - MLog) / MLog -> ((Loghml - MLog) / MLog) + ((((logh + logm + logl) - Loghml) / Loghml) * (((Loghml - MLog) / MLog) + 1)); interval-3.2.0/src/crlibm/gappa/log-td/log-td-accurate.gappa0000644000000000000000000002151713316017127021777 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA log2h = (_log2h); log2m = (_log2m); log2l = (_log2l); Log2hml = log2h + log2m + log2l; #MAPLE logih = (_logih); logim = (_logim); logil = (_logil); Logihml = logih + logim + logil; #MAPLE accPolyC14 = (_accPolyC14); accPolyC13 = (_accPolyC13); accPolyC12 = (_accPolyC12); accPolyC11 = (_accPolyC11); accPolyC10 = (_accPolyC10); accPolyC9h = (_accPolyC9h); accPolyC9l = (_accPolyC9l); AccPolyC9hl = accPolyC9h + accPolyC9l; #MAPLE accPolyC8h = (_accPolyC8h); accPolyC8l = (_accPolyC8l); AccPolyC8hl = accPolyC8h + accPolyC8l; #MAPLE accPolyC7h = (_accPolyC7h); accPolyC7l = (_accPolyC7l); AccPolyC7hl = accPolyC7h + accPolyC7l; #MAPLE accPolyC6h = (_accPolyC6h); accPolyC6l = (_accPolyC6l); AccPolyC6hl = accPolyC6h + accPolyC6l; #MAPLE accPolyC5h = (_accPolyC5h); accPolyC5l = (_accPolyC5l); AccPolyC5hl = accPolyC5h + accPolyC5l; #MAPLE accPolyC4h = (_accPolyC4h); accPolyC4l = (_accPolyC4l); AccPolyC4hl = accPolyC4h + accPolyC4l; #MAPLE accPolyC3h = (_accPolyC3h); accPolyC3l = (_accPolyC3l); AccPolyC3hl = accPolyC3h + accPolyC3l; #MAPLE E = 1; #MAPLE zh = (Z); zl = Z - zh; #MAPLE highPoly = accPolyC10 + zh * (accPolyC11 + zh * (accPolyC12 + zh * (accPolyC13 + zh * accPolyC14))); T1hl = zh * highPoly; #MAPLE T2 = AccPolyC9hl + T1hl; #MAPLE T3 = Z * T2hl; #MAPLE T4 = AccPolyC8hl + T3hl; #MAPLE T5 = Z * T4hl; #MAPLE T6 = AccPolyC7hl + T5hl; #MAPLE T7 = Z * T6hl; #MAPLE T8 = AccPolyC6hl + T7hl; #MAPLE T9 = Z * T8hl; #MAPLE T10 = AccPolyC5hl + T9hl; #MAPLE T11 = Z * T10hl; #MAPLE T12 = AccPolyC4hl + T11hl; #MAPLE T13 = Z * T12hl; #MAPLE T14 = AccPolyC3hl + T13hl; #MAPLE ZSquare = Z * Z; #MAPLE ZCube = Z * ZSquarehml; #MAPLE HigherPolyMultZ = T14hl * ZCubehml; #MAPLE ZSquareHalfhml = -0.5 * ZSquarehml; #MAPLE PolyWithSquare = ZSquareHalfhml + HigherPolyMultZhml; #MAPLE Poly = Z + PolyWithSquarehml; #MAPLE Logy = Logihml + Polyhml; #MAPLE Log2edhml = E * Log2hml; #MAPLE Logover = Log2edhml + Logyhml; #MAPLE #Mathematical definition of the logarithm MHighPoly = accPolyC10 + Z * (accPolyC11 + Z * (accPolyC12 + Z * (accPolyC13 + Z * accPolyC14))); #MAPLE MT1 = Z * MHighPoly; #MAPLE MT2 = AccPolyC9hl + MT1; #MAPLE MT3 = Z * MT2; #MAPLE MT4 = AccPolyC8hl + MT3; #MAPLE MT5 = Z * MT4; #MAPLE MT6 = AccPolyC7hl + MT5; #MAPLE MT7 = Z * MT6; #MAPLE MT8 = AccPolyC6hl + MT7; #MAPLE MT9 = Z * MT8; #MAPLE MT10 = AccPolyC5hl + MT9; #MAPLE MT11 = Z * MT10; #MAPLE MT12 = AccPolyC4hl + MT11; #MAPLE MT13 = Z * MT12; #MAPLE MT14 = AccPolyC3hl + MT13; #MAPLE MZSquare = Z * Z; #MAPLE MZCube = Z * MZSquare; #MAPLE MHigherPolyMultZ = MT14 * MZCube; #MAPLE MZSquareHalf = -0.5 * MZSquare; #MAPLE MPolyWithSquare = MZSquareHalf + MHigherPolyMultZ; #MAPLE MPoly = Z + MPolyWithSquare; #MAPLE MLogy = MLogi + MLog1pZ; #MAPLE MLog2E = E * MLog2; #MAPLE MLog = MLog2E + MLogy; #MAPLE #Useful additional definitions delta1 = highPoly - MHighPoly; #MAPLE delta2 = T1hl - MT1; #MAPLE delta3 = T2hl - MT2; #MAPLE delta4 = T3hl - MT3; #MAPLE delta5 = T4hl - MT4; #MAPLE delta6 = T5hl - MT5; #MAPLE delta7 = T6hl - MT6; #MAPLE delta8 = T7hl - MT7; #MAPLE delta9 = T8hl - MT8; #MAPLE delta10 = T9hl - MT9; #MAPLE delta11 = T10hl - MT10; #MAPLE delta12 = T11hl - MT11; #MAPLE delta13 = T12hl - MT12; #MAPLE delta14 = T13hl - MT13; #MAPLE delta15 = T14hl - MT14; #MAPLE delta16 = ZSquarehml - MZSquare; #MAPLE delta17 = ZCubehml - MZCube; #MAPLE delta18 = HigherPolyMultZhml - MHigherPolyMultZ; #MAPLE delta19 = ZSquareHalfhml - MZSquareHalf; #MAPLE delta20 = PolyWithSquarehml - MPolyWithSquare; #MAPLE delta21 = Polyhml - MPoly; #MAPLE delta22 = Logyhml - MLogy; #MAPLE delta23 = Log2edhml - MLog2E; #MAPLE delta24 = Loghml - MLog; #MAPLE delta25 = Logihml - MLogi; #MAPLE delta26 = Polyhml - MLog1pZ; #MAPLE #End additional definitions { (T2hl - T2) / T2 in [-1b-103,1b-103] /\ (T3hl - T3) / T3 in [-1b-102,1b-102] /\ (T4hl - T4) / T4 in [-1b-103,1b-103] /\ (T5hl - T5) / T5 in [-1b-102,1b-102] /\ (T6hl - T6) / T6 in [-1b-103,1b-103] /\ (T7hl - T7) / T7 in [-1b-102,1b-102] /\ (T8hl - T8) / T8 in [-1b-103,1b-103] /\ (T9hl - T9) / T9 in [-1b-102,1b-102] /\ (T10hl - T10) / T10 in [-1b-103,1b-103] /\ (T11hl - T11) / T11 in [-1b-102,1b-102] /\ (T12hl - T12) / T12 in [-1b-103,1b-103] /\ (T13hl - T13) / T13 in [-1b-102,1b-102] /\ (T14hl - T14) / T14 in [-1b-103,1b-103] /\ (ZSquarehml - ZSquare) / ZSquare in [-1b-149,1b-149] /\ (ZCubehml - ZCube) / ZCube in [-1b-144,1b-144] /\ (HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ in [-1b-141,1b-141] /\ (PolyWithSquarehml - PolyWithSquare) / PolyWithSquare in [-1b-137,1b-137] /\ (Polyhml - Poly) / Poly in [-1b-134,1b-134] /\ (Logyhml - Logy) / Logy in [-1b-128,1b-128] /\ (Loghml - Logover) / Logover in [-1b-123,1b-123] /\ (Log2hml - MLog2) / MLog2 in [-1b-126,1b-126] /\ (Logihml - MLogi) / MLogi in [-1b-159,1b-159] /\ (MPoly - MLog1pZ) / MLog1pZ in [-_epsilonApproxAccurate,_epsilonApproxAccurate] /\ Z in [_zmin,_zmax] /\ ((logh + logm + logl) - Loghml) / Loghml in [-1b-159,1b-159] -> ((logh + logm + logl) - MLog) / MLog in [-5735b-132,5735b-132] } MLog1pZ -> MPoly * (1 / (((MPoly - MLog1pZ) / MLog1pZ) + 1)); MLog2 -> Log2hml * (1 / (((Log2hml - MLog2) / MLog2) + 1)); MLogi -> Logihml * (1 / (((Logihml - MLogi) / MLogi) + 1)); T2hl -> (T2 * ((T2hl - T2) / T2)) + T2; T3hl -> (T3 * ((T3hl - T3) / T3)) + T3; T4hl -> (T4 * ((T4hl - T4) / T4)) + T4; T5hl -> (T5 * ((T5hl - T5) / T5)) + T5; T6hl -> (T6 * ((T6hl - T6) / T6)) + T6; T7hl -> (T7 * ((T7hl - T7) / T7)) + T7; T8hl -> (T8 * ((T8hl - T8) / T8)) + T8; T9hl -> (T9 * ((T9hl - T9) / T9)) + T9; T10hl -> (T10 * ((T10hl - T10) / T10)) + T10; T11hl -> (T11 * ((T11hl - T11) / T11)) + T11; T12hl -> (T12 * ((T12hl - T12) / T12)) + T12; T13hl -> (T13 * ((T13hl - T13) / T13)) + T13; T14hl -> (T14 * ((T14hl - T14) / T14)) + T14; ZSquarehml -> (ZSquare * ((ZSquarehml - ZSquare) / ZSquare)) + ZSquare; ZCubehml -> (ZCube * ((ZCubehml - ZCube) / ZCube)) + ZCube; HigherPolyMultZhml -> (HigherPolyMultZ * ((HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ)) + HigherPolyMultZ; PolyWithSquarehml -> (PolyWithSquare * ((PolyWithSquarehml - PolyWithSquare) / PolyWithSquare)) + PolyWithSquare; Polyhml -> (Poly * ((Polyhml - Poly) / Poly)) + Poly; Logyhml -> (Logy * ((Logyhml - Logy) / Logy)) + Logy; delta3 -> delta2 + (T2 * ((T2hl - T2) / T2)); delta4 -> Z * delta3 + T3 * ((T3hl - T3) / T3); delta5 -> delta4 + (T4 * ((T4hl - T4) / T4)); delta6 -> Z * delta5 + T5 * ((T5hl - T5) / T5); delta7 -> delta6 + (T6 * ((T6hl - T6) / T6)); delta8 -> Z * delta7 + T7 * ((T7hl - T7) / T7); delta9 -> delta8 + (T8 * ((T8hl - T8) / T8)); delta10 -> Z * delta9 + T9 * ((T9hl - T9) / T9); delta11 -> delta10 + (T10 * ((T10hl - T10) / T10)); delta12 -> Z * delta11 + T11 * ((T11hl - T11) / T11); delta13 -> delta12 + (T12 * ((T12hl - T12) / T12)); delta14 -> Z * delta13 + T13 * ((T13hl - T13) / T13); delta15 -> delta14 + (T14 * ((T14hl - T14) / T14)); delta16 -> Z*Z*((ZSquarehml - ZSquare) / ZSquare); delta17 -> Z * delta16 + ZCube * ((ZCubehml - ZCube) / ZCube); delta18 -> delta15 * delta17 + delta15 * MZCube + delta17 * MT14 + HigherPolyMultZ * ((HigherPolyMultZhml - HigherPolyMultZ) / HigherPolyMultZ); delta20 -> delta19 + delta18 + PolyWithSquare * ((PolyWithSquarehml - PolyWithSquare) / PolyWithSquare); delta21 -> delta20 + Poly * ((Polyhml - Poly) / Poly); delta22 -> delta25 + delta26 + Logy * ((Logyhml - Logy) / Logy); delta26 -> delta21 + MLog1pZ * ((MPoly - MLog1pZ) / MLog1pZ); delta24 -> delta23 + delta22 + Logover * ((Loghml - Logover) / Logover); ((logh + logm + logl) - MLog) / MLog -> ((Loghml - MLog) / MLog) + ((((logh + logm + logl) - Loghml) / Loghml) * (((Loghml - MLog) / MLog) + 1));interval-3.2.0/src/crlibm/gappa/log-td/log-td.gappa0000644000000000000000000001175213316017127020212 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA log2h = (_log2h); log2m = (_log2m); log2l = (_log2l); c3 = (_c3); c4 = (_c4); c5 = (_c5); c6 = (_c6); c7 = (_c7); E = 1; #MAPLE logih = (_logih); logim = (_logim); logil = (_logil); zh = (Z); zl = Z - zh; #MAPLE polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); ZhSquarehl = zh * zh; #MAPLE zhSquareh = (ZhSquarehl); zhSquarel = (ZhSquarehl - zhSquareh); zhSquareHalfh = zhSquareh * (-0.5); #MAPLE zhSquareHalfl = zhSquarel * (-0.5); #MAPLE ZhSquareHalfhl = ZhSquarehl * (-0.5); #MAPLE polyUpper = polyHorner * (zh * zhSquareh); temp = (zh * zl); T1hl = polyUpper - temp; #MAPLE t1h = (T1hl); t1l = (T1hl - t1h); T2 = Z + ZhSquareHalfhl; #MAPLE t2h = (T2hl); t2l = (T2hl - t2h); PE = T2hl + T1hl; #MAPLE ph = (Phl); pl = (Phl - ph); Log2hed = E * log2h; #MAPLE Log2med = E * log2m; #MAPLE Log2edhm = Log2hed + Log2med; #MAPLE log2edh = (Log2edhm); log2edl = (Log2edhm - log2edh); #Useful additional definitions Log2hm = log2h + log2m; #MAPLE Logihm = logih + logim; #MAPLE #End additional LogTabPoly = Logihm + Phl; #MAPLE logTabPolyh = (LogTabPolyhl); logTabPolyl = (LogTabPolyhl - logTabPolyh); LogE = Log2edhm + LogTabPolyhl; #MAPLE logh = (Loghm); logm = (Loghm - logh); #Mathematical definition of the logarithm and the polynomial Phigher = (c3 + Z * (c4 + Z * (c5 + Z * (c6 + Z * c7)))); #MAPLE ZZZ = Z*Z*Z; #MAPLE ZZZPhigher = ZZZ * Phigher; #MAPLE HZZ = (-0.5*Z*Z); #MAPLE ZpHZZ = Z + HZZ; #MAPLE P = ZpHZZ + ZZZPhigher; #MAPLE Log2E = E * Log2; #MAPLE Log1pZpTab = Log1pZ + Logir; #MAPLE Log = Log2E + Log1pZpTab; #MAPLE # Useful additional definitions HZZsimp = HZZ + (zh * zl); #MAPLE ZpHZZsimp = Z + HZZsimp; #MAPLE ZZZPhigherPzhzl = ZZZPhigher - zh * zl; #MAPLE zhCube = zh * zhSquareh; #MAPLE delta1 = T2hl - T2; #MAPLE delta2 = polyUpper - (polyHorner * zhCube); #MAPLE delta3 = zhCube - ZZZ; #MAPLE delta4 = Phl - PE; #MAPLE delta5 = Loghm - LogE; #MAPLE delta6 = P - Log1pZ; #MAPLE delta7 = LogTabPolyhl - LogTabPoly; #MAPLE # End additional { (T2hl - T2) / T2 in [-1b-103,1b-103] /\ (Phl - PE) / PE in [-1b-103,1b-103] /\ (LogTabPolyhl - LogTabPoly) / LogTabPoly in [-1b-103,1b-103] /\ (Loghm - LogE) / LogE in [-1b-103,1b-103] /\ (Log2hm - Log2) / Log2 in [-1b-84,1b-84] /\ (Logihm - Logir) / Logir in [-1b-106,1b-106] /\ Z in [_zmin,_zmax] /\ (P - Log1pZ) / Log1pZ in [-_epsilonApproxQuick,_epsilonApproxQuick] /\ ((logh + logm) - Loghm) / Loghm in [-1b-106,1b-106] -> ((logh + logm) - Log) / Log in [-5b-65,5b-65] } T2hl - T2 -> ((T2hl - T2) / T2) * T2; T2hl -> (T2hl - T2) + T2; Phl - PE -> ((Phl - PE) / PE) * PE; Phl -> (Phl - PE) + PE; LogTabPolyhl -> (LogTabPolyhl - LogTabPoly) + LogTabPoly; Loghm -> (Loghm - LogE) + LogE; Log2 -> Log2hm * (1 / (((Log2hm - Log2) / Log2) + 1)); Logir -> Logihm * (1 / (((Logihm - Logir) / Logir) + 1)); LogTabPolyhl - LogTabPoly -> ((LogTabPolyhl - LogTabPoly) / LogTabPoly) * LogTabPoly; HZZsimp -> (-0.5 * zh * zh) - (0.5 * zl * zl); T2hl - ZpHZZsimp -> (0.5 * zl * zl) + delta1; zhCube - ZZZ -> (Z * (zhSquareh - Z * Z)) - (zl * zhSquareh); polyUpper - ZZZPhigher -> ZZZ * (polyHorner - Phigher) + polyHorner * delta3 + delta2; ZpHZZ + ZZZPhigher -> ZpHZZsimp + ZZZPhigherPzhzl; Phl - P -> (T2hl - ZpHZZsimp) + (T1hl - ZZZPhigherPzhzl) + delta4; Log1pZ -> P * (1 / (((P - Log1pZ) / Log1pZ) + 1)); P - Log1pZ -> ((P - Log1pZ) / Log1pZ) * Log1pZ; Phl - Log1pZ -> (Phl - P) + delta6; LogTabPolyhl - Log1pZpTab -> (Logihm - Logir) + (Phl - Log1pZ) + delta7; Loghm - Log -> (Log2edhm - Log2E) + (LogTabPolyhl - Log1pZpTab) + delta5; (logh + logm) - Loghm -> (((logh + logm) - Loghm) / Loghm) * Loghm; (logh + logm) - Log -> ((logh + logm) - Loghm) + (Loghm - Log);interval-3.2.0/src/crlibm/gappa/sqrt-proof.sh0000755000000000000000000000236213316017127017274 0ustar 00000000000000#/bin/bash # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA GAPPA=~/schorle/gappa/src/gappa echo Proving error bound on sqrt12... sed -f sqrt.sed sqrt12.gappa | $GAPPA echo Proving error bound on sqrt13... sed -f sqrt.sed sqrt13.gappa | $GAPPA interval-3.2.0/src/crlibm/gappa/sqrt.sed0000644000000000000000000000112113316017127016277 0ustar 00000000000000s/_epsilonApprox/3.19769311343973090277659766935447078312230091629790e-03/g s/_ERecSqrtmMin/7.07000000000000000000000000000000000000000000000000e-01/g s/_ERecSqrtmMax/1.41430000000000000000000000000000000000000000000000e+00/g s/_SQRTPOLYC0/2.50385236695888790947606139525305479764938354492188e+00/g s/_SQRTPOLYC1/-3.29763389114324168005509818613063544034957885742188e+00/g s/_SQRTPOLYC2/2.75726076139124520736345402838196605443954467773438e+00/g s/_SQRTPOLYC3/-1.15233725777933848632983426796272397041320800781250e+00/g s/_SQRTPOLYC4/1.86900066679800969104974228685023263096809387207031e-01/g interval-3.2.0/src/crlibm/gappa/sqrt12.gappa0000644000000000000000000001447013316017127016772 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #@ -Eprecision=108 # In this Gappa file, the mathematical values are not # marked with a leading M but with a leading E (for exact) # The reason is that we have already variables starting # with the letter M # Rounding operators and sequences definition @double = float; @Add22 = add_rel<102>; @Mul22 = mul_rel<102>; # Instantiating of constants SQRTPOLYC0 = double(_SQRTPOLYC0); SQRTPOLYC1 = double(_SQRTPOLYC1); SQRTPOLYC2 = double(_SQRTPOLYC2); SQRTPOLYC3 = double(_SQRTPOLYC3); SQRTPOLYC4 = double(_SQRTPOLYC4); # Definition of what is a sqrt # We start with the reciprocal square root. The square root is its reciprocal. # The reduced argument m is the square of its root. ESqrtm = 1 / ERecSqrtm; m = ESqrtm * ESqrtm; ERecM = 1 / m; # Translation of the code r0 double= SQRTPOLYC0 + m * (SQRTPOLYC1 + m * (SQRTPOLYC2 + m * (SQRTPOLYC3 + m * SQRTPOLYC4))); r1 double= (1/2) * r0 * (3 - m * (r0 * r0)); r2 double= (1/2) * r1 * (3 - m * (r1 * r1)); R2Sqhl = r2 * r2; R2PHr2hl = (3/2) * r2; MMr2hl = m * r2; MMr2Chl = Mul22(MMr2hl, R2Sqhl); MHmMr2Chl = -(1/2) * MMr2Chl; R3hl = Add22(R2PHr2hl, MHmMr2Chl); R3Sqhl = Mul22(R3hl,R3hl); MMr3Sqhl = Mul22(m,R3Sqhl); # The next translation of the code is correct only if we can prove that # mMr3Sqh is exactly 1 in each case # We show this below T1 = 1 + -(1/2) * (MMr3Sqhl - 1); R4hl = Mul22(R3hl,T1); Srtmhl = Mul22(m,R4hl); # Show that mMr3Sqh is exactly 1 in each case # We round the double-double result MMr3Sqhl to double # precision and show that the result is in the singleton # interval [1,1] mMr3Sqh = double(MMr3Sqhl); # Mathematical equivalents (marked with E for exact) Er0 = SQRTPOLYC0 + m * (SQRTPOLYC1 + m * (SQRTPOLYC2 + m * (SQRTPOLYC3 + m * SQRTPOLYC4))); Er1 = (1/2) * Er0 * (3 - m * (Er0 * Er0)); Er2 = (1/2) * Er1 * (3 - m * (Er1 * Er1)); #Definition of the errors epsilon = (Srtmhl - ESqrtm) / ESqrtm; epsilonApproxMath0 = (Er0 - ERecSqrtm) / ERecSqrtm; epsilonApproxMath1 = (Er1 - ERecSqrtm) / ERecSqrtm; epsilonApproxMath2 = (Er2 - ERecSqrtm) / ERecSqrtm; epsilonApproxArith0 = (r0 - ERecSqrtm) / ERecSqrtm; epsilonApproxArith1 = (r1 - ERecSqrtm) / ERecSqrtm; epsilonApproxArith2 = (r2 - ERecSqrtm) / ERecSqrtm; epsilonApproxArith3 = (R3hl - ERecSqrtm) / ERecSqrtm; epsilonApproxArith4 = (R4hl - ERecSqrtm) / ERecSqrtm; epsilon0 = (r0 - Er0) / Er0; epsilon1 = (r1 - Er1) / Er1; epsilon2 = (r2 - Er2) / Er2; epsilon3 = ((R2PHr2hl + MHmMr2Chl) - ERecSqrtm) / ERecSqrtm; epsilon4 = ((R3hl * T1) - ERecSqrtm) / ERecSqrtm; epsilon5 = ((T1 - 3/2) - (-1/2 * m * R3hl * R3hl)) / (-1/2 * m * R3hl * R3hl); epsilon6 = (MMr3Sqhl - (m * (R3hl * R3hl))) / (m * (R3hl * R3hl)); epsilon7 = (R3Sqhl - ERecM) / ERecM; epsilon8 = (MMr3Sqhl - 1) / 1; epsilon9 = ((R3hl * R3hl) - ERecM) / ERecM; epsilon10 = ((m * R3Sqhl) - 1) / 1; epsilon11 = ((m * R4hl) - ESqrtm) / ESqrtm; epsilonOp0 = (MMr2Chl - (MMr2hl * R2Sqhl)) / (MMr2hl * R2Sqhl); epsilonOp1 = (R3hl - (R2PHr2hl + MHmMr2Chl)) / (R2PHr2hl + MHmMr2Chl); epsilonOp2 = (R3Sqhl - (R3hl * R3hl)) / (R3hl * R3hl); epsilonOp3 = (MMr3Sqhl - (m * R3Sqhl)) / (m * R3Sqhl); epsilonOp4 = (R4hl - (R3hl * T1)) / (R3hl * T1); epsilonOp5 = (Srtmhl - (m * R4hl)) / (m * R4hl); #Logical implication to prove { ( ERecSqrtm in [_ERecSqrtmMin,_ERecSqrtmMax] /\ epsilonApproxMath0 in [-_epsilonApprox,_epsilonApprox] ) -> ( epsilon in [-1b-100,1b-100] # Accuracy bound /\ mMr3Sqh in [1,1] # For showing that mMr3Sqh is always equal to 1 (see above) ) } # Hints for bounding the variables in the code (not the errors) Er0 -> ERecSqrtm * epsilonApproxMath0 + ERecSqrtm; Er1 -> ERecSqrtm * epsilonApproxMath1 + ERecSqrtm; Er2 -> ERecSqrtm * epsilonApproxMath2 + ERecSqrtm; r0 -> Er0 * epsilon0 + Er0; r1 -> Er1 * epsilon1 + Er1; r2 -> Er2 * epsilon2 + Er2; (R2PHr2hl + MHmMr2Chl) -> ERecSqrtm * epsilon3 + ERecSqrtm; MMr3Sqhl -> 1 + epsilon8; # Hints for the Newton iteration epsilonApproxMath1 -> -3/2 * epsilonApproxMath0 * epsilonApproxMath0 - 1/2 * epsilonApproxMath0 * epsilonApproxMath0 * epsilonApproxMath0; epsilonApproxMath2 -> -3/2 * epsilonApproxMath1 * epsilonApproxMath1 - 1/2 * epsilonApproxMath1 * epsilonApproxMath1 * epsilonApproxMath1; # Hints for the Newton iteration with integrated arithmetical errors epsilon3 -> -3/2 * epsilonApproxArith2 * epsilonApproxArith2 -1/2 * epsilonApproxArith2 * epsilonApproxArith2 * epsilonApproxArith2 -1/2 * epsilonOp0 -3/2 * epsilonApproxArith2 * epsilonOp0 -3/2 * epsilonApproxArith2 * epsilonApproxArith2 * epsilonOp0 -1/2 * epsilonApproxArith2 * epsilonApproxArith2 * epsilonApproxArith2 * epsilonOp0; epsilon5 -> epsilon6; epsilon4 -> -3/2 * epsilonApproxArith3 * epsilonApproxArith3 -1/2 * epsilonApproxArith3 * epsilonApproxArith3 * epsilonApproxArith3 -1/2 * epsilon5 -3/2 * epsilon5 * epsilonApproxArith3 -3/2 * epsilon5 * epsilonApproxArith3 * epsilonApproxArith3 -1/2 * epsilon5 * epsilonApproxArith3 * epsilonApproxArith3 * epsilonApproxArith3; epsilon9 -> 2 * epsilonApproxArith3 + epsilonApproxArith3 * epsilonApproxArith3; epsilon10 -> epsilon7; epsilon11 -> epsilonApproxArith4; # Meta-Hints r0 ~ Er0; r1 ~ Er1; r2 ~ Er2; interval-3.2.0/src/crlibm/gappa/sqrt13.gappa0000644000000000000000000001765313316017127017001 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #@ -Eprecision=108 # In this Gappa file, the mathematical values are not # marked with a leading M but with a leading E (for exact) # The reason is that we have already variables starting # with the letter M # Rounding operators and sequences definition @double = float; @Add22 = add_rel<102>; @Mul22 = mul_rel<102>; # Instantiating of constants SQRTPOLYC0 = double(_SQRTPOLYC0); SQRTPOLYC1 = double(_SQRTPOLYC1); SQRTPOLYC2 = double(_SQRTPOLYC2); SQRTPOLYC3 = double(_SQRTPOLYC3); SQRTPOLYC4 = double(_SQRTPOLYC4); # Definition of what is a sqrt # We start with the reciprocal square root. The square root is its reciprocal. # The reduced argument m is the square of its root. ESqrtm = 1 / ERecSqrtm; m = ESqrtm * ESqrtm; ERecM = 1 / m; # Translation of the code r0 double= SQRTPOLYC0 + m * (SQRTPOLYC1 + m * (SQRTPOLYC2 + m * (SQRTPOLYC3 + m * SQRTPOLYC4))); r1 double= (1/2) * r0 * (3 - m * (r0 * r0)); r2 double= (1/2) * r1 * (3 - m * (r1 * r1)); R2Sqhl = r2 * r2; R2PHr2hl = (3/2) * r2; MMr2hl = m * r2; MMr2Chl = Mul22(MMr2hl, R2Sqhl); MHmMr2Chl = -(1/2) * MMr2Chl; R3hl = Add22(R2PHr2hl, MHmMr2Chl); R3Sqhl = Mul22(R3hl,R3hl); MMr3Sqhl = Mul22(m,R3Sqhl); # The next translation of the code is correct only if we can prove that # mMr3Sqh is exactly 1 in each case # We show this below T1 = 1 + -(1/2) * (MMr3Sqhl - 1); R4hl = Mul22(R3hl,T1); R4Sqhml = mul_rel<149>(R4hl,R4hl); MMr4Sqhml = mul_rel<148>(m,R4Sqhml); # The next translation of the code is correct only if we can prove that # mMr4Sqh is exactly 1 in each case # We show this below T2 = 1 + -(1/2) * (MMr4Sqhml - 1); R5hml = mul_rel<148>(R4hl,T2); Srtmhml = mul_rel<148>(m,R5hml); # Show that mMr3Sqh and mMr4Sqh are exactly 1 in each case # We round the double-double and triple-double results MMr3Sqhl # and MMr3Sqhml to double precision and show that the rounding # result is in the singleton interval [1,1] mMr3Sqh = double(MMr3Sqhl); mMr4Sqh = double(MMr4Sqhml); # Mathematical equivalents (marked with E for exact) Er0 = SQRTPOLYC0 + m * (SQRTPOLYC1 + m * (SQRTPOLYC2 + m * (SQRTPOLYC3 + m * SQRTPOLYC4))); Er1 = (1/2) * Er0 * (3 - m * (Er0 * Er0)); Er2 = (1/2) * Er1 * (3 - m * (Er1 * Er1)); #Definition of the errors epsilon = (Srtmhml - ESqrtm) / ESqrtm; epsilonApproxMath0 = (Er0 - ERecSqrtm) / ERecSqrtm; epsilonApproxMath1 = (Er1 - ERecSqrtm) / ERecSqrtm; epsilonApproxMath2 = (Er2 - ERecSqrtm) / ERecSqrtm; epsilonApproxArith0 = (r0 - ERecSqrtm) / ERecSqrtm; epsilonApproxArith1 = (r1 - ERecSqrtm) / ERecSqrtm; epsilonApproxArith2 = (r2 - ERecSqrtm) / ERecSqrtm; epsilonApproxArith3 = (R3hl - ERecSqrtm) / ERecSqrtm; epsilonApproxArith4 = (R4hl - ERecSqrtm) / ERecSqrtm; epsilonApproxArith5 = (R5hml - ERecSqrtm) / ERecSqrtm; epsilon0 = (r0 - Er0) / Er0; epsilon1 = (r1 - Er1) / Er1; epsilon2 = (r2 - Er2) / Er2; epsilon3 = ((R2PHr2hl + MHmMr2Chl) - ERecSqrtm) / ERecSqrtm; epsilon4 = ((R3hl * T1) - ERecSqrtm) / ERecSqrtm; epsilon5 = ((T1 - 3/2) - (-1/2 * m * R3hl * R3hl)) / (-1/2 * m * R3hl * R3hl); epsilon6 = (MMr3Sqhl - (m * (R3hl * R3hl))) / (m * (R3hl * R3hl)); epsilon7 = (R3Sqhl - ERecM) / ERecM; epsilon8 = (MMr3Sqhl - 1) / 1; epsilon9 = ((R3hl * R3hl) - ERecM) / ERecM; epsilon10 = ((m * R3Sqhl) - 1) / 1; epsilon11 = ((T2 - 3/2) - (-1/2 * m * R4hl * R4hl)) / (-1/2 * m * R4hl * R4hl); epsilon12 = (MMr4Sqhml - (m * (R4hl * R4hl))) / (m * (R4hl * R4hl)); epsilon13 = ((R4hl * T2) - ERecSqrtm) / ERecSqrtm; epsilon14 = (MMr4Sqhml - 1) / 1; epsilon15 = (R4Sqhml - ERecM) / ERecM; epsilon16 = ((R4hl * R4hl) - ERecM) / ERecM; epsilon17 = ((m * R4Sqhml) - 1) / 1; epsilon18 = ((m * R5hml) - ESqrtm) / ESqrtm; epsilonOp0 = (MMr2Chl - (MMr2hl * R2Sqhl)) / (MMr2hl * R2Sqhl); epsilonOp1 = (R3hl - (R2PHr2hl + MHmMr2Chl)) / (R2PHr2hl + MHmMr2Chl); epsilonOp2 = (R3Sqhl - (R3hl * R3hl)) / (R3hl * R3hl); epsilonOp3 = (MMr3Sqhl - (m * R3Sqhl)) / (m * R3Sqhl); epsilonOp4 = (R4hl - (R3hl * T1)) / (R3hl * T1); epsilonOp5 = (R4Sqhml - (R4hl * R4hl)) / (R4hl * R4hl); epsilonOp6 = (MMr4Sqhml - (m * R4Sqhml)) / (m * R4Sqhml); epsilonOp7 = (R5hml - (R4hl * T2)) / (R4hl * T2); #Logical implication to prove { ( ERecSqrtm in [_ERecSqrtmMin,_ERecSqrtmMax] /\ epsilonApproxMath0 in [-_epsilonApprox,_epsilonApprox] ) -> ( epsilon in [-1b-146,1b-146] # Accuracy bound /\ mMr3Sqh in [1,1] # For showing that mMr3Sqh is always equal to 1 (see above) /\ mMr4Sqh in [1,1] # For showing that mMr4Sqh is always equal to 1 (see above) ) } # Hints for bounding the variables in the code (not the errors) Er0 -> ERecSqrtm * epsilonApproxMath0 + ERecSqrtm; Er1 -> ERecSqrtm * epsilonApproxMath1 + ERecSqrtm; Er2 -> ERecSqrtm * epsilonApproxMath2 + ERecSqrtm; r0 -> Er0 * epsilon0 + Er0; r1 -> Er1 * epsilon1 + Er1; r2 -> Er2 * epsilon2 + Er2; (R2PHr2hl + MHmMr2Chl) -> ERecSqrtm * epsilon3 + ERecSqrtm; MMr3Sqhl -> 1 + epsilon8; MMr4Sqhml -> 1 + epsilon14; # Hints for the Newton iteration epsilonApproxMath1 -> -3/2 * epsilonApproxMath0 * epsilonApproxMath0 - 1/2 * epsilonApproxMath0 * epsilonApproxMath0 * epsilonApproxMath0; epsilonApproxMath2 -> -3/2 * epsilonApproxMath1 * epsilonApproxMath1 - 1/2 * epsilonApproxMath1 * epsilonApproxMath1 * epsilonApproxMath1; # Hints for the Newton iteration with integrated arithmetical errors epsilon3 -> -3/2 * epsilonApproxArith2 * epsilonApproxArith2 -1/2 * epsilonApproxArith2 * epsilonApproxArith2 * epsilonApproxArith2 -1/2 * epsilonOp0 -3/2 * epsilonApproxArith2 * epsilonOp0 -3/2 * epsilonApproxArith2 * epsilonApproxArith2 * epsilonOp0 -1/2 * epsilonApproxArith2 * epsilonApproxArith2 * epsilonApproxArith2 * epsilonOp0; epsilon5 -> epsilon6; epsilon4 -> -3/2 * epsilonApproxArith3 * epsilonApproxArith3 -1/2 * epsilonApproxArith3 * epsilonApproxArith3 * epsilonApproxArith3 -1/2 * epsilon5 -3/2 * epsilon5 * epsilonApproxArith3 -3/2 * epsilon5 * epsilonApproxArith3 * epsilonApproxArith3 -1/2 * epsilon5 * epsilonApproxArith3 * epsilonApproxArith3 * epsilonApproxArith3; epsilon9 -> 2 * epsilonApproxArith3 + epsilonApproxArith3 * epsilonApproxArith3; epsilon10 -> epsilon7; epsilon11 -> epsilon12; epsilon13 -> -3/2 * epsilonApproxArith4 * epsilonApproxArith4 -1/2 * epsilonApproxArith4 * epsilonApproxArith4 * epsilonApproxArith4 -1/2 * epsilon11 -3/2 * epsilon11 * epsilonApproxArith4 -3/2 * epsilon11 * epsilonApproxArith4 * epsilonApproxArith4 -1/2 * epsilon11 * epsilonApproxArith4 * epsilonApproxArith4 * epsilonApproxArith4; epsilon16 -> 2 * epsilonApproxArith4 + epsilonApproxArith4 * epsilonApproxArith4; epsilon17 -> epsilon15; epsilon18 -> epsilonApproxArith5; # Meta-Hints r0 ~ Er0; r1 ~ Er1; r2 ~ Er2; interval-3.2.0/src/crlibm/gappa/trigos/SinCosCase3.gappa0000644000000000000000000002332413316017127021220 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Usage: You need to set the constants cah, cal, sah, sal. Running the trigo.mpl Maple script # should create 64 files in maple/TEMPTRIG, which can be tested independently as # sed -f ../maple/TEMPTRIG/SinACosA_1.sed trigoSinCosCase3.gappa | ~/gappa/src/gappa > /dev/null # NOTATION CONVENTION # Variables that correspond to double-precision variables in the code begin with a small letter # Other variables begin with a capital letter. # Variables that will be replaced with Maple-computed constants begin with an underscore # Otherwise avoid underscores as they are painful to carry on to LaTeX :) # Rounding operators and sequences definition @IEEEdouble = float; # polynomial coefficients, computed by Maple s3 = IEEEdouble(_s3); s5 = IEEEdouble(_s5); s7 = IEEEdouble(_s7); c2 = IEEEdouble(_c2); c4 = IEEEdouble(_c4); c6 = IEEEdouble(_c6); # Table values, computed by Maple cah = IEEEdouble(_cah); cal = IEEEdouble(_cal); sah = IEEEdouble(_sah); sal = IEEEdouble(_sal); # The variables used here: # x input # My perfect reduced argument # Yhl = yh+yl, his distance to My is specified as an hypothesis # Mts perfect ts # Mtc perfect tc # Msinx exact result for sin(x) # Msina, Mcosa perfect sin(kPi/256) and cos(kPi/256) yh = IEEEdouble(Yhl); yl = Yhl - yh; ####################################################################### # First, a transcription of the actual computation, which could (and # should eventually) be generated automatically from the actual code # ---------------------Code shared by sin and cos, cut from ComputeTrigWithArgRed : yh2 IEEEdouble= yh * yh; ts IEEEdouble= yh2 * (s3 + yh2*(s5 + yh2*s7)); tc IEEEdouble= yh2 * (c2 + yh2*(c4 + yh2*c6)); # ---------------------Code for the sine, cut from DosinNotZero: # Mul12(&cahyh_h,&cahyh_l, cah, yh); cahyh = cah * yh; cahyh_h = IEEEdouble(cahyh); cahyh_l = cahyh - cahyh_h; # Exact equation because Mul12 is exact # Add12(thi, tlo, sah, cahyh_h); TSin = sah + cahyh_h; thiSin = IEEEdouble(TSin); tloSin1 = TSin - thiSin; # Exact equation because Add12 is exact # Rem: need to Rename tlo to tloSin1, and its second use to tloSin2. # It would be safer to translate code to single-assignment before # using Gappa, modern compilers won't make any difference. # tlo = tc*sah+(ts*cahyh_h+(sal+(tlo+(cahyh_l+(cal*yh + cah*yl))))) ; tloSin2 IEEEdouble= tc*sah + (ts*cahyh_h + (sal + (tloSin1 + (cahyh_l + (cal*yh + cah*yl))))); # Add12(*reshi, *reslo, thi, tlo); ResSinhilo = thiSin + tloSin2; # we don't need to split it for the proof. # ---------------------Code for the cos, cut from DoCosNotZero: # Mul12(&sahyh_h,&sahyh_l, sah, yh); sahyh = sah * yh; sahyh_h = IEEEdouble(sahyh); sahyh_l = sahyh - sahyh_h; # Exact equation because Mul12 is exact # Add12(thi, tlo, cah, -sahyh_h); TCos = cah - sahyh_h; thiCos = IEEEdouble(TCos); tloCos1 = TCos - thiCos; # Exact equation because Add12 is exact # tlo = tc*sah+(ts*cahyh_h+(sal+(tlo+(cahyh_l+(cal*yh + cah*yl))))) ; tloCos2 IEEEdouble= tc*cah-(ts*sahyh_h-(cal+(tloCos1-(sahyh_l+(sal*yh+sah*yl))))) ; # Add12(*pch, *pcl, thi, tlo); ResCoshilo = thiCos + tloCos2; # No need to split it for the proof. ####################################################################### #Definitions of the mathematical objects #------------------------------------- #With these notations, the exact sine and cosine are given by these #exact mathematical formulae Msinx = Msiny * Mcosa + Mcosy * Msina; Mcosx = Mcosy * Mcosa - Msiny * Msina; # Now let us pile up layers of approximations #------------------------------------- # yh2 is an approximation to : My2 = My*My; # through three layers: # 1/ Yhl=yh+hl = My +/- delta_ArgRed : in the hypotheses below # 2/ yh = Yhl - yl : already written # 3/ rounding error in the mult : already written #------------------------------------- # ts is an approximation to : Mts = My2 * (s3 + My2*(s5 + My2*s7)); # through two layers: # 1/ the approximation y2 of My2 : done just above # 2/ the rounding errors in Horner : already written #------------------------------------- PolySinY = My * (1 + Mts); # PolySinY is an approximation to sin(My) as expressed in the hypotheses below : # PolySinY - Msiny in [-0.24126e-23, 0.24126e-23] # delta_approx_Sin_Case3 #------------------------------------- # Same for PolyCosY Mtc = My2 * (c2 +(My2 * (c4 + (My2 * c6)))); PolyCosY = 1 + Mtc; #------------------------------------- #tc is an approximation to Mtc through the rounding errors, defined #in the definition of tc. Same for ts #------------------------------------- # SinReconstrExact is an approximation to ResSinhilo SinReconstrExact = PolySinY * Mcosa + PolyCosY * Msina ; # The delta between ResSinhilo and SinReconstrExact is due to the two # mathematical poly approx, and has been defined just above CosReconstrExact = PolyCosY * Mcosa - PolySinY * Msina ; #------------------------------------- # The reconstruction approximates the following SinReconstrNoRound = Yhl*(1 + ts)*(cah+cal) + (1 + tc)*(sah+sal); # where Yhl is an approximation to Y # ts is an approximation to Mts # tc is an approximation to Mtc : all already described # All what we still need to express is that the actual computation will neglect some terms CosReconstrNoRound = ( (1 + tc) * (cah+cal) - Yhl * (1 + ts) * (sah+sal) ); #------------------------------------- # tloSin2 is an approximation to TloSin2NoRound (because of rounding error in the operations, already described) TloSin2NoRound = tc*sah+(ts*cahyh_h+(sal+(tloSin1+(cahyh_l+(cal*yh+cah*yl))))) ; TloCos2NoRound = tc*cah-(ts*sahyh_h-(cal+(tloCos1-(sahyh_l+(sal*yh+sah*yl))))); # tloSinNoRound is an approximation to SinReconstrNoRound - tSinhi, the # difference being the neglected terms. This error will be given as an hint NeglectedSinTerms = SinReconstrNoRound - (thiSin + TloSin2NoRound); NeglectedCosTerms = CosReconstrNoRound - (thiCos + TloCos2NoRound); # And finally, ResSinhilo is an approximation to Msinx through many layers which are given in the hints. ########################################################################################### # The theorem to prove { # (Yhl in [-_ymaxCase3, -1b-200] \/ Yhl in [-1b-200, _ymaxCase3]) # computed by Maple Yhl in [-_ymaxCase3, _ymaxCase3] # computed by Maple /\ Yhl - My in [-_delta_ArgRed, _delta_ArgRed] # computed by Maple /\ PolySinY - Msiny in [-_delta_approx_Sin_Case3, _delta_approx_Sin_Case3] # computed by Maple /\ PolyCosY - Mcosy in [-_delta_approx_Cos_Case3, _delta_approx_Cos_Case3] # computed by Maple /\ Msina-sah-sal in [-1b-104, 1b-104] /\ Mcosa-cah-cal in [-1b-104, 1b-104] # double-double absolute rounding error, with margin -> (ResSinhilo - Msinx)/Msinx in [-3b-66,3b-66] /\ (ResCoshilo - Mcosx)/Mcosx in [-3b-66,3b-66] } ########################################################################################### # Hints to the reduction engine: Gappa is not supposed to be clever, it's an assistant # To get bounds on Msinx, try ResSinhilo Msinx -> ResSinhilo - (ResSinhilo - Msinx); Mcosx -> ResCoshilo - (ResCoshilo - Mcosx); # To get bounds on Msina, try sah+sal Msina -> sah + sal + (Msina - sah - sal); Mcosa -> cah + cal + (Mcosa - cah - cal); # To get bounds on My, try Yhl My -> Yhl - (Yhl - My); # One layer of approx error, and one layer of rounding error for Msiny and Mcosy 1 + tc - Mcosy -> (1 + tc - PolyCosY) + (PolyCosY - Mcosy); (My + My * ts) - Msiny -> ((My + My * ts) - PolySinY) + (PolySinY - Msiny); # Layers of approximations ResSinhilo - Msinx -> (ResSinhilo - SinReconstrNoRound) + (SinReconstrNoRound - SinReconstrExact) + (SinReconstrExact - Msinx); ResCoshilo - Mcosx -> (ResCoshilo - CosReconstrNoRound) + (CosReconstrNoRound - CosReconstrExact) + (CosReconstrExact - Mcosx); NeglectedSinTerms -> sal*tc + cal*yl + ts*(cahyh_l + cah*yl + cal*yh + cal*yl); ResSinhilo - SinReconstrNoRound -> (ResSinhilo - (thiSin + TloSin2NoRound)) - (SinReconstrNoRound - (thiSin + TloSin2NoRound)) ; NeglectedCosTerms -> cal*tc - sal*yl - ts*(sahyh_l + sah*yl + sal*yh + sal*yl); ResCoshilo - CosReconstrNoRound -> (ResCoshilo - (thiCos + TloCos2NoRound)) - (CosReconstrNoRound - (thiCos + TloCos2NoRound)) ; Yhl*(1 + ts)*(cah+cal) - PolySinY * Mcosa -> (Yhl*(1 + ts)- PolySinY)*(cah+cal) - PolySinY*(Mcosa - cah - cal) ; (1 + tc) * (cah+cal) - PolyCosY * Mcosa -> ((1 + tc)- PolyCosY) * (cah+cal) - PolyCosY * (Mcosa - cah -cal); (1 + tc)*(sah+sal) - PolyCosY * Msina -> ((1 + tc)- PolyCosY) * (sah+sal) - PolyCosY * (Msina - sah -sal); interval-3.2.0/src/crlibm/gappa/trigos/SinZero.gappa0000644000000000000000000001525313316017127020536 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # test with gappa -Munconstrained < sin.gappa # The proof is not complete, as it doesn't work without -Munconstrained. # What it means is that Gappa is unable to prove that some denominators are not null. # It's OK to me but it takes some more work to get a formal proof. @IEEEdouble = float; # Convention 1: uncapitalized variables match the variables in the C code. Other variables begin with a capital letter # Convention 2: variables beginning with "M" are mathematical ideal # yh+yl is a double-double (call it Yhl) yh = IEEEdouble(Yhl); yl = Yhl-yh; # The following, along with one hypothesis, ensures that yl is a double, too. dummyZero = IEEEdouble(yl)-yl; #--------------- Transcription of the C code -------------------------- s3 = IEEEdouble(-1.6666666666666665741480812812369549646974e-01); s5 = IEEEdouble(8.3333333333333332176851016015461937058717e-03); s7 = IEEEdouble(-1.9841269841269841252631711547849135968136e-04); yh2 IEEEdouble= yh * yh; ts IEEEdouble= yh2 * (s3 + yh2*(s5 + yh2*s7)); r IEEEdouble= yl + yh*ts; s = yh + r; # no rounding, it is the Fast2Sum #-------- Mathematical definition of what we are approximating -------- My2 = My*My; Mts = My2 * (s3 + My2*(s5 + My2*s7)); PolySinY = My + My*Mts; epsargred = (Yhl - My)/My; epstotal = (s - SinY)/SinY; epsapprox = (PolySinY - SinY)/SinY; epsround = (s - PolySinY)/PolySinY; # Layers of approximation on s S1 = yh + (yl + IEEEdouble(yh*ts)); # remove last round S2 = yh + (yl + yh*ts); # remove penultimate round S3 = (yh+yl) + (yh+yl)*ts; # put yl back in eps1 = (s-S1)/S1; eps2 = (S1-S2)/S2; eps3 = (S2-S3)/S3; eps4 = (S3-PolySinY)/PolySinY; yhts = IEEEdouble(yh*ts); # just to make the hints lighter p3 IEEEdouble= s3 + yh2*(s5 + yh2*s7); # idem tsNoRound = yh2 * (s3 + yh2*(s5 + yh2*s7)); epsy2 = (yh2-My2)/My2; epsy2_argred = (Yhl*Yhl-My2)/My2; epsy2_negl_yl = (yh*yh-Yhl*Yhl)/(Yhl*Yhl); epsy2_rnd = (yh2-yh*yh)/(yh*yh); #---------------------- The theorem to prove -------------------------- { # Hypotheses (Yhl in [1b-200, 6.29e-03] \/ Yhl in [ -6.29e-03, -1b-200]) # lower bound guaranteed by Kahan-Douglas algorithm /\ epsargred in [-2.53e-23, 2.53e-23] /\ epsapprox in [-2.26e-24, 2.26e-24] /\ (yl in [1b-200, 6.29e-03] \/ yl in [-6.29e-03, -1b-200]) /\ dummyZero in [0, 0] -> #goal to prove epstotal in ?# [-1b-67, 1b-67] #/\ |s| in ? # At the moment it contains zero } # Yes, it takes one definition, one hypothesis and one hint to manage a double-double input. yl -> IEEEdouble(yl) - dummyZero; # First, some hints for epsy2 # Combination of three relative errors epsy2 -> epsy2_negl_yl + epsy2_rnd + epsy2_argred + epsy2_negl_yl*epsy2_rnd + epsy2_negl_yl*epsy2_argred + epsy2_rnd*epsy2_argred + epsy2_negl_yl*epsy2_rnd*epsy2_argred; # Rewriting hint to remove decorrelation epsy2_argred -> # (epsargred+1)*(epsargred+1) - 1; epsargred*(epsargred + 2); # Another one epsy2_negl_yl -> # (yh*yh-(Yhl*Yhl))/(Yhl*Yhl); # (yh*yh-((yh+yl)*(yh+yl))) / ((yh+yl)*(yh+yl)); # (-2*yh*yl -yl*yl) / (yh*yh + 2*yh*yl + yl*yl); (-2*yl -yl*yl/yh) / (yh + 2*yl + yl*yl/yh) ; # Now the hints for epsround s~S1; S1~S2; S2~S3; S3~PolySinY; eps4 -> # (S3-PolySinY)/PolySinY; # S3/PolySinY - 1; # ((yh+yl) + (yh+yl)*ts) / (My + My*Mts) - 1; # ((yh+yl)/My) * (1+ts)/(1+Mts) - 1; # (epsargred+1) * (1+ts)/(1+Mts) - 1; # epsargred * (1+ts)/(1+Mts) + 1 * (1+ts)/(1+Mts) - 1; # epsargred * (1+ts)/(1+Mts) + (ts-Mts)/(1+Mts); epsargred * (1+ts)/(1+Mts) + Mts*((ts-Mts)/Mts) / (1+Mts); # Now we just need to bound ts-Mts: ts ~ tsNoRound; (tsNoRound - Mts)/Mts -> # yh2/My2 * (s3 + yh2*(s5 + yh2*s7)) / (s3 + My2*(s5 + My2*s7)) - 1 ; (1+epsy2) * (s3 + yh2*(s5 + yh2*s7)) / (s3 + My2*(s5 + My2*s7)) -1; # Now we just need to express My2 in terms of yh2 and epsy2 My2 -> yh2/(1+epsy2); eps3 -> #(S2-S3)/S3 # S2/S3 - 1; # (yh + (yl + yh*ts)) / ((yh+yl) + (yh+yl)*ts) - 1 ; # ((yh+yl) + (yh+yl)*ts - yl*ts) / ((yh+yl) + (yh+yl)*ts) - 1 ; # - yl*ts / ((yh+yl) + (yh+yl)*ts) ; # - (yl/Yhl) * (ts / (1+ts)) ; ((yh-Yhl)/Yhl) * (ts / (1+ts)) ; # change sign to have the expression of a rounding error eps2 -> # (S1-S2)/S2; # (yh + (yl + IEEEdouble(yh*ts))) / (yh + (yl + yh*ts)) -1 ; # (IEEEdouble(yh*ts) - yh*ts) / (yh + yl + yh*ts) ; # ((IEEEdouble(yh*ts) - yh*ts)/(yh*ts)) / ( (yh+yl)/(yh*ts) + 1 ) ; # ts * ((IEEEdouble(yh*ts) - yh*ts)/(yh*ts)) / ( 1 + yl/yh + ts ) ; # Almost OK, just the denominator is poorly bounded ts * ((IEEEdouble(yh*ts) - yh*ts)/(yh*ts)) / ( 1/(1+(yh-Yhl)/Yhl) + ts ) ; yl/yh -> - ((yh-Yhl)/Yhl) / (1+(yh-Yhl)/Yhl); yhts/yh -> ts*((yhts-yh*ts)/(yh*ts) + 1); # !here the most difficult bit. #eps1 -> #(s-S1)/S1; # (IEEEdouble(yl+yhts) - (yl+yhts)) / (yh + yl + yhts); # First make a rounding error appear at the numerator, and factor yh in the denominator, using the hints for yh/yl and yhts/yh below # ((IEEEdouble(yl+yhts) - (yl+yhts))/((yl+yhts)) ) * (yl/yh + yhts/yh) / (1 + yl/yh + yhts/yh); # Now denominator is OK, problem is that numerator needs a proof that yl+yhts is not equal to zero. (yl+yhts)/yh -> yl/yh + yhts/yh; #Hints for epstotal epstotal -> epsapprox + epsround + epsapprox*epsround; # The following are hints added to remove the -Munconstrained PolySinY -> My*(1+Mts); # To show that s doesn't go through zero, we have to make a correlation appear between yl and yh in the sum below: #s -> yh + IEEEdouble(yl + IEEEdouble(yh*ts)); s -> yh * (1+ IEEEdouble(yl + IEEEdouble(yh*ts) )/yh ); interval-3.2.0/src/crlibm/gappa/trigos/TanCase2.gappa0000644000000000000000000000630313316017127020541 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Usage: You need to replace a few constants (beginning by _) by numerical # values. Running the trigo.mpl Maple script will generate a # TEMPTRIG/tanCase2.sed sed script that does it. # Then sed -f TEMPTRIG/TanCase2.sed trigoTanCase2.gappa | gappa > /dev/null # NOTATION CONVENTION # Variables that correspond to double-precision variables in the code begin with a small letter # Other variables begin with a capital letter. # Otherwise avoid underscores as they are painful to carry on to LaTeX :) # Definition of the polynomial constants: t11 = (_t11); t9 = (_t9); t7 = (_t7); t5 = (_t5); t3h = (_t3h); t3l = (_t3l); ####################################################################### # First, a transcription of the actual computation, which could (and # should eventually) be generated automatically from the actual code # ---------------------Code cut from tan_rn : # x2 = x*x; x2 = x * x; X2 = x*x; # p5 = t5 + x2*(t7 + x2*(t9 + x2*t11)); p5 = t5 + x2*(t7 + x2*(t9 + x2*t11)); P5 = t5 + X2*(t7 + X2*(t9 + X2*t11)); # tt = x2*(t3h + (t3l + x2*p5)); tt = x2*(t3h + (t3l + x2*p5)); Tt = X2*(t3h + (t3l + X2*p5)); # Add12(rri.rh, rri.rl, x, x*tt); rdd = x + (x*tt); # The Add12 is exact Poly = x+x*Tt; epsilon=(rdd - TanX)/TanX; { x in [1b-30, _xmax] /\ (Poly - TanX)/TanX in [-_maxEpsApprox, _maxEpsApprox] /\ ((Poly - TanX)/TanX)/x in [-_maxEpsApproxOverX, _maxEpsApproxOverX] -> epsilon in ? /\ epsilon/x in [-1b-56,1b-56] } # Use a dichotomy on x to get an interval of epsilon/x epsilon/x $ x; # The usual hint for relative errors, with an additional /x*x so that Gappa uses the Maple-computed mathematical bound (rdd - TanX)/TanX -> (rdd - Poly)/Poly + (((Poly - TanX)/TanX)/x)*x + ((rdd - Poly)/Poly) * ((Poly - TanX)/TanX) ; (rdd - Poly)/Poly -> (((x*tt) - x*Tt) / x) * (x/Poly); # I'm not sure I understand why this one improves the result ((x*tt) - x*Tt)/x -> (((x*tt) - x*tt)/(x*tt)) * tt + (tt - Tt); # Easy hints x/Poly -> 1/(Poly/x); Poly/x -> 1+Tt; interval-3.2.0/src/crlibm/gappa/trigpi/cospi-accurate.gappa0000644000000000000000000002076613316017127022043 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 1b0 + ((x^(1b1)) * ((-50044839772224400049002264095087b-103) + ((x^(1b1)) * (10290057726411619042605446323595b-101 + ((x^(1b1)) * ((-3006744454127613b-51) + ((x^(1b1)) * (4239339756765869b-54 + ((x^(1b1)) * (-7438313106810207b-58)))))))))) # The polynomial implemented is: 1b0 + ((x^(1b1)) * ((-50044839772224400049002264095087b-103) + ((x^(1b1)) * (10290057726411619042605446323595b-101 + ((x^(1b1)) * ((-3006744454127613b-51) + ((x^(1b1)) * (4239339756765869b-54 + ((x^(1b1)) * (-7438313106810207b-58)))))))))) # The domain is [-1b-8;1b-8] # The free variable x is a double precision number, the result cospiprecise_res* is stored on a triple-double number. # The code produces 17 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code cospiprecise_coeff_0h = double(1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00); cospiprecise_coeff_2h = double(-4.93480220054467899615247006295248866081237792968750000000000000000000000000000000e+00); cospiprecise_coeff_2m = double(-3.13264775437072047133490817894057799839785556899468543790021612949203699827194214e-16); cospiprecise_coeff_2hm = cospiprecise_coeff_2h + cospiprecise_coeff_2m; cospiprecise_coeff_4h = double(4.05871212641676848420502210501581430435180664062500000000000000000000000000000000e+00); cospiprecise_coeff_4m = double(-2.66019969731660223662555032718185048048635055542576743903282476821914315223693848e-16); cospiprecise_coeff_4hm = cospiprecise_coeff_4h + cospiprecise_coeff_4m; cospiprecise_coeff_6h = double(-1.33526276885458949905682857206556946039199829101562500000000000000000000000000000e+00); cospiprecise_coeff_8h = double(2.35330630358513925859398341344785876572132110595703125000000000000000000000000000e-01); cospiprecise_coeff_10h = double(-2.58068327360992909313974763563237502239644527435302734375000000000000000000000000e-02); cospiprecise_x_0_pow2hm = xh * xh; cospiprecise_x_0_pow2h = double(cospiprecise_x_0_pow2hm); cospiprecise_x_0_pow2m = cospiprecise_x_0_pow2hm - cospiprecise_x_0_pow2h; cospiprecise_t_1_0h = cospiprecise_coeff_10h; cospiprecise_t_2_0h = double(cospiprecise_t_1_0h * cospiprecise_x_0_pow2h); cospiprecise_t_3_0h = double(cospiprecise_coeff_8h + cospiprecise_t_2_0h); cospiprecise_t_4_0h = double(cospiprecise_t_3_0h * cospiprecise_x_0_pow2h); cospiprecise_t_5_0hm = cospiprecise_coeff_6h + cospiprecise_t_4_0h; cospiprecise_t_5_0h = double(cospiprecise_t_5_0hm); cospiprecise_t_5_0m = cospiprecise_t_5_0hm - cospiprecise_t_5_0h; cospiprecise_t_6_0hm = fma_rel<100>(cospiprecise_t_5_0hm,cospiprecise_x_0_pow2hm,cospiprecise_coeff_4hm); cospiprecise_t_6_0h = double(cospiprecise_t_6_0hm); cospiprecise_t_6_0m = cospiprecise_t_6_0hm - cospiprecise_t_6_0h; cospiprecise_t_7_0hm = fma_rel<100>(cospiprecise_t_6_0hm,cospiprecise_x_0_pow2hm,cospiprecise_coeff_2hm); cospiprecise_t_7_0h = double(cospiprecise_t_7_0hm); cospiprecise_t_7_0m = cospiprecise_t_7_0hm - cospiprecise_t_7_0h; cospiprecise_t_8_0hm = mul_rel<102>(cospiprecise_t_7_0hm,cospiprecise_x_0_pow2hm); cospiprecise_t_8_0h = double(cospiprecise_t_8_0hm); cospiprecise_t_8_0m = cospiprecise_t_8_0hm - cospiprecise_t_8_0h; cospiprecise_t_9_0hml = add_rel<159>(cospiprecise_coeff_0h,cospiprecise_t_8_0hm); cospiprecise_t_9_0ml = cospiprecise_t_9_0hml - cospiprecise_t_9_0h; cospiprecise_t_9_0m = double(cospiprecise_t_9_0ml); cospiprecise_t_9_0l = cospiprecise_t_9_0ml - cospiprecise_t_9_0m; cospiprecise_t_9_0hm = cospiprecise_t_9_0h + cospiprecise_t_9_0m; overlap_cospiprecise_t_9_0 = cospiprecise_t_9_0m / cospiprecise_t_9_0h; cospiprecise_reshml = cospiprecise_t_9_0hml; cospiprecise_reshm = cospiprecise_t_9_0hm; cospiprecise_resml = cospiprecise_t_9_0ml; cospiprecise_resh = cospiprecise_t_9_0h; cospiprecise_resm = cospiprecise_t_9_0m; cospiprecise_resl = cospiprecise_t_9_0l; overlap_cospiprecise_res = overlap_cospiprecise_t_9_0; # Mathematical equivalents Mx = x; Mcospiprecise_coeff_0 = cospiprecise_coeff_0h; Mcospiprecise_coeff_2 = cospiprecise_coeff_2hm; Mcospiprecise_coeff_4 = cospiprecise_coeff_4hm; Mcospiprecise_coeff_6 = cospiprecise_coeff_6h; Mcospiprecise_coeff_8 = cospiprecise_coeff_8h; Mcospiprecise_coeff_10 = cospiprecise_coeff_10h; Mcospiprecise_x_0_pow2 = Mx * Mx; Mcospiprecise_t_1_0 = Mcospiprecise_coeff_10; Mcospiprecise_t_2_0 = Mcospiprecise_t_1_0 * Mcospiprecise_x_0_pow2; Mcospiprecise_t_3_0 = Mcospiprecise_coeff_8 + Mcospiprecise_t_2_0; Mcospiprecise_t_4_0 = Mcospiprecise_t_3_0 * Mcospiprecise_x_0_pow2; Mcospiprecise_t_5_0 = Mcospiprecise_coeff_6 + Mcospiprecise_t_4_0; Mcospiprecise_t_6_0 = (Mcospiprecise_t_5_0 * Mcospiprecise_x_0_pow2) + Mcospiprecise_coeff_4; Mcospiprecise_t_7_0 = (Mcospiprecise_t_6_0 * Mcospiprecise_x_0_pow2) + Mcospiprecise_coeff_2; Mcospiprecise_t_8_0 = Mcospiprecise_t_7_0 * Mcospiprecise_x_0_pow2; Mcospiprecise_t_9_0 = Mcospiprecise_coeff_0 + Mcospiprecise_t_8_0; Mcospiprecise_res = Mcospiprecise_t_9_0; # Definition of the relative arithmetical error epsilon = (cospiprecise_reshml - Mcospiprecise_res) / Mcospiprecise_res; # Implication to prove {(( x in [-1b-8,-1b-408] /\ |overlap_cospiprecise_t_9_0| in [1b-400,1b-52] # Verify the lower bound /\ |cospiprecise_t_9_0ml| in [1b-1021,1b1023] ) \/ ( x in [1b-408,1b-8] /\ |overlap_cospiprecise_t_9_0| in [1b-400,1b-52] # Verify the lower bound /\ |cospiprecise_t_9_0ml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition cospiprecise_x_0_pow2h ~ cospiprecise_x_0_pow2hm; cospiprecise_t_5_0h ~ cospiprecise_t_5_0hm; cospiprecise_t_6_0h ~ cospiprecise_t_6_0hm; cospiprecise_t_7_0h ~ cospiprecise_t_7_0hm; cospiprecise_t_8_0h ~ cospiprecise_t_8_0hm; cospiprecise_t_9_0hm ~ cospiprecise_t_9_0hml; cospiprecise_t_9_0h ~ cospiprecise_t_9_0hm; cospiprecise_t_9_0h ~ cospiprecise_t_9_0hml; cospiprecise_t_9_0m -> cospiprecise_t_9_0h * overlap_cospiprecise_t_9_0; cospiprecise_t_9_0l / cospiprecise_t_9_0m -> - ((cospiprecise_t_9_0m - cospiprecise_t_9_0ml) / cospiprecise_t_9_0ml) / (1 + ((cospiprecise_t_9_0m - cospiprecise_t_9_0ml) / cospiprecise_t_9_0ml)); (cospiprecise_t_9_0hm - cospiprecise_t_9_0hml) / cospiprecise_t_9_0hml -> - (cospiprecise_t_9_0l / cospiprecise_t_9_0m) * (1 / (1 / overlap_cospiprecise_t_9_0 + 1 + (cospiprecise_t_9_0l / cospiprecise_t_9_0m))); cospiprecise_t_9_0ml -> cospiprecise_t_9_0hml / ((1 + ((cospiprecise_t_9_0m - cospiprecise_t_9_0ml) / cospiprecise_t_9_0ml)) / overlap_cospiprecise_t_9_0 + 1); (cospiprecise_t_9_0h - cospiprecise_t_9_0hm) / cospiprecise_t_9_0hm -> - 1 / (1 / overlap_cospiprecise_t_9_0 + 1); cospiprecise_t_9_0h -> cospiprecise_t_9_0hml / (overlap_cospiprecise_t_9_0 / (1 + ((cospiprecise_t_9_0m - cospiprecise_t_9_0ml) / cospiprecise_t_9_0ml)) + 1); # Meta-Hints for Horner scheme cospiprecise_x_0_pow2hm ~ Mcospiprecise_x_0_pow2; cospiprecise_t_1_0h ~ Mcospiprecise_t_1_0; cospiprecise_t_2_0h ~ Mcospiprecise_t_2_0; cospiprecise_t_3_0h ~ Mcospiprecise_t_3_0; cospiprecise_t_4_0h ~ Mcospiprecise_t_4_0; cospiprecise_t_5_0hm ~ Mcospiprecise_t_5_0; cospiprecise_t_6_0hm ~ Mcospiprecise_t_6_0; cospiprecise_t_7_0hm ~ Mcospiprecise_t_7_0; cospiprecise_t_8_0hm ~ Mcospiprecise_t_8_0; cospiprecise_t_9_0hml ~ Mcospiprecise_t_9_0; cospiprecise_reshml ~ Mcospiprecise_res; # Dichotomies for triple-double decomposition $ cospiprecise_t_9_0hml in (0); $ cospiprecise_t_9_0ml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/trigpi/cospi-quick.gappa0000644000000000000000000001157013316017127021361 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: 1b0 + ((x^(1b1)) * ((-2778046668940015b-49) + ((x^(1b1)) * (4569703604931271b-50 + ((x^(1b1)) * (-6013451953439851b-52)))))) # The polynomial implemented is: 1b0 + ((x^(1b1)) * ((-2778046668940015b-49) + ((x^(1b1)) * (4569703604931271b-50 + ((x^(1b1)) * (-6013451953439851b-52)))))) # The domain is [-1b-8;1b-8] # The free variable x is a double precision number, the result cospiquick_res* is stored on a double-double number. # The code produces 13 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code cospiquick_coeff_0h = double(1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00); cospiquick_coeff_2h = double(-4.93480220054467899615247006295248866081237792968750000000000000000000000000000000e+00); cospiquick_coeff_4h = double(4.05871212632582167856298838160000741481781005859375000000000000000000000000000000e+00); cospiquick_coeff_6h = double(-1.33525456323720947970912220625905320048332214355468750000000000000000000000000000e+00); cospiquick_x_0_pow2hm = xh * xh; cospiquick_x_0_pow2h = double(cospiquick_x_0_pow2hm); cospiquick_x_0_pow2m = cospiquick_x_0_pow2hm - cospiquick_x_0_pow2h; cospiquick_t_1_0h = cospiquick_coeff_6h; cospiquick_t_2_0h = double(cospiquick_t_1_0h * cospiquick_x_0_pow2h); cospiquick_t_3_0h = double(cospiquick_coeff_4h + cospiquick_t_2_0h); cospiquick_t_4_0h = double(cospiquick_t_3_0h * cospiquick_x_0_pow2h); cospiquick_t_5_0hm = cospiquick_coeff_2h + cospiquick_t_4_0h; cospiquick_t_5_0h = double(cospiquick_t_5_0hm); cospiquick_t_5_0m = cospiquick_t_5_0hm - cospiquick_t_5_0h; cospiquick_t_6_0hm = mul_rel<102>(cospiquick_t_5_0hm,cospiquick_x_0_pow2hm); cospiquick_t_6_0h = double(cospiquick_t_6_0hm); cospiquick_t_6_0m = cospiquick_t_6_0hm - cospiquick_t_6_0h; cospiquick_t_7_0hm = add_rel<102>(cospiquick_coeff_0h,cospiquick_t_6_0hm); cospiquick_t_7_0h = double(cospiquick_t_7_0hm); cospiquick_t_7_0m = cospiquick_t_7_0hm - cospiquick_t_7_0h; cospiquick_reshm = cospiquick_t_7_0hm; cospiquick_resh = cospiquick_t_7_0h; cospiquick_resm = cospiquick_t_7_0m; # Mathematical equivalents Mx = x; Mcospiquick_coeff_0 = cospiquick_coeff_0h; Mcospiquick_coeff_2 = cospiquick_coeff_2h; Mcospiquick_coeff_4 = cospiquick_coeff_4h; Mcospiquick_coeff_6 = cospiquick_coeff_6h; Mcospiquick_x_0_pow2 = Mx * Mx; Mcospiquick_t_1_0 = Mcospiquick_coeff_6; Mcospiquick_t_2_0 = Mcospiquick_t_1_0 * Mcospiquick_x_0_pow2; Mcospiquick_t_3_0 = Mcospiquick_coeff_4 + Mcospiquick_t_2_0; Mcospiquick_t_4_0 = Mcospiquick_t_3_0 * Mcospiquick_x_0_pow2; Mcospiquick_t_5_0 = Mcospiquick_coeff_2 + Mcospiquick_t_4_0; Mcospiquick_t_6_0 = Mcospiquick_t_5_0 * Mcospiquick_x_0_pow2; Mcospiquick_t_7_0 = Mcospiquick_coeff_0 + Mcospiquick_t_6_0; Mcospiquick_res = Mcospiquick_t_7_0; # Definition of the relative arithmetical error epsilon = (cospiquick_reshm - Mcospiquick_res) / Mcospiquick_res; # Implication to prove {(( x in [-1b-8,-1b-408] ) \/ ( x in [1b-408,1b-8] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition cospiquick_x_0_pow2h ~ cospiquick_x_0_pow2hm; cospiquick_t_5_0h ~ cospiquick_t_5_0hm; cospiquick_t_6_0h ~ cospiquick_t_6_0hm; cospiquick_t_7_0h ~ cospiquick_t_7_0hm; # Meta-Hints for Horner scheme cospiquick_x_0_pow2hm ~ Mcospiquick_x_0_pow2; cospiquick_t_1_0h ~ Mcospiquick_t_1_0; cospiquick_t_2_0h ~ Mcospiquick_t_2_0; cospiquick_t_3_0h ~ Mcospiquick_t_3_0; cospiquick_t_4_0h ~ Mcospiquick_t_4_0; cospiquick_t_5_0hm ~ Mcospiquick_t_5_0; cospiquick_t_6_0hm ~ Mcospiquick_t_6_0; cospiquick_t_7_0hm ~ Mcospiquick_t_7_0; cospiquick_reshm ~ Mcospiquick_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/gappa/trigpi/sinpi-accurate.gappa0000644000000000000000000003010013316017127022027 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: x * (286965175440513682586550324983956956112624645035b-156 + ((x^(1b1)) * ((-3275427103718718266226722463013b-99) + ((x^(1b1)) * (51723471613295412653622130742483b-104 + ((x^(1b1)) * ((-2698847510945475b-52) + ((x^(1b1)) * (2959617474724135b-55 + ((x^(1b1)) * (-4248785555898559b-59))))))))))) # The polynomial implemented is: x * (286965175440513682586550324983956956112624645035b-156 + ((x^(1b1)) * ((-3275427103718718266226722463013b-99) + ((x^(1b1)) * (51723471613295412653622130742483b-104 + ((x^(1b1)) * ((-2698847510945475b-52) + ((x^(1b1)) * (2959617474724135b-55 + ((x^(1b1)) * (-4248785555898559b-59))))))))))) # The domain is [-1b-8;1b-8] # The free variable x is a double precision number, the result sinpiprecise_res* is stored on a triple-double number. # The code produces 18 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code sinpiprecise_coeff_1h = double(3.14159265358979311599796346854418516159057617187500000000000000000000000000000000e+00); sinpiprecise_coeff_1m = double(1.22464679914735320717376402945839660462569212467758006379625612680683843791484833e-16); sinpiprecise_coeff_1l = double(-2.87889731599645993207191707893463395148177292198731390393739579574603302514349608e-33); sinpiprecise_coeff_1hml = sinpiprecise_coeff_1h + sinpiprecise_coeff_1m + sinpiprecise_coeff_1l; sinpiprecise_coeff_3h = double(-5.16771278004997025590228076907806098461151123046875000000000000000000000000000000e+00); sinpiprecise_coeff_3m = double(2.26656228257550136196266687046492287115561324595258696490418515168130397796630859e-16); sinpiprecise_coeff_3hm = sinpiprecise_coeff_3h + sinpiprecise_coeff_3m; sinpiprecise_coeff_5h = double(2.55016403987734552316624103696085512638092041015625000000000000000000000000000000e+00); sinpiprecise_coeff_5m = double(-7.93098961936403945684716222915171282926664203267314023904077657789457589387893677e-17); sinpiprecise_coeff_5hm = sinpiprecise_coeff_5h + sinpiprecise_coeff_5m; sinpiprecise_coeff_7h = double(-5.99264529320792105338000510528218001127243041992187500000000000000000000000000000e-01); sinpiprecise_coeff_9h = double(8.21458866130424236740026344705256633460521697998046875000000000000000000000000000e-02); sinpiprecise_coeff_11h = double(-7.37046804820839888960914976223648409359157085418701171875000000000000000000000000e-03); sinpiprecise_x_0_pow2hm = xh * xh; sinpiprecise_x_0_pow2h = double(sinpiprecise_x_0_pow2hm); sinpiprecise_x_0_pow2m = sinpiprecise_x_0_pow2hm - sinpiprecise_x_0_pow2h; sinpiprecise_t_1_0h = sinpiprecise_coeff_11h; sinpiprecise_t_2_0h = double(sinpiprecise_t_1_0h * sinpiprecise_x_0_pow2h); sinpiprecise_t_3_0h = double(sinpiprecise_coeff_9h + sinpiprecise_t_2_0h); sinpiprecise_t_4_0h = double(sinpiprecise_t_3_0h * sinpiprecise_x_0_pow2h); sinpiprecise_t_5_0hm = sinpiprecise_coeff_7h + sinpiprecise_t_4_0h; sinpiprecise_t_5_0h = double(sinpiprecise_t_5_0hm); sinpiprecise_t_5_0m = sinpiprecise_t_5_0hm - sinpiprecise_t_5_0h; sinpiprecise_t_6_0hm = fma_rel<100>(sinpiprecise_t_5_0hm,sinpiprecise_x_0_pow2hm,sinpiprecise_coeff_5hm); sinpiprecise_t_6_0h = double(sinpiprecise_t_6_0hm); sinpiprecise_t_6_0m = sinpiprecise_t_6_0hm - sinpiprecise_t_6_0h; sinpiprecise_t_7_0hm = fma_rel<100>(sinpiprecise_t_6_0hm,sinpiprecise_x_0_pow2hm,sinpiprecise_coeff_3hm); sinpiprecise_t_7_0h = double(sinpiprecise_t_7_0hm); sinpiprecise_t_7_0m = sinpiprecise_t_7_0hm - sinpiprecise_t_7_0h; sinpiprecise_t_8_0hm = mul_rel<102>(sinpiprecise_t_7_0hm,sinpiprecise_x_0_pow2hm); sinpiprecise_t_8_0h = double(sinpiprecise_t_8_0hm); sinpiprecise_t_8_0m = sinpiprecise_t_8_0hm - sinpiprecise_t_8_0h; sinpiprecise_t_9_0hml = add_rel<152>(sinpiprecise_t_8_0hm,sinpiprecise_coeff_1hml); sinpiprecise_t_9_0ml = sinpiprecise_t_9_0hml - sinpiprecise_t_9_0h; sinpiprecise_t_9_0m = double(sinpiprecise_t_9_0ml); sinpiprecise_t_9_0l = sinpiprecise_t_9_0ml - sinpiprecise_t_9_0m; sinpiprecise_t_9_0hm = sinpiprecise_t_9_0h + sinpiprecise_t_9_0m; overlap_sinpiprecise_t_9_0 = sinpiprecise_t_9_0m / sinpiprecise_t_9_0h; sinpiprecise_t_10_0hml = mul_rel<145>(xh,sinpiprecise_t_9_0hml); sinpiprecise_t_10_0ml = sinpiprecise_t_10_0hml - sinpiprecise_t_10_0h; sinpiprecise_t_10_0m = double(sinpiprecise_t_10_0ml); sinpiprecise_t_10_0l = sinpiprecise_t_10_0ml - sinpiprecise_t_10_0m; sinpiprecise_t_10_0hm = sinpiprecise_t_10_0h + sinpiprecise_t_10_0m; overlap_sinpiprecise_t_10_0 = sinpiprecise_t_10_0m / sinpiprecise_t_10_0h; sinpiprecise_reshml = sinpiprecise_t_10_0hml; sinpiprecise_resml = sinpiprecise_reshml - sinpiprecise_resh; sinpiprecise_resm = double(sinpiprecise_resml); sinpiprecise_resl = sinpiprecise_resml - sinpiprecise_resm; sinpiprecise_reshm = sinpiprecise_resh + sinpiprecise_resm; overlap_sinpiprecise_res = sinpiprecise_resm / sinpiprecise_resh; # Mathematical equivalents Mx = x; Msinpiprecise_coeff_1 = sinpiprecise_coeff_1hml; Msinpiprecise_coeff_3 = sinpiprecise_coeff_3hm; Msinpiprecise_coeff_5 = sinpiprecise_coeff_5hm; Msinpiprecise_coeff_7 = sinpiprecise_coeff_7h; Msinpiprecise_coeff_9 = sinpiprecise_coeff_9h; Msinpiprecise_coeff_11 = sinpiprecise_coeff_11h; Msinpiprecise_x_0_pow2 = Mx * Mx; Msinpiprecise_t_1_0 = Msinpiprecise_coeff_11; Msinpiprecise_t_2_0 = Msinpiprecise_t_1_0 * Msinpiprecise_x_0_pow2; Msinpiprecise_t_3_0 = Msinpiprecise_coeff_9 + Msinpiprecise_t_2_0; Msinpiprecise_t_4_0 = Msinpiprecise_t_3_0 * Msinpiprecise_x_0_pow2; Msinpiprecise_t_5_0 = Msinpiprecise_coeff_7 + Msinpiprecise_t_4_0; Msinpiprecise_t_6_0 = (Msinpiprecise_t_5_0 * Msinpiprecise_x_0_pow2) + Msinpiprecise_coeff_5; Msinpiprecise_t_7_0 = (Msinpiprecise_t_6_0 * Msinpiprecise_x_0_pow2) + Msinpiprecise_coeff_3; Msinpiprecise_t_8_0 = Msinpiprecise_t_7_0 * Msinpiprecise_x_0_pow2; Msinpiprecise_t_9_0 = Msinpiprecise_t_8_0 + Msinpiprecise_coeff_1; Msinpiprecise_t_10_0 = Mx * Msinpiprecise_t_9_0; Msinpiprecise_res = Msinpiprecise_t_10_0; # Definition of the relative arithmetical error epsilon = (sinpiprecise_reshml - Msinpiprecise_res) / Msinpiprecise_res; # Implication to prove {(( x in [-1b-8,-1b-408] /\ |overlap_sinpiprecise_t_9_0| in [1b-400,1b-45] # Verify the lower bound /\ |sinpiprecise_t_9_0ml| in [1b-1021,1b1023] /\ |overlap_sinpiprecise_t_10_0| in [1b-400,1b-40] # Verify the lower bound /\ |sinpiprecise_t_10_0ml| in [1b-1021,1b1023] /\ |overlap_sinpiprecise_res| in [1b-400,1b-52] # Verify the lower bound /\ |sinpiprecise_resml| in [1b-1021,1b1023] ) \/ ( x in [1b-408,1b-8] /\ |overlap_sinpiprecise_t_9_0| in [1b-400,1b-45] # Verify the lower bound /\ |sinpiprecise_t_9_0ml| in [1b-1021,1b1023] /\ |overlap_sinpiprecise_t_10_0| in [1b-400,1b-40] # Verify the lower bound /\ |sinpiprecise_t_10_0ml| in [1b-1021,1b1023] /\ |overlap_sinpiprecise_res| in [1b-400,1b-52] # Verify the lower bound /\ |sinpiprecise_resml| in [1b-1021,1b1023] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition sinpiprecise_x_0_pow2h ~ sinpiprecise_x_0_pow2hm; sinpiprecise_t_5_0h ~ sinpiprecise_t_5_0hm; sinpiprecise_t_6_0h ~ sinpiprecise_t_6_0hm; sinpiprecise_t_7_0h ~ sinpiprecise_t_7_0hm; sinpiprecise_t_8_0h ~ sinpiprecise_t_8_0hm; sinpiprecise_t_9_0hm ~ sinpiprecise_t_9_0hml; sinpiprecise_t_9_0h ~ sinpiprecise_t_9_0hm; sinpiprecise_t_9_0h ~ sinpiprecise_t_9_0hml; sinpiprecise_t_9_0m -> sinpiprecise_t_9_0h * overlap_sinpiprecise_t_9_0; sinpiprecise_t_9_0l / sinpiprecise_t_9_0m -> - ((sinpiprecise_t_9_0m - sinpiprecise_t_9_0ml) / sinpiprecise_t_9_0ml) / (1 + ((sinpiprecise_t_9_0m - sinpiprecise_t_9_0ml) / sinpiprecise_t_9_0ml)); (sinpiprecise_t_9_0hm - sinpiprecise_t_9_0hml) / sinpiprecise_t_9_0hml -> - (sinpiprecise_t_9_0l / sinpiprecise_t_9_0m) * (1 / (1 / overlap_sinpiprecise_t_9_0 + 1 + (sinpiprecise_t_9_0l / sinpiprecise_t_9_0m))); sinpiprecise_t_9_0ml -> sinpiprecise_t_9_0hml / ((1 + ((sinpiprecise_t_9_0m - sinpiprecise_t_9_0ml) / sinpiprecise_t_9_0ml)) / overlap_sinpiprecise_t_9_0 + 1); (sinpiprecise_t_9_0h - sinpiprecise_t_9_0hm) / sinpiprecise_t_9_0hm -> - 1 / (1 / overlap_sinpiprecise_t_9_0 + 1); sinpiprecise_t_9_0h -> sinpiprecise_t_9_0hml / (overlap_sinpiprecise_t_9_0 / (1 + ((sinpiprecise_t_9_0m - sinpiprecise_t_9_0ml) / sinpiprecise_t_9_0ml)) + 1); sinpiprecise_t_10_0hm ~ sinpiprecise_t_10_0hml; sinpiprecise_t_10_0h ~ sinpiprecise_t_10_0hm; sinpiprecise_t_10_0h ~ sinpiprecise_t_10_0hml; sinpiprecise_t_10_0m -> sinpiprecise_t_10_0h * overlap_sinpiprecise_t_10_0; sinpiprecise_t_10_0l / sinpiprecise_t_10_0m -> - ((sinpiprecise_t_10_0m - sinpiprecise_t_10_0ml) / sinpiprecise_t_10_0ml) / (1 + ((sinpiprecise_t_10_0m - sinpiprecise_t_10_0ml) / sinpiprecise_t_10_0ml)); (sinpiprecise_t_10_0hm - sinpiprecise_t_10_0hml) / sinpiprecise_t_10_0hml -> - (sinpiprecise_t_10_0l / sinpiprecise_t_10_0m) * (1 / (1 / overlap_sinpiprecise_t_10_0 + 1 + (sinpiprecise_t_10_0l / sinpiprecise_t_10_0m))); sinpiprecise_t_10_0ml -> sinpiprecise_t_10_0hml / ((1 + ((sinpiprecise_t_10_0m - sinpiprecise_t_10_0ml) / sinpiprecise_t_10_0ml)) / overlap_sinpiprecise_t_10_0 + 1); (sinpiprecise_t_10_0h - sinpiprecise_t_10_0hm) / sinpiprecise_t_10_0hm -> - 1 / (1 / overlap_sinpiprecise_t_10_0 + 1); sinpiprecise_t_10_0h -> sinpiprecise_t_10_0hml / (overlap_sinpiprecise_t_10_0 / (1 + ((sinpiprecise_t_10_0m - sinpiprecise_t_10_0ml) / sinpiprecise_t_10_0ml)) + 1); sinpiprecise_reshm ~ sinpiprecise_reshml; sinpiprecise_resh ~ sinpiprecise_reshm; sinpiprecise_resh ~ sinpiprecise_reshml; sinpiprecise_resm -> sinpiprecise_resh * overlap_sinpiprecise_res; sinpiprecise_resl / sinpiprecise_resm -> - ((sinpiprecise_resm - sinpiprecise_resml) / sinpiprecise_resml) / (1 + ((sinpiprecise_resm - sinpiprecise_resml) / sinpiprecise_resml)); (sinpiprecise_reshm - sinpiprecise_reshml) / sinpiprecise_reshml -> - (sinpiprecise_resl / sinpiprecise_resm) * (1 / (1 / overlap_sinpiprecise_res + 1 + (sinpiprecise_resl / sinpiprecise_resm))); sinpiprecise_resml -> sinpiprecise_reshml / ((1 + ((sinpiprecise_resm - sinpiprecise_resml) / sinpiprecise_resml)) / overlap_sinpiprecise_res + 1); (sinpiprecise_resh - sinpiprecise_reshm) / sinpiprecise_reshm -> - 1 / (1 / overlap_sinpiprecise_res + 1); sinpiprecise_resh -> sinpiprecise_reshml / (overlap_sinpiprecise_res / (1 + ((sinpiprecise_resm - sinpiprecise_resml) / sinpiprecise_resml)) + 1); # Meta-Hints for Horner scheme sinpiprecise_x_0_pow2hm ~ Msinpiprecise_x_0_pow2; sinpiprecise_t_1_0h ~ Msinpiprecise_t_1_0; sinpiprecise_t_2_0h ~ Msinpiprecise_t_2_0; sinpiprecise_t_3_0h ~ Msinpiprecise_t_3_0; sinpiprecise_t_4_0h ~ Msinpiprecise_t_4_0; sinpiprecise_t_5_0hm ~ Msinpiprecise_t_5_0; sinpiprecise_t_6_0hm ~ Msinpiprecise_t_6_0; sinpiprecise_t_7_0hm ~ Msinpiprecise_t_7_0; sinpiprecise_t_8_0hm ~ Msinpiprecise_t_8_0; sinpiprecise_t_9_0hml ~ Msinpiprecise_t_9_0; sinpiprecise_t_10_0hml ~ Msinpiprecise_t_10_0; sinpiprecise_reshml ~ Msinpiprecise_res; # Dichotomies for triple-double decomposition $ sinpiprecise_t_9_0hml in (0); $ sinpiprecise_t_9_0ml in (0); $ sinpiprecise_t_10_0hml in (0); $ sinpiprecise_t_10_0ml in (0); $ sinpiprecise_reshml in (0); $ sinpiprecise_resml in (0); # Dichotomy for the error bound epsilon $ xhml; interval-3.2.0/src/crlibm/gappa/trigpi/sinpi-quick.gappa0000644000000000000000000001221013316017127021356 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # The polynomial to implement is: x * (63719069007931157819019535590437b-104 + ((x^(1b1)) * ((-5818327337647699b-50) + ((x^(1b1)) * (717807363739183b-48 + ((x^(1b1)) * (-337355592074089b-49))))))) # The polynomial implemented is: x * (63719069007931157819019535590437b-104 + ((x^(1b1)) * ((-5818327337647699b-50) + ((x^(1b1)) * (717807363739183b-48 + ((x^(1b1)) * (-337355592074089b-49))))))) # The domain is [-1b-8;1b-8] # The free variable x is a double precision number, the result sinpiquick_res* is stored on a double-double number. # The code produces 13 intermediate and final arithmetical approximations. # Double precision rounding operator: @double = float; # Disable some annoying warnings: #@-Wno-dichotomy-failure # Helper definitions for decomposing the free variable xh = x; # Transcription of the C code sinpiquick_coeff_1h = double(3.14159265358979311599796346854418516159057617187500000000000000000000000000000000e+00); sinpiquick_coeff_1m = double(1.22464971683184787123862072310058851157814368464452070561776508839102461934089661e-16); sinpiquick_coeff_1hm = sinpiquick_coeff_1h + sinpiquick_coeff_1m; sinpiquick_coeff_3h = double(-5.16771278004997025590228076907806098461151123046875000000000000000000000000000000e+00); sinpiquick_coeff_5h = double(2.55016403989992213041659852024167776107788085937500000000000000000000000000000000e+00); sinpiquick_coeff_7h = double(-5.99263913290728922333983064163476228713989257812500000000000000000000000000000000e-01); sinpiquick_x_0_pow2hm = xh * xh; sinpiquick_x_0_pow2h = double(sinpiquick_x_0_pow2hm); sinpiquick_x_0_pow2m = sinpiquick_x_0_pow2hm - sinpiquick_x_0_pow2h; sinpiquick_t_1_0h = sinpiquick_coeff_7h; sinpiquick_t_2_0h = double(sinpiquick_t_1_0h * sinpiquick_x_0_pow2h); sinpiquick_t_3_0h = double(sinpiquick_coeff_5h + sinpiquick_t_2_0h); sinpiquick_t_4_0h = double(sinpiquick_t_3_0h * sinpiquick_x_0_pow2h); sinpiquick_t_5_0hm = sinpiquick_coeff_3h + sinpiquick_t_4_0h; sinpiquick_t_5_0h = double(sinpiquick_t_5_0hm); sinpiquick_t_5_0m = sinpiquick_t_5_0hm - sinpiquick_t_5_0h; sinpiquick_t_6_0hm = fma_rel<100>(sinpiquick_t_5_0hm,sinpiquick_x_0_pow2hm,sinpiquick_coeff_1hm); sinpiquick_t_6_0h = double(sinpiquick_t_6_0hm); sinpiquick_t_6_0m = sinpiquick_t_6_0hm - sinpiquick_t_6_0h; sinpiquick_t_7_0hm = mul_rel<102>(xh,sinpiquick_t_6_0hm); sinpiquick_t_7_0h = double(sinpiquick_t_7_0hm); sinpiquick_t_7_0m = sinpiquick_t_7_0hm - sinpiquick_t_7_0h; sinpiquick_reshm = sinpiquick_t_7_0hm; sinpiquick_resh = sinpiquick_t_7_0h; sinpiquick_resm = sinpiquick_t_7_0m; # Mathematical equivalents Mx = x; Msinpiquick_coeff_1 = sinpiquick_coeff_1hm; Msinpiquick_coeff_3 = sinpiquick_coeff_3h; Msinpiquick_coeff_5 = sinpiquick_coeff_5h; Msinpiquick_coeff_7 = sinpiquick_coeff_7h; Msinpiquick_x_0_pow2 = Mx * Mx; Msinpiquick_t_1_0 = Msinpiquick_coeff_7; Msinpiquick_t_2_0 = Msinpiquick_t_1_0 * Msinpiquick_x_0_pow2; Msinpiquick_t_3_0 = Msinpiquick_coeff_5 + Msinpiquick_t_2_0; Msinpiquick_t_4_0 = Msinpiquick_t_3_0 * Msinpiquick_x_0_pow2; Msinpiquick_t_5_0 = Msinpiquick_coeff_3 + Msinpiquick_t_4_0; Msinpiquick_t_6_0 = (Msinpiquick_t_5_0 * Msinpiquick_x_0_pow2) + Msinpiquick_coeff_1; Msinpiquick_t_7_0 = Mx * Msinpiquick_t_6_0; Msinpiquick_res = Msinpiquick_t_7_0; # Definition of the relative arithmetical error epsilon = (sinpiquick_reshm - Msinpiquick_res) / Msinpiquick_res; # Implication to prove {(( x in [-1b-8,-1b-408] ) \/ ( x in [1b-408,1b-8] )) -> ( epsilon in ? )} # Hints and Meta-Hints for expansion decomposition sinpiquick_x_0_pow2h ~ sinpiquick_x_0_pow2hm; sinpiquick_t_5_0h ~ sinpiquick_t_5_0hm; sinpiquick_t_6_0h ~ sinpiquick_t_6_0hm; sinpiquick_t_7_0h ~ sinpiquick_t_7_0hm; # Meta-Hints for Horner scheme sinpiquick_x_0_pow2hm ~ Msinpiquick_x_0_pow2; sinpiquick_t_1_0h ~ Msinpiquick_t_1_0; sinpiquick_t_2_0h ~ Msinpiquick_t_2_0; sinpiquick_t_3_0h ~ Msinpiquick_t_3_0; sinpiquick_t_4_0h ~ Msinpiquick_t_4_0; sinpiquick_t_5_0hm ~ Msinpiquick_t_5_0; sinpiquick_t_6_0hm ~ Msinpiquick_t_6_0; sinpiquick_t_7_0hm ~ Msinpiquick_t_7_0; sinpiquick_reshm ~ Msinpiquick_res; # Dichotomies for triple-double decomposition # Dichotomy for the error bound epsilon $ xhm; interval-3.2.0/src/crlibm/interval.h0000644000000000000000000003762713316017127015542 0ustar 00000000000000/* * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" typedef struct interval { double INF, SUP;} interval ; #define LOW(x) x.INF #define UP(x) x.SUP #define ASSIGN_LOW(x,e) x.INF=e #define ASSIGN_UP(x,e) x.SUP=e #define TRUE (1+1==2) #define FALSE (1+1==3) interval j_log(); #define TEST_AND_COPY_RDRU_LOG(__cond__, __res_rd__, __yh_rd__, __yl_rd__, __res_ru__, __yh_ru__, __yl_ru__, __eps__) \ { \ db_number yh_rd, yl_rd, u53_rd, yh_ru, yl_ru, u53_ru; \ int yh_rd_neg, yl_rd_neg, yh_ru_neg, yl_ru_neg; \ int rd_ok, ru_ok; \ double save_res_rd=__res_rd__; \ yh_rd.d = __yh_rd__; yl_rd.d = __yl_rd__; \ yh_rd_neg = (yh_rd.i[HI] & 0x80000000); \ yl_rd_neg = (yl_rd.i[HI] & 0x80000000); \ yh_rd.l = yh_rd.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ yl_rd.l = yl_rd.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53_rd.l = (yh_rd.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ yh_ru.d = __yh_ru__; yl_ru.d = __yl_ru__; \ yh_ru_neg = (yh_ru.i[HI] & 0x80000000); \ yl_ru_neg = (yl_ru.i[HI] & 0x80000000); \ yh_ru.l = yh_ru.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ yl_ru.l = yl_ru.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53_ru.l = (yh_ru.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ __cond__ = 0; \ rd_ok=(yl_rd.d > __eps__ * u53_rd.d); \ ru_ok=(yl_ru.d > __eps__ * u53_ru.d); \ if(yl_rd_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next down */ \ yh_rd.d = __yh_rd__; \ if(yh_rd_neg) yh_rd.l++; else yh_rd.l--; /* Beware: fails for zero */ \ __res_rd__ = yh_rd.d ; \ } \ else { \ __res_rd__ = __yh_rd__; \ } \ if(!yl_ru_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next up */ \ yh_ru.d = __yh_ru__; \ if(yh_ru_neg) yh_ru.l--; else yh_ru.l++; /* Beware: fails for zero */ \ __res_ru__ = yh_ru.d ; \ } \ else { \ __res_ru__ = __yh_ru__; \ } \ if(save_res_rd==-1.0/0.0) __res_rd__=-1.0/0.0; \ if(rd_ok && ru_ok){\ interval _res; \ ASSIGN_LOW(_res,__res_rd__); \ ASSIGN_UP(_res,__res_ru__); \ return(_res); \ } \ else if (rd_ok){\ __cond__=1; \ }\ else if (ru_ok){\ __cond__=2; \ }\ } #define TEST_AND_COPY_RDRU_EXP(__cond__, cond1, cond2, __res_rd__, __yh_rd__, __yl_rd__, __res_ru__, __yh_ru__, __yl_ru__, __eps__) \ { \ db_number yh_rd, yl_rd, u53_rd, yh_ru, yl_ru, u53_ru; \ int yh_rd_neg, yl_rd_neg, yh_ru_neg, yl_ru_neg; \ int rd_ok, ru_ok; \ double save_res_rd=__res_rd__; \ double save_res_ru=__res_ru__; \ yh_rd.d = __yh_rd__; yl_rd.d = __yl_rd__; \ yh_rd_neg = (yh_rd.i[HI] & 0x80000000); \ yl_rd_neg = (yl_rd.i[HI] & 0x80000000); \ yh_rd.l = yh_rd.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ yl_rd.l = yl_rd.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53_rd.l = (yh_rd.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ yh_ru.d = __yh_ru__; yl_ru.d = __yl_ru__; \ yh_ru_neg = (yh_ru.i[HI] & 0x80000000); \ yl_ru_neg = (yl_ru.i[HI] & 0x80000000); \ yh_ru.l = yh_ru.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ yl_ru.l = yl_ru.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53_ru.l = (yh_ru.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ __cond__ = 0; \ rd_ok=(yl_rd.d > __eps__ * u53_rd.d); \ ru_ok=(yl_ru.d > __eps__ * u53_ru.d); \ if(yl_rd_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next down */ \ yh_rd.d = __yh_rd__; \ if(yh_rd_neg) yh_rd.l++; else yh_rd.l--; /* Beware: fails for zero */ \ __res_rd__ = yh_rd.d ; \ } \ else { \ __res_rd__ = __yh_rd__; \ } \ if(!yl_ru_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next up */ \ yh_ru.d = __yh_ru__; \ if(yh_ru_neg) yh_ru.l--; else yh_ru.l++; /* Beware: fails for zero */ \ __res_ru__ = yh_ru.d ; \ } \ else { \ __res_ru__ = __yh_ru__; \ } \ if(cond1) __res_rd__=save_res_rd; \ if(cond2) __res_ru__=save_res_ru; \ if(rd_ok && ru_ok){\ __cond__=3; \ } \ else if (rd_ok){\ __cond__=1; \ }\ else if (ru_ok){\ __cond__=2; \ }\ } #define TEST_AND_COPY_RDRU_EXPM1(__cond__, __res_rd__, __yh_rd__, __yl_rd__, __res_ru__, __yh_ru__, __yl_ru__, __eps__) \ { \ db_number yh_rd, yl_rd, u53_rd, yh_ru, yl_ru, u53_ru; \ int yh_rd_neg, yl_rd_neg, yh_ru_neg, yl_ru_neg; \ int rd_ok, ru_ok; \ yh_rd.d = __yh_rd__; yl_rd.d = __yl_rd__; \ yh_rd_neg = (yh_rd.i[HI] & 0x80000000); \ yl_rd_neg = (yl_rd.i[HI] & 0x80000000); \ yh_rd.l = yh_rd.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ yl_rd.l = yl_rd.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53_rd.l = (yh_rd.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ yh_ru.d = __yh_ru__; yl_ru.d = __yl_ru__; \ yh_ru_neg = (yh_ru.i[HI] & 0x80000000); \ yl_ru_neg = (yl_ru.i[HI] & 0x80000000); \ yh_ru.l = yh_ru.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ yl_ru.l = yl_ru.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53_ru.l = (yh_ru.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ __cond__ = 0; \ rd_ok=(yl_rd.d > __eps__ * u53_rd.d); \ ru_ok=(yl_ru.d > __eps__ * u53_ru.d); \ if(yl_rd_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next down */ \ yh_rd.d = __yh_rd__; \ if(yh_rd_neg) yh_rd.l++; else yh_rd.l--; /* Beware: fails for zero */ \ __res_rd__ = yh_rd.d ; \ } \ else { \ __res_rd__ = __yh_rd__; \ } \ if(!yl_ru_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next up */ \ yh_ru.d = __yh_ru__; \ if(yh_ru_neg) yh_ru.l--; else yh_ru.l++; /* Beware: fails for zero */ \ __res_ru__ = yh_ru.d ; \ } \ else { \ __res_ru__ = __yh_ru__; \ } \ if(rd_ok && ru_ok){\ interval _res; \ ASSIGN_LOW(_res,__res_rd__); \ ASSIGN_UP(_res,__res_ru__); \ return(_res); \ } \ else if (rd_ok){\ __cond__=1; \ }\ else if (ru_ok){\ __cond__=2; \ }\ } #define TEST_AND_COPY_RDRU_LOG2(__cond__, __res_rd__, __yh_rd__, __yl_rd__, __res_ru__, __yh_ru__, __yl_ru__, __eps_rd__, __eps_ru__) \ { \ db_number yh_rd, yl_rd, u53_rd, yh_ru, yl_ru, u53_ru; \ int yh_rd_neg, yl_rd_neg, yh_ru_neg, yl_ru_neg; \ int rd_ok, ru_ok; \ yh_rd.d = __yh_rd__; yl_rd.d = __yl_rd__; \ yh_rd_neg = (yh_rd.i[HI] & 0x80000000); \ yl_rd_neg = (yl_rd.i[HI] & 0x80000000); \ yh_rd.l = yh_rd.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ yl_rd.l = yl_rd.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53_rd.l = (yh_rd.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ yh_ru.d = __yh_ru__; yl_ru.d = __yl_ru__; \ yh_ru_neg = (yh_ru.i[HI] & 0x80000000); \ yl_ru_neg = (yl_ru.i[HI] & 0x80000000); \ yh_ru.l = yh_ru.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ yl_ru.l = yl_ru.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ \ u53_ru.l = (yh_ru.l & ULL(7ff0000000000000)) + ULL(0010000000000000); \ __cond__ = 0; \ rd_ok=(yl_rd.d > __eps_rd__ * u53_rd.d); \ ru_ok=(yl_ru.d > __eps_ru__ * u53_ru.d); \ if(yl_rd_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next down */ \ yh_rd.d = __yh_rd__; \ if(yh_rd_neg) yh_rd.l++; else yh_rd.l--; /* Beware: fails for zero */ \ __res_rd__ = yh_rd.d ; \ } \ else { \ __res_rd__ = __yh_rd__; \ } \ if(!yl_ru_neg) { /* The case yl==0 is filtered by the above test*/ \ /* return next up */ \ yh_ru.d = __yh_ru__; \ if(yh_ru_neg) yh_ru.l--; else yh_ru.l++; /* Beware: fails for zero */ \ __res_ru__ = yh_ru.d ; \ } \ else { \ __res_ru__ = __yh_ru__; \ } \ if(rd_ok && ru_ok){\ interval _res; \ ASSIGN_LOW(_res,__res_rd__); \ ASSIGN_UP(_res,__res_ru__); \ return(_res); \ } \ else if (rd_ok){\ __cond__=1; \ }\ else if (ru_ok){\ __cond__=2; \ }\ } #define RETURN_EMPTY_INTERVAL \ { \ interval res; \ ASSIGN_LOW(res,0.0/0.0); \ ASSIGN_UP(res,0.0/0.0); \ return res; \ } interval-3.2.0/src/crlibm/log-de.c0000644000000000000000000003747713316017127015063 0ustar 00000000000000/* * this function computes log, correctly rounded, * using double-extended arithmetic * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Florent de Dinechin * Florent.de.Dinechin at ens-lyon.fr * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA THIS IS EXPERIMENTAL SOFTWARE In particular it changes rounding modes all the time without warning nor restoring. This function compiles both on IA32 and IA64 architectures. On IA64, it needs icc 8.1 or higher, with the following flags (which should be set up by the autoconf). icc -DHAVE_CONFIG_H -Qoption,cpp,--extended_float_types \ -IPF_fp_speculationsafe -c log-de.c;\ mv log-de.o log-td.o; make */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "double-extended.h" #include "log-de.h" static void log_accurate(double_ext* prh, double_ext* prl, double_ext z, int E, int index) { double_ext eh,el, t13, t12, t11, t10, t9, t8, p7h,p7l, t7h,t7l, t6h,t6l, t5h,t5l, t4h,t4l, t3h,t3l, t2h,t2l, t1h,t1l, t0h,t0l; /* Many temporary because single assignment form is nicer for Gappa */ #if !(defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)) double_ext c1h,c2h,c3h,c4h,c5h,c6h,c7h,c8h,c9h,c10h,c11h,c12h,c13h,c14h,c15h; double_ext c1l,c2l,c3l,c4l,c5l,c6l,c7l,c8l; #endif #if EVAL_PERF crlibm_second_step_taken++; #endif /* TODO check the conditions for the double-double ops */ PREFETCH_POLY_ACCURATE; t13 = c13h + z*c14h; t12 = c12h + z*t13; t11 = c11h + z*t12; t10 = c10h + z*t11; t9 = c9h + z*t10; t8 = c8h + z*t9; #if 1 /* This is faster on PIII. Your mileage may vary */ Mul12_ext(&p7h, &p7l, z, t8); Add22_ext(&t7h, &t7l, p7h,p7l, c7h,c7l); #else FMA22_ext(&t7h, &t7l, z,0, t8,0, c7h,c7l); #endif FMA22_ext(&t6h, &t6l, z,0, t7h,t7l, c6h,c6l); FMA22_ext(&t5h, &t5l, z,0, t6h,t6l, c5h,c5l); FMA22_ext(&t4h, &t4l, z,0, t5h,t5l, c4h,c4l); FMA22_ext(&t3h, &t3l, z,0, t4h,t4l, c3h,c3l); FMA22_ext(&t2h, &t2l, z,0, t3h,t3l, c2h,c2l); FMA22_ext(&t1h, &t1l, z,0, t2h,t2l, c1h,c1l); FMA22_ext(&t0h, &t0l, z,0, t1h,t1l, argredtable[index].logirh, argredtable[index].logirl); Mul22_ext(&eh, &el, log2H,log2L, E, 0); Add22_ext(prh, prl, eh,el, t0h,t0l); } double log_rn(double x) { double_ext logirh, r, y, z, th, tl, logde; #if defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) db_number xdb; int E, index, index0, roundtestmask; #else /* assuming Itanium here */ int64_t E, i; uint64_t index, roundtestmask; double c2,c3,c4,c5,c6,c7; #endif #if defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) xdb.d=x; index0 = (xdb.i[HI] & 0x000fffff); index = (index0 + (1<<(20-L-1))) >> (20-L); E = (xdb.i[HI]>>20)-1023; /* extract the exponent */ /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0) return -1.0/0.0; /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0) return (x-x)/0; /* log(-x) = Nan */ /* Else subnormal number */ xdb.d *= two64; /* make x a normal number */ E = -64 + (xdb.i[HI]>>20)-1023; /* extract the exponent */ index0 = (xdb.i[HI] & 0x000fffff); index = (index0 + (1<<(20-L-1))) >> (20-L); } if (xdb.i[HI] >= 0x7ff00000) return x+x; /* Inf or Nan */ DOUBLE_EXTENDED_MODE; /* This one should be overlapped with following integer computation */ /* Extract exponent and mantissa */ xdb.i[HI] = index0 | 0x3ff00000; /* do exponent = 0 */ /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to y>sqrt(2)*/ xdb.i[HI] -= 0x00100000; index = index & INDEXMASK; E++; } y = xdb.d; #else /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ /* Here come the code specific to Itanium processor */ E=0; PREFETCH_POLY_QUICK; /* defined in log-de.h */ y=x; i = _Asm_getf(2/*_FR_D*/, y); /* Cast y to a 64-bit integer */ /* Filter special cases */ if (i<(int64_t)ULL(0010000000000000)){ /* equivalent to : x < 2^(-1022) */ if ((i & ULL(7fffffffffffffff))==0) return -1.0/0.0; /* log(+/-0) = -Inf */ if (i<0) return (x-x)/0; /* log(-x) = Nan */ /* Else subnormal number */ y *= two64; /* make x a normal number */ E = -64; i = _Asm_getf(2/*_FR_D*/, y); /* and update i */ } if (i >= ULL(7ff0000000000000)) return x+x; /* Inf or Nan */ /* Extract exponent and mantissa */ E += (i>>52)-1023; i = i & ULL(000fffffffffffff); /* keep only mantissa */ index = (i + (ULL(1)<<(52-L-1))) >> (52-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to y>sqrt(2)*/ y = _Asm_setf(2/*_FR_D*/, (i | ULL(3ff0000000000000)) - ULL(0010000000000000) ); /* exponent = -1 */ index = index & INDEXMASK; E++; } else y = _Asm_setf(2/*_FR_D*/, i | ULL(3ff0000000000000) ); /* exponent = 0*/ #endif /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ /* All the previous argument reduction was exact */ /* now y holds 1+f, and E is the exponent */ r = (double_ext) (argredtable[index].r); /* approx to 1/y.d */ logirh = argredtable[index].logirh; z = y*r - 1. ; /* even without an FMA, all exact */ #if 0 if(E==0) roundtestmask=ACCURATE_TO_61_BITS; else roundtestmask=ACCURATE_TO_61_BITS; #else roundtestmask=ACCURATE_TO_62_BITS; #endif #ifdef ESTRIN /* Estrin polynomial evaluation */ double_ext z2,z4, p01, p23, p45, p67, p03, p47,p07; z2 = z*z; p67 = c6 + z*c7; p45 = c4 + z*c5; p23 = c2 + z*c3; p01 = logirh + z; z4 = z2*z2; p47 = p45 + z2*p67; p03 = p01 + z2*p23; p07 = p03 + z4*p47; logde = p07 + E*log2H; #endif #ifdef PATERSON double_ext z4,z2,t0,t1,t2,t3,t4,t5,t6,t7,t8; z2 = z * z; t1 = z + ps_alpha; t2 = z + ps_beta; t3 = c3 * z + c2; t4 = z + logirh; z4 = z2 * z2; t5 = z2 + ps_c; t6 = t3 * z2 + t4; t7 = t5 * t1 + t2; t0 = z4 * c7; t8 = t7 * t0 + t6; logde = t8 + E*log2H; #endif #if 0 /* to time the first step only */ BACK_TO_DOUBLE_MODE; return (double)t; #endif /* To test the second step only, comment out the following line */ DE_TEST_AND_RETURN_RN(logde, roundtestmask); log_accurate(&th, &tl, z, E, index); BACK_TO_DOUBLE_MODE; return (double) (th+tl); /* The exact sum of these double-extended is rounded to the nearest */ } double log_rd(double x) { double_ext logirh, r, y, z, th, tl, logde; #if defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) db_number xdb; int E, index, roundtestmask; #else int64_t E, i; uint64_t index, roundtestmask; double_ext c1,c2,c3,c4,c5,c6,c7; #endif E=0; #if defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0) return -1.0/0.0; /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0) return (x-x)/0; /* log(-x) = Nan */ /* Else subnormal number */ E = -64; xdb.d *= two64; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000) return x+x; /* Inf or Nan */ DOUBLE_EXTENDED_MODE; /* This one should be overlapped with following integer computation */ /* Extract exponent and mantissa */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to y>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; #else /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ /* Here come the code specific to Itanium processor */ PREFETCH_POLY_QUICK; /* defined in log-de.h */ y=x; i = _Asm_getf(2/*_FR_D*/, y); /* Cast y to a 64-bit integer */ /* Filter special cases */ if (i<(int64_t)ULL(0010000000000000)){ /* equivalent to : x < 2^(-1022) */ if ((i & ULL(7fffffffffffffff))==0) return -1.0/0.0; /* log(+/-0) = -Inf */ if (i<0) return (x-x)/0; /* log(-x) = Nan */ /* Else subnormal number */ y *= two64; /* make x a normal number */ E = -64; i = _Asm_getf(2/*_FR_D*/, y); /* and update i */ } if (i >= ULL(7ff0000000000000)) return x+x; /* Inf or Nan */ /* Extract exponent and mantissa */ E += (i>>52)-1023; i = i & ULL(000fffffffffffff); /* keep only mantissa */ index = (i + (ULL(1)<<(52-L-1))) >> (52-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to y>sqrt(2)*/ y = _Asm_setf(2/*_FR_D*/, (i | ULL(3ff0000000000000)) - ULL(0010000000000000) ); /* exponent = -1 */ E++; } else y = _Asm_setf(2/*_FR_D*/, i | ULL(3ff0000000000000) ); /* exponent = 0*/ #endif /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ /* All the previous argument reduction was exact */ /* now y holds 1+f, and E is the exponent */ index = index & INDEXMASK; logirh = argredtable[index].logirh; r = (double_ext) (argredtable[index].r); /* approx to 1/y.d */ z = y*r - 1. ; /* even without an FMA, all exact */ if(E==0) roundtestmask=ACCURATE_TO_61_BITS; else roundtestmask=ACCURATE_TO_62_BITS; #ifdef ESTRIN /* Estrin polynomial evaluation */ double_ext z2,z4, p01, p23, p45, p67, p03, p47,p07; z2 = z*z; p67 = c6 + z*c7; p45 = c4 + z*c5; p23 = c2 + z*c3; p01 = logirh + z; z4 = z2*z2; p47 = p45 + z2*p67; p03 = p01 + z2*p23; p07 = p03 + z4*p47; logde = p07 + E*log2H; #endif #ifdef PATERSON double_ext z4,z2,t0,t1,t2,t3,t4,t5,t6,t7,t8; z2 = z * z; t1 = z + ps_alpha; t2 = z + ps_beta; t3 = c3 * z + c2; t4 = z + logirh; z4 = z2 * z2; t5 = z2 + ps_c; t6 = t3 * z2 + t4; t7 = t5 * t1 + t2; t0 = z4 * c7; t8 = t7 * t0 + t6; logde = t8 + E*log2H; #endif #if 0 /* to time the first step only */ BACK_TO_DOUBLE_MODE; return (double)t; #endif /* To test the second step only, comment out the following line */ DE_TEST_AND_RETURN_RD(logde, roundtestmask); log_accurate(&th, &tl, z, E, index); RETURN_SUM_ROUNDED_DOWN(th, tl); } double log_ru(double x) { double_ext logirh, r, y, z, th, tl, logde; #if defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) db_number xdb; int E, index, roundtestmask; #else int64_t E, i; uint64_t index, roundtestmask; double_ext c1,c2,c3,c4,c5,c6,c7; #endif E=0; #if defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0) return -1.0/0.0; /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0) return (x-x)/0; /* log(-x) = Nan */ /* Else subnormal number */ E = -64; xdb.d *= two64; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000) return x+x; /* Inf or Nan */ DOUBLE_EXTENDED_MODE; /* This one should be overlapped with following integer computation */ /* Extract exponent and mantissa */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to y>sqrt(2)*/ index = index & INDEXMASK; xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; #else /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ /* Here come the code specific to Itanium processor */ PREFETCH_POLY_QUICK; /* defined in log-de.h */ y=x; i = _Asm_getf(2/*_FR_D*/, y); /* Cast y to a 64-bit integer */ /* Filter special cases */ if (i<(int64_t)ULL(0010000000000000)){ /* equivalent to : x < 2^(-1022) */ if ((i & ULL(7fffffffffffffff))==0) return -1.0/0.0; /* log(+/-0) = -Inf */ if (i<0) return (x-x)/0; /* log(-x) = Nan */ /* Else subnormal number */ y *= two64; /* make x a normal number */ E = -64; i = _Asm_getf(2/*_FR_D*/, y); /* and update i */ } if (i >= ULL(7ff0000000000000)) return x+x; /* Inf or Nan */ /* Extract exponent and mantissa */ E += (i>>52)-1023; i = i & ULL(000fffffffffffff); /* keep only mantissa */ index = (i + (ULL(1)<<(52-L-1))) >> (52-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to y>sqrt(2)*/ y = _Asm_setf(2/*_FR_D*/, (i | ULL(3ff0000000000000)) - ULL(0010000000000000) ); /* exponent = -1 */ index = index & INDEXMASK; E++; } else y = _Asm_setf(2/*_FR_D*/, i | ULL(3ff0000000000000) ); /* exponent = 0*/ #endif /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ /* All the previous argument reduction was exact */ /* now y holds 1+f, and E is the exponent */ logirh = argredtable[index].logirh; r = (double_ext) (argredtable[index].r); /* approx to 1/y.d */ z = y*r - 1. ; /* even without an FMA, all exact */ if(E==0) roundtestmask=ACCURATE_TO_61_BITS; else roundtestmask=ACCURATE_TO_62_BITS; #ifdef ESTRIN /* Estrin polynomial evaluation */ double_ext z2,z4, p01, p23, p45, p67, p03, p47,p07; z2 = z*z; p67 = c6 + z*c7; p45 = c4 + z*c5; p23 = c2 + z*c3; p01 = logirh + z; z4 = z2*z2; p47 = p45 + z2*p67; p03 = p01 + z2*p23; p07 = p03 + z4*p47; logde = p07 + E*log2H; #endif #ifdef PATERSON double_ext z4,z2,t0,t1,t2,t3,t4,t5,t6,t7,t8; z2 = z * z; t1 = z + ps_alpha; t2 = z + ps_beta; t3 = c3 * z + c2; t4 = z + logirh; z4 = z2 * z2; t5 = z2 + ps_c; t6 = t3 * z2 + t4; t7 = t5 * t1 + t2; t0 = z4 * c7; t8 = t7 * t0 + t6; logde = t8 + E*log2H; #endif #if 0 /* to time the first step only */ BACK_TO_DOUBLE_MODE; return (double)t; #endif /* To test the second step only, comment out the following line */ DE_TEST_AND_RETURN_RU(logde, roundtestmask); log_accurate(&th, &tl, z, E, index); RETURN_SUM_ROUNDED_UP(th, tl); } double log_rz(double x) { if (x>1.0) return log_rd(x); else return log_ru(x); } interval-3.2.0/src/crlibm/log-de.h0000644000000000000000000011262113316017127015051 0ustar 00000000000000/* * this function computes log, correctly rounded, * using double-extended arithmetic * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /*File generated by maple/log-de.mpl*/ #define L 7 #define MAXINDEX 53 #define INDEXMASK 127 static const double two64 = 1.84467440737095516160000000000000000000000000000000e+19 ; #if 1 #define ESTRIN #else #define PATERSON #endif #if defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) #ifdef PATERSON static const long double c7 = 1.42860987471441585385531838903183654565509641543031e-01; static const long double c3 = 3.33333333333333491175099611014687184251670259982347e-01; static const long double c2 = -5.00000000000000049710669608460378299241710919886827e-01; static const long double ps_alpha = -1.16665881748332273275172571436186785831523593515158e+00; static const long double ps_beta = -1.28333333319474127305875182925021249502606224268675e+00; static const long double ps_c = 3.99962323494931883068092062782916684682277264073491e-01; #endif/* PATERSON*/ #ifdef ESTRIN /* Coefficients are read directly from the array thanks to the following macros */ #define c7 c[0] #define c6 c[1] #define c5 c[2] #define c4 c[3] #define c3 c[4] #define c2 c[5] static const double c[7] = { /* c7 = */ 1.42860563385550420889558154158294200897216796875000e-01L, /* c6 = */ -1.66669572609547372854521540830319281667470932006836e-01L, /* c5 = */ 1.99999999967484798357730824136524461209774017333984e-01L, /* c4 = */ -2.49999999984237081251947643067978788167238235473633e-01L, /* c3 = */ 3.33333333333333425851918718763045035302639007568359e-01L, /* c2 = */ -5.00000000000000000000000000000000000000000000000000e-01L, }; #endif/* ESTRIN */ #define c14h ch[0] #define c13h ch[1] #define c12h ch[2] #define c11h ch[3] #define c10h ch[4] #define c9h ch[5] #define c8h ch[6] #define c7h ch[7] #define c6h ch[8] #define c5h ch[9] #define c4h ch[10] #define c3h ch[11] #define c2h ch[12] #define c1h ch[13] #define c7l cl[0] #define c6l cl[1] #define c5l cl[2] #define c4l cl[3] #define c3l cl[4] #define c2l cl[5] #define c1l cl[6] #define PREFETCH_POLY_ACCURATE #else /* not(defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)), assuming Itanium, otherwise we shouldn't be there */ #define PREFETCH_POLY_QUICK c7=c[0]; c6=c[1]; c5=c[2]; c4=c[3]; c3=c[4]; c2=c[5]; #define PREFETCH_POLY_ACCURATE c14h=ch[0]; c13h=ch[1]; c12h=ch[2]; \ c11h=ch[3]; c10h=ch[4]; c9h=ch[5]; c8h=ch[6]; \ c7h=ch[7]; c6h=ch[8]; c5h=ch[9]; c4h=ch[10]; \ c3h=ch[11]; c2h=ch[12]; c1h=ch[13]; \ c7l=cl[0]; c6l=cl[1]; c5l=cl[2]; c4l=cl[3]; c3l=cl[4]; c2l=cl[5]; c1l=cl[6]; #endif /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ static const long double log2H = 6.93147180559945309428690474184975300886435434222221e-01L ; static const long double log2L = -1.14583527267987328109462081210062935494878745868567e-20L ; static const long double ch[14] = { /* ch14 = */ -7.14324161786485507414918953716931326880512642674148e-02L, /* ch13 = */ 7.69266652810744782218957231456624157317492063157260e-02L, /* ch12 = */ -8.33333332381758034492348456712118576206194120459259e-02L, /* ch11 = */ 9.09090908332141065513009973997338164508619229309261e-02L, /* ch10 = */ -1.00000000000001207646721339272755102456358144991100e-01L, /* ch9 = */ 1.11111111111111906697159444623590474066077149473131e-01L, /* ch8 = */ -1.24999999999999999993223736421965597287453419994563e-01L, /* ch7 = */ 1.42857142857142857140921067549133027796415262855589e-01L, /* ch6 = */ -1.66666666666666666671184175718689601808364386670291e-01L, /* ch5 = */ 2.00000000000000000002710505431213761085018632002175e-01L, /* ch4 = */ -2.50000000000000000000000000000000000000000000000000e-01L, /* ch3 = */ 3.33333333333333333342368351437379203616728773340583e-01L, /* ch2 = */ -5.00000000000000000000000000000000000000000000000000e-01L, /* ch1 = */ 1.00000000000000000000000000000000000000000000000000e+00L, }; static const long double cl[8] = { /* cl7 = */ -2.34607301544056142329539178188626637856988425622953e-21L, /* cl6 = */ 4.51747965172264117284728817178707773935320194423540e-21L, /* cl5 = */ -2.71049445588233034921278017356112411600953390125340e-21L, /* cl4 = */ 4.66256664939948057471422101604617896775339795184375e-32L, /* cl3 = */ -9.03501810405641912072078793108404620486918713178584e-21L, /* cl2 = */ -2.17279608948233676401606923369245026501745724471211e-38L, /* cl1 = */ 1.65533283613483715658161425689915551329447733519200e-39L, }; typedef struct rri_tag {float r; long double logirh; long double logirl; } rri ; static const rri argredtable[128] = { { 1.00000000000000000000000000000000000000000000000000e+00L, /* r[0] */ 0.00000000000000000000000000000000000000000000000000e+00L, /* logirh[0] */ 0.00000000000000000000000000000000000000000000000000e+00L, /* logirl[0] */ } , { 9.92187500000000000000000000000000000000000000000000e-01L, /* r[1] */ 7.84317746102589287284596788335511163836599735077471e-03L, /* logirh[1] */ 3.38074607588470016237165513745732472460993853200422e-22L, /* logirl[1] */ } , { 9.84375000000000000000000000000000000000000000000000e-01L, /* r[2] */ 1.57483569681391686082786579570225171664787922054529e-02L, /* logirh[2] */ -7.29146496194247645559133241782926476205899642506092e-22L, /* logirl[2] */ } , { 9.77050781250000000000000000000000000000000000000000e-01L, /* r[3] */ 2.32166515756649942034666594947722728647931944578886e-02L, /* logirh[3] */ 8.16575450536547381330756941074595397347505963439697e-22L, /* logirl[3] */ } , { 9.69726562500000000000000000000000000000000000000000e-01L, /* r[4] */ 3.07411415542805019917064427575903451383965148124844e-02L, /* logirh[4] */ 7.52695325012824272079306803804945762930133964168774e-22L, /* logirl[4] */ } , { 9.62402343750000000000000000000000000000000000000000e-01L, /* r[5] */ 3.83226790066782003103828830453680964751583815086633e-02L, /* logirh[5] */ 1.32588478845446750814375495501523698113568837341268e-21L, /* logirl[5] */ } , { 9.55078125000000000000000000000000000000000000000000e-01L, /* r[6] */ 4.59621355646357592953472545604931553953065304085612e-02L, /* logirh[6] */ -4.35764480179623995168944249774175041700203429439418e-22L, /* logirl[6] */ } , { 9.48242187500000000000000000000000000000000000000000e-01L, /* r[7] */ 5.31453373081281829112658150054970818132460408378392e-02L, /* logirh[7] */ 1.44205225309117178233184984742382173167310218612172e-21L, /* logirl[7] */ } , { 9.41406250000000000000000000000000000000000000000000e-01L, /* r[8] */ 6.03805109889074798701694406916073987190429761540145e-02L, /* logirh[8] */ 1.27621226298941086768118279123481924424995440912208e-21L, /* logirl[8] */ } , { 9.34082031250000000000000000000000000000000000000000e-01L, /* r[9] */ 6.81910167191455281494459790547768562873898190446198e-02L, /* logirh[9] */ -1.70880559998991196112313542261373401163426418187142e-21L, /* logirl[9] */ } , { 9.27734375000000000000000000000000000000000000000000e-01L, /* r[10] */ 7.50098210048665755422673054320092944635689491406083e-02L, /* logirh[10] */ 2.27568935135100192738710607079520297834759644719280e-21L, /* logirl[10] */ } , { 9.20898437500000000000000000000000000000000000000000e-01L, /* r[11] */ 8.24055229659955995008915365096502370079178945161402e-02L, /* logirh[11] */ -2.08652677548826307173863192982976527450361189636477e-21L, /* logirl[11] */ } , { 9.14062500000000000000000000000000000000000000000000e-01L, /* r[12] */ 8.98563291218610470738304384086259091191095649264753e-02L, /* logirh[12] */ 2.81649638824005330910700533403251014557157154610229e-21L, /* logirl[12] */ } , { 9.07714843750000000000000000000000000000000000000000e-01L, /* r[13] */ 9.68249984379543874202667802508770478198130149394274e-02L, /* logirh[13] */ 3.68094693298691578446114201021493215549389467689654e-22L, /* logirl[13] */ } , { 9.01367187500000000000000000000000000000000000000000e-01L, /* r[14] */ 1.03842571096600936786835851777244243976383586414158e-01L, /* logirh[14] */ 2.54338872616873521380798016729106577000795946658943e-21L, /* logirl[14] */ } , { 8.95019531250000000000000000000000000000000000000000e-01L, /* r[15] */ 1.10909738319693389317513541186821512951610202435404e-01L, /* logirh[15] */ 2.35644659310271753015106107980519412012017300780629e-21L, /* logirl[15] */ } , { 8.88671875000000000000000000000000000000000000000000e-01L, /* r[16] */ 1.18027206088557368998193455866818624144798377528787e-01L, /* logirh[16] */ -2.70388097791548543320098495660860118836293912482208e-21L, /* logirl[16] */ } , { 8.82812500000000000000000000000000000000000000000000e-01L, /* r[17] */ 1.24642445207276597340148149156702217510428454261273e-01L, /* logirh[17] */ -1.65479256548791301121285753303466491277640159570672e-21L, /* logirl[17] */ } , { 8.76953125000000000000000000000000000000000000000000e-01L, /* r[18] */ 1.31301737297253491506014363987553394963470054790378e-01L, /* logirh[18] */ -4.44706169007428370264461881106553970898124442872790e-21L, /* logirl[18] */ } , { 8.70605468750000000000000000000000000000000000000000e-01L, /* r[19] */ 1.38566368296257995358167561250617438872723141685128e-01L, /* logirh[19] */ -4.67634371291677236899800289793824808374204801868093e-22L, /* logirl[19] */ } , { 8.64746093750000000000000000000000000000000000000000e-01L, /* r[20] */ 1.45319348376564863616804482160382860911340685561299e-01L, /* logirh[20] */ -1.30029933894575998199859720642569228712037418444249e-21L, /* logirl[20] */ } , { 8.58886718750000000000000000000000000000000000000000e-01L, /* r[21] */ 1.52118241421840233982849116545210677031718660145998e-01L, /* logirh[21] */ 3.64354833902581289681945250205165982842948711023632e-21L, /* logirl[21] */ } , { 8.53515625000000000000000000000000000000000000000000e-01L, /* r[22] */ 1.58391429943917633934029505493601419630067539401352e-01L, /* logirh[22] */ 5.27932393193803736951671071669282537406718712467109e-21L, /* logirl[22] */ } , { 8.47656250000000000000000000000000000000000000000000e-01L, /* r[23] */ 1.65280090939102924306155009692709256796661065891385e-01L, /* logirh[23] */ -2.81510601283365227976423953518023725736246907863349e-21L, /* logirl[23] */ } , { 8.42285156250000000000000000000000000000000000000000e-01L, /* r[24] */ 1.71636656693938272180742846129142264999245526269078e-01L, /* logirh[24] */ 5.29375472570288169027310108578005956387644768823013e-21L, /* logirl[24] */ } , { 8.36425781250000000000000000000000000000000000000000e-01L, /* r[25] */ 1.78617487835278495469731006861646704919621697627008e-01L, /* logirh[25] */ -5.38910368385932491449404580991668679267931166391590e-21L, /* logirl[25] */ } , { 8.31054687500000000000000000000000000000000000000000e-01L, /* r[26] */ 1.85059677026078958999807423657646410219967947341502e-01L, /* logirh[26] */ -2.33471191752401180750814334631327570292249238444557e-21L, /* logirl[26] */ } , { 8.25683593750000000000000000000000000000000000000000e-01L, /* r[27] */ 1.91543637260818105263310805186360852303550927899778e-01L, /* logirh[27] */ -6.00441704121360115108475562878860059804996577890616e-22L, /* logirl[27] */ } , { 8.20312500000000000000000000000000000000000000000000e-01L, /* r[28] */ 1.98069913762093794816921549228894150473934132605791e-01L, /* logirh[28] */ 2.34598738644875224435499574368287811489905562806854e-21L, /* logirl[28] */ } , { 8.15429687500000000000000000000000000000000000000000e-01L, /* r[29] */ 2.04040080748597612311876631219220712409878615289927e-01L, /* logirh[29] */ -6.55266084220369778013064711105338848331692231543846e-23L, /* logirl[29] */ } , { 8.10058593750000000000000000000000000000000000000000e-01L, /* r[30] */ 2.10648695968953912917276914684716615511206327937543e-01L, /* logirh[30] */ -1.26710049189072313882986012728331847015236776848568e-21L, /* logirl[30] */ } , { 8.05175781250000000000000000000000000000000000000000e-01L, /* r[31] */ 2.16694663599799501227903542055486241224571131169796e-01L, /* logirh[31] */ -4.60644559263224179134698153089361151013881754428009e-21L, /* logirl[31] */ } , { 7.99804687500000000000000000000000000000000000000000e-01L, /* r[32] */ 2.23387721746383670218673127283448565094658988527954e-01L, /* logirh[32] */ 4.31742844476737192308069645283904795344591963380062e-21L, /* logirl[32] */ } , { 7.94921875000000000000000000000000000000000000000000e-01L, /* r[33] */ 2.29511439596912796321610469862939396534784464165568e-01L, /* logirh[33] */ 3.43937426407325242308884173752237970071183767432875e-21L, /* logirl[33] */ } , { 7.90039062500000000000000000000000000000000000000000e-01L, /* r[34] */ 2.35672888540961404738862880470229299589846050366759e-01L, /* logirh[34] */ -1.79412857504879722290348395953977521127195555595173e-21L, /* logirl[34] */ } , { 7.85156250000000000000000000000000000000000000000000e-01L, /* r[35] */ 2.41872536420486724268049359698462552614728338085115e-01L, /* logirh[35] */ 4.49037868070153677475908787622962677106946524955373e-21L, /* logirl[35] */ } , { 7.80273437500000000000000000000000000000000000000000e-01L, /* r[36] */ 2.48110859833178427105411859021621978627081261947751e-01L, /* logirh[36] */ -3.57593208515654235641923519987160957618932290654994e-21L, /* logirl[36] */ } , { 7.75878906250000000000000000000000000000000000000000e-01L, /* r[37] */ 2.53758819622682423467613377354723525058943778276443e-01L, /* logirh[37] */ 3.20563840854194897949310719402625620635813869593052e-21L, /* logirl[37] */ } , { 7.70996093750000000000000000000000000000000000000000e-01L, /* r[38] */ 2.60071971903756312988632154459267553647805470973253e-01L, /* logirh[38] */ -5.41882056366019440034410441132485333532494541348922e-21L, /* logirl[38] */ } , { 7.66601562500000000000000000000000000000000000000000e-01L, /* r[39] */ 2.65788087817044662143715211266581377458351198583841e-01L, /* logirh[39] */ 3.40143368552141502891849732509800494117246716875116e-21L, /* logirl[39] */ } , { 7.61718750000000000000000000000000000000000000000000e-01L, /* r[40] */ 2.72177885915815673289249593258531945139111485332251e-01L, /* logirh[40] */ -8.84633307151349513479527937859825353954577224837834e-22L, /* logirl[40] */ } , { 7.57324218750000000000000000000000000000000000000000e-01L, /* r[41] */ 2.77963822982859581314958596909292509735678322613239e-01L, /* logirh[41] */ -3.54474552917897427055990528561562900487032834630297e-21L, /* logirl[41] */ } , { 7.52929687500000000000000000000000000000000000000000e-01L, /* r[42] */ 2.83783432036123604418629065571089142849814379587770e-01L, /* logirh[42] */ 6.65259732689538164307466344899173176872160839687638e-21L, /* logirl[42] */ } , { 7.48535156250000000000000000000000000000000000000000e-01L, /* r[43] */ 2.89637107287584277988401471048973689903505146503448e-01L, /* logirh[43] */ 8.44502718672055373787764268905081131551582182658017e-21L, /* logirl[43] */ } , { 7.44140625000000000000000000000000000000000000000000e-01L, /* r[44] */ 2.95525249912806820310438860044399689286365173757076e-01L, /* logirh[44] */ 1.96418844037132387179566864994176219064092063775800e-21L, /* logirl[44] */ } , { 7.39746093750000000000000000000000000000000000000000e-01L, /* r[45] */ 3.01448268215928886712157847016513301241502631455660e-01L, /* logirh[45] */ -2.80734803827355347488954127622224279750224052590805e-21L, /* logirl[45] */ } , { 7.35839843750000000000000000000000000000000000000000e-01L, /* r[46] */ 3.06742787532902944200221412307527657503669615834951e-01L, /* logirh[46] */ 1.21982177874199009422425119496965659738938728771737e-20L, /* logirl[46] */ } , { 7.31445312500000000000000000000000000000000000000000e-01L, /* r[47] */ 3.12732822082233615765050824264470463731413474306464e-01L, /* logirh[47] */ -2.48117014916151417666322195359345625530313936737052e-21L, /* logirl[47] */ } , { 7.27050781250000000000000000000000000000000000000000e-01L, /* r[48] */ 3.18758953475389418655326981277831066563521744683385e-01L, /* logirh[48] */ 6.18924657142483596407123884547314261312268979674812e-21L, /* logirl[48] */ } , { 7.23144531250000000000000000000000000000000000000000e-01L, /* r[49] */ 3.24146171891599621094504773965994104401033837348223e-01L, /* logirh[49] */ -6.77810676502059511550248363328884520138042030679722e-21L, /* logirl[49] */ } , { 7.19238281250000000000000000000000000000000000000000e-01L, /* r[50] */ 3.29562569696768133456748345322395721268549095839262e-01L, /* logirh[50] */ 3.36942877993616991096538545261104308752103794630367e-21L, /* logirl[50] */ } , { 7.14843750000000000000000000000000000000000000000000e-01L, /* r[51] */ 3.35691291638141535192156258982087990716536296531558e-01L, /* logirh[51] */ -9.33627664815897075676848962806562975738122262236195e-22L, /* logirl[51] */ } , { 7.10937500000000000000000000000000000000000000000000e-01L, /* r[52] */ 3.41170757402767124748460894623214301191183039918542e-01L, /* logirh[52] */ 1.33237705755233408947468410861546874819170412376378e-20L, /* logirl[52] */ } , { 1.41406250000000000000000000000000000000000000000000e+00L, /* r[53] */ -3.46466767346208580905441917763276649111503502354026e-01L, /* logirh[53] */ -1.30202706624963016000170912600455670740294985927040e-20L, /* logirl[53] */ } , { 1.40625000000000000000000000000000000000000000000000e+00L, /* r[54] */ -3.40926586970593210293607733252230218568001873791218e-01L, /* logirh[54] */ -1.14814665281259898750718236421526040752891815931201e-20L, /* logirl[54] */ } , { 1.39843750000000000000000000000000000000000000000000e+00L, /* r[55] */ -3.35355541921137830261656978536599638118786970153451e-01L, /* logirh[55] */ 4.47739872243343904426499770912991919745896227107013e-21L, /* logirl[55] */ } , { 1.39160156250000000000000000000000000000000000000000e+00L, /* r[56] */ -3.30455287103297806430195551752326821315364213660359e-01L, /* logirh[56] */ -3.27456892866201886570311318311258813067527495773846e-21L, /* logirl[56] */ } , { 1.38378906250000000000000000000000000000000000000000e+00L, /* r[57] */ -3.24825434091227342270433858795186665702203754335642e-01L, /* logirh[57] */ 1.19511796024320905916745808450236450294857297262032e-20L, /* logirl[57] */ } , { 1.37597656250000000000000000000000000000000000000000e+00L, /* r[58] */ -3.19163706299227122796481267985591045999171910807490e-01L, /* logirh[58] */ 6.90202297465146164725318961579993617833444966789173e-21L, /* logirl[58] */ } , { 1.36914062500000000000000000000000000000000000000000e+00L, /* r[59] */ -3.14183261995082305749471540678996461792849004268646e-01L, /* logirh[59] */ 4.21220977458500148787692752842598753888865534619897e-21L, /* logirl[59] */ } , { 1.36132812500000000000000000000000000000000000000000e+00L, /* r[60] */ -3.08460785721016099366091275935097826277342392131686e-01L, /* logirh[60] */ 4.88237814815281499208804200664728929895975484184937e-21L, /* logirl[60] */ } , { 1.35449218750000000000000000000000000000000000000000e+00L, /* r[61] */ -3.03426614715378494924018226708284373671631328761578e-01L, /* logirh[61] */ -4.79684803634605371547569285269009577973457927997898e-21L, /* logirl[61] */ } , { 1.34765625000000000000000000000000000000000000000000e+00L, /* r[62] */ -2.98366972551797281470575134987299747990618925541639e-01L, /* logirh[62] */ 5.67470469380282997916448622011708142111988647148768e-21L, /* logirl[62] */ } , { 1.33984375000000000000000000000000000000000000000000e+00L, /* r[63] */ -2.92553002686377439973833616826404124822147423401475e-01L, /* logirh[63] */ -4.36764183772251948513980052351746496236270975543032e-21L, /* logirl[63] */ } , { 1.33300781250000000000000000000000000000000000000000e+00L, /* r[64] */ -2.87437902019607012987821928473586297059227945283055e-01L, /* logirh[64] */ 5.29838789814029919861828480804189667231634001130568e-21L, /* logirl[64] */ } , { 1.32617187500000000000000000000000000000000000000000e+00L, /* r[65] */ -2.82296502519188342454669118919419190660846652463078e-01L, /* logirh[65] */ -1.23161531041331401059141407104196718032007794736410e-20L, /* logirl[65] */ } , { 1.31933593750000000000000000000000000000000000000000e+00L, /* r[66] */ -2.77128532360745762785523768623185958404064876958728e-01L, /* logirh[66] */ -2.43881362128685466800250141549314299428343038574346e-21L, /* logirl[66] */ } , { 1.31250000000000000000000000000000000000000000000000e+00L, /* r[67] */ -2.71933715483641758834396431887547862515930319204926e-01L, /* logirh[67] */ 2.72693735454870053343005187033588239526260949526707e-21L, /* logirl[67] */ } , { 1.30566406250000000000000000000000000000000000000000e+00L, /* r[68] */ -2.66711771502490083769927597945326169792679138481617e-01L, /* logirh[68] */ -1.30538831184550256981566412802003295683583076000542e-20L, /* logirl[68] */ } , { 1.29980468750000000000000000000000000000000000000000e+00L, /* r[69] */ -2.62214012795658537999981055333087454073393018916249e-01L, /* logirh[69] */ -1.35284639805347646364569630725426945939555870993862e-20L, /* logirl[69] */ } , { 1.29296875000000000000000000000000000000000000000000e+00L, /* r[70] */ -2.56940930897500425454356778875997235900285886600614e-01L, /* logirh[70] */ 7.59691096477297380738769966672131808838423827917718e-21L, /* logirl[70] */ } , { 1.28613281250000000000000000000000000000000000000000e+00L, /* r[71] */ -2.51639896143827947226981334161166614649118855595589e-01L, /* logirh[71] */ 1.08451820776528904003677301321556919497451301342926e-20L, /* logirl[71] */ } , { 1.28027343750000000000000000000000000000000000000000e+00L, /* r[72] */ -2.47073678164246748038433351690734696148865623399615e-01L, /* logirh[72] */ -2.70934348074983423389837544898983311835569196319188e-22L, /* logirl[72] */ } , { 1.27343750000000000000000000000000000000000000000000e+00L, /* r[73] */ -2.41719936887145168147327835284077224287102581001818e-01L, /* logirh[73] */ 3.02031937056332418377432311426563822398827693734850e-21L, /* logirl[73] */ } , { 1.26757812500000000000000000000000000000000000000000e+00L, /* r[74] */ -2.37108091664582209921611002934049849955044919624925e-01L, /* logirh[74] */ -1.29385562718796125049667754614832437256004301349817e-21L, /* logirl[74] */ } , { 1.26074218750000000000000000000000000000000000000000e+00L, /* r[75] */ -2.31700585247189405499685169176338206398213515058160e-01L, /* logirh[75] */ 6.62539371561050126516331629758628121599171156714272e-21L, /* logirl[75] */ } , { 1.25488281250000000000000000000000000000000000000000e+00L, /* r[76] */ -2.27042191729867078774313463029876913878979394212365e-01L, /* logirh[76] */ -5.91897037580049650648090820667969090523023685061856e-21L, /* logirl[76] */ } , { 1.24902343750000000000000000000000000000000000000000e+00L, /* r[77] */ -2.22361995979389595864202273933774023362275329418480e-01L, /* logirh[77] */ 1.99231806901499648836052705402258881903978292639586e-21L, /* logirl[77] */ } , { 1.24316406250000000000000000000000000000000000000000e+00L, /* r[78] */ -2.17659792957953425506303912762007257697405293583870e-01L, /* logirh[78] */ -4.74300907803349351890305548951624396775339872866125e-22L, /* logirl[78] */ } , { 1.23632812500000000000000000000000000000000000000000e+00L, /* r[79] */ -2.12145797104668402385590705860884952471678843721747e-01L, /* logirh[79] */ 3.47829660766824246239119087253730459399781610669550e-21L, /* logirl[79] */ } , { 1.23046875000000000000000000000000000000000000000000e+00L, /* r[80] */ -2.07395194346070587155541307955441965304999030195177e-01L, /* logirh[80] */ -3.20427089356426854873522351022491299412381577686272e-21L, /* logirl[80] */ } , { 1.22460937500000000000000000000000000000000000000000e+00L, /* r[81] */ -2.02621915593412910716630305485441709834049106575549e-01L, /* logirh[81] */ 5.50315183352228080702347654662068966867864577851415e-21L, /* logirl[81] */ } , { 1.21875000000000000000000000000000000000000000000000e+00L, /* r[82] */ -1.97825743329919880362068387857910067850752966478467e-01L, /* logirh[82] */ -5.03683339051401224496307307364812285151080899609793e-22L, /* logirl[82] */ } , { 1.21289062500000000000000000000000000000000000000000e+00L, /* r[83] */ -1.93006456893970980236542936414601001615665154531598e-01L, /* logirh[83] */ -8.56513039583118089646992381309540829893520394889616e-22L, /* logirl[83] */ } , { 1.20800781250000000000000000000000000000000000000000e+00L, /* r[84] */ -1.88972566793034805259442719671536536907296977005899e-01L, /* logirh[84] */ -1.46116025447516430873070498908178881036913039739167e-21L, /* logirl[84] */ } , { 1.20214843750000000000000000000000000000000000000000e+00L, /* r[85] */ -1.84110320585000416173803057529045901219433289952576e-01L, /* logirh[85] */ -4.15395156136845605789354429056953059762833513205358e-21L, /* logirl[85] */ } , { 1.19628906250000000000000000000000000000000000000000e+00L, /* r[86] */ -1.79224317379374265237954554075283652991856797598302e-01L, /* logirh[86] */ -1.94838468168540457849663379542888863164719363528710e-21L, /* logirl[86] */ } , { 1.19042968750000000000000000000000000000000000000000e+00L, /* r[87] */ -1.74314323881818430785127331528183702857859316281974e-01L, /* logirh[87] */ 6.22657527069549481059986868787317656634503241639655e-21L, /* logirl[87] */ } , { 1.18554687500000000000000000000000000000000000000000e+00L, /* r[88] */ -1.70204166019990477397598113706855826876562787219882e-01L, /* logirh[88] */ 2.71497198375317303100785063981453318980131866492304e-21L, /* logirl[88] */ } , { 1.17968750000000000000000000000000000000000000000000e+00L, /* r[89] */ -1.65249572895307162873914340328607153196571744047105e-01L, /* logirh[89] */ -1.69710894863316053274660137780472619090744715377758e-21L, /* logirl[89] */ } , { 1.17382812500000000000000000000000000000000000000000e+00L, /* r[90] */ -1.60270309495699794511943195307601683907705591991544e-01L, /* logirh[90] */ -6.04821814795533552862893869629633677033284792785115e-21L, /* logirl[90] */ } , { 1.16894531250000000000000000000000000000000000000000e+00L, /* r[91] */ -1.56101899958520053736952051814945718888338888064027e-01L, /* logirh[91] */ 4.40261722062672347380361273563329366574299418033041e-21L, /* logirl[91] */ } , { 1.16406250000000000000000000000000000000000000000000e+00L, /* r[92] */ -1.51916042025841975066048281095554273179004667326808e-01L, /* logirh[92] */ -5.75514380133023814872665374682664797890000868696983e-21L, /* logirl[92] */ } , { 1.15820312500000000000000000000000000000000000000000e+00L, /* r[93] */ -1.46869773958217667795276076270205578566674375906587e-01L, /* logirh[93] */ 3.74542574364605198240110299363146340829881458953744e-21L, /* logirl[93] */ } , { 1.15332031250000000000000000000000000000000000000000e+00L, /* r[94] */ -1.42645010597909210864992976541820723923592595383525e-01L, /* logirh[94] */ -1.49668764603399746810002277800399641956108986115277e-21L, /* logirl[94] */ } , { 1.14843750000000000000000000000000000000000000000000e+00L, /* r[95] */ -1.38402322859119135682777479434690803827834315598011e-01L, /* logirh[95] */ -2.54839416695838356532650800861069791639429031347559e-21L, /* logirl[95] */ } , { 1.14257812500000000000000000000000000000000000000000e+00L, /* r[96] */ -1.33287222192348708683213263925804170639821677468717e-01L, /* logirh[96] */ -6.43489158716437030647791169560962525141739108779860e-21L, /* logirl[96] */ } , { 1.13769531250000000000000000000000000000000000000000e+00L, /* r[97] */ -1.29004560400347845734790423743998388772524776868522e-01L, /* logirh[97] */ 4.12743043068895141295491814920903816740508819920186e-21L, /* logirl[97] */ } , { 1.13281250000000000000000000000000000000000000000000e+00L, /* r[98] */ -1.24703478500957235860374400920891346800090104807168e-01L, /* logirh[98] */ -3.03211445997192169150157656625233654585699365130551e-21L, /* logirl[98] */ } , { 1.12792968750000000000000000000000000000000000000000e+00L, /* r[99] */ -1.20383817356440820990376872751115300275159825105220e-01L, /* logirh[99] */ -6.02804224141392601725339572746961606433931174921632e-22L, /* logirl[99] */ } , { 1.12304687500000000000000000000000000000000000000000e+00L, /* r[100] */ -1.16045415757842655255155980137393711970617005135864e-01L, /* logirh[100] */ 1.97357499841142715648611745206675471003368015857707e-21L, /* logirl[100] */ } , { 1.11816406250000000000000000000000000000000000000000e+00L, /* r[101] */ -1.11688110388886928867871375231635155955700611229986e-01L, /* logirh[101] */ -1.80234734539512005333983723608110499312624517402909e-21L, /* logirl[101] */ } , { 1.11328125000000000000000000000000000000000000000000e+00L, /* r[102] */ -1.07311735789088050666375585839862338843886391259730e-01L, /* logirh[102] */ -7.99444531291997962572940662749597218537387594367069e-22L, /* logirl[102] */ } , { 1.10839843750000000000000000000000000000000000000000e+00L, /* r[103] */ -1.02916124316049955441049277432563613388083467725664e-01L, /* logirh[103] */ -7.70418045355390537427085452827290090533981671198214e-22L, /* logirl[103] */ } , { 1.10351562500000000000000000000000000000000000000000e+00L, /* r[104] */ -9.85011061069331584304480803337966676735959481447935e-02L, /* logirh[104] */ 2.64634661517646879820354995203947987149684385342190e-21L, /* logirl[104] */ } , { 1.09863281250000000000000000000000000000000000000000e+00L, /* r[105] */ -9.40665090390674124196622452043214934747084043920040e-02L, /* logirh[105] */ -7.85013737527153642092056782136336663408299656719499e-22L, /* logirl[105] */ } , { 1.09375000000000000000000000000000000000000000000000e+00L, /* r[106] */ -8.96121586896871326189772770376418264959283987991512e-02L, /* logirh[106] */ -9.74192340842702289248316897714444315823596817643550e-22L, /* logirl[106] */ } , { 1.08984375000000000000000000000000000000000000000000e+00L, /* r[107] */ -8.60343373418031533820279736779479407005055691115558e-02L, /* logirh[107] */ 2.30146955951865559597249227413865587554269312860475e-22L, /* logirl[107] */ } , { 1.08496093750000000000000000000000000000000000000000e+00L, /* r[108] */ -8.15439840401769007739956988956020467185226152651012e-02L, /* logirh[108] */ 1.75068599249270760931371736454488137316032510066418e-22L, /* logirl[108] */ } , { 1.08007812500000000000000000000000000000000000000000e+00L, /* r[109] */ -7.70333764828270145253981751598537641712027834728360e-02L, /* logirh[109] */ 2.18898335885222504011340723675649479553611259830224e-21L, /* logirl[109] */ } , { 1.07519531250000000000000000000000000000000000000000e+00L, /* r[110] */ -7.25023311232268688402238278334355214838069514371455e-02L, /* logirh[110] */ -2.13213366575366793826831658963525268068913415683098e-21L, /* logirl[110] */ } , { 1.07128906250000000000000000000000000000000000000000e+00L, /* r[111] */ -6.88626546757771517366978307472802356414831592701375e-02L, /* logirh[111] */ -3.28324237603869825985548439776523090582575800369088e-22L, /* logirl[111] */ } , { 1.06640625000000000000000000000000000000000000000000e+00L, /* r[112] */ -6.42943507053972572172256989830874118752035428769886e-02L, /* logirh[112] */ 9.97248717475917389385548315283734311163209646118044e-22L, /* logirl[112] */ } , { 1.06250000000000000000000000000000000000000000000000e+00L, /* r[113] */ -6.06246218164348425809463336011440048878284869715571e-02L, /* logirh[113] */ 3.40201560723741601617729662632506532290642311489711e-22L, /* logirl[113] */ } , { 1.05761718750000000000000000000000000000000000000000e+00L, /* r[114] */ -5.60184414015375172410100661213316897146796691231430e-02L, /* logirh[114] */ 3.11800048645913474307950146912226463632967430723724e-23L, /* logirl[114] */ } , { 1.05371093750000000000000000000000000000000000000000e+00L, /* r[115] */ -5.23181596586815653583246027436004510491329710930586e-02L, /* logirh[115] */ 1.68615246867707396959723624602535685414462357313269e-21L, /* logirl[115] */ } , { 1.04882812500000000000000000000000000000000000000000e+00L, /* r[116] */ -4.76734694693569028189818886920292584363778587430716e-02L, /* logirh[116] */ 1.02131487169049086541356584124809714333053944625270e-21L, /* logirl[116] */ } , { 1.04492187500000000000000000000000000000000000000000e+00L, /* r[117] */ -4.39421218564987631503880941008510774281603517010808e-02L, /* logirh[117] */ 3.19036974975549018917247656911137538435844307015502e-22L, /* logirl[117] */ } , { 1.04101562500000000000000000000000000000000000000000e+00L, /* r[118] */ -4.01967991263367551645860776404761693925138388294727e-02L, /* logirh[118] */ -5.75643838660911109663810221439950742515738641098385e-22L, /* logirl[118] */ } , { 1.03613281250000000000000000000000000000000000000000e+00L, /* r[119] */ -3.54953330145300408896490932525447092871218046639115e-02L, /* logirh[119] */ 9.92857944898394620246865383584341693120429858950945e-23L, /* logirl[119] */ } , { 1.03222656250000000000000000000000000000000000000000e+00L, /* r[120] */ -3.17181802707845397290716514537844972210223204456270e-02L, /* logirh[120] */ -1.96176892105841918795869133037686185923113451571873e-22L, /* logirl[120] */ } , { 1.02832031250000000000000000000000000000000000000000e+00L, /* r[121] */ -2.79267065345224074627335925091742296899610664695501e-02L, /* logirh[121] */ 5.86417835518487049711934217680032678831410128853609e-22L, /* logirl[121] */ } , { 1.02441406250000000000000000000000000000000000000000e+00L, /* r[122] */ -2.41208027968440809158740456216718506254892417928204e-02L, /* logirh[122] */ 3.02985243973796148231999463903827273031077578359612e-22L, /* logirl[122] */ } , { 1.01953125000000000000000000000000000000000000000000e+00L, /* r[123] */ -1.93429628431309346365065977152442044939562038052827e-02L, /* logirh[123] */ 6.01063173693734308460897092397749141966269930081944e-22L, /* logirl[123] */ } , { 1.01562500000000000000000000000000000000000000000000e+00L, /* r[124] */ -1.55041865359652541508843977442755335260926585760899e-02L, /* logirh[124] */ 3.03517018286976482243336130818153212447067590236466e-23L, /* logirl[124] */ } , { 1.01171875000000000000000000000000000000000000000000e+00L, /* r[125] */ -1.16506172199752741354571356803548898284361712285317e-02L, /* logirh[125] */ -1.34307128859459104723409399281441278120110731736138e-22L, /* logirl[125] */ } , { 1.00781250000000000000000000000000000000000000000000e+00L, /* r[126] */ -7.78214044205494894757658497566610300566480873385444e-03L, /* logirh[126] */ 1.13684914529339327537355164185463042556838581909991e-22L, /* logirl[126] */ } , { 1.00390625000000000000000000000000000000000000000000e+00L, /* r[127] */ -3.89864041565732301388162890642963276377486181445420e-03L, /* logirh[127] */ -5.57141894132742469511718763808942289917039607877533e-23L, /* logirl[127] */ } }; interval-3.2.0/src/crlibm/log-td.c0000644000000000000000000011752613316017127015074 0ustar 00000000000000/* * This function computes log, correctly rounded, * using triple double arithmetics * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Christoph Lauter * christoph.lauter at ens-lyon.fr * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "log-td.h" #ifdef BUILD_INTERVAL_FUNCTIONS #include "interval.h" #endif #define AVOID_FMA 0 void log_td_accurate(double *logh, double *logm, double *logl, int E, double ed, int index, double zh, double zl, double logih, double logim) { double highPoly, t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l, t8h, t8l, t9h, t9l, t10h, t10l, t11h, t11l; double t12h, t12l, t13h, t13l, t14h, t14l, zSquareh, zSquarem, zSquarel, zCubeh, zCubem, zCubel, higherPolyMultZh, higherPolyMultZm; double higherPolyMultZl, zSquareHalfh, zSquareHalfm, zSquareHalfl, polyWithSquareh, polyWithSquarem, polyWithSquarel; double polyh, polym, polyl, logil, logyh, logym, logyl, loghover, logmover, loglover, log2edhover, log2edmover, log2edlover; double log2edh, log2edm, log2edl; #if EVAL_PERF crlibm_second_step_taken++; #endif /* Accurate phase: Argument reduction is already done. We must return logh, logm and logl representing the intermediate result in 118 bits precision. We use a 14 degree polynomial, computing the first 3 (the first is 0) coefficients in triple double, calculating the next 7 coefficients in double double arithmetics and the last in double. We must account for zl starting with the monome of degree 4 (7^3 + 53 - 7 >> 118); so double double calculations won't account for it. */ /* Start of the horner scheme */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(accPolyC14,zh,accPolyC13),zh,accPolyC12),zh,accPolyC11),zh,accPolyC10); #else highPoly = accPolyC10 + zh * (accPolyC11 + zh * (accPolyC12 + zh * (accPolyC13 + zh * accPolyC14))); #endif /* We want to write accPolyC3 + zh * (accPoly4 + zh * (accPoly5 + zh * (accPoly6 + zh * (accPoly7 + zh * (accPoly8 + zh * (accPoly9 + zh * highPoly)))))); ( t14 t13 t12 t11 t10 t9 t8 t7 t6 t5 t4 t3 t2 t1 ) with all additions and multiplications in double double arithmetics but we will produce intermediate results labelled t1h/t1l thru t14h/t14l */ Mul12(&t1h, &t1l, zh, highPoly); Add22(&t2h, &t2l, accPolyC9h, accPolyC9l, t1h, t1l); Mul22(&t3h, &t3l, zh, zl, t2h, t2l); Add22(&t4h, &t4l, accPolyC8h, accPolyC8l, t3h, t3l); Mul22(&t5h, &t5l, zh, zl, t4h, t4l); Add22(&t6h, &t6l, accPolyC7h, accPolyC7l, t5h, t5l); Mul22(&t7h, &t7l, zh, zl, t6h, t6l); Add22(&t8h, &t8l, accPolyC6h, accPolyC6l, t7h, t7l); Mul22(&t9h, &t9l, zh, zl, t8h, t8l); Add22(&t10h, &t10l, accPolyC5h, accPolyC5l, t9h, t9l); Mul22(&t11h, &t11l, zh, zl, t10h, t10l); Add22(&t12h, &t12l, accPolyC4h, accPolyC4l, t11h, t11l); Mul22(&t13h, &t13l, zh, zl, t12h, t12l); Add22(&t14h, &t14l, accPolyC3h, accPolyC3l, t13h, t13l); /* We must now prepare (zh + zl)^2 and (zh + zl)^3 as triple doubles */ Mul23(&zSquareh, &zSquarem, &zSquarel, zh, zl, zh, zl); Mul233(&zCubeh, &zCubem, &zCubel, zh, zl, zSquareh, zSquarem, zSquarel); /* We can now multiplicate the middle and higher polynomial by z^3 */ Mul233(&higherPolyMultZh, &higherPolyMultZm, &higherPolyMultZl, t14h, t14l, zCubeh, zCubem, zCubel); /* Multiply now z^2 by -1/2 (exact op) and add to middle and higher polynomial */ zSquareHalfh = zSquareh * -0.5; zSquareHalfm = zSquarem * -0.5; zSquareHalfl = zSquarel * -0.5; Add33(&polyWithSquareh, &polyWithSquarem, &polyWithSquarel, zSquareHalfh, zSquareHalfm, zSquareHalfl, higherPolyMultZh, higherPolyMultZm, higherPolyMultZl); /* Add now zh and zl to obtain the polynomial evaluation result */ Add233(&polyh, &polym, &polyl, zh, zl, polyWithSquareh, polyWithSquarem, polyWithSquarel); /* Reconstruct now log(y) = log(1 + z) - log(ri) by adding logih, logim, logil logil has not been read to the time, do this first */ logil = argredtable[index].logil; Add33(&logyh, &logym, &logyl, logih, logim, logil, polyh, polym, polyl); /* Multiply log2 with E, i.e. log2h, log2m, log2l by ed ed is always less than 2^(12) and log2h and log2m are stored with at least 12 trailing zeros So multiplying naively is correct (up to 134 bits at least) The final result is thus obtained by adding log2 * E to log(y) */ log2edhover = log2h * ed; log2edmover = log2m * ed; log2edlover = log2l * ed; /* It may be necessary to renormalize the tabulated value (multiplied by ed) before adding the to the log(y)-result If needed, uncomment the following Renormalize3-Statement and comment out the copies following it. */ /* Renormalize3(&log2edh, &log2edm, &log2edl, log2edhover, log2edmover, log2edlover); */ log2edh = log2edhover; log2edm = log2edmover; log2edl = log2edlover; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, logyh, logym, logyl); /* Since we can not guarantee in each addition and multiplication procedure that the results are not overlapping, we must renormalize the result before handing it over to the final rounding */ Renormalize3(logh,logm,logl,loghover,logmover,loglover); } /************************************************************* ************************************************************* * ROUNDED TO NEAREST * ************************************************************* *************************************************************/ double log_rn(double x){ db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, logl, roundcst; int E, index; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = ROUNDCST1; else roundcst = ROUNDCST2; if(logh == (logh + (logm * roundcst))) return logh; else { #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log_td_accurate(&logh, &logm, &logl, E, ed, index, zh, zl, logih, logim); ReturnRoundToNearest3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED UPWARDS * ************************************************************* *************************************************************/ double log_ru(double x) { db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, logl, roundcst; int E, index; if (x == 1.0) return 0.0; /* This the only case in which the image under log of a double is a double. */ E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RU(logh, logm, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log_td_accurate(&logh, &logm, &logl, E, ed, index, zh, zl, logih, logim); ReturnRoundUpwards3(logh, logm, logl); } /************************************************************* ************************************************************* * ROUNDED DOWNWARDS * ************************************************************* *************************************************************/ double log_rd(double x) { db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, logl, roundcst; int E, index; if (x == 1.0) return 0.0; /* This the only case in which the image under log of a double is a double. */ E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RD(logh, logm, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log_td_accurate(&logh, &logm, &logl, E, ed, index, zh, zl, logih, logim); ReturnRoundDownwards3(logh, logm, logl); } /************************************************************* ************************************************************* * ROUNDED TOWARDS ZERO * ************************************************************* *************************************************************/ double log_rz(double x) { db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, logl, roundcst; int E, index; if (x == 1.0) return 0.0; /* This the only case in which the image under log of a double is a double. */ E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RZ(logh, logm, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log_td_accurate(&logh, &logm, &logl, E, ed, index, zh, zl, logih, logim); ReturnRoundTowardsZero3(logh, logm, logl); } #ifdef BUILD_INTERVAL_FUNCTIONS interval j_log(interval x) { interval res; int roundable; int cs_inf=0; int cs_sup=0; double x_inf,x_sup; x_inf=LOW(x); x_sup=UP(x); double res_inf, res_sup, res_simple_inf, res_simple_sup; db_number xdb_sup; double y_sup, ed_sup, ri_sup, logih_sup, logim_sup, yrih_sup, yril_sup, th_sup, zh_sup, zl_sup; double polyHorner_sup, zhSquareh_sup, zhSquarel_sup, polyUpper_sup, zhSquareHalfh_sup, zhSquareHalfl_sup; double t1h_sup, t1l_sup, t2h_sup, t2l_sup, ph_sup, pl_sup, log2edh_sup, log2edl_sup, logTabPolyh_sup, logTabPolyl_sup, logh_sup, logm_sup, logl_sup, roundcst; int E_sup, index_sup; db_number xdb_inf; double y_inf, ed_inf, ri_inf, logih_inf, logim_inf, yrih_inf, yril_inf, th_inf, zh_inf, zl_inf; double polyHorner_inf, zhSquareh_inf, zhSquarel_inf, polyUpper_inf, zhSquareHalfh_inf, zhSquareHalfl_inf; double t1h_inf, t1l_inf, t2h_inf, t2l_inf, ph_inf, pl_inf, log2edh_inf, log2edl_inf, logTabPolyh_inf, logTabPolyl_inf, logh_inf, logm_inf, logl_inf; int E_inf, index_inf; E_inf=0; xdb_inf.d=x_inf; E_sup=0; xdb_sup.d=x_sup; if (__builtin_expect( (x_inf == 1.0) || (!(x_inf<=x_sup)) || (xdb_sup.i[HI] < 0) || (xdb_inf.i[HI] < 0x00100000) || (((xdb_inf.i[HI] & 0x7fffffff)|xdb_inf.i[LO])==0) || (xdb_inf.i[HI] < 0) || (xdb_inf.i[HI] >= 0x7ff00000) || (x_sup == 1.0) || (xdb_sup.i[HI] < 0x00100000) || (((xdb_sup.i[HI] & 0x7fffffff)|xdb_sup.i[LO])==0) || (xdb_sup.i[HI] < 0) || (xdb_sup.i[HI] >= 0x7ff00000) || ((xdb_inf.d<00) && (xdb_sup.d>0) ) ,FALSE)) { if (!(x_inf<=x_sup)) RETURN_EMPTY_INTERVAL; if (xdb_sup.i[HI] < 0) RETURN_EMPTY_INTERVAL; if ((xdb_inf.d<00) && (xdb_sup.d>0) ) { ASSIGN_LOW(res,-1.0/0.0); ASSIGN_UP(res,log_ru(UP(x))); return res; } ASSIGN_LOW(res,log_rd(LOW(x))); ASSIGN_UP(res,log_ru(UP(x))); return res; } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E_inf += (xdb_inf.i[HI]>>20)-1023; /* extract the exponent */ E_sup += (xdb_sup.i[HI]>>20)-1023; /* extract the exponent */ index_inf = (xdb_inf.i[HI] & 0x000fffff); index_sup = (xdb_sup.i[HI] & 0x000fffff); xdb_inf.i[HI] = index_inf | 0x3ff00000; /* do exponent = 0 */ xdb_sup.i[HI] = index_sup | 0x3ff00000; /* do exponent = 0 */ index_inf = (index_inf + (1<<(20-L-1))) >> (20-L); index_sup = (index_sup + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index_inf >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb_inf.i[HI] -= 0x00100000; E_inf++; } /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index_sup >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb_sup.i[HI] -= 0x00100000; E_sup++; } y_inf = xdb_inf.d; y_sup = xdb_sup.d; index_inf = index_inf & INDEXMASK; index_sup = index_sup & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed_inf = (double) E_inf; ed_sup = (double) E_sup; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri_inf = argredtable[index_inf].ri; ri_sup = argredtable[index_sup].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih_inf = argredtable[index_inf].logih; logih_sup = argredtable[index_sup].logih; logim_inf = argredtable[index_inf].logim; logim_sup = argredtable[index_sup].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih_inf, &yril_inf, y_inf, ri_inf); Mul12(&yrih_sup, &yril_sup, y_sup, ri_sup); th_inf = yrih_inf - 1.0; th_sup = yrih_sup - 1.0; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Add12Cond(zh_inf, zl_inf, th_inf, yril_inf); Add12Cond(zh_sup, zl_sup, th_sup, yril_sup); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner_inf = FMA(FMA(FMA(FMA(c7,zh_inf,c6),zh_inf,c5),zh_inf,c4),zh_inf,c3); polyHorner_sup = FMA(FMA(FMA(FMA(c7,zh_sup,c6),zh_sup,c5),zh_sup,c4),zh_sup,c3); #else polyHorner_inf = c3 + zh_inf * (c4 + zh_inf * (c5 + zh_inf * (c6 + zh_inf * c7))); polyHorner_sup = c3 + zh_sup * (c4 + zh_sup * (c5 + zh_sup * (c6 + zh_sup * c7))); #endif Mul12(&zhSquareh_inf, &zhSquarel_inf, zh_inf, zh_inf); Mul12(&zhSquareh_sup, &zhSquarel_sup, zh_sup, zh_sup); polyUpper_inf = polyHorner_inf * (zh_inf * zhSquareh_inf); polyUpper_sup = polyHorner_sup * (zh_sup * zhSquareh_sup); zhSquareHalfh_inf = zhSquareh_inf * -0.5; zhSquareHalfh_sup = zhSquareh_sup * -0.5; zhSquareHalfl_inf = zhSquarel_inf * -0.5; zhSquareHalfl_sup = zhSquarel_sup * -0.5; Add12(t1h_inf, t1l_inf, polyUpper_inf, -1 * (zh_inf * zl_inf)); Add12(t1h_sup, t1l_sup, polyUpper_sup, -1 * (zh_sup * zl_sup)); Add22(&t2h_inf, &t2l_inf, zh_inf, zl_inf, zhSquareHalfh_inf, zhSquareHalfl_inf); Add22(&t2h_sup, &t2l_sup, zh_sup, zl_sup, zhSquareHalfh_sup, zhSquareHalfl_sup); Add22(&ph_inf, &pl_inf, t2h_inf, t2l_inf, t1h_inf, t1l_inf); Add22(&ph_sup, &pl_sup, t2h_sup, t2l_sup, t1h_sup, t1l_sup); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh_inf, log2edl_inf, log2h * ed_inf, log2m * ed_inf); /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh_sup, log2edl_sup, log2h * ed_sup, log2m * ed_sup); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh_inf, &logTabPolyl_inf, logih_inf, logim_inf, ph_inf, pl_inf); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh_inf, &logm_inf, log2edh_inf, log2edl_inf, logTabPolyh_inf, logTabPolyl_inf); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh_sup, &logTabPolyl_sup, logih_sup, logim_sup, ph_sup, pl_sup); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh_sup, &logm_sup, log2edh_sup, log2edl_sup, logTabPolyh_sup, logTabPolyl_sup); /* Rounding test and eventual return or call to the accurate function */ roundcst = RDROUNDCST1; if(cs_inf) { res_inf=res_simple_inf; } if(cs_sup) { res_sup=res_simple_sup; } //TEST_AND_COPY_RDRU_LOG(roundable,res_inf,logh_inf,logm_inf,res_sup,logh_sup,logm_sup,roundcst); //#define TEST_AND_COPY_RDRU_LOG(__cond__, __res_inf__, __yh_inf__, __yl_inf__, __res_sup__, __yh_sup__, __yl_sup__, __eps__) db_number yh_inf, yl_inf, u53_inf, yh_sup, yl_sup, u53_sup; int yh_inf_neg, yl_inf_neg, yh_sup_neg, yl_sup_neg; int rd_ok, ru_ok; double save_res_inf=res_inf; yh_inf.d = logh_inf; yl_inf.d = logm_inf; yh_inf_neg = (yh_inf.i[HI] & 0x80000000); yl_inf_neg = (yl_inf.i[HI] & 0x80000000); yh_inf.l = yh_inf.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ yl_inf.l = yl_inf.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ u53_inf.l = (yh_inf.l & ULL(7ff0000000000000)) + ULL(0010000000000000); yh_sup.d = logh_sup; yl_sup.d = logm_sup; yh_sup_neg = (yh_sup.i[HI] & 0x80000000); yl_sup_neg = (yl_sup.i[HI] & 0x80000000); yh_sup.l = yh_sup.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ yl_sup.l = yl_sup.l & 0x7fffffffffffffffLL; /* compute the absolute value*/ u53_sup.l = (yh_sup.l & ULL(7ff0000000000000)) + ULL(0010000000000000); roundable = 0; rd_ok=(yl_inf.d > roundcst * u53_inf.d); ru_ok=(yl_sup.d > roundcst * u53_sup.d); if(yl_inf_neg) { /* The case yl==0 is filtered by the above test*/ /* return next down */ yh_inf.d = logh_inf; if(yh_inf_neg) yh_inf.l++; else yh_inf.l--; /* Beware: fails for zero */ res_inf = yh_inf.d ; } else { res_inf = logh_inf; } if(!yl_sup_neg) { /* The case yl==0 is filtered by the above test*/ /* return next up */ yh_sup.d = logh_sup; if(yh_sup_neg) yh_sup.l--; else yh_sup.l++; /* Beware: fails for zero */ res_sup = yh_sup.d ; } else { res_sup = logh_sup; } if(save_res_inf==-1.0/0.0) res_inf=-1.0/0.0; if(rd_ok && ru_ok){ ASSIGN_LOW(res,res_inf); ASSIGN_UP(res,res_sup); return(res); } else if (rd_ok){ roundable=1; } else if (ru_ok){ roundable=2; } #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif if (roundable==1) { log_td_accurate(&logh_sup, &logm_sup, &logl_sup, E_sup, ed_sup, index_sup, zh_sup, zl_sup, logih_sup, logim_sup); RoundUpwards3(&res_sup, logh_sup, logm_sup, logl_sup); } if (roundable==2) { log_td_accurate(&logh_inf, &logm_inf, &logl_inf, E_inf, ed_inf, index_inf, zh_inf, zl_inf, logih_inf, logim_inf); RoundDownwards3(&res_inf, logh_inf, logm_inf, logl_inf); } if (roundable==0) { log_td_accurate(&logh_inf, &logm_inf, &logl_inf, E_inf, ed_inf, index_inf, zh_inf, zl_inf, logih_inf, logim_inf); RoundDownwards3(&res_inf, logh_inf, logm_inf, logl_inf); log_td_accurate(&logh_sup, &logm_sup, &logl_sup, E_sup, ed_sup, index_sup, zh_sup, zl_sup, logih_sup, logim_sup); RoundUpwards3(&res_sup, logh_sup, logm_sup, logl_sup); } ASSIGN_LOW(res,res_inf); ASSIGN_UP(res,res_sup); return res; } #endif interval-3.2.0/src/crlibm/log-td.h0000644000000000000000000013141613316017127015073 0ustar 00000000000000/* * This function computes log, correctly rounded, * using triple double arithmetics * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" /*File generated by maple/log-td.mpl*/ #define L 7 #define MAXINDEX 53 #define INDEXMASK 127 #define two52 4.50359962737049600000000000000000000000000000000000e+15 #define log2h 6.93147180559890330187045037746429443359375000000000e-01 #define log2m 5.49792301870850242169664946507035702127907939029683e-14 #define log2l -1.31246984177852556920995753667322295879593697972250e-27 #define ROUNDCST1 1.00277296776935912123020172797003775857085744686284e+00 #define ROUNDCST2 1.00277296776935912123020172797003775857085744686284e+00 #define RDROUNDCST1 1.53329341668337408143884997262066747209318683475599e-19 #define RDROUNDCST2 1.53329341668337408143884997262066747209318683475599e-19 #define c3 3.33333333333333370340767487505218014121055603027344e-01 #define c4 -2.49999999990904886448817023847368545830249786376953e-01 #define c5 1.99999999978980019799124079327157232910394668579102e-01 #define c6 -1.66669050883027802800739891608827747404575347900391e-01 #define c7 1.42860109897981618631845890377007890492677688598633e-01 #define accPolyC3h 3.33333333333333314829616256247390992939472198486328e-01 #define accPolyC3l 1.85037170770859413132312241283212169118117639547054e-17 #define accPolyC4h -2.50000000000000000000000000000000000000000000000000e-01 #define accPolyC4l 4.62199018306924685334006418421322154174127637249391e-33 #define accPolyC5h 2.00000000000000011102230246251565404236316680908203e-01 #define accPolyC5l -1.11022302443127785678379338452126964515833173338601e-17 #define accPolyC6h -1.66666666666666657414808128123695496469736099243164e-01 #define accPolyC6l -9.25185854591372488017120157358742564605503054108327e-18 #define accPolyC7h 1.42857142857142849212692681248881854116916656494141e-01 #define accPolyC7l 7.92868209382438390589949095717120486682310988838960e-18 #define accPolyC8h -1.25000000000000000000000000000000000000000000000000e-01 #define accPolyC8l 3.42769668947376590645174407718339199260639267364101e-21 #define accPolyC9h 1.11111111111111521276839653182832989841699600219727e-01 #define accPolyC9l 4.33331955380787609416227741118274520376899199903317e-18 #define accPolyC10 -1.00000000000000699440505513848620466887950897216797e-01 #define accPolyC11 9.09090908567022348840680479042930528521537780761719e-02 #define accPolyC12 -8.33333332642126056732934102910803630948066711425781e-02 #define accPolyC13 7.69261287585959879775643344146374147385358810424805e-02 #define accPolyC14 -7.14319092953022982683819464000407606363296508789062e-02 typedef struct rri_tag {float ri; double logih; double logim; double logil;} rri; static const rri argredtable[128] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* r[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logih[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logim[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logil[0] */ } , { 9.92248058319091796875000000000000000000000000000000e-01, /* r[1] */ 7.78214416734525436109004559170898573938757181167603e-03, /* logih[1] */ -1.28191618904143681948935996668824218266800862156024e-20, /* logim[1] */ 1.17655068600225378123891861200215069271455859581641e-37, /* logil[1] */ } , { 9.84615325927734375000000000000000000000000000000000e-01, /* r[2] */ 1.55042461406118062261505485821544425562024116516113e-02, /* logih[2] */ -3.27761516207149627029928635703400435929630184221293e-19, /* logim[2] */ 2.95200020707030964072253388818190769795416371257942e-37, /* logil[2] */ } , { 9.77099180221557617187500000000000000000000000000000e-01, /* r[3] */ 2.31671170235356708999585606534310500137507915496826e-02, /* logih[3] */ 5.57833156048330069504471566938468802334954100224869e-19, /* logim[3] */ 4.08416064054113313191746248503653555682943539201798e-35, /* logil[3] */ } , { 9.69696998596191406250000000000000000000000000000000e-01, /* r[4] */ 3.07716288644317437217523547587916254997253417968750e-02, /* logih[4] */ 1.04316437964092669923942103072089812062131860035492e-18, /* logim[4] */ -8.26837774892530079043982861155759865584698067912967e-36, /* logil[4] */ } , { 9.62406039237976074218750000000000000000000000000000e-01, /* r[5] */ 3.83188391564273991840572364253603154793381690979004e-02, /* logih[5] */ 1.54512636366303706650320890230224472259662656606095e-18, /* logim[5] */ 8.30977110244055528389241824578843983429633068152463e-35, /* logil[5] */ } , { 9.55223917961120605468750000000000000000000000000000e-01, /* r[6] */ 4.58094969157468376308450785927561810240149497985840e-02, /* logih[6] */ -3.30123051072550842868548428055668582607719074881820e-18, /* logim[6] */ 1.64164772626574162996727598513545022472742050176492e-34, /* logil[6] */ } , { 9.48148131370544433593750000000000000000000000000000e-01, /* r[7] */ 5.32445322139413548812036935942160198464989662170410e-02, /* logih[7] */ 2.23755385085953619415254057336256700540433618368589e-18, /* logim[7] */ -9.41330315099866735037984721876103977945647219756033e-35, /* logil[7] */ } , { 9.41176414489746093750000000000000000000000000000000e-01, /* r[8] */ 6.06246814210813916856679384181916248053312301635742e-02, /* logih[8] */ 2.64247317995478646334926909653435556549332769494295e-18, /* logim[8] */ 1.55075207452234839722600788456166299408429635417895e-34, /* logil[8] */ } , { 9.34306621551513671875000000000000000000000000000000e-01, /* r[9] */ 6.79506060291548280583029395529592875391244888305664e-02, /* logih[9] */ 5.65862161871167282533541105359923619273100535513035e-18, /* logim[9] */ -3.57889357320249912090032102867532919048871786355064e-34, /* logil[9] */ } , { 9.27536249160766601562500000000000000000000000000000e-01, /* r[10] */ 7.52234026111362058530929175503842998296022415161133e-02, /* logih[10] */ 1.00828755349783911736541446332784521904773238841865e-18, /* logim[10] */ 7.77966415828014771486738038255868010153689429282538e-36, /* logil[10] */ } , { 9.20863270759582519531250000000000000000000000000000e-01, /* r[11] */ 8.24437111205913314426751981045526918023824691772461e-02, /* logih[11] */ -4.27419767632228646217014766651675738804062364961374e-18, /* logim[11] */ 3.58539257549786746072726449331073277906948658046759e-34, /* logil[11] */ } , { 9.14285659790039062500000000000000000000000000000000e-01, /* r[12] */ 8.96122182943336897942288032936630770564079284667969e-02, /* logih[12] */ -5.42674234758262048883730612286095846547194397615989e-18, /* logim[12] */ -7.94903110897686868047461590865098481976776339992810e-35, /* logil[12] */ } , { 9.07801389694213867187500000000000000000000000000000e-01, /* r[13] */ 9.67296581235191493819414176869031507521867752075195e-02, /* logih[13] */ 1.17499431052084706890372286741885325822732164697539e-18, /* logim[13] */ -7.47188021694240554877009439429630012902672969107896e-35, /* logil[13] */ } , { 9.01408433914184570312500000000000000000000000000000e-01, /* r[14] */ 1.03796812308095232069149460585322231054306030273438e-01, /* logih[14] */ -1.46116759252442942691327623497388991415382979093093e-18, /* logim[14] */ -5.84766064918572844473631496354606243606272630720064e-35, /* logil[14] */ } , { 8.95104885101318359375000000000000000000000000000000e-01, /* r[15] */ 1.10814377516161077785739053069846704602241516113281e-01, /* logih[15] */ -5.75514509579248124656596649605847554012818793702281e-18, /* logim[15] */ 3.29977719536339952907783192540462408052319847426319e-34, /* logil[15] */ } , { 8.88888835906982421875000000000000000000000000000000e-01, /* r[16] */ 1.17783095261030007483427084480354096740484237670898e-01, /* logih[16] */ -1.19709798867727449215060005668653850880775796697715e-18, /* logim[16] */ 8.04222018353684236067064017226062133396406008492921e-35, /* logil[16] */ } , { 8.82758617401123046875000000000000000000000000000000e-01, /* r[17] */ 1.24703482226247538977581541530526010319590568542480e-01, /* logih[17] */ 2.28663295749049514726834658528273231115811065734312e-18, /* logim[17] */ -3.51123005875932392272239647660221882537057244586168e-35, /* logil[17] */ } , { 8.76712322235107421875000000000000000000000000000000e-01, /* r[18] */ 1.31576365239299886145118989588809199631214141845703e-01, /* logih[18] */ 1.11230010175930229418362785876222391520299564865730e-17, /* logim[18] */ 7.27451645836749926637643602480531900716806359121297e-34, /* logil[18] */ } , { 8.70748281478881835937500000000000000000000000000000e-01, /* r[19] */ 1.38402343348215994822680841025430709123611450195312e-01, /* logih[19] */ -7.69528416335144553864151614176326744245393995127969e-18, /* logim[19] */ 1.14202629230472885861778260955781649682548331183808e-34, /* logil[19] */ } , { 8.64864826202392578125000000000000000000000000000000e-01, /* r[20] */ 1.45182054547982469783207193358975928276777267456055e-01, /* logih[20] */ 8.24244856152552570070228105635897158979868211170798e-18, /* logim[20] */ -6.13072808770694892835379995250538817854995507648779e-34, /* logil[20] */ } , { 8.59060406684875488281250000000000000000000000000000e-01, /* r[21] */ 1.51916037369229123266123337998578790575265884399414e-01, /* logih[21] */ -1.04296908000297145574171199957656893307239877379000e-17, /* logim[21] */ -5.53636436435840586444373230094200986769217138540854e-34, /* logil[21] */ } , { 8.53333353996276855468750000000000000000000000000000e-01, /* r[22] */ 1.58605005962251938145257668111298698931932449340820e-01, /* logih[22] */ -8.86065192248216377790637508171938194510660992474042e-19, /* logim[22] */ -5.87995214834401673695486864800931832452468264932844e-35, /* logil[22] */ } , { 8.47682118415832519531250000000000000000000000000000e-01, /* r[23] */ 1.65249573826629747586025587224867194890975952148438e-01, /* logih[23] */ -9.66125475305916070790888958698289394696700966750453e-18, /* logim[23] */ 1.22853647999759344001960461047755491313341721869856e-34, /* logil[23] */ } , { 8.42105269432067871093750000000000000000000000000000e-01, /* r[24] */ 1.71850249476078659194300257695431355386972427368164e-01, /* logih[24] */ -6.02245395887480538795512923412250309472746231920746e-18, /* logim[24] */ 1.52961687917434402329553899350235008490821862631877e-34, /* logil[24] */ } , { 8.36601257324218750000000000000000000000000000000000e-01, /* r[25] */ 1.78407717077464861299418430462537799030542373657227e-01, /* logih[25] */ -1.24324832026190372515095573175819374097319572461178e-17, /* logim[25] */ -5.99222696564577786410580709003476847421843326905428e-34, /* logil[25] */ } , { 8.31168889999389648437500000000000000000000000000000e-01, /* r[26] */ 1.84922267713498816865680396404059138149023056030273e-01, /* logih[26] */ 9.96243711860796179875713739627414673019270693540839e-18, /* logim[26] */ -1.99546782893888540832510298706525540082513642365204e-34, /* logil[26] */ } , { 8.25806498527526855468750000000000000000000000000000e-01, /* r[27] */ 1.91394796188954025017991966706176754087209701538086e-01, /* logih[27] */ -8.22643020277300444045205706293674132131812201700538e-18, /* logim[27] */ 5.69056030867564774930537188285078930441778787828211e-34, /* logil[27] */ } , { 8.20512771606445312500000000000000000000000000000000e-01, /* r[28] */ 1.97825802934566419288842098467284813523292541503906e-01, /* logih[28] */ 1.28212649590622342007825921152819823725126964367518e-17, /* logim[28] */ 4.34712978477783827374998481132430084872238812357849e-34, /* logil[28] */ } , { 8.15286636352539062500000000000000000000000000000000e-01, /* r[29] */ 2.04215526527529805944638496839615982025861740112305e-01, /* logih[29] */ 2.73382699896480606605004885268461286375739934002155e-18, /* logim[29] */ 1.88415596219599490517606146615135776386751947516623e-34, /* logil[29] */ } , { 8.10126543045043945312500000000000000000000000000000e-01, /* r[30] */ 2.10564817536124687658016796376614365726709365844727e-01, /* logih[30] */ 2.68952644992466202072392146799884466396384136175691e-18, /* logim[30] */ -1.58883120037037559046153789501260274259127656480088e-34, /* logil[30] */ } , { 8.05031418800354003906250000000000000000000000000000e-01, /* r[31] */ 2.16873972759550226463431954471161589026451110839844e-01, /* logih[31] */ -1.23625140584833845652640860288020787431726668393088e-17, /* logim[31] */ -1.28369360755661214950804825668450767372141502246786e-34, /* logil[31] */ } , { 7.99999952316284179687500000000000000000000000000000e-01, /* r[32] */ 2.23143610918856316605030087885097600519657135009766e-01, /* logih[32] */ -9.09120001124270523314725361445863555491966823753373e-18, /* logim[32] */ 1.15945802868784933647836819275496182741822080543604e-34, /* logil[32] */ } , { 7.95031070709228515625000000000000000000000000000000e-01, /* r[33] */ 2.29374082438394522043267897970508784055709838867188e-01, /* logih[33] */ -1.08890120418598083770448590672876580941469212582837e-17, /* logim[33] */ 4.74877924128943438272197143958394008126523960202900e-34, /* logil[33] */ } , { 7.90123462677001953125000000000000000000000000000000e-01, /* r[34] */ 2.35566063862186342303672859088692348450422286987305e-01, /* logih[34] */ -2.39433728738216998660812173360881116827035967139939e-18, /* logim[34] */ -9.62471867414270770251397101906428335828045927610883e-35, /* logil[34] */ } , { 7.85276055335998535156250000000000000000000000000000e-01, /* r[35] */ 2.41719960170209802186036540661007165908813476562500e-01, /* logih[35] */ 2.39578119451184969695376143676233310543075971208880e-18, /* logim[35] */ 1.86231935097448741662637615288316997021879162207127e-34, /* logil[35] */ } , { 7.80487775802612304687500000000000000000000000000000e-01, /* r[36] */ 2.47836201157484947721343360171886160969734191894531e-01, /* logih[36] */ -1.24321923457726137680465119406863072977770725701004e-17, /* logim[36] */ -2.09577513970149680056365167860895085898294691979404e-34, /* logil[36] */ } , { 7.75757551193237304687500000000000000000000000000000e-01, /* r[37] */ 2.53915241645931488712051304901251569390296936035156e-01, /* logih[37] */ -6.31336333527435824035156315376733999545148217960567e-18, /* logim[37] */ 4.63496313971202069379055986715253908538961883067566e-35, /* logil[37] */ } , { 7.71084308624267578125000000000000000000000000000000e-01, /* r[38] */ 2.59957561689829752538116736104711890220642089843750e-01, /* logih[38] */ -7.05748899290965383754297836711168798219001736647281e-18, /* logim[38] */ 4.27245447011230141916526741370315150982259792796987e-34, /* logil[38] */ } , { 7.66467094421386718750000000000000000000000000000000e-01, /* r[39] */ 2.65963511244235673025571031757863238453865051269531e-01, /* logih[39] */ -2.24162125724264292804912034054420308588570407662844e-17, /* logim[39] */ 4.90471140265143981765909599584287898945638617268867e-34, /* logil[39] */ } , { 7.61904716491699218750000000000000000000000000000000e-01, /* r[40] */ 2.71933775088288309795814257086021825671195983886719e-01, /* logih[40] */ 7.83390223779535346513505580003968001040971161798700e-19, /* logim[40] */ -3.02585215101390470982866376614279464778757620082138e-35, /* logil[40] */ } , { 7.57396459579467773437500000000000000000000000000000e-01, /* r[41] */ 2.77868437964940373507971571598318405449390411376953e-01, /* logih[41] */ -2.69368711734232128278453248569958166651302969280381e-17, /* logim[41] */ 1.27334496810554064003001771076892864921428144153570e-33, /* logil[41] */ } , { 7.52941131591796875000000000000000000000000000000000e-01, /* r[42] */ 2.83768232735291170421021433867281302809715270996094e-01, /* logih[42] */ -2.03265852251844689554711830689719609838328388091381e-17, /* logim[42] */ 3.99265876662456660849597520210659365811534845502505e-34, /* logil[42] */ } , { 7.48538017272949218750000000000000000000000000000000e-01, /* r[43] */ 2.89633285132462114930262941925320774316787719726562e-01, /* logih[43] */ -7.21962253363417273270454867455071277489833577725373e-18, /* logim[43] */ -2.16150227221931053192432009592422674631830770048369e-34, /* logil[43] */ } , { 7.44186043739318847656250000000000000000000000000000e-01, /* r[44] */ 2.95464216619126196494704572614864446222782135009766e-01, /* logih[44] */ -1.47072146829197428851717511710908602721304319475328e-17, /* logim[44] */ 4.88114627787723832872543510409367916590649903129304e-34, /* logil[44] */ } , { 7.39884376525878906250000000000000000000000000000000e-01, /* r[45] */ 3.01261352929903802877475982313626445829868316650391e-01, /* logih[45] */ 1.87070681938931680167624656750430985298856099421569e-17, /* logim[45] */ 1.51413799416501325421897094776870076323182009328971e-33, /* logil[45] */ } , { 7.35632181167602539062500000000000000000000000000000e-01, /* r[46] */ 3.07025039020202172856954803137341514229774475097656e-01, /* logih[46] */ -5.38102227896180596526923200171118043417676846319102e-18, /* logim[46] */ 2.06712483430759996475892191286335029882052180959917e-34, /* logil[46] */ } , { 7.31428623199462890625000000000000000000000000000000e-01, /* r[47] */ 3.12755639223383730129768309780047275125980377197266e-01, /* logih[47] */ -7.57930782773895721056011815787401170737920404028723e-18, /* logim[47] */ 8.39475110593319988799512618628582752750846924050440e-35, /* logil[47] */ } , { 7.27272748947143554687500000000000000000000000000000e-01, /* r[48] */ 3.18453701316212645089365196326980367302894592285156e-01, /* logih[48] */ 2.71147705440665649189983820006370647423267349507715e-17, /* logim[48] */ 4.61673001741568050305139864943649666789926072891368e-34, /* logil[48] */ } , { 7.23163843154907226562500000000000000000000000000000e-01, /* r[49] */ 3.24119466791566834817928111078799702227115631103516e-01, /* logih[49] */ -6.22349090807112113628215383245238541760656175683922e-18, /* logim[49] */ -2.94864944946984528585289533414905600786096792764282e-34, /* logil[49] */ } , { 7.19101071357727050781250000000000000000000000000000e-01, /* r[50] */ 3.29753359015631464234985514849540777504444122314453e-01, /* logih[50] */ -2.38987037434306035496609341036867889075145964580121e-17, /* logim[50] */ -1.22161021411351376080765213758661026982900357467596e-33, /* logil[50] */ } , { 7.15083837509155273437500000000000000000000000000000e-01, /* r[51] */ 3.35355487904429983014864546930766664445400238037109e-01, /* logih[51] */ -2.15530481136091842439480783176785939188081961777809e-17, /* logim[51] */ 5.65377778536716902900522531845470344712374772157319e-34, /* logil[51] */ } , { 7.11111068725585937500000000000000000000000000000000e-01, /* r[52] */ 3.40926646575239744585417156486073508858680725097656e-01, /* logih[52] */ 1.74672070296268393919501631375949801326271042364782e-17, /* logim[52] */ 1.28757784323920807504216254145051967795248381758825e-33, /* logil[52] */ } , { 1.41436457633972167968750000000000000000000000000000e+00, /* r[53] */ -3.46680367578929504723816990008344873785972595214844e-01, /* logih[53] */ -2.63487075436177288054440686474043695042741778901884e-17, /* logim[53] */ -1.38972774108545698123375234719775474495262622652200e-33, /* logil[53] */ } , { 1.40659332275390625000000000000000000000000000000000e+00, /* r[54] */ -3.41170697798120592381110327551141381263732910156250e-01, /* logih[54] */ 1.93668606486849623510457675345565515553170548397263e-17, /* logim[54] */ -6.31924577586791945681481090971933602378723267089765e-34, /* logil[54] */ } , { 1.39890718460083007812500000000000000000000000000000e+00, /* r[55] */ -3.35691349380139503200126682713744230568408966064453e-01, /* logih[55] */ 8.91843232308579533655667936963342665384096382048557e-18, /* logim[55] */ -7.43852632990846244963757376301756885994340719135686e-34, /* logil[55] */ } , { 1.39130425453186035156250000000000000000000000000000e+00, /* r[56] */ -3.30241619815349218836075806393637321889400482177734e-01, /* logih[56] */ -1.69271534756955752333877800530082817995576241189249e-17, /* logim[56] */ -2.05124125474152062675126703058085713735683777118919e-34, /* logil[56] */ } , { 1.38378381729125976562500000000000000000000000000000e+00, /* r[57] */ -3.24821643615624322531942880232236348092555999755859e-01, /* logih[57] */ 1.93287622140617006961244731990086787828970688523722e-17, /* logim[57] */ -1.40211415833516824405184666805315188814704601258065e-33, /* logil[57] */ } , { 1.37634420394897460937500000000000000000000000000000e+00, /* r[58] */ -3.19430856448034428130000605960958637297153472900391e-01, /* logih[58] */ 5.58442737360353866559969930374464901851229137435661e-18, /* logim[58] */ -2.25313306148742433454599602113064828727792769150620e-34, /* logil[58] */ } , { 1.36898398399353027343750000000000000000000000000000e+00, /* r[59] */ -3.14068847182749744106899925100151449441909790039062e-01, /* logih[59] */ 1.74087330539322720259314067705480812845274240645592e-17, /* logim[59] */ 2.87763442397890459672608687761118393908121210479900e-34, /* logil[59] */ } , { 1.36170220375061035156250000000000000000000000000000e+00, /* r[60] */ -3.08735537528966208498104606405831873416900634765625e-01, /* logih[60] */ 2.31380218279209479391607966489385619371870731511261e-17, /* logim[60] */ 5.75649697670342883220331709767832654878804183961435e-34, /* logil[60] */ } , { 1.35449743270874023437500000000000000000000000000000e+00, /* r[61] */ -3.03430487161918061023158088573836721479892730712891e-01, /* logih[61] */ 5.88591784280850309549180895879864991445414905765635e-18, /* logim[61] */ 3.80740105286783019924475997846877792541810370319751e-34, /* logil[61] */ } , { 1.34736847877502441406250000000000000000000000000000e+00, /* r[62] */ -2.98153415159913837140237546918797306716442108154297e-01, /* logih[62] */ -8.81391967432414632609646763074561636922040597203571e-18, /* logim[62] */ -2.02736910549706342663167850737697734462522018249963e-34, /* logil[62] */ } , { 1.34031414985656738281250000000000000000000000000000e+00, /* r[63] */ -2.92904026677480888718463347686338238418102264404297e-01, /* logih[63] */ 1.79356774462556308958502912313675336181211584010969e-17, /* logim[63] */ 1.02350086185905899058999882149766002774623879978153e-34, /* logil[63] */ } , { 1.33333325386047363281250000000000000000000000000000e+00, /* r[64] */ -2.87682012847134349620148441317724063992500305175781e-01, /* logih[64] */ -2.60715355783435444041951693925565689223533295668838e-17, /* logim[64] */ -9.83372234709377378449141028490939682198507140512540e-34, /* logil[64] */ } , { 1.32642483711242675781250000000000000000000000000000e+00, /* r[65] */ -2.82487230428967117656924301627441309392452239990234e-01, /* logih[65] */ 2.49452771019268745755792758464310261659699707675018e-17, /* logim[65] */ -1.40230272425562150522506576584140991296902734870694e-33, /* logil[65] */ } , { 1.31958770751953125000000000000000000000000000000000e+00, /* r[66] */ -2.77319345020877350282972884087939746677875518798828e-01, /* logih[66] */ 7.44521346975934828880026635948320543669274837358637e-18, /* logim[66] */ -5.41922476182319969711469733445405189836277342215443e-34, /* logil[66] */ } , { 1.31282043457031250000000000000000000000000000000000e+00, /* r[67] */ -2.72177826311169102080356196893262676894664764404297e-01, /* logih[67] */ -1.94604737767255604321061638736698666324990178271015e-17, /* logim[67] */ 4.93318792723831633917605655356651628446409622108869e-34, /* logil[67] */ } , { 1.30612254142761230468750000000000000000000000000000e+00, /* r[68] */ -2.67062856029558426396164350080653093755245208740234e-01, /* logih[68] */ 1.42676910305707233200559864526771082234384991613068e-17, /* logim[68] */ 9.40874014190123375853921812584677628111272401841540e-34, /* logil[68] */ } , { 1.29949235916137695312500000000000000000000000000000e+00, /* r[69] */ -2.61973695252477101202970288795768283307552337646484e-01, /* logih[69] */ -1.59130185496344773949627658712806321021374170989957e-17, /* logim[69] */ 2.05966526658843352548575822504612882857523370085076e-34, /* logil[69] */ } , { 1.29292941093444824218750000000000000000000000000000e+00, /* r[70] */ -2.56910505054635363020310023784986697137355804443359e-01, /* logih[70] */ -2.32939629151451727444770801596466641031683815428509e-17, /* logim[70] */ -1.43942742464573220634874496721239465737503205324375e-33, /* logil[70] */ } , { 1.28643226623535156250000000000000000000000000000000e+00, /* r[71] */ -2.51872701711453261808060233306605368852615356445312e-01, /* logih[71] */ -2.58573188266130078596915247890597291360969537163785e-17, /* logim[71] */ 3.36064630885731507350249551263037246653963144676932e-34, /* logil[71] */ } , { 1.27999997138977050781250000000000000000000000000000e+00, /* r[72] */ -2.46860055579783743695543307694606482982635498046875e-01, /* logih[72] */ -1.36174299951708605118822966558244798958741114531493e-17, /* logim[72] */ -8.23883896198784591738914635896001757021238114385808e-35, /* logil[72] */ } , { 1.27363181114196777343750000000000000000000000000000e+00, /* r[73] */ -2.41872513137422084916750009142560884356498718261719e-01, /* logih[73] */ -2.91827950997726014268071786281330008614392694540440e-18, /* logim[73] */ 8.66387628958027677722140876839269007945711340420961e-35, /* logil[73] */ } , { 1.26732683181762695312500000000000000000000000000000e+00, /* r[74] */ -2.36909825309450927655063878773944452404975891113281e-01, /* logih[74] */ 4.97049401191734143236484721843489954792294974449682e-18, /* logim[74] */ 2.12212094628219632031384179435720857347529888567725e-34, /* logil[74] */ } , { 1.26108384132385253906250000000000000000000000000000e+00, /* r[75] */ -2.31971542737545860513037609962339047342538833618164e-01, /* logih[75] */ 1.20064411563385414488688519726171456939870706105353e-17, /* logim[75] */ -5.20241965000144345106493348505238495111737026311766e-34, /* logil[75] */ } , { 1.25490188598632812500000000000000000000000000000000e+00, /* r[76] */ -2.27057391030699523559732710964453872293233871459961e-01, /* logih[76] */ -9.55134517665639461592830714479938653876650013848813e-18, /* logim[76] */ -7.00052160915705629865262646818211330004502638341784e-34, /* logil[76] */ } , { 1.24878048896789550781250000000000000000000000000000e+00, /* r[77] */ -2.22167466272476882283015697794326115399599075317383e-01, /* logih[77] */ 1.12308837854924459441805420173945034636561801020789e-17, /* logim[77] */ 1.05992689326800868505291338111574353445179905470698e-34, /* logil[77] */ } , { 1.24271845817565917968750000000000000000000000000000e+00, /* r[78] */ -2.17301285003207084178811214769666548818349838256836e-01, /* logih[78] */ -1.37599098464784711367545798871014398359913153389606e-17, /* logim[78] */ -5.44676947016522950876420214713413739910691265570885e-34, /* logil[78] */ } , { 1.23671507835388183593750000000000000000000000000000e+00, /* r[79] */ -2.12458734101899110457978281374380458146333694458008e-01, /* logih[79] */ 3.12575020468223244847667531342710056704202576314513e-18, /* logim[79] */ 1.27082738610098894087384580413567050181540844264548e-35, /* logil[79] */ } , { 1.23076915740966796875000000000000000000000000000000e+00, /* r[80] */ -2.07639305173597937814733427330793347209692001342773e-01, /* logih[80] */ -1.20531726306040366742269494142059745690218464556184e-17, /* logim[80] */ 3.33883514126655983920316543317695602289579500921493e-34, /* logil[80] */ } , { 1.22488045692443847656250000000000000000000000000000e+00, /* r[81] */ -2.02843253050716987306856253781006671488285064697266e-01, /* logih[81] */ -1.66453566992001313940518505696243672056063400746100e-18, /* logim[81] */ 2.78446239404510241881587234176263335863162887428131e-35, /* logil[81] */ } , { 1.21904754638671875000000000000000000000000000000000e+00, /* r[82] */ -1.98069854157447239328959653903439175337553024291992e-01, /* logih[82] */ -3.74277289637934596837745314540095849706853736054736e-18, /* logim[82] */ 2.20940287174632344749918330821286328950105212564345e-34, /* logil[82] */ } , { 1.21327018737792968750000000000000000000000000000000e+00, /* r[83] */ -1.93319348256398265695210625381150748580694198608398e-01, /* logih[83] */ -4.63045754803609100012916107813305239709411987466506e-18, /* logim[83] */ 3.81311992624323390610440652445847060246376140730432e-34, /* logil[83] */ } , { 1.20754718780517578125000000000000000000000000000000e+00, /* r[84] */ -1.88591184708711112616441596401273272931575775146484e-01, /* logih[84] */ 7.43216311628945500204739783937941202296964434266492e-18, /* logim[84] */ -4.02931080995428730719681936637527024502063366412999e-34, /* logil[84] */ } , { 1.20187783241271972656250000000000000000000000000000e+00, /* r[85] */ -1.83885194019779485419263664880418218672275543212891e-01, /* logih[85] */ 4.12613043545869607985270580107985887836449099592842e-18, /* logim[85] */ -1.13080344207561908198013613253456946184091830340475e-34, /* logil[85] */ } , { 1.19626164436340332031250000000000000000000000000000e+00, /* r[86] */ -1.79201397792742966874612875471939332783222198486328e-01, /* logih[86] */ 1.25197515140082668570664893296659406065442168045883e-17, /* logim[86] */ 2.08673445558311131685127966451011169090072111640797e-34, /* logil[86] */ } , { 1.19069766998291015625000000000000000000000000000000e+00, /* r[87] */ -1.74539412626609380385644954003510065376758575439453e-01, /* logih[87] */ 8.52219781255028950312107624449830634785785378861392e-18, /* logim[87] */ 5.46720442033771639415150684633589460164820712880324e-34, /* logil[87] */ } , { 1.18518519401550292968750000000000000000000000000000e+00, /* r[88] */ -1.69899044245978042555478282338299322873353958129883e-01, /* logih[88] */ 4.86800738580472456380134000450154397097303177737598e-19, /* logim[88] */ -4.48365665383134519709151659261825733866549119396251e-36, /* logil[88] */ } , { 1.17972350120544433593750000000000000000000000000000e+00, /* r[89] */ -1.65280090007780350314092743246874306350946426391602e-01, /* logih[89] */ 1.05991222445546499578510819426998369466676418510398e-18, /* logim[89] */ 2.15535973016890499002202117947684925307171077322261e-36, /* logil[89] */ } , { 1.17431187629699707031250000000000000000000000000000e+00, /* r[90] */ -1.60682338849634120947484916541725397109985351562500e-01, /* logih[90] */ 5.38493323815703006679696841052856196024573538758454e-18, /* logim[90] */ 1.60200163876329179080224417109933041789065267300895e-34, /* logil[90] */ } , { 1.16894984245300292968750000000000000000000000000000e+00, /* r[91] */ -1.56105775199027185795586092353914864361286163330078e-01, /* logih[91] */ 1.32405772531609804709122583998125231935523184710352e-17, /* logim[91] */ 4.88933388697666736600942679327919927438390701656817e-35, /* logil[91] */ } , { 1.16363644599914550781250000000000000000000000000000e+00, /* r[92] */ -1.51549968907714105448292229993967339396476745605469e-01, /* logih[92] */ 1.77181633478899593214922561799512844823326841018122e-18, /* logim[92] */ 5.44951453107128861626798538797020344311568819287008e-35, /* logil[92] */ } , { 1.15837097167968750000000000000000000000000000000000e+00, /* r[93] */ -1.47014683357163111754317696977523155510425567626953e-01, /* logih[93] */ 4.46701777108311388441189058844554903695616000674812e-18, /* logim[93] */ -1.53168389834566630100313932781112142055948393405761e-34, /* logil[93] */ } , { 1.15315318107604980468750000000000000000000000000000e+00, /* r[94] */ -1.42500086821669674774781810810964088886976242065430e-01, /* logih[94] */ -2.21668083020505832726646787146199970227457581911830e-18, /* logim[94] */ -4.73140768447350921077611938776759805597533720242102e-36, /* logil[94] */ } , { 1.14798212051391601562500000000000000000000000000000e+00, /* r[95] */ -1.38005723310861472263866289722500368952751159667969e-01, /* logih[95] */ -9.06035372834454229539393713977175584764482079542462e-18, /* logim[95] */ -6.58482110068426815722709702700082916058774211791842e-34, /* logil[95] */ } , { 1.14285707473754882812500000000000000000000000000000e+00, /* r[96] */ -1.33531333019876075063336884340969845652580261230469e-01, /* logih[96] */ 3.66452824974217778950176131406293356640863401093569e-18, /* logim[96] */ 6.15050085774566840615703784135477182311292227710416e-35, /* logil[96] */ } , { 1.13777780532836914062500000000000000000000000000000e+00, /* r[97] */ -1.29077066489528990977930789085803553462028503417969e-01, /* logih[97] */ 7.97904258955058431558707127373439732289437010877585e-19, /* logim[97] */ -4.72584148771245137732808879600361038781792271619664e-35, /* logil[97] */ } , { 1.13274335861206054687500000000000000000000000000000e+00, /* r[98] */ -1.24642441481986290807704165217728586867451667785645e-01, /* logih[98] */ -1.12998120773332791412288663337308123303520797473827e-18, /* logim[98] */ 5.04751909879024305911295754405025108738663901055449e-35, /* logil[98] */ } , { 1.12775325775146484375000000000000000000000000000000e+00, /* r[99] */ -1.20227386019965673535914163494453532621264457702637e-01, /* logih[99] */ -4.10132123403305460439841682733159064509468253505934e-18, /* logim[99] */ 1.89802934268459828223199224893946334512039168636632e-34, /* logil[99] */ } , { 1.12280702590942382812500000000000000000000000000000e+00, /* r[100] */ -1.15831822975702269928888199501670897006988525390625e-01, /* logih[100] */ -4.33848450767153009712329850176816190393287866962401e-18, /* logim[100] */ -3.16979691573058896647113947407157157214490081484725e-34, /* logil[100] */ } , { 1.11790394783020019531250000000000000000000000000000e+00, /* r[101] */ -1.11455456757806464773707944004854653030633926391602e-01, /* logih[101] */ -5.25227837292521929481451677551514755953859335394548e-18, /* logim[101] */ -1.35455162271740897316919848287529722248286557667632e-34, /* logil[101] */ } , { 1.11304354667663574218750000000000000000000000000000e+00, /* r[102] */ -1.07098197023655139492603893813793547451496124267578e-01, /* logih[102] */ 3.47169710366632825350486634041554320998659998614468e-18, /* logim[102] */ 4.16291803858237783591365989446195611338780307382474e-35, /* logil[102] */ } , { 1.10822510719299316406250000000000000000000000000000e+00, /* r[103] */ -1.02759733026446364867467764270259067416191101074219e-01, /* logih[103] */ 5.14131173582414775653668171432178439238499706689565e-18, /* logim[103] */ -2.03511710633920722432014459953905354472733979743122e-34, /* logil[103] */ } , { 1.10344839096069335937500000000000000000000000000000e+00, /* r[104] */ -9.84401771213754411826712953370588365942239761352539e-02, /* logih[104] */ 4.43863133643792238822177111529042861410430977956950e-18, /* logim[104] */ 3.12055863098469149547827014037274497005231280699218e-34, /* logil[104] */ } , { 1.09871244430541992187500000000000000000000000000000e+00, /* r[105] */ -9.41389890512167593072945237508974969387054443359375e-02, /* logih[105] */ 2.37342936135295683496202513568031672884920488134173e-19, /* logim[105] */ 2.33721773003055253003147894270712826153088420940698e-35, /* logil[105] */ } , { 1.09401702880859375000000000000000000000000000000000e+00, /* r[106] */ -8.98562695172144959565585509153606835752725601196289e-02, /* logih[106] */ 6.27446602451052736319026996501069657057280086335290e-19, /* logim[106] */ -3.52284010127094716016693656249620808330731317587528e-35, /* logil[106] */ } , { 1.08936166763305664062500000000000000000000000000000e+00, /* r[107] */ -8.55918986704354706196440361054555978626012802124023e-02, /* logih[107] */ -5.03513826084130895904008327416965851388338774947593e-18, /* logim[107] */ 6.86424026896698901114373288904478288437409959196820e-35, /* logil[107] */ } , { 1.08474564552307128906250000000000000000000000000000e+00, /* r[108] */ -8.13455314205279167438789045263547450304031372070312e-02, /* logih[108] */ 1.86223784192593707654359268192644483006930996779864e-18, /* logim[108] */ -9.08215611660981343459991418247070342987317386688394e-35, /* logil[108] */ } , { 1.08016872406005859375000000000000000000000000000000e+00, /* r[109] */ -7.71172549156562414651716608204878866672515869140625e-02, /* logih[109] */ 4.37349590112793692636976332290601524356283649435490e-18, /* logim[109] */ -2.43638510650083687411626047741666976256819270953612e-34, /* logil[109] */ } , { 1.07563018798828125000000000000000000000000000000000e+00, /* r[110] */ -7.29067112034412351251333461732428986579179763793945e-02, /* logih[110] */ 6.30693084361487082247322771068486204374546343933133e-18, /* logim[110] */ 3.44825082371128400572272238979928316738696119124015e-34, /* logil[110] */ } , { 1.07112979888916015625000000000000000000000000000000e+00, /* r[111] */ -6.87139782297249979148290321973036043345928192138672e-02, /* logih[111] */ -4.40922228882126717948257852084234011599535648658716e-18, /* logim[111] */ 2.00071285755297414487130516445636815235532199087333e-34, /* logil[111] */ } , { 1.06666660308837890625000000000000000000000000000000e+00, /* r[112] */ -6.45384615329246263959461771264614071696996688842773e-02, /* logih[112] */ 6.47055724777502681297997296903095954212491541204973e-18, /* logim[112] */ -3.53995576621708408093066388957026321212073337996708e-34, /* logil[112] */ } , { 1.06224060058593750000000000000000000000000000000000e+00, /* r[113] */ -6.03804513842609302809449900450999848544597625732422e-02, /* logih[113] */ 2.15703432342306119511642925211564389619524247753812e-18, /* logim[113] */ -3.99051054966201464148223117427430962485432571249835e-35, /* logil[113] */ } , { 1.05785131454467773437500000000000000000000000000000e+00, /* r[114] */ -5.62397891033892469159205518280941760167479515075684e-02, /* logih[114] */ 3.28339677990388790029372693220459728960401288179580e-18, /* logim[114] */ 1.51915205677141595589208947882243470550543557886170e-35, /* logil[114] */ } , { 1.05349802970886230468750000000000000000000000000000e+00, /* r[115] */ -5.21160840267197236763685452842764789238572120666504e-02, /* logih[115] */ -2.76876652450490527514912306264172616345243137067863e-19, /* logim[115] */ 4.97747635693761803951848478678221385327287067714555e-36, /* logil[115] */ } , { 1.04918026924133300781250000000000000000000000000000e+00, /* r[116] */ -4.80091633070045681330739739678392652422189712524414e-02, /* logih[116] */ -1.43903217358996287866324353045636173989420593009940e-18, /* logim[116] */ 9.24533961563047616614044310774847027299245259235749e-35, /* logil[116] */ } , { 1.04489803314208984375000000000000000000000000000000e+00, /* r[117] */ -4.39193047153486545997047585387917933985590934753418e-02, /* logih[117] */ -1.76247347066130256555880115492006953917590179181782e-18, /* logim[117] */ 2.95067167680037492936848210009098107643918346324819e-35, /* logil[117] */ } , { 1.04065036773681640625000000000000000000000000000000e+00, /* r[118] */ -3.98458712942959952796329048396728467196226119995117e-02, /* logih[118] */ 3.12956491324511750770873688790894657687633404551217e-18, /* logim[118] */ 9.08530842942513514982993220469010912494881545842223e-35, /* logil[118] */ } , { 1.03643727302551269531250000000000000000000000000000e+00, /* r[119] */ -3.57891329972944774451271143789199413731694221496582e-02, /* logih[119] */ -2.94786708868720304892365707065135221787713948130908e-19, /* logim[119] */ 1.84384763058385810856389175018656477977822636794864e-35, /* logil[119] */ } , { 1.03225803375244140625000000000000000000000000000000e+00, /* r[120] */ -3.17486685122574663342476242178236134350299835205078e-02, /* logih[120] */ -3.03821748520802146852642560679641488082417537178322e-18, /* logim[120] */ 6.90127669441551609256721347857289051065660383455449e-35, /* logil[120] */ } , { 1.02811241149902343750000000000000000000000000000000e+00, /* r[121] */ -2.77245107619511835239656249996187398210167884826660e-02, /* logih[121] */ 1.56537436220084983093655029081028016172956628311065e-18, /* logim[121] */ -4.26959324792631463690822650182944301609062827136870e-35, /* logil[121] */ } , { 1.02399992942810058593750000000000000000000000000000e+00, /* r[122] */ -2.37164576994431455791989549197751330211758613586426e-02, /* logih[122] */ -1.57190014657555079881764699090245893269914973184857e-19, /* logim[122] */ 4.62721637019171363059082221740445258999073602747011e-36, /* logil[122] */ } , { 1.01992034912109375000000000000000000000000000000000e+00, /* r[123] */ -1.97245351501005340699723689112943247891962528228760e-02, /* logih[123] */ 1.34458916305708123412045028332259969564528051018263e-18, /* logim[123] */ -6.02768376061644464555810636396264987280148524662430e-35, /* logil[123] */ } , { 1.01587295532226562500000000000000000000000000000000e+00, /* r[124] */ -1.57482973634926158579272481574662378989160060882568e-02, /* logih[124] */ -1.00208727697080412925749596659626020152032796409604e-18, /* logim[124] */ 7.75790823155383991507800579878754988160969197338737e-35, /* logil[124] */ } , { 1.01185774803161621093750000000000000000000000000000e+00, /* r[125] */ -1.17879957989121472716753658005472971126437187194824e-02, /* logih[125] */ 2.12843993900806841444093729096134188145078357457959e-19, /* logim[125] */ -7.36236149534638490756917054603187520349493909791838e-36, /* logil[125] */ } , { 1.00787401199340820312500000000000000000000000000000e+00, /* r[126] */ -7.84317373573558719590526067122482345439493656158447e-03, /* logih[126] */ -2.76470798179560918828283984091643257584228907545928e-19, /* logim[126] */ 1.46121103426200283031313413564673422143931331178612e-35, /* logil[126] */ } , { 1.00392150878906250000000000000000000000000000000000e+00, /* r[127] */ -3.91383971648977691676352108629544090945273637771606e-03, /* logih[127] */ -4.28019276224719221462393891683495367484578724177817e-19, /* logim[127] */ -2.25272542183557712010826889962617244762256960750126e-35, /* logil[127] */ } }; interval-3.2.0/src/crlibm/log.c0000644000000000000000000020374513316017127014466 0ustar 00000000000000/* * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "log.h" void p_accu(double *p_resh, double *p_resm, double *p_resl, double xh, double xm) { double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h; double p_t_6_0h; double p_t_7_0h; double p_t_8_0h; double p_t_9_0h, p_t_9_0m; double p_t_10_0h, p_t_10_0m; double p_t_11_0h, p_t_11_0m; double p_t_12_0h, p_t_12_0m; double p_t_13_0h, p_t_13_0m; double p_t_14_0h, p_t_14_0m; double p_t_15_0h, p_t_15_0m; double p_t_16_0h, p_t_16_0m, p_t_16_0l; double p_t_17_0h, p_t_17_0m, p_t_17_0l; double p_t_18_0h, p_t_18_0m, p_t_18_0l; double p_t_19_0h, p_t_19_0m, p_t_19_0l; double p_t_20_0h, p_t_20_0m, p_t_20_0l; double p_t_21_0h, p_t_21_0m, p_t_21_0l; #if EVAL_PERF crlibm_second_step_taken++; #endif p_t_1_0h = p_coeff_accu_12h; p_t_2_0h = p_t_1_0h * xh; p_t_3_0h = p_coeff_accu_11h + p_t_2_0h; p_t_4_0h = p_t_3_0h * xh; p_t_5_0h = p_coeff_accu_10h + p_t_4_0h; p_t_6_0h = p_t_5_0h * xh; p_t_7_0h = p_coeff_accu_9h + p_t_6_0h; p_t_8_0h = p_t_7_0h * xh; Add12(p_t_9_0h,p_t_9_0m,p_coeff_accu_8h,p_t_8_0h); MulAdd22(&p_t_10_0h,&p_t_10_0m,p_coeff_accu_7h,p_coeff_accu_7m,xh,xm,p_t_9_0h,p_t_9_0m); MulAdd22(&p_t_11_0h,&p_t_11_0m,p_coeff_accu_6h,p_coeff_accu_6m,xh,xm,p_t_10_0h,p_t_10_0m); MulAdd22(&p_t_12_0h,&p_t_12_0m,p_coeff_accu_5h,p_coeff_accu_5m,xh,xm,p_t_11_0h,p_t_11_0m); Mul22(&p_t_13_0h,&p_t_13_0m,p_t_12_0h,p_t_12_0m,xh,xm); Add122(&p_t_14_0h,&p_t_14_0m,p_coeff_accu_4h,p_t_13_0h,p_t_13_0m); Mul22(&p_t_15_0h,&p_t_15_0m,p_t_14_0h,p_t_14_0m,xh,xm); Add23(&p_t_16_0h,&p_t_16_0m,&p_t_16_0l,p_coeff_accu_3h,p_coeff_accu_3m,p_t_15_0h,p_t_15_0m); Mul233(&p_t_17_0h,&p_t_17_0m,&p_t_17_0l,xh,xm,p_t_16_0h,p_t_16_0m,p_t_16_0l); Add133(&p_t_18_0h,&p_t_18_0m,&p_t_18_0l,p_coeff_accu_2h,p_t_17_0h,p_t_17_0m,p_t_17_0l); Mul233(&p_t_19_0h,&p_t_19_0m,&p_t_19_0l,xh,xm,p_t_18_0h,p_t_18_0m,p_t_18_0l); Add133(&p_t_20_0h,&p_t_20_0m,&p_t_20_0l,p_coeff_accu_1h,p_t_19_0h,p_t_19_0m,p_t_19_0l); Mul233(&p_t_21_0h,&p_t_21_0m,&p_t_21_0l,xh,xm,p_t_20_0h,p_t_20_0m,p_t_20_0l); Renormalize3(p_resh,p_resm,p_resl,p_t_21_0h,p_t_21_0m,p_t_21_0l); } /************************************************************* ************************************************************* * ROUNDED TO NEAREST * ************************************************************* *************************************************************/ double log_rn(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, log2edh, log2edl, log2edm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus exact The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and possible return or call to the accurate function */ if(logh == (logh + (logm * RNROUNDCST))) return logh; else { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); log2edh = log2h * ed; log2edm = log2m * ed; log2edl = log2l * ed; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, logyh, logym, logyl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundToNearest3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED UPWARDS * ************************************************************* *************************************************************/ double log_ru(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, log2edh, log2edl, log2edm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; if (x == 1.0) return 0.0; /* This the only case in which the image under log of a double is a double. */ E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus exact The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and possible return or call to the accurate function */ TEST_AND_RETURN_RU(logh, logm, RDROUNDCST); { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); log2edh = log2h * ed; log2edm = log2m * ed; log2edl = log2l * ed; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, logyh, logym, logyl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundUpwards3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED DOWNWARDS * ************************************************************* *************************************************************/ double log_rd(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, log2edh, log2edl, log2edm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; if (x == 1.0) return 0.0; /* This the only case in which the image under log of a double is a double. */ E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus exact The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and possible return or call to the accurate function */ TEST_AND_RETURN_RD(logh, logm, RDROUNDCST); { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); log2edh = log2h * ed; log2edm = log2m * ed; log2edl = log2l * ed; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, logyh, logym, logyl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundDownwards3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED TOWARDS ZERO * ************************************************************* *************************************************************/ double log_rz(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, log2edh, log2edl, log2edm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; if (x == 1.0) return 0.0; /* This the only case in which the image under log of a double is a double. */ E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus exact The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and possible return or call to the accurate function */ TEST_AND_RETURN_RZ(logh, logm, RDROUNDCST); { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); log2edh = log2h * ed; log2edm = log2m * ed; log2edl = log2l * ed; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, logyh, logym, logyl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundTowardsZero3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED TO NEAREST * ************************************************************* *************************************************************/ double log2_rn(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; double log2TabPolyh, log2TabPolyl, log2yh, log2ym, log2yl; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log2(x) = E + 1/log(2) * (log(1+z) - log(ri)) Carry out everything in double double precision */ /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Multiply by 1/log(2) */ Mul22(&log2TabPolyh,&log2TabPolyl, RECPRLOG2H, RECPRLOG2L, logTabPolyh, logTabPolyl); /* Add E */ Add122(&logh, &logm, ed, log2TabPolyh, log2TabPolyl); /* Rounding test and possible return or call to the accurate function */ if(logh == (logh + (logm * RNROUNDCST))) return logh; else { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); Mul233(&log2yh,&log2ym,&log2yl,RECPRLOG2H,RECPRLOG2L,logyh,logym,logyl); Add133(&loghover,&logmover,&loglover,ed,log2yh,log2ym,log2yl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundToNearest3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED UPWARDS * ************************************************************* *************************************************************/ double log2_ru(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; double log2TabPolyh, log2TabPolyl, log2yh, log2ym, log2yl; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); /* Test now if the argument is an exact power of 2 i.e. if the mantissa is exactly 1 (0x0..0 with the implicit bit) This test is necessary for filtering out the cases where the final rounding test cannot distinguish between an exact algebraic number and a hard case to round */ if ((index | xdb.i[LO]) == 0) { /* Handle the "trivial" case for log2: The argument is an exact power of 2, return thus just the exponant of the number */ return (double) E; } xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log2(x) = E + 1/log(2) * (log(1+z) - log(ri)) Carry out everything in double double precision */ /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Multiply by 1/log(2) */ Mul22(&log2TabPolyh,&log2TabPolyl, RECPRLOG2H, RECPRLOG2L, logTabPolyh, logTabPolyl); /* Add E */ Add122(&logh, &logm, ed, log2TabPolyh, log2TabPolyl); /* Rounding test and eventual return or call to the accurate function */ TEST_AND_RETURN_RU(logh, logm, RDROUNDCST); { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); Mul233(&log2yh,&log2ym,&log2yl,RECPRLOG2H,RECPRLOG2L,logyh,logym,logyl); Add133(&loghover,&logmover,&loglover,ed,log2yh,log2ym,log2yl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundUpwards3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED DOWNWARDS * ************************************************************* *************************************************************/ double log2_rd(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; double log2TabPolyh, log2TabPolyl, log2yh, log2ym, log2yl; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); /* Test now if the argument is an exact power of 2 i.e. if the mantissa is exactly 1 (0x0..0 with the implicit bit) This test is necessary for filtering out the cases where the final rounding test cannot distinguish between an exact algebraic number and a hard case to round */ if ((index | xdb.i[LO]) == 0) { /* Handle the "trivial" case for log2: The argument is an exact power of 2, return thus just the exponant of the number */ return (double) E; } xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log2(x) = E + 1/log(2) * (log(1+z) - log(ri)) Carry out everything in double double precision */ /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Multiply by 1/log(2) */ Mul22(&log2TabPolyh,&log2TabPolyl, RECPRLOG2H, RECPRLOG2L, logTabPolyh, logTabPolyl); /* Add E */ Add122(&logh, &logm, ed, log2TabPolyh, log2TabPolyl); /* Rounding test and eventual return or call to the accurate function */ TEST_AND_RETURN_RD(logh, logm, RDROUNDCST); { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); Mul233(&log2yh,&log2ym,&log2yl,RECPRLOG2H,RECPRLOG2L,logyh,logym,logyl); Add133(&loghover,&logmover,&loglover,ed,log2yh,log2ym,log2yl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundDownwards3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED TOWARDS ZERO * ************************************************************* *************************************************************/ double log2_rz(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; double log2TabPolyh, log2TabPolyl, log2yh, log2ym, log2yl; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); /* Test now if the argument is an exact power of 2 i.e. if the mantissa is exactly 1 (0x0..0 with the implicit bit) This test is necessary for filtering out the cases where the final rounding test cannot distinguish between an exact algebraic number and a hard case to round */ if ((index | xdb.i[LO]) == 0) { /* Handle the "trivial" case for log2: The argument is an exact power of 2, return thus just the exponant of the number */ return (double) E; } xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log2(x) = E + 1/log(2) * (log(1+z) - log(ri)) Carry out everything in double double precision */ /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Multiply by 1/log(2) */ Mul22(&log2TabPolyh,&log2TabPolyl, RECPRLOG2H, RECPRLOG2L, logTabPolyh, logTabPolyl); /* Add E */ Add122(&logh, &logm, ed, log2TabPolyh, log2TabPolyl); /* Rounding test and possible return or call to the accurate function */ TEST_AND_RETURN_RZ(logh, logm, RDROUNDCST); { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); Mul233(&log2yh,&log2ym,&log2yl,RECPRLOG2H,RECPRLOG2L,logyh,logym,logyl); Add133(&loghover,&logmover,&loglover,ed,log2yh,log2ym,log2yl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundTowardsZero3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED TO NEAREST * ************************************************************* *************************************************************/ double log10_rn(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, log2edh, log2edl, log2edm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; double log10TabPolyh, log10TabPolyl; double log10yh, log10ym, log10yl; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log_10(2) as log210h + log210m + log210l where log210h and log210m have 10 trailing zeros Multiplication of ed (double E) and log210h and m is thus exact The overall accuracy of log10h + log10m + log10l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log210m is smaller than log210h and both are scaled by ed */ Add12(log2edh, log2edl, log210h * ed, log210m * ed); /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Multiply by 1/log(10) */ Mul22(&log10TabPolyh,&log10TabPolyl,RECPRLOG10H,RECPRLOG10M,logTabPolyh,logTabPolyl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22(&logh, &logm, log2edh, log2edl, log10TabPolyh, log10TabPolyl); /* Rounding test and possible return or call to the accurate function */ if(logh == (logh + (logm * RNROUNDCST))) return logh; else { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); Mul33(&log10yh,&log10ym,&log10yl,RECPRLOG10H,RECPRLOG10M,RECPRLOG10L,logyh,logym,logyl); log2edh = log210h * ed; log2edm = log210m * ed; log2edl = log210l * ed; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, log10yh, log10ym, log10yl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundToNearest3(logh, logm, logl); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED UPWARDS * ************************************************************* *************************************************************/ double log10_ru(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, log2edh, log2edl, log2edm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; double log10TabPolyh, log10TabPolyl; double log10yh, log10ym, log10yl; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log_10(2) as log210h + log210m + log210l where log210h and log210m have 10 trailing zeros Multiplication of ed (double E) and log210h and m is thus exact The overall accuracy of log10h + log10m + log10l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log210m is smaller than log210h and both are scaled by ed */ Add12(log2edh, log2edl, log210h * ed, log210m * ed); /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Multiply by 1/log(10) */ Mul22(&log10TabPolyh,&log10TabPolyl,RECPRLOG10H,RECPRLOG10M,logTabPolyh,logTabPolyl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22(&logh, &logm, log2edh, log2edl, log10TabPolyh, log10TabPolyl); /* Rounding test and possible return or call to the accurate function */ TEST_AND_RETURN_RU(logh, logm, RDROUNDCST); { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); Mul33(&log10yh,&log10ym,&log10yl,RECPRLOG10H,RECPRLOG10M,RECPRLOG10L,logyh,logym,logyl); log2edh = log210h * ed; log2edm = log210m * ed; log2edl = log210l * ed; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, log10yh, log10ym, log10yl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundUpwards3Unfiltered(logh, logm, logl, WORSTCASEACCURACY); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED DOWNWARDS * ************************************************************* *************************************************************/ double log10_rd(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, log2edh, log2edl, log2edm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; double log10TabPolyh, log10TabPolyl; double log10yh, log10ym, log10yl; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log_10(2) as log210h + log210m + log210l where log210h and log210m have 10 trailing zeros Multiplication of ed (double E) and log210h and m is thus exact The overall accuracy of log10h + log10m + log10l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log210m is smaller than log210h and both are scaled by ed */ Add12(log2edh, log2edl, log210h * ed, log210m * ed); /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Multiply by 1/log(10) */ Mul22(&log10TabPolyh,&log10TabPolyl,RECPRLOG10H,RECPRLOG10M,logTabPolyh,logTabPolyl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22(&logh, &logm, log2edh, log2edl, log10TabPolyh, log10TabPolyl); /* Rounding test and possible return or call to the accurate function */ TEST_AND_RETURN_RD(logh, logm, RDROUNDCST); { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); Mul33(&log10yh,&log10ym,&log10yl,RECPRLOG10H,RECPRLOG10M,RECPRLOG10L,logyh,logym,logyl); log2edh = log210h * ed; log2edm = log210m * ed; log2edl = log210l * ed; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, log10yh, log10ym, log10yl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundDownwards3Unfiltered(logh, logm, logl, WORSTCASEACCURACY); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED TOWARDS ZERO * ************************************************************* *************************************************************/ double log10_rz(double x){ db_number xdb, yhdb; double yh, yl, ed, ri, logih, logim, logil, yrih, yril, th, zh, zl; double ph, pl, pm, log2edh, log2edl, log2edm, logTabPolyh, logTabPolyl, logh, logm, logl; int E, index; double zhSquare, zhCube, zhSquareHalf; double p35, p46, p36; double pUpper; double zhSquareHalfPlusZl; double zhFour; double logyh, logym, logyl; double loghover, logmover, loglover; double log10TabPolyh, log10TabPolyl; double log10yh, log10ym, log10yl; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 exactly Exactness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial approximation */ zhSquare = zh * zh; /* 1 */ p35 = p_coeff_3h + zhSquare * p_coeff_5h; /* 3 */ p46 = p_coeff_4h + zhSquare * p_coeff_6h; /* 3 */ zhCube = zhSquare * zh; /* 2 */ zhSquareHalf = p_coeff_2h * zhSquare; /* 2 */ zhFour = zhSquare * zhSquare; /* 2 */ p36 = zhCube * p35 + zhFour * p46; /* 4 */ zhSquareHalfPlusZl = zhSquareHalf + zl; /* 3 */ pUpper = zhSquareHalfPlusZl + p36; /* 5 */ Add12(ph,pl,zh,pUpper); /* 8 */ /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log_10(2) as log210h + log210m + log210l where log210h and log210m have 10 trailing zeros Multiplication of ed (double E) and log210h and m is thus exact The overall accuracy of log10h + log10m + log10l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log210m is smaller than log210h and both are scaled by ed */ Add12(log2edh, log2edl, log210h * ed, log210m * ed); /* Add logih and logim to ph and pl */ Add22(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Multiply by 1/log(10) */ Mul22(&log10TabPolyh,&log10TabPolyl,RECPRLOG10H,RECPRLOG10M,logTabPolyh,logTabPolyl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22(&logh, &logm, log2edh, log2edl, log10TabPolyh, log10TabPolyl); /* Rounding test and possible return or call to the accurate function */ TEST_AND_RETURN_RZ(logh, logm, RDROUNDCST); { logil = argredtable[index].logil; p_accu(&ph, &pm, &pl, zh, zl); Add33(&logyh, &logym, &logyl, logih, logim, logil, ph, pm, pl); Mul33(&log10yh,&log10ym,&log10yl,RECPRLOG10H,RECPRLOG10M,RECPRLOG10L,logyh,logym,logyl); log2edh = log210h * ed; log2edm = log210m * ed; log2edl = log210l * ed; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, log10yh, log10ym, log10yl); Renormalize3(&logh,&logm,&logl,loghover,logmover,loglover); ReturnRoundTowardsZero3Unfiltered(logh, logm, logl, WORSTCASEACCURACY); } /* Accurate phase launched */ } interval-3.2.0/src/crlibm/log.h0000644000000000000000000025661413316017127014476 0ustar 00000000000000/* * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" #define L 8 #define MAXINDEX 106 #define INDEXMASK 255 #define two52 4.50359962737049600000000000000000000000000000000000e+15 #define log2h 6.93147180559890330187045037746429443359375000000000e-01 #define log2m 5.49792301870850242169664946507035702127907939029683e-14 #define log2l -1.31246984177852556920995753667322295879593697972250e-27 #define log210h 0.3010299956639528318191878497600555419921875 #define log210m 0.28363394551042263094578877949012915560267344972089631482958793640137e-13 #define log210l 0.27013429058980534315374921000428327002971066904842912935671669760243e-26 #define RNROUNDCST 1.01587301587301598581442042834326647273327977070694e+00 #define RDROUNDCST 8.67361737988403547205962240695953369140625000000000e-19 #define RECPRLOG2H 0.1442695040888963387004650940070860087871551513671875e1 #define RECPRLOG2L 0.203552737409310331110210900522069120325603861485809498166e-16 #define RECPRLOG10H 0.43429448190325181666793241674895398318767547607421875 #define RECPRLOG10M 0.109831965021676507273885982186335434116483395815071742729340797950499108992516994476318359375e-16 #define RECPRLOG10L 0.3717181233110958966699817676973599714051656514224857273631510154667658260758842841533296404155084502463068929500877857208251953125e-33 #define WORSTCASEACCURACY 0.5316911983139663491615228241121378304e37 #define p_coeff_accu_1h 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00 #define p_coeff_accu_2h -5.00000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 #define p_coeff_accu_3h 3.33333333333333314829616256247390992939472198486328125000000000000000000000000000e-01 #define p_coeff_accu_3m 1.85037170770874789756988228974262968046011237606765509333683894510613754391670227e-17 #define p_coeff_accu_4h -2.50000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 #define p_coeff_accu_5h 2.00000000000000011102230246251565404236316680908203125000000000000000000000000000e-01 #define p_coeff_accu_5m -1.11022359498086234952280980357986354308310664976318371532926221334491856396198273e-17 #define p_coeff_accu_6h -1.66666666666666657414808128123695496469736099243164062500000000000000000000000000e-01 #define p_coeff_accu_6m -9.25186011742975917381555124745579318634206911138887982626322070700553013011813164e-18 #define p_coeff_accu_7h 1.42857142857142876968268296877795364707708358764648437500000000000000000000000000e-01 #define p_coeff_accu_7m -1.29473592850074078984540189203202170950776491657307348814853753538045566529035568e-17 #define p_coeff_accu_8h -1.25000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 #define p_coeff_accu_9h 1.11111111107490570515388128569611581042408943176269531250000000000000000000000000e-01 #define p_coeff_accu_10h -9.99999999987549875735126647668948862701654434204101562500000000000000000000000000e-02 #define p_coeff_accu_11h 9.09099561261329930372809826621960382908582687377929687500000000000000000000000000e-02 #define p_coeff_accu_12h -8.33339031627361587206692661311535630375146865844726562500000000000000000000000000e-02 #define p_coeff_1h 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00 #define p_coeff_2h -5.00000000000000000000000000000000000000000000000000000000000000000000000000000000e-01 #define p_coeff_3h 3.33333333332438030982558530013193376362323760986328125000000000000000000000000000e-01 #define p_coeff_4h -2.49999999998981758952965037678950466215610504150390625000000000000000000000000000e-01 #define p_coeff_5h 2.00000758681036727715252254711231216788291931152343750000000000000000000000000000e-01 #define p_coeff_6h -1.66667399943076749435633132634393405169248580932617187500000000000000000000000000e-01 typedef struct rri_tag {float ri; double logih; double logim; double logil;} rri; static const rri argredtable[256] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* r[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logih[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logim[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logil[0] */ } , { 9.96109008789062500000000000000000000000000000000000e-01, /* r[1] */ 3.89858081101432385473515296325786039233207702636719e-03, /* logih[1] */ 1.25346004307267304894640684851581512787262559024016e-19, /* logim[1] */ 4.64325168845438317713718561737934247375332721265836e-36, /* logil[1] */ } , { 9.92248535156250000000000000000000000000000000000000e-01, /* r[2] */ 7.78166360501043267300369521421998797450214624404907e-03, /* logih[2] */ -4.89592386148351837006945254137918249482580247924126e-20, /* logim[2] */ -1.08409213368413141614035817819969540383455164545947e-36, /* logil[2] */ } , { 9.88416671752929687500000000000000000000000000000000e-01, /* r[3] */ 1.16509375949922621557020008253857668023556470870972e-02, /* logih[3] */ -2.25226774360965572201294117569374162214377850269541e-19, /* logim[3] */ -5.11945341084299010662466108636073292979157772198876e-36, /* logil[3] */ } , { 9.84615325927734375000000000000000000000000000000000e-01, /* r[4] */ 1.55042461406118062261505485821544425562024116516113e-02, /* logih[4] */ -3.27761516207149627029928635703400435929630184221293e-19, /* logim[4] */ 2.95200020707030964072253388818190769795416371257942e-37, /* logil[4] */ } , { 9.80842590332031250000000000000000000000000000000000e-01, /* r[5] */ 1.93432906687309343063407851559531991370022296905518e-02, /* logih[5] */ -2.15862131267131143148684267329697650453139578671228e-19, /* logim[5] */ -1.15271369538876060199548423508281675592171686662266e-35, /* logil[5] */ } , { 9.77099418640136718750000000000000000000000000000000e-01, /* r[6] */ 2.31668730170368035448102972395645338110625743865967e-02, /* logih[6] */ -1.17910860908392752354910733048566386347187195159043e-18, /* logim[6] */ 2.49612518164524848780028044162189727076238619175360e-35, /* logil[6] */ } , { 9.73383903503417968750000000000000000000000000000000e-01, /* r[7] */ 2.69767180833710221166121812075289199128746986389160e-02, /* logih[7] */ -5.57795528916207151895634361214250967547427159484621e-20, /* logim[7] */ -3.62294468430332561712587522351589910764493467585522e-36, /* logil[7] */ } , { 9.69696998596191406250000000000000000000000000000000e-01, /* r[8] */ 3.07716288644317437217523547587916254997253417968750e-02, /* logih[8] */ 1.04316437964092669923942103072089812062131860035492e-18, /* logim[8] */ -8.26837774892530079043982861155759865584698067912967e-36, /* logil[8] */ } , { 9.66037750244140625000000000000000000000000000000000e-01, /* r[9] */ 3.45523666054986522411240912333596497774124145507812e-02, /* logih[9] */ -1.65910748103534385407065291371523592570431641990885e-18, /* logim[9] */ 3.38525826535166864039714297442413583169978770990777e-35, /* logil[9] */ } , { 9.62406158447265625000000000000000000000000000000000e-01, /* r[10] */ 3.83187152905357653054352340404875576496124267578125e-02, /* logih[10] */ -2.35909906471143038057626284336250570775789572626881e-18, /* logim[10] */ -1.85563428635831615187251482536612501452930840707165e-34, /* logil[10] */ } , { 9.58801269531250000000000000000000000000000000000000e-01, /* r[11] */ 4.20714523392945807800380464414047310128808021545410e-02, /* logih[11] */ -3.12838632664719081818569863425510803330088438244181e-18, /* logim[11] */ -3.22458892012633541790068267080237442991762885883976e-35, /* logil[11] */ } , { 9.55224037170410156250000000000000000000000000000000e-01, /* r[12] */ 4.58093721185345026380986155345453880727291107177734e-02, /* logih[12] */ 1.90149189679431067655792024548961427427986403667162e-18, /* logim[12] */ -1.35330568979098264467186032289860101304045776545335e-34, /* logil[12] */ } , { 9.51672554016113281250000000000000000000000000000000e-01, /* r[13] */ 4.95342592225851141574111125009949319064617156982422e-02, /* logih[13] */ 3.41051514612607272315747347640360336610752192297493e-18, /* logim[13] */ -1.62776077654054345674690342025587161986806134248965e-34, /* logil[13] */ } , { 9.48147773742675781250000000000000000000000000000000e-01, /* r[14] */ 5.32449093996618869062409373782429611310362815856934e-02, /* logih[14] */ -1.64505111621921275224226259698905780842959106366420e-18, /* logim[14] */ 4.14442397515940112138679619536747848472625603933844e-35, /* logil[14] */ } , { 9.44649696350097656250000000000000000000000000000000e-01, /* r[15] */ 5.69411119045622124423822185690369224175810813903809e-02, /* logih[15] */ 4.78734188028619786114736923282640611331114908534069e-19, /* logim[15] */ -3.93713999997785260153004737038398583853656485310521e-35, /* logil[15] */ } , { 9.41176414489746093750000000000000000000000000000000e-01, /* r[16] */ 6.06246814210813916856679384181916248053312301635742e-02, /* logih[16] */ 2.64247317995478646334926909653435556549332769494295e-18, /* logim[16] */ 1.55075207452234839722600788456166299408429635417895e-34, /* logil[16] */ } , { 9.37728881835937500000000000000000000000000000000000e-01, /* r[17] */ 6.42944103100438063558286216903070453554391860961914e-02, /* logih[17] */ 2.60793481490786257498313263319157616690600921511114e-18, /* logim[17] */ -1.45909124358216952997721245377778825212735363222186e-34, /* logil[17] */ } , { 9.34306144714355468750000000000000000000000000000000e-01, /* r[18] */ 6.79511163940274415251607820209756027907133102416992e-02, /* logih[18] */ -1.24892173295840496632514736205386405076267738428183e-18, /* logim[18] */ -5.86027190792146940250174345622545434589551590207709e-35, /* logil[18] */ } , { 9.30909156799316406250000000000000000000000000000000e-01, /* r[19] */ 7.15935824064956455314856498262088280171155929565430e-02, /* logih[19] */ 6.55833354527865440910555403220649032260269042308564e-18, /* logim[19] */ -8.65001743565124847036366836203555319976499748416219e-35, /* logil[19] */ } , { 9.27536010742187500000000000000000000000000000000000e-01, /* r[20] */ 7.52236596561950549011399402843380812555551528930664e-02, /* logih[20] */ -5.92608668643342447178482655547063763942218784624419e-18, /* logim[20] */ 3.06299284565641653395923152025230697760630110042913e-34, /* logil[20] */ } , { 9.24187660217285156250000000000000000000000000000000e-01, /* r[21] */ 7.88401324882942039495858921327453572303056716918945e-02, /* logih[21] */ -3.70086061559488005172131811140468915784794102784056e-18, /* logim[21] */ -9.85152871853396304228341002410386896660946235409677e-36, /* logil[21] */ } , { 9.20863151550292968750000000000000000000000000000000e-01, /* r[22] */ 8.24438405744429975152698375495674554258584976196289e-02, /* logih[22] */ 5.70211515844839148682574255471016004503183577701328e-18, /* logim[22] */ -2.25007518842967334560085413287805841472581599706844e-34, /* logil[22] */ } , { 9.17562484741210937500000000000000000000000000000000e-01, /* r[23] */ 8.60345981121580505313062303685001097619533538818359e-02, /* logih[23] */ -4.22948398727754542981422162560881574021096207871627e-18, /* logim[23] */ 6.94601543497627089738149551411013780692459600238783e-35, /* logil[23] */ } , { 9.14285659790039062500000000000000000000000000000000e-01, /* r[24] */ 8.96122182943336897942288032936630770564079284667969e-02, /* logih[24] */ -5.42674234758262048883730612286095846547194397615989e-18, /* logim[24] */ -7.94903110897686868047461590865098481976776339992810e-35, /* logil[24] */ } , { 9.11031723022460937500000000000000000000000000000000e-01, /* r[25] */ 9.31775601303663630892160085750219877809286117553711e-02, /* logih[25] */ -6.69498457328524671915466867735988222404310795846756e-18, /* logim[25] */ -3.79652072557870206332532254269355336020140715029263e-34, /* logil[25] */ } , { 9.07801628112792968750000000000000000000000000000000e-01, /* r[26] */ 9.67293954905792813248055495023436378687620162963867e-02, /* logih[26] */ -5.63846837522303146603627132880140909669766724948486e-19, /* logim[26] */ -1.66000291590412401400936599792255612972352892524385e-35, /* logil[26] */ } , { 9.04593467712402343750000000000000000000000000000000e-01, /* r[27] */ 1.00269643153498413945534650792978936806321144104004e-01, /* logih[27] */ 4.98554274018507013478029967753506544988890129859642e-18, /* logim[27] */ 5.59670179615967929691409415615538777735120155881527e-35, /* logil[27] */ } , { 9.01408195495605468750000000000000000000000000000000e-01, /* r[28] */ 1.03797076803746321504995364648493705317378044128418e-01, /* logih[28] */ 5.48528900130158927281223188042337652391677694528930e-18, /* logim[28] */ 4.14171393686520487202261794304840175447148562557926e-37, /* logil[28] */ } , { 8.98245811462402343750000000000000000000000000000000e-01, /* r[29] */ 1.07311515996984602194785907158802729099988937377930e-01, /* logih[29] */ -6.49440034445526829025678761855551439585344802732716e-18, /* logim[29] */ 2.57958632702602934657456152939453502266815184956115e-34, /* logil[29] */ } , { 8.95105361938476562500000000000000000000000000000000e-01, /* r[30] */ 1.10813844799784330663605658173764823004603385925293e-01, /* logih[30] */ 1.13646120297132443922718632465223191456150489503195e-18, /* logim[30] */ -5.28316759830006376644472821184088330546878296734027e-35, /* logil[30] */ } , { 8.91985893249511718750000000000000000000000000000000e-01, /* r[31] */ 1.14304961269881905083778406151395756751298904418945e-01, /* logih[31] */ -1.82657204548789933700890276210347276483341044028754e-18, /* logim[31] */ -1.78975695662999910835938906470926846720934095410310e-34, /* logil[31] */ } , { 8.88889312744140625000000000000000000000000000000000e-01, /* r[32] */ 1.17782558819338939448684300259628798812627792358398e-01, /* logih[32] */ -1.23330863425085901895045843903611194329827297821512e-18, /* logim[32] */ -3.52820989557939438405682761152717048907334161666144e-35, /* logil[32] */ } , { 8.85812759399414062500000000000000000000000000000000e-01, /* r[33] */ 1.21249683217221515540984455583384260535240173339844e-01, /* logih[33] */ 5.31311945158451973155842240649445065131843549390499e-18, /* logim[33] */ 2.54343506313921505744140357189546013839546072665324e-34, /* logil[33] */ } , { 8.82759094238281250000000000000000000000000000000000e-01, /* r[34] */ 1.24702942059298146904033899318164912983775138854980e-01, /* logih[34] */ -4.70371819449250479521866847789744043656802774985674e-18, /* logim[34] */ 1.97104582593396093851604773181347759433213428836825e-35, /* logil[34] */ } , { 8.79725456237792968750000000000000000000000000000000e-01, /* r[35] */ 1.28145401734214903211039882080513052642345428466797e-01, /* logih[35] */ 1.14781745994570133838663940952936924060234053388495e-17, /* logim[35] */ 5.58511031530272548588108480038230630258110787014421e-34, /* logil[35] */ } , { 8.76712799072265625000000000000000000000000000000000e-01, /* r[36] */ 1.31575821347060167854081669247534591704607009887695e-01, /* logih[36] */ 1.10715436488867456364710847828940395046896276123492e-17, /* logim[36] */ -1.96739988161444008557083655799953663793248304761174e-34, /* logil[36] */ } , { 8.73720169067382812500000000000000000000000000000000e-01, /* r[37] */ 1.34995127284602528527912568279134575277566909790039e-01, /* logih[37] */ 1.13443032556618420511047729873477099334314080223232e-17, /* logim[37] */ 7.84084139347542359388184229855467642926900448087157e-35, /* logil[37] */ } , { 8.70748519897460937500000000000000000000000000000000e-01, /* r[38] */ 1.38402069539410921272803989268140867352485656738281e-01, /* logih[38] */ 4.44235871792103837022419240194760193308637586385155e-18, /* logim[38] */ -2.41881295582206144619569746427861787915591569677161e-34, /* logil[38] */ } , { 8.67796897888183593750000000000000000000000000000000e-01, /* r[39] */ 1.41797580309475756976667071285191923379898071289062e-01, /* logih[39] */ -7.24160172735387143794870117732197886365507642151672e-18, /* logim[39] */ -5.22451781240386018101218933838001385853101358775197e-34, /* logil[39] */ } , { 8.64865303039550781250000000000000000000000000000000e-01, /* r[40] */ 1.45181503205145640000850448814162518829107284545898e-01, /* logih[40] */ 8.19907012376636936299584542046629720669747968826019e-18, /* logim[40] */ -6.12684085112129298490441309408007876014850876364407e-34, /* logil[40] */ } , { 8.61952781677246093750000000000000000000000000000000e-01, /* r[41] */ 1.48554787455398934481465289536572527140378952026367e-01, /* logih[41] */ 6.78516779658958104936774808506523119026706496843219e-18, /* logim[41] */ -3.27826043728243463792408633436129695451318517711142e-34, /* logil[41] */ } , { 8.59060287475585937500000000000000000000000000000000e-01, /* r[42] */ 1.51916176136301706023346014262642711400985717773438e-01, /* logih[42] */ 6.48466714403849150058443502305577974475027830695770e-18, /* logim[42] */ -1.48928080867016213912478822372262107645375280995355e-34, /* logil[42] */ } , { 8.56186866760253906250000000000000000000000000000000e-01, /* r[43] */ 1.55266624374856387902354981633834540843963623046875e-01, /* logih[43] */ 1.18940768999581165815608386146027685954807862619905e-18, /* logim[43] */ -2.19216119241235749930116667974585541598333050913847e-35, /* logil[43] */ } , { 8.53333473205566406250000000000000000000000000000000e-01, /* r[44] */ 1.58604866263878874210746516837389208376407623291016e-01, /* logih[44] */ 1.12555359025026447024891292897564756165016667291108e-17, /* logim[44] */ 2.51566303827199528440805207088944780959353108097571e-34, /* logil[44] */ } , { 8.50498199462890625000000000000000000000000000000000e-01, /* r[45] */ 1.61932984182099809489230324288655538111925125122070e-01, /* logih[45] */ 9.77539264526997233823717660784682214608240520802842e-18, /* logim[45] */ 5.24985245146816572034425662478272808361990734810588e-34, /* logil[45] */ } , { 8.47681999206542968750000000000000000000000000000000e-01, /* r[46] */ 1.65249714456348534286078688637644518166780471801758e-01, /* logih[46] */ -1.00939900169186480779679825710639265028332267691135e-17, /* logim[46] */ 3.90825918506438654133771548917512854530368619051813e-34, /* logil[46] */ } , { 8.44884872436523437500000000000000000000000000000000e-01, /* r[47] */ 1.68554906544493537934314986159733962267637252807617e-01, /* logih[47] */ -4.88067069357233088835045523845127031889038644659894e-18, /* logim[47] */ -2.74436628602599193485144954170980402729323560852447e-34, /* logil[47] */ } , { 8.42104911804199218750000000000000000000000000000000e-01, /* r[48] */ 1.71850674159259697582058379339287057518959045410156e-01, /* logih[48] */ -5.99824278835946286993892764844703773122678476390412e-18, /* logim[48] */ 3.70682933452027240591056472269948014540566701592829e-34, /* logil[48] */ } , { 8.39344024658203125000000000000000000000000000000000e-01, /* r[49] */ 1.75134615249951913762416211284289602190256118774414e-01, /* logih[49] */ -3.58390218411179180194443037963547505253027562280581e-18, /* logim[49] */ 3.31228661881018068740534361547868152976577021044761e-34, /* logil[49] */ } , { 8.36601257324218750000000000000000000000000000000000e-01, /* r[50] */ 1.78407717077464861299418430462537799030542373657227e-01, /* logih[50] */ -1.24324832026190372515095573175819374097319572461178e-17, /* logim[50] */ -5.99222696564577786410580709003476847421843326905428e-34, /* logil[50] */ } , { 8.33876609802246093750000000000000000000000000000000e-01, /* r[51] */ 1.81669837446455789686794446424755733460187911987305e-01, /* logih[51] */ 1.01814383360123408182300498809467596332645378664897e-18, /* logim[51] */ -3.86254258528557102676238695420952114271137939703806e-35, /* logil[51] */ } , { 8.31169128417968750000000000000000000000000000000000e-01, /* r[52] */ 1.84921980866207286142710586318571586161851882934570e-01, /* logih[52] */ 3.00841482639628279758161917890436573438957544374876e-18, /* logim[52] */ -4.99319538644221397164613342913055299248197716579930e-36, /* logil[52] */ } , { 8.28478813171386718750000000000000000000000000000000e-01, /* r[53] */ 1.88164014957424269303132291497604455798864364624023e-01, /* logih[53] */ 2.44293806976014644991303628324646254244852750452761e-18, /* logim[53] */ -1.81631690797919082130114101842168376499919500191654e-34, /* logil[53] */ } , { 8.25806617736816406250000000000000000000000000000000e-01, /* r[54] */ 1.91394651833973583610060131832142360508441925048828e-01, /* logih[54] */ -1.21322104713829577894210219067304263334028383887345e-17, /* logim[54] */ 5.04102454790153462302483289986561437522938374164401e-34, /* logil[54] */ } , { 8.23151588439941406250000000000000000000000000000000e-01, /* r[55] */ 1.94614905180994807176730887476878706365823745727539e-01, /* logih[55] */ -2.40704484907151006187800247197019539577410611794596e-18, /* logim[55] */ 1.66766736549683531224402325253460134456943558772782e-34, /* logil[55] */ } , { 8.20512771606445312500000000000000000000000000000000e-01, /* r[56] */ 1.97825802934566419288842098467284813523292541503906e-01, /* logih[56] */ 1.28212649590622342007825921152819823725126964367518e-17, /* logim[56] */ 4.34712978477783827374998481132430084872238812357849e-34, /* logil[56] */ } , { 8.17891120910644531250000000000000000000000000000000e-01, /* r[57] */ 2.01026055259733327229554333825944922864437103271484e-01, /* logih[57] */ -1.14998212245338630994656980851947792972358234996197e-17, /* logim[57] */ 5.79624076358083101943179592654253175121330546055049e-34, /* logil[57] */ } , { 8.15286636352539062500000000000000000000000000000000e-01, /* r[58] */ 2.04215526527529805944638496839615982025861740112305e-01, /* logih[58] */ 2.73382699896480606605004885268461286375739934002155e-18, /* logim[58] */ 1.88415596219599490517606146615135776386751947516623e-34, /* logil[58] */ } , { 8.12698364257812500000000000000000000000000000000000e-01, /* r[59] */ 2.07395253950717145530191487523552495986223220825195e-01, /* logih[59] */ -6.62391092234198860395870331818350936803399446817708e-18, /* logim[59] */ 3.21769751525760188204600268636020811532764524000701e-34, /* logil[59] */ } , { 8.10126304626464843750000000000000000000000000000000e-01, /* r[60] */ 2.10565111834115831213054548243235331028699874877930e-01, /* logih[60] */ -4.23598623593001075035023138647901308953697217452223e-18, /* logim[60] */ -1.60116079297919794843846440200207561215761229589523e-34, /* logil[60] */ } , { 8.07571411132812500000000000000000000000000000000000e-01, /* r[61] */ 2.13723792956059033265603375184582546353340148925781e-01, /* logih[61] */ 1.19332110118934137902010996837627215742078591974979e-17, /* logim[61] */ -7.02796906150255788492393691981023760796809185404715e-34, /* logil[61] */ } , { 8.05031776428222656250000000000000000000000000000000e-01, /* r[62] */ 2.16873528518765484873753734973433893173933029174805e-01, /* logih[62] */ 4.52808917121474736889640990984402645764765520737700e-18, /* logim[62] */ 2.11628056886638280859096959251776961524147228058240e-34, /* logil[62] */ } , { 8.02507400512695312500000000000000000000000000000000e-01, /* r[63] */ 2.20014202197813590888841872583725489675998687744141e-01, /* logih[63] */ -1.00259431805058570834488582628193862678340769016279e-17, /* logim[63] */ 2.36589934049562797440015684747135353020590849639512e-35, /* logil[63] */ } , { 8.00000190734863281250000000000000000000000000000000e-01, /* r[64] */ 2.23143312895659085004496091642067767679691314697266e-01, /* logih[64] */ -9.09578810556902738974378981655445966403155329846157e-18, /* logim[64] */ -5.51860343858009857142907585246296630664802326325794e-34, /* logil[64] */ } , { 7.97508239746093750000000000000000000000000000000000e-01, /* r[65] */ 2.26263112406488331451726025989046320319175720214844e-01, /* logih[65] */ 7.84336071516770930915783866759877344054363308944707e-18, /* logim[65] */ -7.43454080890818906474334427543025223771612621973504e-34, /* logil[65] */ } , { 7.95030593872070312500000000000000000000000000000000e-01, /* r[66] */ 2.29374682210301245044448137377912644296884536743164e-01, /* logih[66] */ 9.99309522150144532067602885659542180850459285940861e-18, /* logim[66] */ -4.39495185580213541392726686857289780092191688844937e-34, /* logil[66] */ } , { 7.92570114135742187500000000000000000000000000000000e-01, /* r[67] */ 2.32474305048552654096027936247992329299449920654297e-01, /* logih[67] */ 1.04347973999915730650942527525177991072062294027967e-17, /* logim[67] */ -1.80285268643432323262428865765338414917111027539735e-34, /* logil[67] */ } , { 7.90122985839843750000000000000000000000000000000000e-01, /* r[68] */ 2.35566667359392301062115393506246618926525115966797e-01, /* logih[68] */ -2.32375103902642573879242169796960376755737712824341e-18, /* logim[68] */ -7.21655842491838760103086913983188439028934238517299e-35, /* logil[68] */ } , { 7.87692070007324218750000000000000000000000000000000e-01, /* r[69] */ 2.38648039598734706956406625977251678705215454101562e-01, /* logih[69] */ 4.46784339552128548812794219055404768324811281554067e-18, /* logim[69] */ 3.43429150836221389256015518963937864776602443392546e-34, /* logil[69] */ } , { 7.85276412963867187500000000000000000000000000000000e-01, /* r[70] */ 2.41719504753563907417657219411921687424182891845703e-01, /* logih[70] */ 8.87409122027180881908249517818731600449617581699438e-18, /* logim[70] */ 3.56004039882748459631384958577457237860217830111311e-34, /* logil[70] */ } , { 7.82875061035156250000000000000000000000000000000000e-01, /* r[71] */ 2.44782160173725865659477562985557597130537033081055e-01, /* logih[71] */ 7.08526813357121959967478591264305016478056070347997e-19, /* logim[71] */ -2.15778795199788554090353514030659386443684641384067e-35, /* logil[71] */ } , { 7.80488014221191406250000000000000000000000000000000e-01, /* r[72] */ 2.47835895683715751180997699520958121865987777709961e-01, /* logih[72] */ -1.24386417338518064252295447791954905943026800534449e-17, /* logim[72] */ -7.44029524146381752722089691180123292021312364800709e-34, /* logil[72] */ } , { 7.78115272521972656250000000000000000000000000000000e-01, /* r[73] */ 2.50880600583786306234657104141660965979099273681641e-01, /* logih[73] */ -5.50964893191169223547312201897322976952633356221949e-18, /* logim[73] */ 1.08676143776419160887508248412493151436373152102143e-34, /* logil[73] */ } , { 7.75757789611816406250000000000000000000000000000000e-01, /* r[74] */ 2.53914934309519335631222247684490866959095001220703e-01, /* logih[74] */ 1.97004950260539049796252522941686709480407437591843e-17, /* logim[74] */ -4.67670757123999808225422970015919189294430827275674e-34, /* logil[74] */ } , { 7.73413658142089843750000000000000000000000000000000e-01, /* r[75] */ 2.56941240096642986578956424636999145150184631347656e-01, /* logih[75] */ 1.32566282149745092578207739537715284043427717085946e-17, /* logim[75] */ 4.53175814618419018222032309863239909606680701492128e-34, /* logil[75] */ } , { 7.71084785461425781250000000000000000000000000000000e-01, /* r[76] */ 2.59956943291808351137461841062759049236774444580078e-01, /* logih[76] */ 2.06326460492966557658914107366598455972739008175724e-17, /* logim[76] */ -7.60856026131926782522027611178961885575241901312259e-34, /* logil[76] */ } , { 7.68768310546875000000000000000000000000000000000000e-01, /* r[77] */ 2.62965641547506734365668989994446747004985809326172e-01, /* logih[77] */ 7.11583631875541699557981308503843876478401404595290e-18, /* logim[77] */ -3.16162183522749672668805346311289437550800994700732e-34, /* logil[77] */ } , { 7.66467094421386718750000000000000000000000000000000e-01, /* r[78] */ 2.65963511244235673025571031757863238453865051269531e-01, /* logih[78] */ -2.24162125724264292804912034054420308588570407662844e-17, /* logim[78] */ 4.90471140265143981765909599584287898945638617268867e-34, /* logil[78] */ } , { 7.64179229736328125000000000000000000000000000000000e-01, /* r[79] */ 2.68952923432744239740088687540264800190925598144531e-01, /* logih[79] */ 2.05657969150984247532516778784947182213125204986197e-17, /* logim[79] */ 8.79232077986017876500084195761038723390008355613575e-34, /* logil[79] */ } , { 7.61904716491699218750000000000000000000000000000000e-01, /* r[80] */ 2.71933775088288309795814257086021825671195983886719e-01, /* logih[80] */ 7.83390223779535346513505580003968001040971161798700e-19, /* logim[80] */ -3.02585215101390470982866376614279464778757620082138e-35, /* logil[80] */ } , { 7.59643554687500000000000000000000000000000000000000e-01, /* r[81] */ 2.74905962710071116728016704655601643025875091552734e-01, /* logih[81] */ 2.24378545796980422658699919057279901542517325778057e-17, /* logim[81] */ -3.78062443833687207202366076315857540989955154523774e-34, /* logil[81] */ } , { 7.57396697998046875000000000000000000000000000000000e-01, /* r[82] */ 2.77868123177963777248322685409220866858959197998047e-01, /* logih[82] */ -9.27762050905122039629311187603838349834122732550062e-19, /* logim[82] */ 9.57930007453583023320781825922648925161484087998588e-35, /* logil[82] */ } , { 7.55162239074707031250000000000000000000000000000000e-01, /* r[83] */ 2.80822666626178107929234784023719839751720428466797e-01, /* logih[83] */ -1.78889070415104263420345604636729594822616937899043e-17, /* logim[83] */ -8.11660316854587609717942096562096327563941648142083e-34, /* logil[83] */ } , { 7.52941131591796875000000000000000000000000000000000e-01, /* r[84] */ 2.83768232735291170421021433867281302809715270996094e-01, /* logih[84] */ -2.03265852251844689554711830689719609838328388091381e-17, /* logim[84] */ 3.99265876662456660849597520210659365811534845502505e-34, /* logil[84] */ } , { 7.50733375549316406250000000000000000000000000000000e-01, /* r[85] */ 2.86704716154329075639140000930638052523136138916016e-01, /* logih[85] */ 3.24928817686474637809609763405716794874549598154899e-18, /* logim[85] */ 7.05436161547905729808903355104769078626665732260995e-35, /* logil[85] */ } , { 7.48538017272949218750000000000000000000000000000000e-01, /* r[86] */ 2.89633285132462114930262941925320774316787719726562e-01, /* logih[86] */ -7.21962253363417273270454867455071277489833577725373e-18, /* logim[86] */ -2.16150227221931053192432009592422674631830770048369e-34, /* logil[86] */ } , { 7.46356010437011718750000000000000000000000000000000e-01, /* r[87] */ 2.92552566827507520841322730120737105607986450195312e-01, /* logih[87] */ -1.44160166726851833613115205797213493080706067439112e-17, /* logim[87] */ 1.50883511667334677559761930721175960406498771143078e-33, /* logil[87] */ } , { 7.44186401367187500000000000000000000000000000000000e-01, /* r[88] */ 2.95463736056791381745512126144603826105594635009766e-01, /* logih[88] */ -2.16822486635513901824879610162201037763987226540717e-17, /* logim[88] */ -1.40892440842074578649628629534891601913263524738738e-33, /* logil[88] */ } , { 7.42029190063476562500000000000000000000000000000000e-01, /* r[89] */ 2.98366696880353166054788971450761891901493072509766e-01, /* logih[89] */ 2.66045054346745240447394933749591251388042727860864e-17, /* logim[89] */ -3.07182222949536546434743015167904826317676758257458e-34, /* logil[89] */ } , { 7.39884376525878906250000000000000000000000000000000e-01, /* r[90] */ 3.01261352929903802877475982313626445829868316650391e-01, /* logih[90] */ 1.87070681938931680167624656750430985298856099421569e-17, /* logim[90] */ 1.51413799416501325421897094776870076323182009328971e-33, /* logil[90] */ } , { 7.37751960754394531250000000000000000000000000000000e-01, /* r[91] */ 3.04147607413525478126103962495108135044574737548828e-01, /* logih[91] */ 3.98176030022005428666814320744852118370551740170454e-18, /* logim[91] */ 3.59055661804361869634622461801260435821255127014094e-34, /* logil[91] */ } , { 7.35631942749023437500000000000000000000000000000000e-01, /* r[92] */ 3.07025363120511873837870098213898018002510070800781e-01, /* logih[92] */ -1.23081724383312479171164681702153119269476305242331e-17, /* logim[92] */ -6.24921351181214466368980458020870680109978000216335e-34, /* logil[92] */ } , { 7.33524322509765625000000000000000000000000000000000e-01, /* r[93] */ 3.09894522426349294796921185479732230305671691894531e-01, /* logih[93] */ -2.61915759435025688106872344425103515717035435880289e-17, /* logim[93] */ 4.37310119650947955282720454157502418725525261502025e-34, /* logil[93] */ } , { 7.31428146362304687500000000000000000000000000000000e-01, /* r[94] */ 3.12756291149352327884969326987629756331443786621094e-01, /* logih[94] */ -1.44526601334660927537554677783431908198308471431891e-17, /* logim[94] */ -3.16489425801456252779886240767137743149201554486977e-34, /* logil[94] */ } , { 7.29344367980957031250000000000000000000000000000000e-01, /* r[95] */ 3.15609274450035781622858621631166897714138031005859e-01, /* logih[95] */ -9.15211307104414041770693082901206817295591874336170e-18, /* logim[95] */ 6.92571319717017620584068946677928779786499453239802e-34, /* logil[95] */ } , { 7.27272987365722656250000000000000000000000000000000e-01, /* r[96] */ 3.18453373490729885197936255281092599034309387207031e-01, /* logih[96] */ 2.70995327783651104083044967572356846238550856314185e-17, /* logim[96] */ 1.34600088520445299315193549306530996100489980654781e-33, /* logil[96] */ } , { 7.25212097167968750000000000000000000000000000000000e-01, /* r[97] */ 3.21291119093343235935122947921627201139926910400391e-01, /* logih[97] */ -1.12319519421036650171892375714176815116984091579206e-17, /* logim[97] */ 1.04447652287031956508644916042846488744189014580391e-34, /* logil[97] */ } , { 7.23163604736328125000000000000000000000000000000000e-01, /* r[98] */ 3.24119796479811983491714499905356205999851226806641e-01, /* logih[98] */ -7.94647062012309773892598593677083791992627350537440e-18, /* logim[98] */ 4.59384159170382657706167409359736689725722940359763e-34, /* logil[98] */ } , { 7.21126556396484375000000000000000000000000000000000e-01, /* r[99] */ 3.26940628117956100240348860097583383321762084960938e-01, /* logih[99] */ -1.74837694038376657608222314076357694142138010418063e-17, /* logim[99] */ -1.40581148273538852383687808274899460858762058571376e-34, /* logil[99] */ } , { 7.19100952148437500000000000000000000000000000000000e-01, /* r[100] */ 3.29753524791075502964332599731278605759143829345703e-01, /* logih[100] */ 2.12653812605676265381615743640534834022512048496019e-18, /* logim[100] */ 5.25095014117827902230536920855568345417341287940175e-35, /* logil[100] */ } , { 7.17086791992187500000000000000000000000000000000000e-01, /* r[101] */ 3.32558396904723163611805603068205527961254119873047e-01, /* logih[101] */ -1.04519949901622285684034183132329427334699936682984e-17, /* logim[101] */ 4.45654546722256244026954176794662799321355430560371e-34, /* logil[101] */ } , { 7.15084075927734375000000000000000000000000000000000e-01, /* r[102] */ 3.35355154491021822948937369801569730043411254882812e-01, /* logih[102] */ 1.83262596742990833823701524552706571217123614816200e-17, /* logim[102] */ -1.29569615760463452723681409704842983753419687255982e-33, /* logil[102] */ } , { 7.13091850280761718750000000000000000000000000000000e-01, /* r[103] */ 3.38145044591559529312263521205750294029712677001953e-01, /* logih[103] */ -1.46763527756214729603846930349999949900828274067634e-17, /* logim[103] */ 3.85996984621058858499977696727737728999708408076829e-34, /* logil[103] */ } , { 7.11111068725585937500000000000000000000000000000000e-01, /* r[104] */ 3.40926646575239744585417156486073508858680725097656e-01, /* logih[104] */ 1.74672070296268393919501631375949801326271042364782e-17, /* logim[104] */ 1.28757784323920807504216254145051967795248381758825e-33, /* logil[104] */ } , { 7.09141731262207031250000000000000000000000000000000e-01, /* r[105] */ 3.43699869378304490030728857163921929895877838134766e-01, /* logih[105] */ -5.19524092664710997838651465181771916951448804942375e-18, /* logim[105] */ 2.01852276300632912138205204757451068299686003381730e-34, /* logil[105] */ } , { 1.41436386108398437500000000000000000000000000000000e+00, /* r[106] */ -3.46679861870620553698785215601674281060695648193359e-01, /* logih[106] */ -1.28487666876426526117753107153366705047319625953434e-17, /* logim[106] */ 1.35559275452957780052106182147355087625385646501787e-37, /* logil[106] */ } , { 1.41046905517578125000000000000000000000000000000000e+00, /* r[107] */ -3.43922312315162792550893300358438864350318908691406e-01, /* logih[107] */ 4.92019729190951095471164720202037831908390366509329e-18, /* logim[107] */ 3.82551714632527355673617639808721263761194697351796e-34, /* logil[107] */ } , { 1.40659332275390625000000000000000000000000000000000e+00, /* r[108] */ -3.41170697798120592381110327551141381263732910156250e-01, /* logih[108] */ 1.93668606486849623510457675345565515553170548397263e-17, /* logim[108] */ -6.31924577586791945681481090971933602378723267089765e-34, /* logil[108] */ } , { 1.40274047851562500000000000000000000000000000000000e+00, /* r[109] */ -3.38427807898675381270692241741926409304141998291016e-01, /* logih[109] */ 6.54538052872786451417312049621269831217791334849587e-18, /* logim[109] */ -1.38134173915396180632358800838166951094785757798298e-34, /* logil[109] */ } , { 1.39890670776367187500000000000000000000000000000000e+00, /* r[110] */ -3.35691008516038780218337933547445572912693023681641e-01, /* logih[110] */ 7.19133786441628176722646778964275817014488601387322e-18, /* logim[110] */ 2.28260205775013127550656696784879220819429866829588e-36, /* logil[110] */ } , { 1.39509582519531250000000000000000000000000000000000e+00, /* r[111] */ -3.32963104810430066127224790761829353868961334228516e-01, /* logih[111] */ 2.31257782383773679965596591934497042170211009414751e-17, /* logim[111] */ -8.99899918826696456699888760884182179403739540341569e-34, /* logil[111] */ } , { 1.39130401611328125000000000000000000000000000000000e+00, /* r[112] */ -3.30241448451969343835799008957110345363616943359375e-01, /* logih[112] */ 1.08328391473436749190918194684471671377932692613855e-17, /* logim[112] */ 2.05469820214513767177005852735365876929387324182847e-34, /* logil[112] */ } , { 1.38753318786621093750000000000000000000000000000000e+00, /* r[113] */ -3.27527485535248186199197562018525786697864532470703e-01, /* logih[113] */ 2.56707416856969394221064681139222300535027158809986e-17, /* logim[113] */ 2.48018075170015936943477306695127673525907564478115e-34, /* logil[113] */ } , { 1.38378334045410156250000000000000000000000000000000e+00, /* r[114] */ -3.24821299026220644545759341781376861035823822021484e-01, /* logih[114] */ -2.40283588419711964440744928607170649222918319264531e-17, /* logim[114] */ 1.40448044142609986920740213180800276002578003774456e-33, /* logil[114] */ } , { 1.38005447387695312500000000000000000000000000000000e+00, /* r[115] */ -3.22122972213921499040623075416078791022300720214844e-01, /* logih[115] */ -1.66818907547914379914312063731519121720479863896485e-17, /* logim[115] */ -8.55009499177937534961617974327717063975398325813083e-34, /* logil[115] */ } , { 1.37634468078613281250000000000000000000000000000000e+00, /* r[116] */ -3.19431202899942479067618705812492407858371734619141e-01, /* logih[116] */ -1.38115565915964367886690142912485000070964727867745e-18, /* logim[116] */ -1.22984664179014233019202567735778158211873499167925e-35, /* logil[116] */ } , { 1.37265396118164062500000000000000000000000000000000e+00, /* r[117] */ -3.16746063834650870560949442733544856309890747070312e-01, /* logih[117] */ -1.15419278228466239427477637425076471306644591952148e-17, /* logim[117] */ 3.41592451858080777739018945315482424309486529068749e-34, /* logil[117] */ } , { 1.36898422241210937500000000000000000000000000000000e+00, /* r[118] */ -3.14069021340052600965719875603099353611469268798828e-01, /* logih[118] */ -7.31349707246752102101544908905981332227259572261770e-18, /* logim[118] */ -3.93910979025310412654744290737242169075928226381889e-34, /* logil[118] */ } , { 1.36533355712890625000000000000000000000000000000000e+00, /* r[119] */ -3.11398762981856647158451778523158282041549682617188e-01, /* logih[119] */ -2.10262028332851499303996266991953733885100475347425e-17, /* logim[119] */ 3.10172118073247334983412381313166324533523917848591e-34, /* logil[119] */ } , { 1.36170196533203125000000000000000000000000000000000e+00, /* r[120] */ -3.08735362440316629673020543123129755258560180664062e-01, /* logih[120] */ 1.61997507738300932313233656106715605269821143050038e-17, /* logim[120] */ -4.94737397643073988821957091336118905427415985059196e-34, /* logil[120] */ } , { 1.35808944702148437500000000000000000000000000000000e+00, /* r[121] */ -3.06078893698965515124399416890810243785381317138672e-01, /* logih[121] */ -2.14383901488893084851347644248966504652364110743417e-17, /* logim[121] */ -1.04285659471621119336484757092986113762774232464117e-34, /* logil[121] */ } , { 1.35449790954589843750000000000000000000000000000000e+00, /* r[122] */ -3.03430839201768942636761039466364309191703796386719e-01, /* logih[122] */ -2.36272540975444581798067226838922324791286981755800e-17, /* logim[122] */ 7.63193414263891924102062717951976678650366075861562e-34, /* logil[122] */ } , { 1.35092353820800781250000000000000000000000000000000e+00, /* r[123] */ -3.00788460935273893603891792736249044537544250488281e-01, /* logih[123] */ 1.31911240315125569456750230823426654574574756805059e-17, /* logim[123] */ 6.09798153293836260383095031169419558002984888039367e-34, /* logil[123] */ } , { 1.34736824035644531250000000000000000000000000000000e+00, /* r[124] */ -2.98153238208616611082391045783879235386848449707031e-01, /* logih[124] */ 1.72077626940949324831538094445960560173054776887669e-17, /* logim[124] */ 1.50419727472329867273356373006418522570851500586450e-33, /* logil[124] */ } , { 1.34383201599121093750000000000000000000000000000000e+00, /* r[125] */ -2.95525246187516521523264145798748359084129333496094e-01, /* logih[125] */ 6.61166908095413536634982853435304018965741335429843e-18, /* logim[125] */ -1.66439777489787908751728074566359602553422366675323e-34, /* logil[125] */ } , { 1.34031486511230468750000000000000000000000000000000e+00, /* r[126] */ -2.92904560325168261680772729960153810679912567138672e-01, /* logih[126] */ -6.83776292620451776752481870270640194860145197512462e-18, /* logim[126] */ 1.55562105120034357822530615049801316732267321042243e-34, /* logil[126] */ } , { 1.33681488037109375000000000000000000000000000000000e+00, /* r[127] */ -2.90289829573938562568002907937625423073768615722656e-01, /* logih[127] */ 1.05531301797230420241902730814804872346105655886287e-17, /* logim[127] */ 4.79041533288401481752223531420283794797478252934091e-34, /* logil[127] */ } , { 1.33333396911621093750000000000000000000000000000000e+00, /* r[128] */ -2.87682549288825417654891225538449361920356750488281e-01, /* logih[128] */ -2.61077462239171302791459888459712394960284043875709e-17, /* logim[128] */ 2.49074425570525367279357114033805399391008799131216e-34, /* logil[128] */ } , { 1.32987022399902343750000000000000000000000000000000e+00, /* r[129] */ -2.85081361532236732259093514585401862859725952148438e-01, /* logih[129] */ 5.43627399844908067645917310959280553768099267155506e-18, /* logim[129] */ -1.40940968647840734289903124482303996508342832614184e-34, /* logil[129] */ } , { 1.32642555236816406250000000000000000000000000000000e+00, /* r[130] */ -2.82487769664605981034810611163266003131866455078125e-01, /* logih[130] */ 1.40579607152920466183148026056253132184915242828454e-17, /* logim[130] */ 8.55245308058326661171909652892008079386885810342353e-35, /* logil[130] */ } , { 1.32299804687500000000000000000000000000000000000000e+00, /* r[131] */ -2.79900408846770476500864788249600678682327270507812e-01, /* logih[131] */ -1.83143097611448426823122105710887862843742634907885e-17, /* logim[131] */ 7.32680743617844937675707357797053020869120027100328e-34, /* logil[131] */ } , { 1.31958770751953125000000000000000000000000000000000e+00, /* r[132] */ -2.77319345020877350282972884087939746677875518798828e-01, /* logih[132] */ 7.44521346975934828880026635948320543669274837358637e-18, /* logim[132] */ -5.41922476182319969711469733445405189836277342215443e-34, /* logil[132] */ } , { 1.31619453430175781250000000000000000000000000000000e+00, /* r[133] */ -2.74744644396217541082449997702497057616710662841797e-01, /* logih[133] */ -1.35539016985663678510001485327198622349128587937948e-17, /* logim[133] */ -2.47605212552478755864671758320404239244847510600429e-34, /* logil[133] */ } , { 1.31282043457031250000000000000000000000000000000000e+00, /* r[134] */ -2.72177826311169102080356196893262676894664764404297e-01, /* logih[134] */ -1.94604737767255604321061638736698666324990178271015e-17, /* logim[134] */ 4.93318792723831633917605655356651628446409622108869e-34, /* logil[134] */ } , { 1.30946350097656250000000000000000000000000000000000e+00, /* r[135] */ -2.69617512088877908649209302893723361194133758544922e-01, /* logih[135] */ -4.36842068525796679795304490876810534098425489515634e-19, /* logim[135] */ -2.59640519936698818691794834943491001573704557192093e-35, /* logil[135] */ } , { 1.30612182617187500000000000000000000000000000000000e+00, /* r[136] */ -2.67062308411773363658880953153129667043685913085938e-01, /* logih[136] */ 7.36505541266105414954508218919326623562242166589177e-18, /* logim[136] */ 4.30859840846165501987206211849479522591226050316009e-34, /* logil[136] */ } , { 1.30279922485351562500000000000000000000000000000000e+00, /* r[137] */ -2.64515199434744108231143400189466774463653564453125e-01, /* logih[137] */ -1.68423739176487233694295158507739753610875825604997e-17, /* logim[137] */ -2.52387133235317228793067248082680461143877917377527e-34, /* logil[137] */ } , { 1.29949188232421875000000000000000000000000000000000e+00, /* r[138] */ -2.61973328311307873672575396994943730533123016357422e-01, /* logih[138] */ -3.75057237736452977469227410853090805509462799202680e-18, /* logim[138] */ -2.50001621249400187276643559364982462572917581991553e-34, /* logil[138] */ } , { 1.29620170593261718750000000000000000000000000000000e+00, /* r[139] */ -2.59438223113541976960760848669451661407947540283203e-01, /* logih[139] */ -1.75050620652398740735421575793594666738296743072718e-18, /* logim[139] */ -1.76879556289338598533013427354560697647411264656770e-34, /* logil[139] */ } , { 1.29292869567871093750000000000000000000000000000000e+00, /* r[140] */ -2.56909951848923512329747609328478574752807617187500e-01, /* logih[140] */ -2.49955762333036735703890989320152300242733956262258e-17, /* logim[140] */ 6.46984311731974220303858069024859972656679564537485e-34, /* logil[140] */ } , { 1.28967285156250000000000000000000000000000000000000e+00, /* r[141] */ -2.54388582770868065807690072688274085521697998046875e-01, /* logih[141] */ 1.42784459055047481334238305742929320333571952363668e-17, /* logim[141] */ 1.44560161052022205741731365640574141772476641472904e-33, /* logil[141] */ } , { 1.28643226623535156250000000000000000000000000000000e+00, /* r[142] */ -2.51872701711453261808060233306605368852615356445312e-01, /* logih[142] */ -2.58573188266130078596915247890597291360969537163785e-17, /* logim[142] */ 3.36064630885731507350249551263037246653963144676932e-34, /* logil[142] */ } , { 1.28320884704589843750000000000000000000000000000000e+00, /* r[143] */ -2.49363852624658294265813651691132690757513046264648e-01, /* logih[143] */ 6.17564000922762053278709883095158100872225794241962e-18, /* logim[143] */ -3.59696250405991778286139521640842821567504780771091e-34, /* logil[143] */ } , { 1.28000068664550781250000000000000000000000000000000e+00, /* r[144] */ -2.46860614373184877878841803067189175635576248168945e-01, /* logih[144] */ -1.36688909483265210237069537981338704526084198528804e-17, /* logim[144] */ -4.92999816324333714793093560012211883282871708512667e-34, /* logil[144] */ } , { 1.27680778503417968750000000000000000000000000000000e+00, /* r[145] */ -2.44363044996024708632731403668003622442483901977539e-01, /* logih[145] */ 1.09486381393098425629951474169192910961933895685875e-17, /* logim[145] */ 1.13614657049426843838447103108579796261058240882279e-34, /* logil[145] */ } , { 1.27363204956054687500000000000000000000000000000000e+00, /* r[146] */ -2.41872700333246426485089841662556864321231842041016e-01, /* logih[146] */ 3.58546134799758558220376210039678485387885916926961e-18, /* logim[146] */ -2.20085959592144414214775971267831972426029128230714e-34, /* logil[146] */ } , { 1.27047157287597656250000000000000000000000000000000e+00, /* r[147] */ -2.39388148774497988569009976345114409923553466796875e-01, /* logih[147] */ -8.15278529428586557427891691038658199587387144643622e-18, /* logim[147] */ -4.48801512822497796294159745847501737318770920712608e-34, /* logil[147] */ } , { 1.26732635498046875000000000000000000000000000000000e+00, /* r[148] */ -2.36909449055089427194076279192813672125339508056641e-01, /* logih[148] */ -1.95941703600043116666763494344574061919652321991003e-18, /* logim[148] */ -7.12890529228103914163560488030577203415481759502335e-36, /* logil[148] */ } , { 1.26419830322265625000000000000000000000000000000000e+00, /* r[149] */ -2.34438168880390956916315303715236950665712356567383e-01, /* logih[149] */ -6.99651372151112997059366610960978925151468620541361e-18, /* logim[149] */ 2.72198075748279584311862548086147097324308430232999e-34, /* logil[149] */ } , { 1.26108360290527343750000000000000000000000000000000e+00, /* r[150] */ -2.31971353679059938412976293875544797629117965698242e-01, /* logih[150] */ -5.77385522134567574535417063256881508583112235194305e-18, /* logim[150] */ 3.79366854190657220850283401392416116381504642214271e-34, /* logil[150] */ } , { 1.25798606872558593750000000000000000000000000000000e+00, /* r[151] */ -2.29512084071926747430580917352926917374134063720703e-01, /* logih[151] */ -8.73917888836756753861059666333090512067547544675485e-18, /* logim[151] */ -5.69482104001851921922283043288492925754991621288172e-34, /* logil[151] */ } , { 1.25490188598632812500000000000000000000000000000000e+00, /* r[152] */ -2.27057391030699523559732710964453872293233871459961e-01, /* logih[152] */ -9.55134517665639461592830714479938653876650013848813e-18, /* logim[152] */ -7.00052160915705629865262646818211330004502638341784e-34, /* logil[152] */ } , { 1.25183296203613281250000000000000000000000000000000e+00, /* r[153] */ -2.24608846873032674817949327916721813380718231201172e-01, /* logih[153] */ -2.19162128124331068197096372804387663813879070153910e-18, /* logim[153] */ 8.00496321203755877183709886194177284253312594316861e-35, /* logil[153] */ } , { 1.24878120422363281250000000000000000000000000000000e+00, /* r[154] */ -2.22168039035695707994477743341121822595596313476562e-01, /* logih[154] */ 1.07342637360833029593335438601345228992436813797418e-17, /* logim[154] */ -7.67553083967135214121581596311206028889095496603001e-34, /* logil[154] */ } , { 1.24574279785156250000000000000000000000000000000000e+00, /* r[155] */ -2.19731976787238214576802874944405630230903625488281e-01, /* logih[155] */ -1.35345511944004269567659266993040497754817745842460e-17, /* logim[155] */ -7.06055747414660075242875132218211703222886262645151e-34, /* logil[155] */ } , { 1.24271774291992187500000000000000000000000000000000e+00, /* r[156] */ -2.17300709445695711119483917173056397587060928344727e-01, /* logih[156] */ -1.55632648024565809587441742115549412481509415401206e-18, /* logim[156] */ -2.73645872916697873734554009814155050548437865470935e-35, /* logil[156] */ } , { 1.23970985412597656250000000000000000000000000000000e+00, /* r[157] */ -2.14877363629256634691699900940875522792339324951172e-01, /* logih[157] */ 5.51412653363101081432833599630524903528204879298177e-18, /* logim[157] */ 1.93479402223180105608082323440368830737884048556178e-34, /* logil[157] */ } , { 1.23671531677246093750000000000000000000000000000000e+00, /* r[158] */ -2.12458926885637500170389557752059772610664367675781e-01, /* logih[158] */ 9.62416986757368333294762208707250932658825738879454e-18, /* logim[158] */ 1.34243694982089823913061491133601163572475339258708e-34, /* logil[158] */ } , { 1.23373413085937500000000000000000000000000000000000e+00, /* r[159] */ -2.10045449157502006620745760301360860466957092285156e-01, /* logih[159] */ -1.14897192287332807026526402359503839328475948011071e-17, /* logim[159] */ 3.22998731854659925401919707956820087718358954278512e-34, /* logil[159] */ } , { 1.23077011108398437500000000000000000000000000000000e+00, /* r[160] */ -2.07640080033725998864824191514344420284032821655273e-01, /* logih[160] */ -1.21752158956595077938199084785214052668704102263663e-17, /* logim[160] */ 3.85113498704488412720849922642321502513839838743598e-34, /* logil[160] */ } , { 1.22781753540039062500000000000000000000000000000000e+00, /* r[161] */ -2.05238231877337917730130811833078041672706604003906e-01, /* logih[161] */ -6.49170319816279074800980031896509389281475760737419e-18, /* logim[161] */ 7.54230794214336863035202362512077511130553782508548e-35, /* logil[161] */ } , { 1.22488021850585937500000000000000000000000000000000e+00, /* r[162] */ -2.02843058404291731733337655896320939064025878906250e-01, /* logih[162] */ -2.09733857251185914090082750810867355591642377167668e-18, /* logim[162] */ -7.58503055294887496788011335562125472007511746053015e-35, /* logil[162] */ } , { 1.22195625305175781250000000000000000000000000000000e+00, /* r[163] */ -2.00453060641940739028399320886819623410701751708984e-01, /* logih[163] */ -6.53774572382445798876000474193661396320697712784592e-18, /* logim[163] */ 3.51772439194901607097398534803672574024027259307605e-34, /* logil[163] */ } , { 1.21904754638671875000000000000000000000000000000000e+00, /* r[164] */ -1.98069854157447239328959653903439175337553024291992e-01, /* logih[164] */ -3.74277289637934596837745314540095849706853736054736e-18, /* logim[164] */ 2.20940287174632344749918330821286328950105212564345e-34, /* logil[164] */ } , { 1.21615219116210937500000000000000000000000000000000e+00, /* r[165] */ -1.95691932918147681874643240007571876049041748046875e-01, /* logih[165] */ -7.08261236288433014439133183526990067310528978959932e-18, /* logim[165] */ -1.96435463626369637687474243037286042706661477855383e-34, /* logil[165] */ } , { 1.21327018737792968750000000000000000000000000000000e+00, /* r[166] */ -1.93319348256398265695210625381150748580694198608398e-01, /* logih[166] */ -4.63045754803609100012916107813305239709411987466506e-18, /* logim[166] */ 3.81311992624323390610440652445847060246376140730432e-34, /* logil[166] */ } , { 1.21040153503417968750000000000000000000000000000000e+00, /* r[167] */ -1.90952151695252925200918525661109015345573425292969e-01, /* logih[167] */ -5.80616769316522716849138580075656569977606755839734e-18, /* logim[167] */ 1.34601476508880492535970189187338024694052031880198e-34, /* logil[167] */ } , { 1.20754623413085937500000000000000000000000000000000e+00, /* r[168] */ -1.88590394946867745407104166588396765291690826416016e-01, /* logih[168] */ 7.58724192474608110981409818070149841661745061197758e-18, /* logim[168] */ 5.09865531698430288976485112090438508546399086848170e-34, /* logil[168] */ } , { 1.20470619201660156250000000000000000000000000000000e+00, /* r[169] */ -1.86235713160088522943880207094480283558368682861328e-01, /* logih[169] */ 9.83598941678855625746040824683214800947055255023752e-18, /* logim[169] */ 2.46513729584939313689642856331884108597210035577156e-35, /* logil[169] */ } , { 1.20187759399414062500000000000000000000000000000000e+00, /* r[170] */ -1.83884995648034593740405284734151791781187057495117e-01, /* logih[170] */ -6.70852935530959296202331099325187741392981643909817e-18, /* logim[170] */ 3.00844769658087560728352059501736867279973513368500e-34, /* logil[170] */ } , { 1.19906234741210937500000000000000000000000000000000e+00, /* r[171] */ -1.81539874203132112207015325111569836735725402832031e-01, /* logih[171] */ 9.29803006036969326009349085152256934923841308327213e-18, /* logim[171] */ -5.87687279777529126455867415463448459437016045941915e-34, /* logil[171] */ } , { 1.19626235961914062500000000000000000000000000000000e+00, /* r[172] */ -1.79201995701676053407425115437945351004600524902344e-01, /* logih[172] */ 1.07244987411303504039951333305926418667267361291349e-17, /* logim[172] */ 6.96460410267841846987295265759921471979042436315030e-34, /* logil[172] */ } , { 1.19347381591796875000000000000000000000000000000000e+00, /* r[173] */ -1.76868227651996584581794991208880674093961715698242e-01, /* logih[173] */ -1.10573571536398568326433843554050954952961171968919e-17, /* logim[173] */ -7.15366049912217554019889444240641484300247544429326e-34, /* logil[173] */ } , { 1.19069862365722656250000000000000000000000000000000e+00, /* r[174] */ -1.74540213563705776111945056072727311402559280395508e-01, /* logih[174] */ 1.41441535586615290351432125355737755606926544229499e-18, /* logim[174] */ -9.09232357027904656212336285800609485022315015052927e-35, /* logil[174] */ } , { 1.18793487548828125000000000000000000000000000000000e+00, /* r[175] */ -1.72216400825300264276762618464999832212924957275391e-01, /* logih[175] */ 4.70555006507071052711499439464966393443028017169630e-18, /* logim[175] */ -2.05933939394796488034283377335053411303251320729741e-36, /* logil[175] */ } , { 1.18518447875976562500000000000000000000000000000000e+00, /* r[176] */ -1.69898440748772083797035747920745052397251129150391e-01, /* logih[176] */ 5.57386986936216704195834036089361797810285720893573e-19, /* logim[176] */ 1.95979458384118524767836145844611746655750937760436e-35, /* logil[176] */ } , { 1.18244743347167968750000000000000000000000000000000e+00, /* r[177] */ -1.67586386672116810503396777676243800669908523559570e-01, /* logih[177] */ -2.10518678245997312072852724987229988978414584927966e-18, /* logim[177] */ 1.28828497071302497365120049253927765655050473764692e-34, /* logil[177] */ } , { 1.17972373962402343750000000000000000000000000000000e+00, /* r[178] */ -1.65280292104758808058306840393925085663795471191406e-01, /* logih[178] */ 6.23517789601925714710479118600106051919949505966744e-19, /* logim[178] */ -3.18208255979837719298953172591840257465716328738635e-35, /* logil[178] */ } , { 1.17701148986816406250000000000000000000000000000000e+00, /* r[179] */ -1.62978590225533376267819107852119486778974533081055e-01, /* logih[179] */ -9.90718539912068708756719628839252162668848272704435e-18, /* logim[179] */ 2.65318297676807803018499365510556573456222990710937e-34, /* logil[179] */ } , { 1.17431259155273437500000000000000000000000000000000e+00, /* r[180] */ -1.60682947934438519199673578441434074193239212036133e-01, /* logih[180] */ 3.58966483931976449925223154468506323464461604873135e-18, /* logim[180] */ -2.61108466517449169019772324573366398622685617699208e-35, /* logil[180] */ } , { 1.17162513732910156250000000000000000000000000000000e+00, /* r[181] */ -1.58391791297011308436992749193450435996055603027344e-01, /* logih[181] */ 1.17290336952422323777350005767652445704229453391095e-17, /* logim[181] */ -2.09345211610593757799592941150206031045717866622119e-34, /* logil[181] */ } , { 1.16894912719726562500000000000000000000000000000000e+00, /* r[182] */ -1.56105163319945505762120774306822568178176879882812e-01, /* logih[182] */ 1.28628359267905556190943307276740736661339408993324e-17, /* logim[182] */ -5.95304689974676498338427563732575867009069071311929e-34, /* logil[182] */ } , { 1.16628646850585937500000000000000000000000000000000e+00, /* r[183] */ -1.53824742577648665431411245663184672594070434570312e-01, /* logih[183] */ -1.21520306098644174029034710109981732360242413879415e-18, /* logim[183] */ -3.46376210577156535712238040881332980606390914922373e-35, /* logil[183] */ } , { 1.16363716125488281250000000000000000000000000000000e+00, /* r[184] */ -1.51550583580380926473907265972229652106761932373047e-01, /* logih[184] */ -5.27431191607729841894071463956904781997884546886957e-18, /* logim[184] */ -2.12312727053942207829403955523840244683485282807904e-34, /* logil[184] */ } , { 1.16099739074707031250000000000000000000000000000000e+00, /* r[185] */ -1.49279455294684920696468566347903106361627578735352e-01, /* logih[185] */ 1.30791371646357520506414737413216453391959478831327e-17, /* logim[185] */ 7.56862790077388154224564404755685931026804721911961e-34, /* logil[185] */ } , { 1.15837097167968750000000000000000000000000000000000e+00, /* r[186] */ -1.47014683357163111754317696977523155510425567626953e-01, /* logih[186] */ 4.46701777108311388441189058844554903695616000674812e-18, /* logim[186] */ -1.53168389834566630100313932781112142055948393405761e-34, /* logil[186] */ } , { 1.15575599670410156250000000000000000000000000000000e+00, /* r[187] */ -1.44754672455130850572402323450660333037376403808594e-01, /* logih[187] */ -1.11765997308804560786725769664171557832093187263628e-17, /* logim[187] */ -2.54391351083201803872348589456916885864191215547753e-34, /* logil[187] */ } , { 1.15315246582031250000000000000000000000000000000000e+00, /* r[188] */ -1.42499466560657650493482151432544924318790435791016e-01, /* logih[188] */ 9.99697434471805963116106325782098963574947115358262e-18, /* logim[188] */ -4.16991647873877558887722645601154258382043780560798e-34, /* logil[188] */ } , { 1.15056228637695312500000000000000000000000000000000e+00, /* r[189] */ -1.40250767556271416225399661925621330738067626953125e-01, /* logih[189] */ -2.42967383902664590341317347111432842699638485445637e-18, /* logim[189] */ 1.89046895909651011241835667303830696393887263209723e-35, /* logil[189] */ } , { 1.14798164367675781250000000000000000000000000000000e+00, /* r[190] */ -1.38005307940927829379873514881182927638292312622070e-01, /* logih[190] */ 3.09897250271566693336611278140158537034235759176630e-18, /* logim[190] */ 4.18076944171954954430079149735725094064207802954500e-35, /* logil[190] */ } , { 1.14541435241699218750000000000000000000000000000000e+00, /* r[191] */ -1.35766451383654063178596516081597656011581420898438e-01, /* logih[191] */ -1.26737144704388924877419888090078242028004784977676e-17, /* logim[191] */ -6.55254988981886759240332153938275164053851414525063e-34, /* logil[191] */ } , { 1.14285659790039062500000000000000000000000000000000e+00, /* r[192] */ -1.33530915787250736848079668561695143580436706542969e-01, /* logih[192] */ 3.70059774900097017560711245248993036856587443848886e-18, /* logim[192] */ -1.44076022950175208091543146453702789322369025821334e-34, /* logil[192] */ } , { 1.14031219482421875000000000000000000000000000000000e+00, /* r[193] */ -1.31302080023902228989030049888242501765489578247070e-01, /* logih[193] */ 9.77595259647047985795328829376646744546732643730202e-18, /* logim[193] */ 7.14001485916042767804723486534578453220499721661498e-34, /* logil[193] */ } , { 1.13777732849121093750000000000000000000000000000000e+00, /* r[194] */ -1.29076647394292753912026228135800920426845550537109e-01, /* logih[194] */ 1.29614980241403171231290027930196525012258765738554e-17, /* logim[194] */ -5.85566533144206341645149580771754974185386331638589e-34, /* logil[194] */ } , { 1.13525581359863281250000000000000000000000000000000e+00, /* r[195] */ -1.26858011968173783889923811329936143010854721069336e-01, /* logih[195] */ -1.69678439390834976532815985483256409225876795508054e-18, /* logim[195] */ -2.71228529760193445477650881984529057919186509828788e-35, /* logil[195] */ } , { 1.13274383544921875000000000000000000000000000000000e+00, /* r[196] */ -1.24642862439702989396650423259416129440069198608398e-01, /* logih[196] */ 5.78470166144150337574069781581246057448668006106709e-18, /* logim[196] */ -1.51194875373975987733573028833303263737665603241701e-34, /* logil[196] */ } , { 1.13024330139160156250000000000000000000000000000000e+00, /* r[197] */ -1.22432920514188886551565360605309251695871353149414e-01, /* logih[197] */ -1.49693760153482569091449280029762521944027633466473e-18, /* logim[197] */ -5.39965434369591591869001705818915138621233644825736e-35, /* logil[197] */ } , { 1.12775421142578125000000000000000000000000000000000e+00, /* r[198] */ -1.20228231660540529901481932029128074645996093750000e-01, /* logih[198] */ 2.66388161368585650190234204294063114917602653271451e-18, /* logim[198] */ -4.74069350504018899441229048102955157835045789801575e-35, /* logil[198] */ } , { 1.12527465820312500000000000000000000000000000000000e+00, /* r[199] */ -1.18027146483910813645756832102051703259348869323730e-01, /* logih[199] */ -3.60219775645429345296067350839693560520470018134018e-18, /* logim[199] */ -2.54791949912299670752413217558541051658120178578709e-36, /* logil[199] */ } , { 1.12280654907226562500000000000000000000000000000000e+00, /* r[200] */ -1.15831398292521231541130077857815194875001907348633e-01, /* logih[200] */ -4.31427333715618757910709691609269654043220111432066e-18, /* logim[200] */ -9.92584460384660583856113744874441511647452425237725e-35, /* logil[200] */ } , { 1.12034988403320312500000000000000000000000000000000e+00, /* r[201] */ -1.13641032979606732000732449705537874251604080200195e-01, /* logih[201] */ -2.80052852737773106136039129617512559000765084602728e-18, /* logim[201] */ 1.05442382041672403942755754838681010220413395137635e-34, /* logil[201] */ } , { 1.11790466308593750000000000000000000000000000000000e+00, /* r[202] */ -1.11456096576200411329971018403739435598254203796387e-01, /* logih[202] */ -5.77990794389030241792168588642671979086900695176190e-18, /* logim[202] */ -1.69142770089478743453734869721080946466526879559136e-35, /* logil[202] */ } , { 1.11546897888183593750000000000000000000000000000000e+00, /* r[203] */ -1.09274925343603279692672458622837439179420471191406e-01, /* logih[203] */ -3.85400236141315267161376748908212877710726873076641e-18, /* logim[203] */ -2.42661397467022652703862793756433704621690971685882e-34, /* logil[203] */ } , { 1.11304283142089843750000000000000000000000000000000e+00, /* r[204] */ -1.07097554410911677269524489020113833248615264892578e-01, /* logih[204] */ 1.80247443768247945406811707831640352654515433418144e-18, /* logim[204] */ -1.85453257375612125088595374639844790140667033156959e-34, /* logil[204] */ } , { 1.11062812805175781250000000000000000000000000000000e+00, /* r[205] */ -1.04925736401603963976469913177425041794776916503906e-01, /* logih[205] */ 2.91414777009923095944264947235313742597856028896167e-18, /* logim[205] */ -3.61510340016815217927552346757607780248730263443438e-35, /* logil[205] */ } , { 1.10822486877441406250000000000000000000000000000000e+00, /* r[206] */ -1.02759517890908286252837910978996660560369491577148e-01, /* logih[206] */ 4.71099321843214355541046112004586746562119362394250e-18, /* logim[206] */ -1.09517195512805323092039219231698490527876281773580e-34, /* logil[206] */ } , { 1.10583114624023437500000000000000000000000000000000e+00, /* r[207] */ -1.00597220775924339752904757006035652011632919311523e-01, /* logih[207] */ -3.42156695637354590153605355608799216036823724345522e-18, /* logim[207] */ -1.24284989441486949568174045668508613287571207046391e-36, /* logil[207] */ } , { 1.10344886779785156250000000000000000000000000000000e+00, /* r[208] */ -9.84406092549116179535317883164680097252130508422852e-02, /* logih[208] */ 4.38755240283229348312039895902645159531255023723883e-18, /* logim[208] */ 1.60705777926564974905947594633801050091055265351041e-34, /* logil[208] */ } , { 1.10107612609863281250000000000000000000000000000000e+00, /* r[209] */ -9.62879980375207500387091386073734611272811889648438e-02, /* logih[209] */ -3.66395854119785801784314943749236711112635925431669e-18, /* logim[209] */ 1.90682128658230085463599916944170383720123953153313e-34, /* logil[209] */ } , { 1.09871292114257812500000000000000000000000000000000e+00, /* r[210] */ -9.41394230474431603639118293358478695154190063476562e-02, /* logih[210] */ -1.52427934389046025790404533372637255540123275063242e-18, /* logim[210] */ 2.38117709862259339359946293808333798071470115227448e-35, /* logil[210] */ } , { 1.09635925292968750000000000000000000000000000000000e+00, /* r[211] */ -9.19949203356747319260122708328708540648221969604492e-02, /* logih[211] */ -5.76786325743187763097260207334809269062162873149715e-18, /* logim[211] */ -1.16076884637403681975821590448659743070392522145404e-34, /* logil[211] */ } , { 1.09401702880859375000000000000000000000000000000000e+00, /* r[212] */ -8.98562695172144959565585509153606835752725601196289e-02, /* logih[212] */ 6.27446602451052736319026996501069657057280086335290e-19, /* logim[212] */ -3.52284010127094716016693656249620808330731317587528e-35, /* logil[212] */ } , { 1.09168434143066406250000000000000000000000000000000e+00, /* r[213] */ -8.77217709115478833092893751199881080538034439086914e-02, /* logih[213] */ -1.37126670070706012825933173130657669787213551002177e-18, /* logim[213] */ -1.23989072968810371061913173649528401394932986260312e-36, /* logil[213] */ } , { 1.08936119079589843750000000000000000000000000000000e+00, /* r[214] */ -8.55914609487157390654843425181752536445856094360352e-02, /* logih[214] */ -6.73539996941766729916657848715943989064126863847235e-18, /* logim[214] */ 3.21430126927804602931832802266482628675064054148856e-34, /* logil[214] */ } , { 1.08704948425292968750000000000000000000000000000000e+00, /* r[215] */ -8.34671307946482227135831521991349291056394577026367e-02, /* logih[215] */ -2.59301417543796652810804139098455715391427697882095e-18, /* logim[215] */ 1.65211492395331390788992293150317962555299571277512e-34, /* logil[215] */ } , { 1.08474540710449218750000000000000000000000000000000e+00, /* r[216] */ -8.13453116283524013674366415216354653239250183105469e-02, /* logih[216] */ -5.06533259416045510334473576398828704896081639774469e-18, /* logim[216] */ 3.58554694819254814251485471545002207143063628923407e-34, /* logil[216] */ } , { 1.08245277404785156250000000000000000000000000000000e+00, /* r[217] */ -7.92295531972000560694269211126083973795175552368164e-02, /* logih[217] */ 3.08430116625330602805431897032551509181475376762118e-18, /* logim[217] */ 1.27521745632715758795764081462338721511029897619340e-34, /* logil[217] */ } , { 1.08016967773437500000000000000000000000000000000000e+00, /* r[218] */ -7.71181378091099767324578806437784805893898010253906e-02, /* logih[218] */ -2.75912394291266277302481383554992246538214466259557e-18, /* logim[218] */ 5.96984502944699741108276688448842397927326332487835e-35, /* logil[218] */ } , { 1.07789421081542968750000000000000000000000000000000e+00, /* r[219] */ -7.50093329917183998523100285638065543025732040405273e-02, /* logih[219] */ 1.21553538095744083798831566922580286219799129072055e-18, /* logim[219] */ -5.89842100461659880732549401024388472535698324065996e-35, /* logil[219] */ } , { 1.07563018798828125000000000000000000000000000000000e+00, /* r[220] */ -7.29067112034412351251333461732428986579179763793945e-02, /* logih[220] */ 6.30693084361487082247322771068486204374546343933133e-18, /* logim[220] */ 3.44825082371128400572272238979928316738696119124015e-34, /* logil[220] */ } , { 1.07337570190429687500000000000000000000000000000000e+00, /* r[221] */ -7.08085439330154442494347222236683592200279235839844e-02, /* logih[221] */ 6.21205862241802265972824064219836764844223885696046e-18, /* logim[221] */ -2.58313322603855039499688568243180373305456453270216e-34, /* logil[221] */ } , { 1.07112884521484375000000000000000000000000000000000e+00, /* r[222] */ -6.87130878850236020971564698811562266200780868530273e-02, /* logih[222] */ 2.70354961689989817022493816753711952290500355166865e-18, /* logim[222] */ -4.32103888921541828258452321965605627074720991923399e-35, /* logil[222] */ } , { 1.06889343261718750000000000000000000000000000000000e+00, /* r[223] */ -6.66239382216213954501782268380338791757822036743164e-02, /* logih[223] */ 5.70083134370999669291082348348689873755740434296954e-18, /* logim[223] */ -8.10096531474775368286716199375642728810684749797528e-35, /* logil[223] */ } , { 1.06666755676269531250000000000000000000000000000000e+00, /* r[224] */ -6.45393556022498676716381282858492340892553329467773e-02, /* logih[224] */ 6.27679858230689064724912619776653321119382603385890e-18, /* logim[224] */ 3.82578436460361832583744997495972964625953636902884e-34, /* logil[224] */ } , { 1.06444931030273437500000000000000000000000000000000e+00, /* r[225] */ -6.24575859017184389920807063845131779089570045471191e-02, /* logih[225] */ 3.12396238135026689723293065657341228563060732941880e-18, /* logim[225] */ -2.56480637242869270592951014242676091679089182875022e-35, /* logil[225] */ } , { 1.06224060058593750000000000000000000000000000000000e+00, /* r[226] */ -6.03804513842609302809449900450999848544597625732422e-02, /* logih[226] */ 2.15703432342306119511642925211564389619524247753812e-18, /* logim[226] */ -3.99051054966201464148223117427430962485432571249835e-35, /* logil[226] */ } , { 1.06004142761230468750000000000000000000000000000000e+00, /* r[227] */ -5.83079900133864140188144631338218459859490394592285e-02, /* logih[227] */ -2.26614868674930470856533040936568995022733760870024e-18, /* logim[227] */ 4.93654463845011924979397150953449636718851245018416e-36, /* logil[227] */ } , { 1.05785179138183593750000000000000000000000000000000e+00, /* r[228] */ -5.62402398633818634277048431613366119563579559326172e-02, /* logih[228] */ 3.23622784070623643425179422456037835068049704948076e-18, /* logim[228] */ 8.21211163681263455010708306384902557377035880000243e-35, /* logil[228] */ } , { 1.05566978454589843750000000000000000000000000000000e+00, /* r[229] */ -5.41754323534648848936789988783857552334666252136230e-02, /* logih[229] */ -1.63682825416879776300941023746021061378436290037990e-18, /* logim[229] */ -7.00922691871793498425237363067495151340436490327669e-35, /* logil[229] */ } , { 1.05349731445312500000000000000000000000000000000000e+00, /* r[230] */ -5.21154050923886280610730636908556334674358367919922e-02, /* logih[230] */ -6.39781587823151025739574281786018493556176254138154e-19, /* logim[230] */ 3.56720195764935648932285840665933091100063235873938e-35, /* logil[230] */ } , { 1.05133438110351562500000000000000000000000000000000e+00, /* r[231] */ -5.00601964830668655359602325916057452559471130371094e-02, /* logih[231] */ 2.51984665593202228822706788872411441168875867302045e-18, /* logim[231] */ -2.18342737706092628156578807143832418432366157819325e-35, /* logil[231] */ } , { 1.04918098449707031250000000000000000000000000000000e+00, /* r[232] */ -4.80098450349349045729319129804935073480010032653809e-02, /* logih[232] */ -1.52080250600506339582829684987843924335937235135276e-18, /* logim[232] */ -9.24379674215907095849380058311583825692328514013958e-35, /* logil[232] */ } , { 1.04703521728515625000000000000000000000000000000000e+00, /* r[233] */ -4.59625676982170078277434299707238096743822097778320e-02, /* logih[233] */ -3.31972713633937264538106994059359671095924053342216e-18, /* logim[233] */ -1.13937339607744860727400568917500096969385851217146e-34, /* logil[233] */ } , { 1.04489707946777343750000000000000000000000000000000e+00, /* r[234] */ -4.39183920188736254264227909516193903982639312744141e-02, /* logih[234] */ -1.56343240701227240066055187635828001828861125718036e-18, /* logim[234] */ -3.02746820911254374279963651479509453045839237097215e-35, /* logil[234] */ } , { 1.04277038574218750000000000000000000000000000000000e+00, /* r[235] */ -4.18810038843394558116806081216054735705256462097168e-02, /* logih[235] */ 7.08767348853067953695390709296896788518980234122108e-19, /* logim[235] */ 5.81746887353045891576525685995993541223272544408687e-36, /* logil[235] */ } , { 1.04065132141113281250000000000000000000000000000000e+00, /* r[236] */ -3.98467877153236421650106535707891453057527542114258e-02, /* logih[236] */ 2.90303379363907111194760685579166515046306452777543e-18, /* logim[236] */ -1.87179669992551157656392090580258428294705323369769e-34, /* logil[236] */ } , { 1.03853988647460937500000000000000000000000000000000e+00, /* r[237] */ -3.78157713717320251300968436680705053731799125671387e-02, /* logih[237] */ 1.31557218113972830753744753624727966873659341218890e-19, /* logim[237] */ 3.06309949074642996410908941009119700992862883848855e-36, /* logil[237] */ } , { 1.03643798828125000000000000000000000000000000000000e+00, /* r[238] */ -3.57898231070667913189531361695117084309458732604980e-02, /* logih[238] */ 2.61901199505080724827733891681136430570574020973310e-18, /* logim[238] */ -1.03901456915381040350545966439681190782130708435783e-34, /* logil[238] */ } , { 1.03434371948242187500000000000000000000000000000000e+00, /* r[239] */ -3.37671381422615726752844977909262524917721748352051e-02, /* logih[239] */ 5.67782765535494174549017056202204751471356116304136e-19, /* logim[239] */ 2.53528355791248032893098939659784274260892498065275e-35, /* logil[239] */ } , { 1.03225898742675781250000000000000000000000000000000e+00, /* r[240] */ -3.17495923838522486892799179258872754871845245361328e-02, /* logih[240] */ -3.27645416513913885099937157154221271265660318847254e-18, /* logim[240] */ 8.28856608327529296008590058532581223963810647767730e-35, /* logil[240] */ } , { 1.03018188476562500000000000000000000000000000000000e+00, /* r[241] */ -2.97353738029609328263891399046769947744905948638916e-02, /* logih[241] */ -1.42123656023807324094007557899495837832764341820361e-18, /* logim[241] */ 6.91675602259020207318590223540920124856020443401708e-35, /* logil[241] */ } , { 1.02811241149902343750000000000000000000000000000000e+00, /* r[242] */ -2.77245107619511835239656249996187398210167884826660e-02, /* logih[242] */ 1.56537436220084983093655029081028016172956628311065e-18, /* logim[242] */ -4.26959324792631463690822650182944301609062827136870e-35, /* logil[242] */ } , { 1.02605247497558593750000000000000000000000000000000e+00, /* r[243] */ -2.57188906410827818060926830412427079863846302032471e-02, /* logih[243] */ -4.32555496623632207496744723792774270215720987145012e-19, /* logim[243] */ 1.52055580639983796045911400446456477822011205599594e-35, /* logil[243] */ } , { 1.02400016784667968750000000000000000000000000000000e+00, /* r[244] */ -2.37166905300757423213919850013553514145314693450928e-02, /* logih[244] */ 1.57595637918687487090746306283132097902404584964498e-18, /* logim[244] */ 9.74151980884630209236553635927232431547283770922398e-36, /* logil[244] */ } , { 1.02195549011230468750000000000000000000000000000000e+00, /* r[245] */ -2.17179390838950908682036811114812735468149185180664e-02, /* logih[245] */ 1.51145445644716133590266967637567408648790588957093e-19, /* logim[245] */ -6.02620888867536172611371375475252817876600211415641e-36, /* logil[245] */ } , { 1.01992034912109375000000000000000000000000000000000e+00, /* r[246] */ -1.97245351501005340699723689112943247891962528228760e-02, /* logih[246] */ 1.34458916305708123412045028332259969564528051018263e-18, /* logim[246] */ -6.02768376061644464555810636396264987280148524662430e-35, /* logil[246] */ } , { 1.01789283752441406250000000000000000000000000000000e+00, /* r[247] */ -1.77346449295557526126820846457121660932898521423340e-02, /* logih[247] */ 7.79495017362897286873974720552694669993891890935313e-19, /* logim[247] */ 1.36178679065204639598156495958075391845124350978061e-35, /* logil[247] */ } , { 1.01587295532226562500000000000000000000000000000000e+00, /* r[248] */ -1.57482973634926158579272481574662378989160060882568e-02, /* logih[248] */ -1.00208727697080412925749596659626020152032796409604e-18, /* logim[248] */ 7.75790823155383991507800579878754988160969197338737e-35, /* logil[248] */ } , { 1.01386070251464843750000000000000000000000000000000e+00, /* r[249] */ -1.37655214863766119093302364717601449228823184967041e-02, /* logih[249] */ -5.48983179446608237058051237183129839336112673134214e-19, /* logim[249] */ -1.07124914949087525209371623912638443397942890041101e-35, /* logil[249] */ } , { 1.01185798645019531250000000000000000000000000000000e+00, /* r[250] */ -1.17882314234863290469679242278289166279137134552002e-02, /* logih[250] */ -2.27798661830469484283633290231243375517062716277910e-19, /* logim[250] */ -1.39810745565350762832359759144648110107303965002540e-35, /* logil[250] */ } , { 1.00986099243164062500000000000000000000000000000000e+00, /* r[251] */ -9.81269012531632393858682661402781377546489238739014e-03, /* logih[251] */ -6.97507609288120398034926564017756235032809786202962e-19, /* logim[251] */ -4.77223430605379546730200636004016887477665718525716e-35, /* logil[251] */ } , { 1.00787353515625000000000000000000000000000000000000e+00, /* r[252] */ -7.84270062375400263399161104871382121928036212921143e-03, /* logih[252] */ -2.40330730071604899669779379793438954457155324844264e-19, /* logim[252] */ 1.77453639459760487861944622725812265877091856705197e-36, /* logil[252] */ } , { 1.00589370727539062500000000000000000000000000000000e+00, /* r[253] */ -5.87640732328869111467106733925902517512440681457520e-03, /* logih[253] */ -4.48574348377346892833940286850982368331573394791167e-20, /* logim[253] */ -1.60289170664661311448886936584931944274496990139304e-36, /* logil[253] */ } , { 1.00392150878906250000000000000000000000000000000000e+00, /* r[254] */ -3.91383971648977691676352108629544090945273637771606e-03, /* logih[254] */ -4.28019276224719221462393891683495367484578724177817e-19, /* logim[254] */ -2.25272542183557712010826889962617244762256960750126e-35, /* logil[254] */ } , { 1.00195693969726562500000000000000000000000000000000e+00, /* r[255] */ -1.95502738522272592053274919976502133067697286605835e-03, /* logih[255] */ 4.23091354502479132756026938785685564809899588018682e-20, /* logim[255] */ 2.38479717170645227429169885358660522796868401607905e-36, /* logil[255] */ } }; interval-3.2.0/src/crlibm/log10-td.c0000644000000000000000000007204313316017127015227 0ustar 00000000000000/* * This function computes log10, correctly rounded, * using experimental techniques based on triple double arithmetics * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Christoph Lauter * christoph.lauter at ens-lyon.fr * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA THIS IS EXPERIMENTAL SOFTWARE ********************************************************** * * NOTE: THIS FUNCTION USES SOME BASIC SEQUENCES AND * FURTHER FINAL ROUNDING SEQUENCES WITH SPECIAL CASE * TESTS NO FORMAL PROOF IS AVAILABLE FOR IN THE MOMENT * ********************************************************** */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "log10-td.h" #define AVOID_FMA 0 void log10_td_accurate(double *logb10h, double *logb10m, double *logb10l, int E, double ed, int index, double zh, double zl, double logih, double logim) { double highPoly, t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l, t8h, t8l, t9h, t9l, t10h, t10l, t11h, t11l; double t12h, t12l, t13h, t13l, t14h, t14l, zSquareh, zSquarem, zSquarel, zCubeh, zCubem, zCubel, higherPolyMultZh, higherPolyMultZm; double higherPolyMultZl, zSquareHalfh, zSquareHalfm, zSquareHalfl, polyWithSquareh, polyWithSquarem, polyWithSquarel; double polyh, polym, polyl, logil, logyh, logym, logyl, loghover, logmover, loglover, log2edhover, log2edmover, log2edlover; double log2edh, log2edm, log2edl, logb10hover, logb10mover, logb10lover; double logyhnorm, logymnorm, logylnorm; #if EVAL_PERF crlibm_second_step_taken++; #endif /* Accurate phase: Argument reduction is already done. We must return logh, logm and logl representing the intermediate result in 118 bits precision. We use a 14 degree polynomial, computing the first 3 (the first is 0) coefficients in triple double, calculating the next 7 coefficients in double double arithmetics and the last in double. We must account for zl starting with the monome of degree 4 (7^3 + 53 - 7 >> 118); so double double calculations won't account for it. */ /* Start of the horner scheme */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(accPolyC14,zh,accPolyC13),zh,accPolyC12),zh,accPolyC11),zh,accPolyC10); #else highPoly = accPolyC10 + zh * (accPolyC11 + zh * (accPolyC12 + zh * (accPolyC13 + zh * accPolyC14))); #endif /* We want to write accPolyC3 + zh * (accPoly4 + zh * (accPoly5 + zh * (accPoly6 + zh * (accPoly7 + zh * (accPoly8 + zh * (accPoly9 + zh * highPoly)))))); ( t14 t13 t12 t11 t10 t9 t8 t7 t6 t5 t4 t3 t2 t1 ) with all additions and multiplications in double double arithmetics but we will produce intermediate results labelled t1h/t1l thru t14h/t14l */ Mul12(&t1h, &t1l, zh, highPoly); Add22(&t2h, &t2l, accPolyC9h, accPolyC9l, t1h, t1l); Mul22(&t3h, &t3l, zh, zl, t2h, t2l); Add22(&t4h, &t4l, accPolyC8h, accPolyC8l, t3h, t3l); Mul22(&t5h, &t5l, zh, zl, t4h, t4l); Add22(&t6h, &t6l, accPolyC7h, accPolyC7l, t5h, t5l); Mul22(&t7h, &t7l, zh, zl, t6h, t6l); Add22(&t8h, &t8l, accPolyC6h, accPolyC6l, t7h, t7l); Mul22(&t9h, &t9l, zh, zl, t8h, t8l); Add22(&t10h, &t10l, accPolyC5h, accPolyC5l, t9h, t9l); Mul22(&t11h, &t11l, zh, zl, t10h, t10l); Add22(&t12h, &t12l, accPolyC4h, accPolyC4l, t11h, t11l); Mul22(&t13h, &t13l, zh, zl, t12h, t12l); Add22(&t14h, &t14l, accPolyC3h, accPolyC3l, t13h, t13l); /* We must now prepare (zh + zl)^2 and (zh + zl)^3 as triple doubles */ Mul23(&zSquareh, &zSquarem, &zSquarel, zh, zl, zh, zl); Mul233(&zCubeh, &zCubem, &zCubel, zh, zl, zSquareh, zSquarem, zSquarel); /* We can now multiplicate the middle and higher polynomial by z^3 */ Mul233(&higherPolyMultZh, &higherPolyMultZm, &higherPolyMultZl, t14h, t14l, zCubeh, zCubem, zCubel); /* Multiply now z^2 by -1/2 (exact op) and add to middle and higher polynomial */ zSquareHalfh = zSquareh * -0.5; zSquareHalfm = zSquarem * -0.5; zSquareHalfl = zSquarel * -0.5; Add33(&polyWithSquareh, &polyWithSquarem, &polyWithSquarel, zSquareHalfh, zSquareHalfm, zSquareHalfl, higherPolyMultZh, higherPolyMultZm, higherPolyMultZl); /* Add now zh and zl to obtain the polynomial evaluation result */ Add233(&polyh, &polym, &polyl, zh, zl, polyWithSquareh, polyWithSquarem, polyWithSquarel); /* Reconstruct now log(y) = log(1 + z) - log(ri) by adding logih, logim, logil logil has not been read to the time, do this first */ logil = argredtable[index].logil; Add33(&logyh, &logym, &logyl, logih, logim, logil, polyh, polym, polyl); /* Renormalize logyh, logym and logyl to a non-overlapping triple-double for winning some accuracy in the final ln(x) result before multiplying with log10inv THIS MAY NOT BE NECESSARY NOR SUFFICIENT */ Renormalize3(&logyhnorm, &logymnorm, &logylnorm, logyh, logym, logyl); /* Multiply log2 with E, i.e. log2h, log2m, log2l by ed ed is always less than 2^(12) and log2h and log2m are stored with at least 12 trailing zeros So multiplying naively is correct (up to 134 bits at least) The final result is thus obtained by adding log2 * E to log(y) */ log2edhover = log2h * ed; log2edmover = log2m * ed; log2edlover = log2l * ed; /* It may be necessary to renormalize the tabulated value (multiplied by ed) before adding the to the log(y)-result If needed, uncomment the following Renormalize3-Statement and comment out the copies following it. */ /* Renormalize3(&log2edh, &log2edm, &log2edl, log2edhover, log2edmover, log2edlover); */ log2edh = log2edhover; log2edm = log2edmover; log2edl = log2edlover; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, logyhnorm, logymnorm, logylnorm); /* Change logarithm base from natural base to base 10 by multiplying */ Mul33(&logb10hover, &logb10mover, &logb10lover, log10invh, log10invm, log10invl, loghover, logmover, loglover); /* Since we can not guarantee in each addition and multiplication procedure that the results are not overlapping, we must renormalize the result before handing it over to the final rounding */ Renormalize3(logb10h,logb10m,logb10l,logb10hover,logb10mover,logb10lover); } /************************************************************* ************************************************************* * ROUNDED TO NEAREST * ************************************************************* *************************************************************/ double log10_rn(double x){ db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, roundcst; double logb10h, logb10m, logb10l; int E, index; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Change logarithm base from natural base to base 10 by multiplying */ Mul22(&logb10h, &logb10m, log10invh, log10invm, logh, logm); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = ROUNDCST1; else roundcst = ROUNDCST2; if(logb10h == (logb10h + (logb10m * roundcst))) return logb10h; else { #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log10_td_accurate(&logb10h, &logb10m, &logb10l, E, ed, index, zh, zl, logih, logim); ReturnRoundToNearest3(logb10h, logb10m, logb10l); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED UPWARDS * ************************************************************* *************************************************************/ double log10_ru(double x) { db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, roundcst; double logb10h, logb10m, logb10l; int E, index; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Change logarithm base from natural base to base 10 by multiplying */ Mul22(&logb10h, &logb10m, log10invh, log10invm, logh, logm); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RU(logb10h, logb10m, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log10_td_accurate(&logb10h, &logb10m, &logb10l, E, ed, index, zh, zl, logih, logim); ReturnRoundUpwards3Unfiltered(logb10h, logb10m, logb10l, WORSTCASEACCURACY); } /************************************************************* ************************************************************* * ROUNDED DOWNWARDS * ************************************************************* *************************************************************/ double log10_rd(double x) { db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, roundcst; double logb10h, logb10m, logb10l; int E, index; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Change logarithm base from natural base to base 10 by multiplying */ Mul22(&logb10h, &logb10m, log10invh, log10invm, logh, logm); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RD(logb10h, logb10m, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log10_td_accurate(&logb10h, &logb10m, &logb10l, E, ed, index, zh, zl, logih, logim); ReturnRoundDownwards3Unfiltered(logb10h, logb10m, logb10l, WORSTCASEACCURACY); } /************************************************************* ************************************************************* * ROUNDED TOWARDS ZERO * ************************************************************* *************************************************************/ double log10_rz(double x) { db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, roundcst; double logb10h, logb10m, logb10l; int E, index; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Change logarithm base from natural base to base 10 by multiplying */ Mul22(&logb10h, &logb10m, log10invh, log10invm, logh, logm); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RZ(logb10h, logb10m, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log10_td_accurate(&logb10h, &logb10m, &logb10l, E, ed, index, zh, zl, logih, logim); ReturnRoundTowardsZero3Unfiltered(logb10h, logb10m, logb10l, WORSTCASEACCURACY); } interval-3.2.0/src/crlibm/log10-td.h0000644000000000000000000013214713316017127015236 0ustar 00000000000000/* * This function computes log10, correctly rounded, * using experimental techniques based on triple double arithmetics * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" /*File generated by maple/log10-td.mpl*/ #define L 7 #define MAXINDEX 53 #define INDEXMASK 127 #define two52 4.50359962737049600000000000000000000000000000000000e+15 #define log2h 6.93147180559890330187045037746429443359375000000000e-01 #define log2m 5.49792301870850242169664946507035702127907939029683e-14 #define log2l -1.31246984177852556920995753667322295879593697972250e-27 #define log10invh 4.34294481903251816667932416748953983187675476074219e-01 #define log10invm 1.09831965021676507273885982186335434116483395815072e-17 #define log10invl 3.71718123311095896669981767697359971405165651422486e-34 #define WORSTCASEACCURACY 5.31691198313966349161522824112137830400000000000000e+36 #define ROUNDCST1 1.00787401574803160796292764473221714405939530505554e+00 #define ROUNDCST2 1.00787401574803160796292764473221714405939530505554e+00 #define RDROUNDCST1 4.33680868994201773602981120347976684570312500000000e-19 #define RDROUNDCST2 4.33680868994201773602981120347976684570312500000000e-19 #define c3 3.33333333333333370340767487505218014121055603027344e-01 #define c4 -2.49999999990904886448817023847368545830249786376953e-01 #define c5 1.99999999978980019799124079327157232910394668579102e-01 #define c6 -1.66669050883027802800739891608827747404575347900391e-01 #define c7 1.42860109897981618631845890377007890492677688598633e-01 #define accPolyC3h 3.33333333333333314829616256247390992939472198486328e-01 #define accPolyC3l 1.85037170770859413132312241283212169118117639547054e-17 #define accPolyC4h -2.50000000000000000000000000000000000000000000000000e-01 #define accPolyC4l 4.62199018306924685334006418421322154174127637249391e-33 #define accPolyC5h 2.00000000000000011102230246251565404236316680908203e-01 #define accPolyC5l -1.11022302443127785678379338452126964515833173338601e-17 #define accPolyC6h -1.66666666666666657414808128123695496469736099243164e-01 #define accPolyC6l -9.25185854591372488017120157358742564605503054108327e-18 #define accPolyC7h 1.42857142857142849212692681248881854116916656494141e-01 #define accPolyC7l 7.92868209382438390589949095717120486682310988838960e-18 #define accPolyC8h -1.25000000000000000000000000000000000000000000000000e-01 #define accPolyC8l 3.42769668947376590645174407718339199260639267364101e-21 #define accPolyC9h 1.11111111111111521276839653182832989841699600219727e-01 #define accPolyC9l 4.33331955380787609416227741118274520376899199903317e-18 #define accPolyC10 -1.00000000000000699440505513848620466887950897216797e-01 #define accPolyC11 9.09090908567022348840680479042930528521537780761719e-02 #define accPolyC12 -8.33333332642126056732934102910803630948066711425781e-02 #define accPolyC13 7.69261287585959879775643344146374147385358810424805e-02 #define accPolyC14 -7.14319092953022982683819464000407606363296508789062e-02 typedef struct rri_tag {float ri; double logih; double logim; double logil;} rri; static const rri argredtable[128] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* r[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logih[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logim[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logil[0] */ } , { 9.92248058319091796875000000000000000000000000000000e-01, /* r[1] */ 7.78214416734525436109004559170898573938757181167603e-03, /* logih[1] */ -1.28191618904143681948935996668824218266800862156024e-20, /* logim[1] */ 1.17655068600225378123891861200215069271455859581641e-37, /* logil[1] */ } , { 9.84615325927734375000000000000000000000000000000000e-01, /* r[2] */ 1.55042461406118062261505485821544425562024116516113e-02, /* logih[2] */ -3.27761516207149627029928635703400435929630184221293e-19, /* logim[2] */ 2.95200020707030964072253388818190769795416371257942e-37, /* logil[2] */ } , { 9.77099180221557617187500000000000000000000000000000e-01, /* r[3] */ 2.31671170235356708999585606534310500137507915496826e-02, /* logih[3] */ 5.57833156048330069504471566938468802334954100224869e-19, /* logim[3] */ 4.08416064054113313191746248503653555682943539201798e-35, /* logil[3] */ } , { 9.69696998596191406250000000000000000000000000000000e-01, /* r[4] */ 3.07716288644317437217523547587916254997253417968750e-02, /* logih[4] */ 1.04316437964092669923942103072089812062131860035492e-18, /* logim[4] */ -8.26837774892530079043982861155759865584698067912967e-36, /* logil[4] */ } , { 9.62406039237976074218750000000000000000000000000000e-01, /* r[5] */ 3.83188391564273991840572364253603154793381690979004e-02, /* logih[5] */ 1.54512636366303706650320890230224472259662656606095e-18, /* logim[5] */ 8.30977110244055528389241824578843983429633068152463e-35, /* logil[5] */ } , { 9.55223917961120605468750000000000000000000000000000e-01, /* r[6] */ 4.58094969157468376308450785927561810240149497985840e-02, /* logih[6] */ -3.30123051072550842868548428055668582607719074881820e-18, /* logim[6] */ 1.64164772626574162996727598513545022472742050176492e-34, /* logil[6] */ } , { 9.48148131370544433593750000000000000000000000000000e-01, /* r[7] */ 5.32445322139413548812036935942160198464989662170410e-02, /* logih[7] */ 2.23755385085953619415254057336256700540433618368589e-18, /* logim[7] */ -9.41330315099866735037984721876103977945647219756033e-35, /* logil[7] */ } , { 9.41176414489746093750000000000000000000000000000000e-01, /* r[8] */ 6.06246814210813916856679384181916248053312301635742e-02, /* logih[8] */ 2.64247317995478646334926909653435556549332769494295e-18, /* logim[8] */ 1.55075207452234839722600788456166299408429635417895e-34, /* logil[8] */ } , { 9.34306621551513671875000000000000000000000000000000e-01, /* r[9] */ 6.79506060291548280583029395529592875391244888305664e-02, /* logih[9] */ 5.65862161871167282533541105359923619273100535513035e-18, /* logim[9] */ -3.57889357320249912090032102867532919048871786355064e-34, /* logil[9] */ } , { 9.27536249160766601562500000000000000000000000000000e-01, /* r[10] */ 7.52234026111362058530929175503842998296022415161133e-02, /* logih[10] */ 1.00828755349783911736541446332784521904773238841865e-18, /* logim[10] */ 7.77966415828014771486738038255868010153689429282538e-36, /* logil[10] */ } , { 9.20863270759582519531250000000000000000000000000000e-01, /* r[11] */ 8.24437111205913314426751981045526918023824691772461e-02, /* logih[11] */ -4.27419767632228646217014766651675738804062364961374e-18, /* logim[11] */ 3.58539257549786746072726449331073277906948658046759e-34, /* logil[11] */ } , { 9.14285659790039062500000000000000000000000000000000e-01, /* r[12] */ 8.96122182943336897942288032936630770564079284667969e-02, /* logih[12] */ -5.42674234758262048883730612286095846547194397615989e-18, /* logim[12] */ -7.94903110897686868047461590865098481976776339992810e-35, /* logil[12] */ } , { 9.07801389694213867187500000000000000000000000000000e-01, /* r[13] */ 9.67296581235191493819414176869031507521867752075195e-02, /* logih[13] */ 1.17499431052084706890372286741885325822732164697539e-18, /* logim[13] */ -7.47188021694240554877009439429630012902672969107896e-35, /* logil[13] */ } , { 9.01408433914184570312500000000000000000000000000000e-01, /* r[14] */ 1.03796812308095232069149460585322231054306030273438e-01, /* logih[14] */ -1.46116759252442942691327623497388991415382979093093e-18, /* logim[14] */ -5.84766064918572844473631496354606243606272630720064e-35, /* logil[14] */ } , { 8.95104885101318359375000000000000000000000000000000e-01, /* r[15] */ 1.10814377516161077785739053069846704602241516113281e-01, /* logih[15] */ -5.75514509579248124656596649605847554012818793702281e-18, /* logim[15] */ 3.29977719536339952907783192540462408052319847426319e-34, /* logil[15] */ } , { 8.88888835906982421875000000000000000000000000000000e-01, /* r[16] */ 1.17783095261030007483427084480354096740484237670898e-01, /* logih[16] */ -1.19709798867727449215060005668653850880775796697715e-18, /* logim[16] */ 8.04222018353684236067064017226062133396406008492921e-35, /* logil[16] */ } , { 8.82758617401123046875000000000000000000000000000000e-01, /* r[17] */ 1.24703482226247538977581541530526010319590568542480e-01, /* logih[17] */ 2.28663295749049514726834658528273231115811065734312e-18, /* logim[17] */ -3.51123005875932392272239647660221882537057244586168e-35, /* logil[17] */ } , { 8.76712322235107421875000000000000000000000000000000e-01, /* r[18] */ 1.31576365239299886145118989588809199631214141845703e-01, /* logih[18] */ 1.11230010175930229418362785876222391520299564865730e-17, /* logim[18] */ 7.27451645836749926637643602480531900716806359121297e-34, /* logil[18] */ } , { 8.70748281478881835937500000000000000000000000000000e-01, /* r[19] */ 1.38402343348215994822680841025430709123611450195312e-01, /* logih[19] */ -7.69528416335144553864151614176326744245393995127969e-18, /* logim[19] */ 1.14202629230472885861778260955781649682548331183808e-34, /* logil[19] */ } , { 8.64864826202392578125000000000000000000000000000000e-01, /* r[20] */ 1.45182054547982469783207193358975928276777267456055e-01, /* logih[20] */ 8.24244856152552570070228105635897158979868211170798e-18, /* logim[20] */ -6.13072808770694892835379995250538817854995507648779e-34, /* logil[20] */ } , { 8.59060406684875488281250000000000000000000000000000e-01, /* r[21] */ 1.51916037369229123266123337998578790575265884399414e-01, /* logih[21] */ -1.04296908000297145574171199957656893307239877379000e-17, /* logim[21] */ -5.53636436435840586444373230094200986769217138540854e-34, /* logil[21] */ } , { 8.53333353996276855468750000000000000000000000000000e-01, /* r[22] */ 1.58605005962251938145257668111298698931932449340820e-01, /* logih[22] */ -8.86065192248216377790637508171938194510660992474042e-19, /* logim[22] */ -5.87995214834401673695486864800931832452468264932844e-35, /* logil[22] */ } , { 8.47682118415832519531250000000000000000000000000000e-01, /* r[23] */ 1.65249573826629747586025587224867194890975952148438e-01, /* logih[23] */ -9.66125475305916070790888958698289394696700966750453e-18, /* logim[23] */ 1.22853647999759344001960461047755491313341721869856e-34, /* logil[23] */ } , { 8.42105269432067871093750000000000000000000000000000e-01, /* r[24] */ 1.71850249476078659194300257695431355386972427368164e-01, /* logih[24] */ -6.02245395887480538795512923412250309472746231920746e-18, /* logim[24] */ 1.52961687917434402329553899350235008490821862631877e-34, /* logil[24] */ } , { 8.36601257324218750000000000000000000000000000000000e-01, /* r[25] */ 1.78407717077464861299418430462537799030542373657227e-01, /* logih[25] */ -1.24324832026190372515095573175819374097319572461178e-17, /* logim[25] */ -5.99222696564577786410580709003476847421843326905428e-34, /* logil[25] */ } , { 8.31168889999389648437500000000000000000000000000000e-01, /* r[26] */ 1.84922267713498816865680396404059138149023056030273e-01, /* logih[26] */ 9.96243711860796179875713739627414673019270693540839e-18, /* logim[26] */ -1.99546782893888540832510298706525540082513642365204e-34, /* logil[26] */ } , { 8.25806498527526855468750000000000000000000000000000e-01, /* r[27] */ 1.91394796188954025017991966706176754087209701538086e-01, /* logih[27] */ -8.22643020277300444045205706293674132131812201700538e-18, /* logim[27] */ 5.69056030867564774930537188285078930441778787828211e-34, /* logil[27] */ } , { 8.20512771606445312500000000000000000000000000000000e-01, /* r[28] */ 1.97825802934566419288842098467284813523292541503906e-01, /* logih[28] */ 1.28212649590622342007825921152819823725126964367518e-17, /* logim[28] */ 4.34712978477783827374998481132430084872238812357849e-34, /* logil[28] */ } , { 8.15286636352539062500000000000000000000000000000000e-01, /* r[29] */ 2.04215526527529805944638496839615982025861740112305e-01, /* logih[29] */ 2.73382699896480606605004885268461286375739934002155e-18, /* logim[29] */ 1.88415596219599490517606146615135776386751947516623e-34, /* logil[29] */ } , { 8.10126543045043945312500000000000000000000000000000e-01, /* r[30] */ 2.10564817536124687658016796376614365726709365844727e-01, /* logih[30] */ 2.68952644992466202072392146799884466396384136175691e-18, /* logim[30] */ -1.58883120037037559046153789501260274259127656480088e-34, /* logil[30] */ } , { 8.05031418800354003906250000000000000000000000000000e-01, /* r[31] */ 2.16873972759550226463431954471161589026451110839844e-01, /* logih[31] */ -1.23625140584833845652640860288020787431726668393088e-17, /* logim[31] */ -1.28369360755661214950804825668450767372141502246786e-34, /* logil[31] */ } , { 7.99999952316284179687500000000000000000000000000000e-01, /* r[32] */ 2.23143610918856316605030087885097600519657135009766e-01, /* logih[32] */ -9.09120001124270523314725361445863555491966823753373e-18, /* logim[32] */ 1.15945802868784933647836819275496182741822080543604e-34, /* logil[32] */ } , { 7.95031070709228515625000000000000000000000000000000e-01, /* r[33] */ 2.29374082438394522043267897970508784055709838867188e-01, /* logih[33] */ -1.08890120418598083770448590672876580941469212582837e-17, /* logim[33] */ 4.74877924128943438272197143958394008126523960202900e-34, /* logil[33] */ } , { 7.90123462677001953125000000000000000000000000000000e-01, /* r[34] */ 2.35566063862186342303672859088692348450422286987305e-01, /* logih[34] */ -2.39433728738216998660812173360881116827035967139939e-18, /* logim[34] */ -9.62471867414270770251397101906428335828045927610883e-35, /* logil[34] */ } , { 7.85276055335998535156250000000000000000000000000000e-01, /* r[35] */ 2.41719960170209802186036540661007165908813476562500e-01, /* logih[35] */ 2.39578119451184969695376143676233310543075971208880e-18, /* logim[35] */ 1.86231935097448741662637615288316997021879162207127e-34, /* logil[35] */ } , { 7.80487775802612304687500000000000000000000000000000e-01, /* r[36] */ 2.47836201157484947721343360171886160969734191894531e-01, /* logih[36] */ -1.24321923457726137680465119406863072977770725701004e-17, /* logim[36] */ -2.09577513970149680056365167860895085898294691979404e-34, /* logil[36] */ } , { 7.75757551193237304687500000000000000000000000000000e-01, /* r[37] */ 2.53915241645931488712051304901251569390296936035156e-01, /* logih[37] */ -6.31336333527435824035156315376733999545148217960567e-18, /* logim[37] */ 4.63496313971202069379055986715253908538961883067566e-35, /* logil[37] */ } , { 7.71084308624267578125000000000000000000000000000000e-01, /* r[38] */ 2.59957561689829752538116736104711890220642089843750e-01, /* logih[38] */ -7.05748899290965383754297836711168798219001736647281e-18, /* logim[38] */ 4.27245447011230141916526741370315150982259792796987e-34, /* logil[38] */ } , { 7.66467094421386718750000000000000000000000000000000e-01, /* r[39] */ 2.65963511244235673025571031757863238453865051269531e-01, /* logih[39] */ -2.24162125724264292804912034054420308588570407662844e-17, /* logim[39] */ 4.90471140265143981765909599584287898945638617268867e-34, /* logil[39] */ } , { 7.61904716491699218750000000000000000000000000000000e-01, /* r[40] */ 2.71933775088288309795814257086021825671195983886719e-01, /* logih[40] */ 7.83390223779535346513505580003968001040971161798700e-19, /* logim[40] */ -3.02585215101390470982866376614279464778757620082138e-35, /* logil[40] */ } , { 7.57396459579467773437500000000000000000000000000000e-01, /* r[41] */ 2.77868437964940373507971571598318405449390411376953e-01, /* logih[41] */ -2.69368711734232128278453248569958166651302969280381e-17, /* logim[41] */ 1.27334496810554064003001771076892864921428144153570e-33, /* logil[41] */ } , { 7.52941131591796875000000000000000000000000000000000e-01, /* r[42] */ 2.83768232735291170421021433867281302809715270996094e-01, /* logih[42] */ -2.03265852251844689554711830689719609838328388091381e-17, /* logim[42] */ 3.99265876662456660849597520210659365811534845502505e-34, /* logil[42] */ } , { 7.48538017272949218750000000000000000000000000000000e-01, /* r[43] */ 2.89633285132462114930262941925320774316787719726562e-01, /* logih[43] */ -7.21962253363417273270454867455071277489833577725373e-18, /* logim[43] */ -2.16150227221931053192432009592422674631830770048369e-34, /* logil[43] */ } , { 7.44186043739318847656250000000000000000000000000000e-01, /* r[44] */ 2.95464216619126196494704572614864446222782135009766e-01, /* logih[44] */ -1.47072146829197428851717511710908602721304319475328e-17, /* logim[44] */ 4.88114627787723832872543510409367916590649903129304e-34, /* logil[44] */ } , { 7.39884376525878906250000000000000000000000000000000e-01, /* r[45] */ 3.01261352929903802877475982313626445829868316650391e-01, /* logih[45] */ 1.87070681938931680167624656750430985298856099421569e-17, /* logim[45] */ 1.51413799416501325421897094776870076323182009328971e-33, /* logil[45] */ } , { 7.35632181167602539062500000000000000000000000000000e-01, /* r[46] */ 3.07025039020202172856954803137341514229774475097656e-01, /* logih[46] */ -5.38102227896180596526923200171118043417676846319102e-18, /* logim[46] */ 2.06712483430759996475892191286335029882052180959917e-34, /* logil[46] */ } , { 7.31428623199462890625000000000000000000000000000000e-01, /* r[47] */ 3.12755639223383730129768309780047275125980377197266e-01, /* logih[47] */ -7.57930782773895721056011815787401170737920404028723e-18, /* logim[47] */ 8.39475110593319988799512618628582752750846924050440e-35, /* logil[47] */ } , { 7.27272748947143554687500000000000000000000000000000e-01, /* r[48] */ 3.18453701316212645089365196326980367302894592285156e-01, /* logih[48] */ 2.71147705440665649189983820006370647423267349507715e-17, /* logim[48] */ 4.61673001741568050305139864943649666789926072891368e-34, /* logil[48] */ } , { 7.23163843154907226562500000000000000000000000000000e-01, /* r[49] */ 3.24119466791566834817928111078799702227115631103516e-01, /* logih[49] */ -6.22349090807112113628215383245238541760656175683922e-18, /* logim[49] */ -2.94864944946984528585289533414905600786096792764282e-34, /* logil[49] */ } , { 7.19101071357727050781250000000000000000000000000000e-01, /* r[50] */ 3.29753359015631464234985514849540777504444122314453e-01, /* logih[50] */ -2.38987037434306035496609341036867889075145964580121e-17, /* logim[50] */ -1.22161021411351376080765213758661026982900357467596e-33, /* logil[50] */ } , { 7.15083837509155273437500000000000000000000000000000e-01, /* r[51] */ 3.35355487904429983014864546930766664445400238037109e-01, /* logih[51] */ -2.15530481136091842439480783176785939188081961777809e-17, /* logim[51] */ 5.65377778536716902900522531845470344712374772157319e-34, /* logil[51] */ } , { 7.11111068725585937500000000000000000000000000000000e-01, /* r[52] */ 3.40926646575239744585417156486073508858680725097656e-01, /* logih[52] */ 1.74672070296268393919501631375949801326271042364782e-17, /* logim[52] */ 1.28757784323920807504216254145051967795248381758825e-33, /* logil[52] */ } , { 1.41436457633972167968750000000000000000000000000000e+00, /* r[53] */ -3.46680367578929504723816990008344873785972595214844e-01, /* logih[53] */ -2.63487075436177288054440686474043695042741778901884e-17, /* logim[53] */ -1.38972774108545698123375234719775474495262622652200e-33, /* logil[53] */ } , { 1.40659332275390625000000000000000000000000000000000e+00, /* r[54] */ -3.41170697798120592381110327551141381263732910156250e-01, /* logih[54] */ 1.93668606486849623510457675345565515553170548397263e-17, /* logim[54] */ -6.31924577586791945681481090971933602378723267089765e-34, /* logil[54] */ } , { 1.39890718460083007812500000000000000000000000000000e+00, /* r[55] */ -3.35691349380139503200126682713744230568408966064453e-01, /* logih[55] */ 8.91843232308579533655667936963342665384096382048557e-18, /* logim[55] */ -7.43852632990846244963757376301756885994340719135686e-34, /* logil[55] */ } , { 1.39130425453186035156250000000000000000000000000000e+00, /* r[56] */ -3.30241619815349218836075806393637321889400482177734e-01, /* logih[56] */ -1.69271534756955752333877800530082817995576241189249e-17, /* logim[56] */ -2.05124125474152062675126703058085713735683777118919e-34, /* logil[56] */ } , { 1.38378381729125976562500000000000000000000000000000e+00, /* r[57] */ -3.24821643615624322531942880232236348092555999755859e-01, /* logih[57] */ 1.93287622140617006961244731990086787828970688523722e-17, /* logim[57] */ -1.40211415833516824405184666805315188814704601258065e-33, /* logil[57] */ } , { 1.37634420394897460937500000000000000000000000000000e+00, /* r[58] */ -3.19430856448034428130000605960958637297153472900391e-01, /* logih[58] */ 5.58442737360353866559969930374464901851229137435661e-18, /* logim[58] */ -2.25313306148742433454599602113064828727792769150620e-34, /* logil[58] */ } , { 1.36898398399353027343750000000000000000000000000000e+00, /* r[59] */ -3.14068847182749744106899925100151449441909790039062e-01, /* logih[59] */ 1.74087330539322720259314067705480812845274240645592e-17, /* logim[59] */ 2.87763442397890459672608687761118393908121210479900e-34, /* logil[59] */ } , { 1.36170220375061035156250000000000000000000000000000e+00, /* r[60] */ -3.08735537528966208498104606405831873416900634765625e-01, /* logih[60] */ 2.31380218279209479391607966489385619371870731511261e-17, /* logim[60] */ 5.75649697670342883220331709767832654878804183961435e-34, /* logil[60] */ } , { 1.35449743270874023437500000000000000000000000000000e+00, /* r[61] */ -3.03430487161918061023158088573836721479892730712891e-01, /* logih[61] */ 5.88591784280850309549180895879864991445414905765635e-18, /* logim[61] */ 3.80740105286783019924475997846877792541810370319751e-34, /* logil[61] */ } , { 1.34736847877502441406250000000000000000000000000000e+00, /* r[62] */ -2.98153415159913837140237546918797306716442108154297e-01, /* logih[62] */ -8.81391967432414632609646763074561636922040597203571e-18, /* logim[62] */ -2.02736910549706342663167850737697734462522018249963e-34, /* logil[62] */ } , { 1.34031414985656738281250000000000000000000000000000e+00, /* r[63] */ -2.92904026677480888718463347686338238418102264404297e-01, /* logih[63] */ 1.79356774462556308958502912313675336181211584010969e-17, /* logim[63] */ 1.02350086185905899058999882149766002774623879978153e-34, /* logil[63] */ } , { 1.33333325386047363281250000000000000000000000000000e+00, /* r[64] */ -2.87682012847134349620148441317724063992500305175781e-01, /* logih[64] */ -2.60715355783435444041951693925565689223533295668838e-17, /* logim[64] */ -9.83372234709377378449141028490939682198507140512540e-34, /* logil[64] */ } , { 1.32642483711242675781250000000000000000000000000000e+00, /* r[65] */ -2.82487230428967117656924301627441309392452239990234e-01, /* logih[65] */ 2.49452771019268745755792758464310261659699707675018e-17, /* logim[65] */ -1.40230272425562150522506576584140991296902734870694e-33, /* logil[65] */ } , { 1.31958770751953125000000000000000000000000000000000e+00, /* r[66] */ -2.77319345020877350282972884087939746677875518798828e-01, /* logih[66] */ 7.44521346975934828880026635948320543669274837358637e-18, /* logim[66] */ -5.41922476182319969711469733445405189836277342215443e-34, /* logil[66] */ } , { 1.31282043457031250000000000000000000000000000000000e+00, /* r[67] */ -2.72177826311169102080356196893262676894664764404297e-01, /* logih[67] */ -1.94604737767255604321061638736698666324990178271015e-17, /* logim[67] */ 4.93318792723831633917605655356651628446409622108869e-34, /* logil[67] */ } , { 1.30612254142761230468750000000000000000000000000000e+00, /* r[68] */ -2.67062856029558426396164350080653093755245208740234e-01, /* logih[68] */ 1.42676910305707233200559864526771082234384991613068e-17, /* logim[68] */ 9.40874014190123375853921812584677628111272401841540e-34, /* logil[68] */ } , { 1.29949235916137695312500000000000000000000000000000e+00, /* r[69] */ -2.61973695252477101202970288795768283307552337646484e-01, /* logih[69] */ -1.59130185496344773949627658712806321021374170989957e-17, /* logim[69] */ 2.05966526658843352548575822504612882857523370085076e-34, /* logil[69] */ } , { 1.29292941093444824218750000000000000000000000000000e+00, /* r[70] */ -2.56910505054635363020310023784986697137355804443359e-01, /* logih[70] */ -2.32939629151451727444770801596466641031683815428509e-17, /* logim[70] */ -1.43942742464573220634874496721239465737503205324375e-33, /* logil[70] */ } , { 1.28643226623535156250000000000000000000000000000000e+00, /* r[71] */ -2.51872701711453261808060233306605368852615356445312e-01, /* logih[71] */ -2.58573188266130078596915247890597291360969537163785e-17, /* logim[71] */ 3.36064630885731507350249551263037246653963144676932e-34, /* logil[71] */ } , { 1.27999997138977050781250000000000000000000000000000e+00, /* r[72] */ -2.46860055579783743695543307694606482982635498046875e-01, /* logih[72] */ -1.36174299951708605118822966558244798958741114531493e-17, /* logim[72] */ -8.23883896198784591738914635896001757021238114385808e-35, /* logil[72] */ } , { 1.27363181114196777343750000000000000000000000000000e+00, /* r[73] */ -2.41872513137422084916750009142560884356498718261719e-01, /* logih[73] */ -2.91827950997726014268071786281330008614392694540440e-18, /* logim[73] */ 8.66387628958027677722140876839269007945711340420961e-35, /* logil[73] */ } , { 1.26732683181762695312500000000000000000000000000000e+00, /* r[74] */ -2.36909825309450927655063878773944452404975891113281e-01, /* logih[74] */ 4.97049401191734143236484721843489954792294974449682e-18, /* logim[74] */ 2.12212094628219632031384179435720857347529888567725e-34, /* logil[74] */ } , { 1.26108384132385253906250000000000000000000000000000e+00, /* r[75] */ -2.31971542737545860513037609962339047342538833618164e-01, /* logih[75] */ 1.20064411563385414488688519726171456939870706105353e-17, /* logim[75] */ -5.20241965000144345106493348505238495111737026311766e-34, /* logil[75] */ } , { 1.25490188598632812500000000000000000000000000000000e+00, /* r[76] */ -2.27057391030699523559732710964453872293233871459961e-01, /* logih[76] */ -9.55134517665639461592830714479938653876650013848813e-18, /* logim[76] */ -7.00052160915705629865262646818211330004502638341784e-34, /* logil[76] */ } , { 1.24878048896789550781250000000000000000000000000000e+00, /* r[77] */ -2.22167466272476882283015697794326115399599075317383e-01, /* logih[77] */ 1.12308837854924459441805420173945034636561801020789e-17, /* logim[77] */ 1.05992689326800868505291338111574353445179905470698e-34, /* logil[77] */ } , { 1.24271845817565917968750000000000000000000000000000e+00, /* r[78] */ -2.17301285003207084178811214769666548818349838256836e-01, /* logih[78] */ -1.37599098464784711367545798871014398359913153389606e-17, /* logim[78] */ -5.44676947016522950876420214713413739910691265570885e-34, /* logil[78] */ } , { 1.23671507835388183593750000000000000000000000000000e+00, /* r[79] */ -2.12458734101899110457978281374380458146333694458008e-01, /* logih[79] */ 3.12575020468223244847667531342710056704202576314513e-18, /* logim[79] */ 1.27082738610098894087384580413567050181540844264548e-35, /* logil[79] */ } , { 1.23076915740966796875000000000000000000000000000000e+00, /* r[80] */ -2.07639305173597937814733427330793347209692001342773e-01, /* logih[80] */ -1.20531726306040366742269494142059745690218464556184e-17, /* logim[80] */ 3.33883514126655983920316543317695602289579500921493e-34, /* logil[80] */ } , { 1.22488045692443847656250000000000000000000000000000e+00, /* r[81] */ -2.02843253050716987306856253781006671488285064697266e-01, /* logih[81] */ -1.66453566992001313940518505696243672056063400746100e-18, /* logim[81] */ 2.78446239404510241881587234176263335863162887428131e-35, /* logil[81] */ } , { 1.21904754638671875000000000000000000000000000000000e+00, /* r[82] */ -1.98069854157447239328959653903439175337553024291992e-01, /* logih[82] */ -3.74277289637934596837745314540095849706853736054736e-18, /* logim[82] */ 2.20940287174632344749918330821286328950105212564345e-34, /* logil[82] */ } , { 1.21327018737792968750000000000000000000000000000000e+00, /* r[83] */ -1.93319348256398265695210625381150748580694198608398e-01, /* logih[83] */ -4.63045754803609100012916107813305239709411987466506e-18, /* logim[83] */ 3.81311992624323390610440652445847060246376140730432e-34, /* logil[83] */ } , { 1.20754718780517578125000000000000000000000000000000e+00, /* r[84] */ -1.88591184708711112616441596401273272931575775146484e-01, /* logih[84] */ 7.43216311628945500204739783937941202296964434266492e-18, /* logim[84] */ -4.02931080995428730719681936637527024502063366412999e-34, /* logil[84] */ } , { 1.20187783241271972656250000000000000000000000000000e+00, /* r[85] */ -1.83885194019779485419263664880418218672275543212891e-01, /* logih[85] */ 4.12613043545869607985270580107985887836449099592842e-18, /* logim[85] */ -1.13080344207561908198013613253456946184091830340475e-34, /* logil[85] */ } , { 1.19626164436340332031250000000000000000000000000000e+00, /* r[86] */ -1.79201397792742966874612875471939332783222198486328e-01, /* logih[86] */ 1.25197515140082668570664893296659406065442168045883e-17, /* logim[86] */ 2.08673445558311131685127966451011169090072111640797e-34, /* logil[86] */ } , { 1.19069766998291015625000000000000000000000000000000e+00, /* r[87] */ -1.74539412626609380385644954003510065376758575439453e-01, /* logih[87] */ 8.52219781255028950312107624449830634785785378861392e-18, /* logim[87] */ 5.46720442033771639415150684633589460164820712880324e-34, /* logil[87] */ } , { 1.18518519401550292968750000000000000000000000000000e+00, /* r[88] */ -1.69899044245978042555478282338299322873353958129883e-01, /* logih[88] */ 4.86800738580472456380134000450154397097303177737598e-19, /* logim[88] */ -4.48365665383134519709151659261825733866549119396251e-36, /* logil[88] */ } , { 1.17972350120544433593750000000000000000000000000000e+00, /* r[89] */ -1.65280090007780350314092743246874306350946426391602e-01, /* logih[89] */ 1.05991222445546499578510819426998369466676418510398e-18, /* logim[89] */ 2.15535973016890499002202117947684925307171077322261e-36, /* logil[89] */ } , { 1.17431187629699707031250000000000000000000000000000e+00, /* r[90] */ -1.60682338849634120947484916541725397109985351562500e-01, /* logih[90] */ 5.38493323815703006679696841052856196024573538758454e-18, /* logim[90] */ 1.60200163876329179080224417109933041789065267300895e-34, /* logil[90] */ } , { 1.16894984245300292968750000000000000000000000000000e+00, /* r[91] */ -1.56105775199027185795586092353914864361286163330078e-01, /* logih[91] */ 1.32405772531609804709122583998125231935523184710352e-17, /* logim[91] */ 4.88933388697666736600942679327919927438390701656817e-35, /* logil[91] */ } , { 1.16363644599914550781250000000000000000000000000000e+00, /* r[92] */ -1.51549968907714105448292229993967339396476745605469e-01, /* logih[92] */ 1.77181633478899593214922561799512844823326841018122e-18, /* logim[92] */ 5.44951453107128861626798538797020344311568819287008e-35, /* logil[92] */ } , { 1.15837097167968750000000000000000000000000000000000e+00, /* r[93] */ -1.47014683357163111754317696977523155510425567626953e-01, /* logih[93] */ 4.46701777108311388441189058844554903695616000674812e-18, /* logim[93] */ -1.53168389834566630100313932781112142055948393405761e-34, /* logil[93] */ } , { 1.15315318107604980468750000000000000000000000000000e+00, /* r[94] */ -1.42500086821669674774781810810964088886976242065430e-01, /* logih[94] */ -2.21668083020505832726646787146199970227457581911830e-18, /* logim[94] */ -4.73140768447350921077611938776759805597533720242102e-36, /* logil[94] */ } , { 1.14798212051391601562500000000000000000000000000000e+00, /* r[95] */ -1.38005723310861472263866289722500368952751159667969e-01, /* logih[95] */ -9.06035372834454229539393713977175584764482079542462e-18, /* logim[95] */ -6.58482110068426815722709702700082916058774211791842e-34, /* logil[95] */ } , { 1.14285707473754882812500000000000000000000000000000e+00, /* r[96] */ -1.33531333019876075063336884340969845652580261230469e-01, /* logih[96] */ 3.66452824974217778950176131406293356640863401093569e-18, /* logim[96] */ 6.15050085774566840615703784135477182311292227710416e-35, /* logil[96] */ } , { 1.13777780532836914062500000000000000000000000000000e+00, /* r[97] */ -1.29077066489528990977930789085803553462028503417969e-01, /* logih[97] */ 7.97904258955058431558707127373439732289437010877585e-19, /* logim[97] */ -4.72584148771245137732808879600361038781792271619664e-35, /* logil[97] */ } , { 1.13274335861206054687500000000000000000000000000000e+00, /* r[98] */ -1.24642441481986290807704165217728586867451667785645e-01, /* logih[98] */ -1.12998120773332791412288663337308123303520797473827e-18, /* logim[98] */ 5.04751909879024305911295754405025108738663901055449e-35, /* logil[98] */ } , { 1.12775325775146484375000000000000000000000000000000e+00, /* r[99] */ -1.20227386019965673535914163494453532621264457702637e-01, /* logih[99] */ -4.10132123403305460439841682733159064509468253505934e-18, /* logim[99] */ 1.89802934268459828223199224893946334512039168636632e-34, /* logil[99] */ } , { 1.12280702590942382812500000000000000000000000000000e+00, /* r[100] */ -1.15831822975702269928888199501670897006988525390625e-01, /* logih[100] */ -4.33848450767153009712329850176816190393287866962401e-18, /* logim[100] */ -3.16979691573058896647113947407157157214490081484725e-34, /* logil[100] */ } , { 1.11790394783020019531250000000000000000000000000000e+00, /* r[101] */ -1.11455456757806464773707944004854653030633926391602e-01, /* logih[101] */ -5.25227837292521929481451677551514755953859335394548e-18, /* logim[101] */ -1.35455162271740897316919848287529722248286557667632e-34, /* logil[101] */ } , { 1.11304354667663574218750000000000000000000000000000e+00, /* r[102] */ -1.07098197023655139492603893813793547451496124267578e-01, /* logih[102] */ 3.47169710366632825350486634041554320998659998614468e-18, /* logim[102] */ 4.16291803858237783591365989446195611338780307382474e-35, /* logil[102] */ } , { 1.10822510719299316406250000000000000000000000000000e+00, /* r[103] */ -1.02759733026446364867467764270259067416191101074219e-01, /* logih[103] */ 5.14131173582414775653668171432178439238499706689565e-18, /* logim[103] */ -2.03511710633920722432014459953905354472733979743122e-34, /* logil[103] */ } , { 1.10344839096069335937500000000000000000000000000000e+00, /* r[104] */ -9.84401771213754411826712953370588365942239761352539e-02, /* logih[104] */ 4.43863133643792238822177111529042861410430977956950e-18, /* logim[104] */ 3.12055863098469149547827014037274497005231280699218e-34, /* logil[104] */ } , { 1.09871244430541992187500000000000000000000000000000e+00, /* r[105] */ -9.41389890512167593072945237508974969387054443359375e-02, /* logih[105] */ 2.37342936135295683496202513568031672884920488134173e-19, /* logim[105] */ 2.33721773003055253003147894270712826153088420940698e-35, /* logil[105] */ } , { 1.09401702880859375000000000000000000000000000000000e+00, /* r[106] */ -8.98562695172144959565585509153606835752725601196289e-02, /* logih[106] */ 6.27446602451052736319026996501069657057280086335290e-19, /* logim[106] */ -3.52284010127094716016693656249620808330731317587528e-35, /* logil[106] */ } , { 1.08936166763305664062500000000000000000000000000000e+00, /* r[107] */ -8.55918986704354706196440361054555978626012802124023e-02, /* logih[107] */ -5.03513826084130895904008327416965851388338774947593e-18, /* logim[107] */ 6.86424026896698901114373288904478288437409959196820e-35, /* logil[107] */ } , { 1.08474564552307128906250000000000000000000000000000e+00, /* r[108] */ -8.13455314205279167438789045263547450304031372070312e-02, /* logih[108] */ 1.86223784192593707654359268192644483006930996779864e-18, /* logim[108] */ -9.08215611660981343459991418247070342987317386688394e-35, /* logil[108] */ } , { 1.08016872406005859375000000000000000000000000000000e+00, /* r[109] */ -7.71172549156562414651716608204878866672515869140625e-02, /* logih[109] */ 4.37349590112793692636976332290601524356283649435490e-18, /* logim[109] */ -2.43638510650083687411626047741666976256819270953612e-34, /* logil[109] */ } , { 1.07563018798828125000000000000000000000000000000000e+00, /* r[110] */ -7.29067112034412351251333461732428986579179763793945e-02, /* logih[110] */ 6.30693084361487082247322771068486204374546343933133e-18, /* logim[110] */ 3.44825082371128400572272238979928316738696119124015e-34, /* logil[110] */ } , { 1.07112979888916015625000000000000000000000000000000e+00, /* r[111] */ -6.87139782297249979148290321973036043345928192138672e-02, /* logih[111] */ -4.40922228882126717948257852084234011599535648658716e-18, /* logim[111] */ 2.00071285755297414487130516445636815235532199087333e-34, /* logil[111] */ } , { 1.06666660308837890625000000000000000000000000000000e+00, /* r[112] */ -6.45384615329246263959461771264614071696996688842773e-02, /* logih[112] */ 6.47055724777502681297997296903095954212491541204973e-18, /* logim[112] */ -3.53995576621708408093066388957026321212073337996708e-34, /* logil[112] */ } , { 1.06224060058593750000000000000000000000000000000000e+00, /* r[113] */ -6.03804513842609302809449900450999848544597625732422e-02, /* logih[113] */ 2.15703432342306119511642925211564389619524247753812e-18, /* logim[113] */ -3.99051054966201464148223117427430962485432571249835e-35, /* logil[113] */ } , { 1.05785131454467773437500000000000000000000000000000e+00, /* r[114] */ -5.62397891033892469159205518280941760167479515075684e-02, /* logih[114] */ 3.28339677990388790029372693220459728960401288179580e-18, /* logim[114] */ 1.51915205677141595589208947882243470550543557886170e-35, /* logil[114] */ } , { 1.05349802970886230468750000000000000000000000000000e+00, /* r[115] */ -5.21160840267197236763685452842764789238572120666504e-02, /* logih[115] */ -2.76876652450490527514912306264172616345243137067863e-19, /* logim[115] */ 4.97747635693761803951848478678221385327287067714555e-36, /* logil[115] */ } , { 1.04918026924133300781250000000000000000000000000000e+00, /* r[116] */ -4.80091633070045681330739739678392652422189712524414e-02, /* logih[116] */ -1.43903217358996287866324353045636173989420593009940e-18, /* logim[116] */ 9.24533961563047616614044310774847027299245259235749e-35, /* logil[116] */ } , { 1.04489803314208984375000000000000000000000000000000e+00, /* r[117] */ -4.39193047153486545997047585387917933985590934753418e-02, /* logih[117] */ -1.76247347066130256555880115492006953917590179181782e-18, /* logim[117] */ 2.95067167680037492936848210009098107643918346324819e-35, /* logil[117] */ } , { 1.04065036773681640625000000000000000000000000000000e+00, /* r[118] */ -3.98458712942959952796329048396728467196226119995117e-02, /* logih[118] */ 3.12956491324511750770873688790894657687633404551217e-18, /* logim[118] */ 9.08530842942513514982993220469010912494881545842223e-35, /* logil[118] */ } , { 1.03643727302551269531250000000000000000000000000000e+00, /* r[119] */ -3.57891329972944774451271143789199413731694221496582e-02, /* logih[119] */ -2.94786708868720304892365707065135221787713948130908e-19, /* logim[119] */ 1.84384763058385810856389175018656477977822636794864e-35, /* logil[119] */ } , { 1.03225803375244140625000000000000000000000000000000e+00, /* r[120] */ -3.17486685122574663342476242178236134350299835205078e-02, /* logih[120] */ -3.03821748520802146852642560679641488082417537178322e-18, /* logim[120] */ 6.90127669441551609256721347857289051065660383455449e-35, /* logil[120] */ } , { 1.02811241149902343750000000000000000000000000000000e+00, /* r[121] */ -2.77245107619511835239656249996187398210167884826660e-02, /* logih[121] */ 1.56537436220084983093655029081028016172956628311065e-18, /* logim[121] */ -4.26959324792631463690822650182944301609062827136870e-35, /* logil[121] */ } , { 1.02399992942810058593750000000000000000000000000000e+00, /* r[122] */ -2.37164576994431455791989549197751330211758613586426e-02, /* logih[122] */ -1.57190014657555079881764699090245893269914973184857e-19, /* logim[122] */ 4.62721637019171363059082221740445258999073602747011e-36, /* logil[122] */ } , { 1.01992034912109375000000000000000000000000000000000e+00, /* r[123] */ -1.97245351501005340699723689112943247891962528228760e-02, /* logih[123] */ 1.34458916305708123412045028332259969564528051018263e-18, /* logim[123] */ -6.02768376061644464555810636396264987280148524662430e-35, /* logil[123] */ } , { 1.01587295532226562500000000000000000000000000000000e+00, /* r[124] */ -1.57482973634926158579272481574662378989160060882568e-02, /* logih[124] */ -1.00208727697080412925749596659626020152032796409604e-18, /* logim[124] */ 7.75790823155383991507800579878754988160969197338737e-35, /* logil[124] */ } , { 1.01185774803161621093750000000000000000000000000000e+00, /* r[125] */ -1.17879957989121472716753658005472971126437187194824e-02, /* logih[125] */ 2.12843993900806841444093729096134188145078357457959e-19, /* logim[125] */ -7.36236149534638490756917054603187520349493909791838e-36, /* logil[125] */ } , { 1.00787401199340820312500000000000000000000000000000e+00, /* r[126] */ -7.84317373573558719590526067122482345439493656158447e-03, /* logih[126] */ -2.76470798179560918828283984091643257584228907545928e-19, /* logim[126] */ 1.46121103426200283031313413564673422143931331178612e-35, /* logil[126] */ } , { 1.00392150878906250000000000000000000000000000000000e+00, /* r[127] */ -3.91383971648977691676352108629544090945273637771606e-03, /* logih[127] */ -4.28019276224719221462393891683495367484578724177817e-19, /* logim[127] */ -2.25272542183557712010826889962617244762256960750126e-35, /* logil[127] */ } }; interval-3.2.0/src/crlibm/log1p.c0000644000000000000000000011275213316017127014724 0ustar 00000000000000/* * Correctly rounded log1p(x) = log(1 + x) * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Christoph Lauter (ENS Lyon) * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "log-td.h" #define AVOID_FMA 0 void log1p_td_accurate(double *logh, double *logm, double *logl, double ed, int index, double zh, double zm, double zl, double logih, double logim) { double highPoly, t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l, t8h, t8l, t9h, t9l, t10h, t10l, t11h, t11l; double t12h, t12l, t13h, t13l, t14h, t14l, zSquareh, zSquarem, zSquarel, zCubeh, zCubem, zCubel, higherPolyMultZh, higherPolyMultZm; double higherPolyMultZl, zSquareHalfh, zSquareHalfm, zSquareHalfl, polyWithSquareh, polyWithSquarem, polyWithSquarel; double polyh, polym, polyl, logil, logyh, logym, logyl, loghover, logmover, loglover, log2edhover, log2edmover, log2edlover; double log2edh, log2edm, log2edl; #if EVAL_PERF crlibm_second_step_taken++; #endif /* Accurate phase: Argument reduction is already done. We must return logh, logm and logl representing the intermediate result in 118 bits precision. We use a 14 degree polynomial, computing the first 3 (the first is 0) coefficients in triple double, calculating the next 7 coefficients in double double arithmetics and the last in double. */ /* Start of the horner scheme */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(accPolyC14,zh,accPolyC13),zh,accPolyC12),zh,accPolyC11),zh,accPolyC10); #else highPoly = accPolyC10 + zh * (accPolyC11 + zh * (accPolyC12 + zh * (accPolyC13 + zh * accPolyC14))); #endif /* We want to write accPolyC3 + zh * (accPoly4 + zh * (accPoly5 + zh * (accPoly6 + zh * (accPoly7 + zh * (accPoly8 + zh * (accPoly9 + zh * highPoly)))))); ( t14 t13 t12 t11 t10 t9 t8 t7 t6 t5 t4 t3 t2 t1 ) with all additions and multiplications in double double arithmetics but we will produce intermediate results labelled t1h/t1l thru t14h/t14l */ Mul12(&t1h, &t1l, zh, highPoly); Add22(&t2h, &t2l, accPolyC9h, accPolyC9l, t1h, t1l); Mul22(&t3h, &t3l, zh, zm, t2h, t2l); Add22(&t4h, &t4l, accPolyC8h, accPolyC8l, t3h, t3l); Mul22(&t5h, &t5l, zh, zm, t4h, t4l); Add22(&t6h, &t6l, accPolyC7h, accPolyC7l, t5h, t5l); Mul22(&t7h, &t7l, zh, zm, t6h, t6l); Add22(&t8h, &t8l, accPolyC6h, accPolyC6l, t7h, t7l); Mul22(&t9h, &t9l, zh, zm, t8h, t8l); Add22(&t10h, &t10l, accPolyC5h, accPolyC5l, t9h, t9l); Mul22(&t11h, &t11l, zh, zm, t10h, t10l); Add22(&t12h, &t12l, accPolyC4h, accPolyC4l, t11h, t11l); Mul22(&t13h, &t13l, zh, zm, t12h, t12l); Add22(&t14h, &t14l, accPolyC3h, accPolyC3l, t13h, t13l); /* We must now prepare (zh + zm)^2 and (zh + zm)^3 as triple doubles */ Mul33(&zSquareh, &zSquarem, &zSquarel, zh, zm, zl, zh, zm, zl); Mul33(&zCubeh, &zCubem, &zCubel, zh, zm, zl, zSquareh, zSquarem, zSquarel); /* We can now multiplicate the middle and higher polynomial by z^3 */ Mul233(&higherPolyMultZh, &higherPolyMultZm, &higherPolyMultZl, t14h, t14l, zCubeh, zCubem, zCubel); /* Multiply now z^2 by -1/2 (exact op) and add to middle and higher polynomial */ zSquareHalfh = zSquareh * -0.5; zSquareHalfm = zSquarem * -0.5; zSquareHalfl = zSquarel * -0.5; Add33(&polyWithSquareh, &polyWithSquarem, &polyWithSquarel, zSquareHalfh, zSquareHalfm, zSquareHalfl, higherPolyMultZh, higherPolyMultZm, higherPolyMultZl); /* Add now zh and zm to obtain the polynomial evaluation result */ Add33(&polyh, &polym, &polyl, zh, zm, zl, polyWithSquareh, polyWithSquarem, polyWithSquarel); /* Reconstruct now log(y) = log(1 + z) - log(ri) by adding logih, logim, logil logil has not been read to the time, do this first */ logil = argredtable[index].logil; Add33(&logyh, &logym, &logyl, logih, logim, logil, polyh, polym, polyl); /* Multiply log2 with E, i.e. log2h, log2m, log2l by ed ed is always less than 2^(12) and log2h and log2m are stored with at least 12 trailing zeros So multiplying naively is correct (up to 134 bits at least) The final result is thus obtained by adding log2 * E to log(y) */ log2edhover = log2h * ed; log2edmover = log2m * ed; log2edlover = log2l * ed; /* It may be necessary to renormalize the tabulated value (multiplied by ed) before adding the to the log(y)-result If needed, uncomment the following Renormalize3-Statement and comment out the copies following it. */ /* Renormalize3(&log2edh, &log2edm, &log2edl, log2edhover, log2edmover, log2edlover); */ log2edh = log2edhover; log2edm = log2edmover; log2edl = log2edlover; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, logyh, logym, logyl); /* Since we can not guarantee in each addition and multiplication procedure that the results are not overlapping, we must renormalize the result before handing it over to the final rounding */ Renormalize3(logh,logm,logl,loghover,logmover,loglover); } /************************************************************* ************************************************************* * ROUNDED TO NEAREST * ************************************************************* *************************************************************/ double log1p_rn(double x){ db_number xdb, shdb, scaledb; double yh, yl, ed, ri, logih, logim, yhrih, yhril, ylri, t1, t2, t3, t4, t5, t6, zh, zm, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, logl, roundcst; double sh, sl; int E, index; xdb.d=x; /* Filter cases */ if ((xdb.i[HI] & 0x7fffffff) < 0x3c900000) { /* We are less than 2^(-54) and return simply an adjusted x This captures also the algebraic case x = 0 */ return x; } if (((xdb.i[HI] & 0x80000000) != 0) && ((xdb.i[HI] & 0x7fffffff) >= 0x3ff00000)) { /* We are less or equal than -1 (-inf and NaN, too), we return -inf for -1 and NaN otherwise */ if (x == -1.0) return x/0.0; return (x-x)/0.0; } if ((xdb.i[HI] & 0x7ff00000) == 0x7ff00000) { /* We are +inf or NaN If +inf, we return +inf (x+x) If NaN, we return NaN (x+x) */ return x+x; } /* Test if |x| < 2^(-8) If yes, short-circuit the range reduction */ if ((xdb.i[HI] & 0x7fffffff) < 0x3f700000) { /* Use the polynomial p(zh + zl) approximating log(1+zh+zl) directly Set E and index to values that read 0.0 in the accurate phase. */ logih = 0.0; logim = 0.0; index = 0; ed = 0.0; index = 0; zh = x; zm = 0.0; zl = 0.0; } else { /* If we are here, |x| >= 2^(-8) and we must perform range reduction */ /* Compute first exactly sh + sl = 1 + x x can move over 1, so use a conditional Add12 */ Add12Cond(sh,sl,1.0,x); /* Transform higher order double to integer */ shdb.d = sh; /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E = 0; E += (shdb.i[HI]>>20)-1023; /* extract the exponent */ index = (shdb.i[HI] & 0x000fffff); shdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ shdb.i[HI] -= 0x00100000; E++; } /* Transform shdb to yh */ yh = shdb.d; /* Compute the index to the table */ index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Test if we have a simple range reduction or a complicated one Simple range reduction for x < 0: x + 1 is exact, sl = 0 exactly Simple range reduction for x > 2^(125) (sh > 2^(125)): x + 1 is not exact but its error less than 2^(-125) Complicated range reduction: other cases */ if ((sl == 0.0) || (E > 125)) { /* Simple range reduction */ Mul12(&yhrih, &yhril, yh, ri); t1 = yhrih - 1.0; Add12Cond(zh, zm, t1, yhril); zl = 0.0; } else { /* Complicated range reduction; E <= 125 */ /* Scale sl accordingly to sh, from which the exponent was extracted We form first 2^(-E) and multiply sl with this value; this gives yl. */ scaledb.i[HI] = (-E + 1023) << 20; scaledb.i[LO] = 0; yl = sl * scaledb.d; /* Do complicated range reduction: zh + zm + zl = (yh + yl) * ri - 1.0 We use zh + zm in the quick phase and zh + zm + zl in the accurate phase The multiplication yl * ri is exact because yl contains at most 9 bits and ri contains at most 24 bits. The substraction yhrih - 1.0 is exact as per Sterbenz' lemma. */ Mul12(&yhrih,&yhril,yh,ri); ylri = yl * ri; t1 = yhrih - 1.0; /* The unnormalized triple-double t1 + yhril + ylri is equal to (yh + yl) * ri - 1.0 As t1 can move over yhril and yhri can move over ylri, we normalize first these values pairwise with Add12Conds. Then we renormalize the pairs by a "inverted" (A.E.) Renormalize3. */ Add12Cond(t2,t3,yhril,ylri); Add12Cond(t4,t5,t1,t2); Add12Cond(t6,zl,t3,t5); Add12Cond(zh,zm,t4,t6); } } /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zm using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zm)); Add22(&t2h, &t2l, zh, zm, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = ROUNDCST1; else roundcst = ROUNDCST2; if(logh == (logh + (logm * roundcst))) return logh; else { #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log1p_td_accurate(&logh, &logm, &logl, ed, index, zh, zm, zl, logih, logim); ReturnRoundToNearest3(logh, logm, logl); } /* Accurate phase launched */ } double log1p_ru(double x) { db_number xdb, shdb, scaledb; double yh, yl, ed, ri, logih, logim, yhrih, yhril, ylri, t1, t2, t3, t4, t5, t6, zh, zm, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, logl, roundcst; double sh, sl; int E, index; xdb.d=x; /* Filter cases */ if ((xdb.i[HI] & 0x7fffffff) < 0x3c900000) { /* We are less than 2^(-54) and return simply an adjusted x If x = 0, the result is algebraic and equal to 0. The series for log(1 + x) = x - 1/2 * x^2 + ... is alternated and converges in this interval. The truncation rest -1/2 * x^2 + 1/3 * x^3 - ... is always negative, so log(1 + x) is always less than x but less than 1 ulp of x away. We round up, so we return x. */ return x; } if (((xdb.i[HI] & 0x80000000) != 0) && ((xdb.i[HI] & 0x7fffffff) >= 0x3ff00000)) { /* We are less or equal than -1 (-inf and NaN, too), we return -inf for -1 and NaN otherwise */ if (x == -1.0) return x/0.0; return (x-x)/0.0; } if ((xdb.i[HI] & 0x7ff00000) == 0x7ff00000) { /* We are +inf or NaN If +inf, we return +inf (x+x) If NaN, we return NaN (x+x) */ return x+x; } /* Test if |x| < 2^(-8) If yes, short-circuit the range reduction */ if ((xdb.i[HI] & 0x7fffffff) < 0x3f700000) { /* Use the polynomial p(zh + zl) approximating log(1+zh+zl) directly Set E and index to values that read 0.0 in the accurate phase. */ logih = 0.0; logim = 0.0; index = 0; ed = 0.0; index = 0; zh = x; zm = 0.0; zl = 0.0; } else { /* If we are here, |x| >= 2^(-8) and we must perform range reduction */ /* Compute first exactly sh + sl = 1 + x x can move over 1, so use a conditional Add12 */ Add12Cond(sh,sl,1.0,x); /* Transform higher order double to integer */ shdb.d = sh; /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E = 0; E += (shdb.i[HI]>>20)-1023; /* extract the exponent */ index = (shdb.i[HI] & 0x000fffff); shdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ shdb.i[HI] -= 0x00100000; E++; } /* Transform shdb to yh */ yh = shdb.d; /* Compute the index to the table */ index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Test if we have a simple range reduction or a complicated one Simple range reduction for x < 0: x + 1 is exact, sl = 0 exactly Simple range reduction for x > 2^(125) (sh > 2^(125)): x + 1 is not exact but its error less than 2^(-125) Complicated range reduction: other cases */ if ((sl == 0.0) || (E > 125)) { /* Simple range reduction */ Mul12(&yhrih, &yhril, yh, ri); t1 = yhrih - 1.0; Add12Cond(zh, zm, t1, yhril); zl = 0.0; } else { /* Complicated range reduction; E <= 125 */ /* Scale sl accordingly to sh, from which the exponent was extracted We form first 2^(-E) and multiply sl with this value; this gives yl. */ scaledb.i[HI] = (-E + 1023) << 20; scaledb.i[LO] = 0; yl = sl * scaledb.d; /* Do complicated range reduction: zh + zm + zl = (yh + yl) * ri - 1.0 We use zh + zm in the quick phase and zh + zm + zl in the accurate phase The multiplication yl * ri is exact because yl contains at most 9 bits and ri contains at most 24 bits. The substraction yhrih - 1.0 is exact as per Sterbenz' lemma. */ Mul12(&yhrih,&yhril,yh,ri); ylri = yl * ri; t1 = yhrih - 1.0; /* The unnormalized triple-double t1 + yhril + ylri is equal to (yh + yl) * ri - 1.0 As t1 can move over yhril and yhri can move over ylri, we normalize first these values pairwise with Add12Conds. Then we renormalize the pairs by a "inverted" (A.E.) Renormalize3. */ Add12Cond(t2,t3,yhril,ylri); Add12Cond(t4,t5,t1,t2); Add12Cond(t6,zl,t3,t5); Add12Cond(zh,zm,t4,t6); } } /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zm using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zm)); Add22(&t2h, &t2l, zh, zm, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RU(logh, logm, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log1p_td_accurate(&logh, &logm, &logl, ed, index, zh, zm, zl, logih, logim); ReturnRoundUpwards3(logh, logm, logl); } double log1p_rd(double x) { db_number xdb, shdb, scaledb; double yh, yl, ed, ri, logih, logim, yhrih, yhril, ylri, t1, t2, t3, t4, t5, t6, zh, zm, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, logl, roundcst; double sh, sl; int E, index; xdb.d=x; /* Filter cases */ if ((xdb.i[HI] & 0x7fffffff) < 0x3c900000) { /* We are less than 2^(-54) and return simply an adjusted x If x = 0, the result is algebraic and equal to 0. The series for log(1 + x) = x - 1/2 * x^2 + ... is alternated and converges in this interval. The truncation rest -1/2 * x^2 + 1/3 * x^3 - ... is always negative, so log(1 + x) is always less than x but less than 1 ulp of x away. We round down, so we return x - 1ulp; */ if (x == 0.0) return x; if (x > 0) { xdb.l--; } else { xdb.l++; } return xdb.d; } if (((xdb.i[HI] & 0x80000000) != 0) && ((xdb.i[HI] & 0x7fffffff) >= 0x3ff00000)) { /* We are less or equal than -1 (-inf and NaN, too), we return -inf for -1 and NaN otherwise */ if (x == -1.0) return x/0.0; return (x-x)/0.0; } if ((xdb.i[HI] & 0x7ff00000) == 0x7ff00000) { /* We are +inf or NaN If +inf, we return +inf (x+x) If NaN, we return NaN (x+x) */ return x+x; } /* Test if |x| < 2^(-8) If yes, short-circuit the range reduction */ if ((xdb.i[HI] & 0x7fffffff) < 0x3f700000) { /* Use the polynomial p(zh + zl) approximating log(1+zh+zl) directly Set E and index to values that read 0.0 in the accurate phase. */ logih = 0.0; logim = 0.0; index = 0; ed = 0.0; index = 0; zh = x; zm = 0.0; zl = 0.0; } else { /* If we are here, |x| >= 2^(-8) and we must perform range reduction */ /* Compute first exactly sh + sl = 1 + x x can move over 1, so use a conditional Add12 */ Add12Cond(sh,sl,1.0,x); /* Transform higher order double to integer */ shdb.d = sh; /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E = 0; E += (shdb.i[HI]>>20)-1023; /* extract the exponent */ index = (shdb.i[HI] & 0x000fffff); shdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ shdb.i[HI] -= 0x00100000; E++; } /* Transform shdb to yh */ yh = shdb.d; /* Compute the index to the table */ index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Test if we have a simple range reduction or a complicated one Simple range reduction for x < 0: x + 1 is exact, sl = 0 exactly Simple range reduction for x > 2^(125) (sh > 2^(125)): x + 1 is not exact but its error less than 2^(-125) Complicated range reduction: other cases */ if ((sl == 0.0) || (E > 125)) { /* Simple range reduction */ Mul12(&yhrih, &yhril, yh, ri); t1 = yhrih - 1.0; Add12Cond(zh, zm, t1, yhril); zl = 0.0; } else { /* Complicated range reduction; E <= 125 */ /* Scale sl accordingly to sh, from which the exponent was extracted We form first 2^(-E) and multiply sl with this value; this gives yl. */ scaledb.i[HI] = (-E + 1023) << 20; scaledb.i[LO] = 0; yl = sl * scaledb.d; /* Do complicated range reduction: zh + zm + zl = (yh + yl) * ri - 1.0 We use zh + zm in the quick phase and zh + zm + zl in the accurate phase The multiplication yl * ri is exact because yl contains at most 9 bits and ri contains at most 24 bits. The substraction yhrih - 1.0 is exact as per Sterbenz' lemma. */ Mul12(&yhrih,&yhril,yh,ri); ylri = yl * ri; t1 = yhrih - 1.0; /* The unnormalized triple-double t1 + yhril + ylri is equal to (yh + yl) * ri - 1.0 As t1 can move over yhril and yhri can move over ylri, we normalize first these values pairwise with Add12Conds. Then we renormalize the pairs by a "inverted" (A.E.) Renormalize3. */ Add12Cond(t2,t3,yhril,ylri); Add12Cond(t4,t5,t1,t2); Add12Cond(t6,zl,t3,t5); Add12Cond(zh,zm,t4,t6); } } /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zm using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zm)); Add22(&t2h, &t2l, zh, zm, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RD(logh, logm, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log1p_td_accurate(&logh, &logm, &logl, ed, index, zh, zm, zl, logih, logim); ReturnRoundDownwards3(logh, logm, logl); } double log1p_rz(double x) { db_number xdb, shdb, scaledb; double yh, yl, ed, ri, logih, logim, yhrih, yhril, ylri, t1, t2, t3, t4, t5, t6, zh, zm, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, logl, roundcst; double sh, sl; int E, index; xdb.d=x; /* Filter cases */ if ((xdb.i[HI] & 0x7fffffff) < 0x3c900000) { /* We are less than 2^(-54) and return simply an adjusted x If x = 0, the result is algebraic and equal to 0. The series for log(1 + x) = x - 1/2 * x^2 + ... is alternated and converges in this interval. The truncation rest -1/2 * x^2 + 1/3 * x^3 - ... is always negative, so log(1 + x) is always less than x but less than 1 ulp of x away. For x < 0, we have log(1 + x) < 0, so we round up and return x; For x > 0, we round down and return x - 1ulp */ if (x > 0) { xdb.l--; return xdb.d; } /* Algebraic case x == 0.0 and round up */ return x; } if (((xdb.i[HI] & 0x80000000) != 0) && ((xdb.i[HI] & 0x7fffffff) >= 0x3ff00000)) { /* We are less or equal than -1 (-inf and NaN, too), we return -inf for -1 and NaN otherwise */ if (x == -1.0) return x/0.0; return (x-x)/0.0; } if ((xdb.i[HI] & 0x7ff00000) == 0x7ff00000) { /* We are +inf or NaN If +inf, we return +inf (x+x) If NaN, we return NaN (x+x) */ return x+x; } /* Test if |x| < 2^(-8) If yes, short-circuit the range reduction */ if ((xdb.i[HI] & 0x7fffffff) < 0x3f700000) { /* Use the polynomial p(zh + zl) approximating log(1+zh+zl) directly Set E and index to values that read 0.0 in the accurate phase. */ logih = 0.0; logim = 0.0; index = 0; ed = 0.0; index = 0; zh = x; zm = 0.0; zl = 0.0; } else { /* If we are here, |x| >= 2^(-8) and we must perform range reduction */ /* Compute first exactly sh + sl = 1 + x x can move over 1, so use a conditional Add12 */ Add12Cond(sh,sl,1.0,x); /* Transform higher order double to integer */ shdb.d = sh; /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E = 0; E += (shdb.i[HI]>>20)-1023; /* extract the exponent */ index = (shdb.i[HI] & 0x000fffff); shdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ shdb.i[HI] -= 0x00100000; E++; } /* Transform shdb to yh */ yh = shdb.d; /* Compute the index to the table */ index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Test if we have a simple range reduction or a complicated one Simple range reduction for x < 0: x + 1 is exact, sl = 0 exactly Simple range reduction for x > 2^(125) (sh > 2^(125)): x + 1 is not exact but its error less than 2^(-125) Complicated range reduction: other cases */ if ((sl == 0.0) || (E > 125)) { /* Simple range reduction */ Mul12(&yhrih, &yhril, yh, ri); t1 = yhrih - 1.0; Add12Cond(zh, zm, t1, yhril); zl = 0.0; } else { /* Complicated range reduction; E <= 125 */ /* Scale sl accordingly to sh, from which the exponent was extracted We form first 2^(-E) and multiply sl with this value; this gives yl. */ scaledb.i[HI] = (-E + 1023) << 20; scaledb.i[LO] = 0; yl = sl * scaledb.d; /* Do complicated range reduction: zh + zm + zl = (yh + yl) * ri - 1.0 We use zh + zm in the quick phase and zh + zm + zl in the accurate phase The multiplication yl * ri is exact because yl contains at most 9 bits and ri contains at most 24 bits. The substraction yhrih - 1.0 is exact as per Sterbenz' lemma. */ Mul12(&yhrih,&yhril,yh,ri); ylri = yl * ri; t1 = yhrih - 1.0; /* The unnormalized triple-double t1 + yhril + ylri is equal to (yh + yl) * ri - 1.0 As t1 can move over yhril and yhri can move over ylri, we normalize first these values pairwise with Add12Conds. Then we renormalize the pairs by a "inverted" (A.E.) Renormalize3. */ Add12Cond(t2,t3,yhril,ylri); Add12Cond(t4,t5,t1,t2); Add12Cond(t6,zl,t3,t5); Add12Cond(zh,zm,t4,t6); } } /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zm using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zm)); Add22(&t2h, &t2l, zh, zm, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RZ(logh, logm, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log1p_td_accurate(&logh, &logm, &logl, ed, index, zh, zm, zl, logih, logim); ReturnRoundTowardsZero3(logh, logm, logl); } interval-3.2.0/src/crlibm/log2-td.c0000644000000000000000000014346713316017127015161 0ustar 00000000000000/* * This function computes log2, correctly rounded, * using experimental techniques based on triple double arithmetics * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Christoph Lauter * christoph.lauter at ens-lyon.fr * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA THIS IS EXPERIMENTAL SOFTWARE */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "log2-td.h" #ifdef BUILD_INTERVAL_FUNCTIONS #include "interval.h" #endif #define AVOID_FMA 0 void log2_td_accurate(double *logb2h, double *logb2m, double *logb2l, int E, double ed, int index, double zh, double zl, double logih, double logim) { double highPoly, t1h, t1l, t2h, t2l, t3h, t3l, t4h, t4l, t5h, t5l, t6h, t6l, t7h, t7l, t8h, t8l, t9h, t9l, t10h, t10l, t11h, t11l; double t12h, t12l, t13h, t13l, t14h, t14l, zSquareh, zSquarem, zSquarel, zCubeh, zCubem, zCubel, higherPolyMultZh, higherPolyMultZm; double higherPolyMultZl, zSquareHalfh, zSquareHalfm, zSquareHalfl, polyWithSquareh, polyWithSquarem, polyWithSquarel; double polyh, polym, polyl, logil, logyh, logym, logyl, loghover, logmover, loglover, log2edhover, log2edmover, log2edlover; double log2edh, log2edm, log2edl, logb2hover, logb2mover, logb2lover; #if EVAL_PERF crlibm_second_step_taken++; #endif /* Accurate phase: Argument reduction is already done. We must return logh, logm and logl representing the intermediate result in 118 bits precision. We use a 14 degree polynomial, computing the first 3 (the first is 0) coefficients in triple double, calculating the next 7 coefficients in double double arithmetics and the last in double. We must account for zl starting with the monome of degree 4 (7^3 + 53 - 7 >> 118); so double double calculations won't account for it. */ /* Start of the horner scheme */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) highPoly = FMA(FMA(FMA(FMA(accPolyC14,zh,accPolyC13),zh,accPolyC12),zh,accPolyC11),zh,accPolyC10); #else highPoly = accPolyC10 + zh * (accPolyC11 + zh * (accPolyC12 + zh * (accPolyC13 + zh * accPolyC14))); #endif /* We want to write accPolyC3 + zh * (accPoly4 + zh * (accPoly5 + zh * (accPoly6 + zh * (accPoly7 + zh * (accPoly8 + zh * (accPoly9 + zh * highPoly)))))); ( t14 t13 t12 t11 t10 t9 t8 t7 t6 t5 t4 t3 t2 t1 ) with all additions and multiplications in double double arithmetics but we will produce intermediate results labelled t1h/t1l thru t14h/t14l */ Mul12(&t1h, &t1l, zh, highPoly); Add22(&t2h, &t2l, accPolyC9h, accPolyC9l, t1h, t1l); Mul22(&t3h, &t3l, zh, zl, t2h, t2l); Add22(&t4h, &t4l, accPolyC8h, accPolyC8l, t3h, t3l); Mul22(&t5h, &t5l, zh, zl, t4h, t4l); Add22(&t6h, &t6l, accPolyC7h, accPolyC7l, t5h, t5l); Mul22(&t7h, &t7l, zh, zl, t6h, t6l); Add22(&t8h, &t8l, accPolyC6h, accPolyC6l, t7h, t7l); Mul22(&t9h, &t9l, zh, zl, t8h, t8l); Add22(&t10h, &t10l, accPolyC5h, accPolyC5l, t9h, t9l); Mul22(&t11h, &t11l, zh, zl, t10h, t10l); Add22(&t12h, &t12l, accPolyC4h, accPolyC4l, t11h, t11l); Mul22(&t13h, &t13l, zh, zl, t12h, t12l); Add22(&t14h, &t14l, accPolyC3h, accPolyC3l, t13h, t13l); /* We must now prepare (zh + zl)^2 and (zh + zl)^3 as triple doubles */ Mul23(&zSquareh, &zSquarem, &zSquarel, zh, zl, zh, zl); Mul233(&zCubeh, &zCubem, &zCubel, zh, zl, zSquareh, zSquarem, zSquarel); /* We can now multiplicate the middle and higher polynomial by z^3 */ Mul233(&higherPolyMultZh, &higherPolyMultZm, &higherPolyMultZl, t14h, t14l, zCubeh, zCubem, zCubel); /* Multiply now z^2 by -1/2 (exact op) and add to middle and higher polynomial */ zSquareHalfh = zSquareh * -0.5; zSquareHalfm = zSquarem * -0.5; zSquareHalfl = zSquarel * -0.5; Add33(&polyWithSquareh, &polyWithSquarem, &polyWithSquarel, zSquareHalfh, zSquareHalfm, zSquareHalfl, higherPolyMultZh, higherPolyMultZm, higherPolyMultZl); /* Add now zh and zl to obtain the polynomial evaluation result */ Add233(&polyh, &polym, &polyl, zh, zl, polyWithSquareh, polyWithSquarem, polyWithSquarel); /* Reconstruct now log(y) = log(1 + z) - log(ri) by adding logih, logim, logil logil has not been read to the time, do this first */ logil = argredtable[index].logil; Add33(&logyh, &logym, &logyl, logih, logim, logil, polyh, polym, polyl); /* Multiply log2 with E, i.e. log2h, log2m, log2l by ed ed is always less than 2^(12) and log2h and log2m are stored with at least 12 trailing zeros So multiplying naively is correct (up to 134 bits at least) The final result is thus obtained by adding log2 * E to log(y) */ log2edhover = log2h * ed; log2edmover = log2m * ed; log2edlover = log2l * ed; /* It may be necessary to renormalize the tabulated value (multiplied by ed) before adding the to the log(y)-result If needed, uncomment the following Renormalize3-Statement and comment out the copies following it. */ /* Renormalize3(&log2edh, &log2edm, &log2edl, log2edhover, log2edmover, log2edlover); */ log2edh = log2edhover; log2edm = log2edmover; log2edl = log2edlover; Add33(&loghover, &logmover, &loglover, log2edh, log2edm, log2edl, logyh, logym, logyl); /* Change logarithm base from natural base to base 2 by multiplying */ Mul233(&logb2hover, &logb2mover, &logb2lover, log2invh, log2invl, loghover, logmover, loglover); /* Since we can not guarantee in each addition and multiplication procedure that the results are not overlapping, we must renormalize the result before handing it over to the final rounding */ Renormalize3(logb2h,logb2m,logb2l,logb2hover,logb2mover,logb2lover); } /************************************************************* ************************************************************* * ROUNDED TO NEAREST * ************************************************************* *************************************************************/ double log2_rn(double x){ db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, roundcst; double logb2h, logb2m, logb2l; int E, index; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Change logarithm base from natural base to base 2 by multiplying */ Mul22(&logb2h, &logb2m, log2invh, log2invl, logh, logm); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = ROUNDCST1; else roundcst = ROUNDCST2; if(logb2h == (logb2h + (logb2m * roundcst))) return logb2h; else { #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log2_td_accurate(&logb2h, &logb2m, &logb2l, E, ed, index, zh, zl, logih, logim); ReturnRoundToNearest3(logb2h, logb2m, logb2l); } /* Accurate phase launched */ } /************************************************************* ************************************************************* * ROUNDED UPWARDS * ************************************************************* *************************************************************/ double log2_ru(double x) { db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, roundcst; double logb2h, logb2m, logb2l; int E, index; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); /* Test now if the argument is an exact power of 2 i.e. if the mantissa is exactly 1 (0x0..0 with the implicit bit) This test is necessary for filtering out the cases where the final rounding test cannot distinguish between an exact algebraic number and a hard case to round */ if ((index | xdb.i[LO]) == 0) { /* Handle the "trivial" case for log2: The argument is an exact power of 2, return thus just the exponant of the number */ return (double) E; } xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Change logarithm base from natural base to base 2 by multiplying */ Mul22(&logb2h, &logb2m, log2invh, log2invl, logh, logm); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RU(logb2h, logb2m, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log2_td_accurate(&logb2h, &logb2m, &logb2l, E, ed, index, zh, zl, logih, logim); ReturnRoundUpwards3(logb2h, logb2m, logb2l); } /************************************************************* ************************************************************* * ROUNDED DOWNWARDS * ************************************************************* *************************************************************/ double log2_rd(double x) { db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, roundcst; double logb2h, logb2m, logb2l; int E, index; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); /* Test now if the argument is an exact power of 2 i.e. if the mantissa is exactly 1 (0x0..0 with the implicit bit) This test is necessary for filtering out the cases where the final rounding test cannot distinguish between an exact algebraic number and a hard case to round */ if ((index | xdb.i[LO]) == 0) { /* Handle the "trivial" case for log2: The argument is an exact power of 2, return thus just the exponant of the number */ return (double) E; } xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Change logarithm base from natural base to base 2 by multiplying */ Mul22(&logb2h, &logb2m, log2invh, log2invl, logh, logm); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RD(logb2h, logb2m, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log2_td_accurate(&logb2h, &logb2m, &logb2l, E, ed, index, zh, zl, logih, logim); ReturnRoundDownwards3(logb2h, logb2m, logb2l); } /************************************************************* ************************************************************* * ROUNDED TOWARDS ZERO * ************************************************************* *************************************************************/ double log2_rz(double x) { db_number xdb; double y, ed, ri, logih, logim, yrih, yril, th, zh, zl; double polyHorner, zhSquareh, zhSquarel, polyUpper, zhSquareHalfh, zhSquareHalfl; double t1h, t1l, t2h, t2l, ph, pl, log2edh, log2edl, logTabPolyh, logTabPolyl, logh, logm, roundcst; double logb2h, logb2m, logb2l; int E, index; E=0; xdb.d=x; /* Filter cases */ if (xdb.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb.i[HI] & 0x7fffffff)|xdb.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (xdb.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; xdb.d *= two52; /* make x a normal number */ } if (xdb.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); /* Test now if the argument is an exact power of 2 i.e. if the mantissa is exactly 1 (0x0..0 with the implicit bit) This test is necessary for filtering out the cases where the final rounding test cannot distinguish between an exact algebraic number and a hard case to round */ if ((index | xdb.i[LO]) == 0) { /* Handle the "trivial" case for log2: The argument is an exact power of 2, return thus just the exponant of the number */ return (double) E; } xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } y = xdb.d; index = index & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed = (double) E; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih, &yril, y, ri); th = yrih - 1.0; Add12Cond(zh, zl, th, yril); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner = FMA(FMA(FMA(FMA(c7,zh,c6),zh,c5),zh,c4),zh,c3); #else polyHorner = c3 + zh * (c4 + zh * (c5 + zh * (c6 + zh * c7))); #endif Mul12(&zhSquareh, &zhSquarel, zh, zh); polyUpper = polyHorner * (zh * zhSquareh); zhSquareHalfh = zhSquareh * -0.5; zhSquareHalfl = zhSquarel * -0.5; Add12(t1h, t1l, polyUpper, -1 * (zh * zl)); Add22(&t2h, &t2l, zh, zl, zhSquareHalfh, zhSquareHalfl); Add22(&ph, &pl, t2h, t2l, t1h, t1l); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh, log2edl, log2h * ed, log2m * ed); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh, &logTabPolyl, logih, logim, ph, pl); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh, &logm, log2edh, log2edl, logTabPolyh, logTabPolyl); /* Change logarithm base from natural base to base 2 by multiplying */ Mul22(&logb2h, &logb2m, log2invh, log2invl, logh, logm); /* Rounding test and eventual return or call to the accurate function */ if(E==0) roundcst = RDROUNDCST1; else roundcst = RDROUNDCST2; TEST_AND_RETURN_RZ(logb2h, logb2m, roundcst); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif log2_td_accurate(&logb2h, &logb2m, &logb2l, E, ed, index, zh, zl, logih, logim); ReturnRoundTowardsZero3(logb2h, logb2m, logb2l); } #ifdef BUILD_INTERVAL_FUNCTIONS interval j_log2(interval x) { interval res; double res_inf, res_sup, restemp_inf, restemp_sup; int infDone, supDone; int roundable; db_number xdb_inf; double y_inf, ed_inf, ri_inf, logih_inf, logim_inf, yrih_inf, yril_inf, th_inf, zh_inf, zl_inf; double polyHorner_inf, zhSquareh_inf, zhSquarel_inf, polyUpper_inf, zhSquareHalfh_inf, zhSquareHalfl_inf; double t1h_inf, t1l_inf, t2h_inf, t2l_inf, ph_inf, pl_inf, log2edh_inf, log2edl_inf, logTabPolyh_inf, logTabPolyl_inf, logh_inf, logm_inf, roundcst_inf; double logb2h_inf, logb2m_inf, logb2l_inf; int E_inf, index_inf; db_number xdb_sup; double y_sup, ed_sup, ri_sup, logih_sup, logim_sup, yrih_sup, yril_sup, th_sup, zh_sup, zl_sup; double polyHorner_sup, zhSquareh_sup, zhSquarel_sup, polyUpper_sup, zhSquareHalfh_sup, zhSquareHalfl_sup; double t1h_sup, t1l_sup, t2h_sup, t2l_sup, ph_sup, pl_sup, log2edh_sup, log2edl_sup, logTabPolyh_sup, logTabPolyl_sup, logh_sup, logm_sup, roundcst_sup; double logb2h_sup, logb2m_sup, logb2l_sup; int E_sup, index_sup; double x_inf, x_sup; x_inf=LOW(x); x_sup=UP(x); infDone=0; supDone=0; E_inf=0; E_sup=0; xdb_inf.d=x_inf; xdb_sup.d=x_sup; /* Filter cases */ if (xdb_inf.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb_inf.i[HI] & 0x7fffffff)|xdb_inf.i[LO])==0){ infDone=1; restemp_inf = -1.0/0.0; } /* log(+/-0) = -Inf */ if ((xdb_inf.i[HI] < 0) && (infDone==0)){ infDone=1; restemp_inf = (x_inf-x_inf)/0; /* log(-x) = Nan */ } /* Subnormal number */ E_inf = -52; xdb_inf.d *= two52; /* make x a normal number */ } if ((xdb_inf.i[HI] >= 0x7ff00000) && (infDone==0)){ infDone=1; restemp_inf = x_inf+x_inf; /* Inf or Nan */ } /* Filter cases */ if (xdb_sup.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((xdb_sup.i[HI] & 0x7fffffff)|xdb_sup.i[LO])==0){ supDone=1; restemp_sup = -1.0/0.0; } /* log(+/-0) = -Inf */ if ((xdb_sup.i[HI] < 0) && (supDone==0)){ supDone=1; restemp_sup = (x_sup-x_sup)/0; /* log(-x) = Nan */ } /* Subnormal number */ E_sup = -52; xdb_sup.d *= two52; /* make x a normal number */ } if ((xdb_sup.i[HI] >= 0x7ff00000) && (supDone==0)){ supDone=1; restemp_sup = x_sup+x_sup; /* Inf or Nan */ } /* Extract exponent and mantissa Do range reduction, yielding to E holding the exponent and y the mantissa between sqrt(2)/2 and sqrt(2) */ E_inf += (xdb_inf.i[HI]>>20)-1023; /* extract the exponent */ E_sup += (xdb_sup.i[HI]>>20)-1023; /* extract the exponent */ index_inf = (xdb_inf.i[HI] & 0x000fffff); index_sup = (xdb_sup.i[HI] & 0x000fffff); /* Test now if the argument is an exact power of 2 i.e. if the mantissa is exactly 1 (0x0..0 with the implicit bit) This test is necessary for filtering out the cases where the final rounding test cannot distinguish between an exact algebraic number and a hard case to round */ if (((index_inf | xdb_inf.i[LO]) == 0) && (infDone==0)) { /* Handle the "trivial" case for log2: The argument is an exact power of 2, return thus just the exponant of the number */ supDone=1; restemp_inf = (double) E_inf; } if (((index_sup | xdb_sup.i[LO]) == 0) && (supDone==0)) { /* Handle the "trivial" case for log2: The argument is an exact power of 2, return thus just the exponant of the number */ supDone=1; restemp_sup = (double) E_sup; } if((infDone==1) && (supDone==1)) { ASSIGN_LOW(res,restemp_inf); ASSIGN_UP(res,restemp_sup); return res; } if((infDone==0) && (supDone==0)) { xdb_inf.i[HI] = index_inf | 0x3ff00000; /* do exponent = 0 */ xdb_sup.i[HI] = index_sup | 0x3ff00000; /* do exponent = 0 */ index_inf = (index_inf + (1<<(20-L-1))) >> (20-L); index_sup = (index_sup + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index_inf >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb_inf.i[HI] -= 0x00100000; E_inf++; } if (index_sup >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb_sup.i[HI] -= 0x00100000; E_sup++; } y_inf = xdb_inf.d; y_sup = xdb_sup.d; index_inf = index_inf & INDEXMASK; index_sup = index_sup & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed_inf = (double) E_inf; ed_sup = (double) E_sup; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri_inf = argredtable[index_inf].ri; ri_sup = argredtable[index_sup].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih_inf = argredtable[index_inf].logih; logih_sup = argredtable[index_sup].logih; logim_inf = argredtable[index_inf].logim; logim_sup = argredtable[index_sup].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih_inf, &yril_inf, y_inf, ri_inf); Mul12(&yrih_sup, &yril_sup, y_sup, ri_sup); th_inf = yrih_inf - 1.0; th_sup = yrih_sup - 1.0; Add12Cond(zh_inf, zl_inf, th_inf, yril_inf); Add12Cond(zh_sup, zl_sup, th_sup, yril_sup); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner_inf = FMA(FMA(FMA(FMA(c7_inf,zh_inf,c6),zh_inf,c5),zh_inf,c4),zh_inf,c3); polyHorner_sup = FMA(FMA(FMA(FMA(c7,zh_sup,c6),zh_sup,c5),zh_sup,c4),zh_sup,c3); #else polyHorner_inf = c3 + zh_inf * (c4 + zh_inf * (c5 + zh_inf * (c6 + zh_inf * c7))); polyHorner_sup = c3 + zh_sup * (c4 + zh_sup * (c5 + zh_sup * (c6 + zh_sup * c7))); #endif Mul12(&zhSquareh_inf, &zhSquarel_inf, zh_inf, zh_inf); Mul12(&zhSquareh_sup, &zhSquarel_sup, zh_sup, zh_sup); polyUpper_inf = polyHorner_inf * (zh_inf * zhSquareh_inf); polyUpper_sup = polyHorner_sup * (zh_sup * zhSquareh_sup); zhSquareHalfh_inf = zhSquareh_inf * -0.5; zhSquareHalfh_sup = zhSquareh_sup * -0.5; zhSquareHalfl_inf = zhSquarel_inf * -0.5; zhSquareHalfl_sup = zhSquarel_sup * -0.5; Add12(t1h_inf, t1l_inf, polyUpper_inf, -1 * (zh_inf * zl_inf)); Add12(t1h_sup, t1l_sup, polyUpper_sup, -1 * (zh_sup * zl_sup)); Add22(&t2h_inf, &t2l_inf, zh_inf, zl_inf, zhSquareHalfh_inf, zhSquareHalfl_inf); Add22(&t2h_sup, &t2l_sup, zh_sup, zl_sup, zhSquareHalfh_sup, zhSquareHalfl_sup); Add22(&ph_inf, &pl_inf, t2h_inf, t2l_inf, t1h_inf, t1l_inf); Add22(&ph_sup, &pl_sup, t2h_sup, t2l_sup, t1h_sup, t1l_sup); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh_inf, log2edl_inf, log2h * ed_inf, log2m * ed_inf); Add12(log2edh_sup, log2edl_sup, log2h * ed_sup, log2m * ed_sup); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh_inf, &logTabPolyl_inf, logih_inf, logim_inf, ph_inf, pl_inf); Add22Cond(&logTabPolyh_sup, &logTabPolyl_sup, logih_sup, logim_sup, ph_sup, pl_sup); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh_inf, &logm_inf, log2edh_inf, log2edl_inf, logTabPolyh_inf, logTabPolyl_inf); Add22Cond(&logh_sup, &logm_sup, log2edh_sup, log2edl_sup, logTabPolyh_sup, logTabPolyl_sup); /* Change logarithm base from natural base to base 2 by multiplying */ Mul22(&logb2h_inf, &logb2m_inf, log2invh, log2invl, logh_inf, logm_inf); Mul22(&logb2h_sup, &logb2m_sup, log2invh, log2invl, logh_sup, logm_sup); /* Rounding test and eventual return or call to the accurate function */ if(E_inf==0) roundcst_inf = RDROUNDCST1; else roundcst_inf = RDROUNDCST2; if(E_sup==0) roundcst_sup = RDROUNDCST1; else roundcst_sup = RDROUNDCST2; TEST_AND_COPY_RDRU_LOG2(roundable, restemp_inf,logb2h_inf, logb2m_inf, restemp_sup, logb2h_sup, logb2m_sup, roundcst_inf, roundcst_sup); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x_inf); #endif if((roundable==2) || (roundable==0)) { log2_td_accurate(&logb2h_inf, &logb2m_inf, &logb2l_inf, E_inf, ed_inf, index_inf, zh_inf, zl_inf, logih_inf, logim_inf); RoundDownwards3(&restemp_inf,logb2h_inf, logb2m_inf, logb2l_inf); } if((roundable==1) || (roundable==0)) { log2_td_accurate(&logb2h_sup, &logb2m_sup, &logb2l_sup, E_sup, ed_sup, index_sup, zh_sup, zl_sup, logih_sup, logim_sup); RoundUpwards3(&restemp_sup,logb2h_sup, logb2m_sup, logb2l_sup); } ASSIGN_LOW(res,restemp_inf); ASSIGN_UP(res,restemp_sup); return res; } if((infDone==0)) { xdb_inf.i[HI] = index_inf | 0x3ff00000; /* do exponent = 0 */ index_inf = (index_inf + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index_inf >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb_inf.i[HI] -= 0x00100000; E_inf++; } y_inf = xdb_inf.d; index_inf = index_inf & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed_inf = (double) E_inf; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri_inf = argredtable[index_inf].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih_inf = argredtable[index_inf].logih; logim_inf = argredtable[index_inf].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih_inf, &yril_inf, y_inf, ri_inf); th_inf = yrih_inf - 1.0; Add12Cond(zh_inf, zl_inf, th_inf, yril_inf); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner_inf = FMA(FMA(FMA(FMA(c7_inf,zh_inf,c6),zh_inf,c5),zh_inf,c4),zh_inf,c3); #else polyHorner_inf = c3 + zh_inf * (c4 + zh_inf * (c5 + zh_inf * (c6 + zh_inf * c7))); #endif Mul12(&zhSquareh_inf, &zhSquarel_inf, zh_inf, zh_inf); polyUpper_inf = polyHorner_inf * (zh_inf * zhSquareh_inf); zhSquareHalfh_inf = zhSquareh_inf * -0.5; zhSquareHalfl_inf = zhSquarel_inf * -0.5; Add12(t1h_inf, t1l_inf, polyUpper_inf, -1 * (zh_inf * zl_inf)); Add22(&t2h_inf, &t2l_inf, zh_inf, zl_inf, zhSquareHalfh_inf, zhSquareHalfl_inf); Add22(&ph_inf, &pl_inf, t2h_inf, t2l_inf, t1h_inf, t1l_inf); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh_inf, log2edl_inf, log2h * ed_inf, log2m * ed_inf); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh_inf, &logTabPolyl_inf, logih_inf, logim_inf, ph_inf, pl_inf); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh_inf, &logm_inf, log2edh_inf, log2edl_inf, logTabPolyh_inf, logTabPolyl_inf); /* Change logarithm base from natural base to base 2 by multiplying */ Mul22(&logb2h_inf, &logb2m_inf, log2invh, log2invl, logh_inf, logm_inf); /* Rounding test and eventual return or call to the accurate function */ if(E_inf==0) roundcst_inf = RDROUNDCST1; else roundcst_inf = RDROUNDCST2; TEST_AND_COPY_RD(roundable, restemp_inf,logb2h_inf, logb2m_inf, roundcst_inf); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x_inf); #endif if((roundable==0)) { log2_td_accurate(&logb2h_inf, &logb2m_inf, &logb2l_inf, E_inf, ed_inf, index_inf, zh_inf, zl_inf, logih_inf, logim_inf); RoundDownwards3(&restemp_inf,logb2h_inf, logb2m_inf, logb2l_inf); } ASSIGN_LOW(res,restemp_inf); ASSIGN_UP(res,restemp_sup); return res; } if((supDone==0)) { xdb_sup.i[HI] = index_sup | 0x3ff00000; /* do exponent = 0 */ index_sup = (index_sup + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index_sup >= MAXINDEX){ /* corresponds to xdb>sqrt(2)*/ xdb_sup.i[HI] -= 0x00100000; E_sup++; } y_sup = xdb_sup.d; index_sup = index_sup & INDEXMASK; /* Cast integer E into double ed for multiplication later */ ed_sup = (double) E_sup; /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri_sup = argredtable[index_sup].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih_sup = argredtable[index_sup].logih; logim_sup = argredtable[index_sup].logim; /* Do range reduction: zh + zl = y * ri - 1.0 correctly Correctness is assured by use of Mul12 and Add12 even if we don't force ri to have its' LSBs set to zero Discard zl for higher monome degrees */ Mul12(&yrih_sup, &yril_sup, y_sup, ri_sup); th_sup = yrih_sup - 1.0; Add12Cond(zh_sup, zl_sup, th_sup, yril_sup); /* Polynomial evaluation Use a 7 degree polynomial Evaluate the higher 5 terms in double precision (-7 * 3 = -21) using Horner's scheme Evaluate the lower 3 terms (the last is 0) in double double precision accounting also for zl using an ad hoc method */ #if defined(PROCESSOR_HAS_FMA) && !defined(AVOID_FMA) polyHorner_sup = FMA(FMA(FMA(FMA(c7,zh_sup,c6),zh_sup,c5),zh_sup,c4),zh_sup,c3); #else polyHorner_sup = c3 + zh_sup * (c4 + zh_sup * (c5 + zh_sup * (c6 + zh_sup * c7))); #endif Mul12(&zhSquareh_sup, &zhSquarel_sup, zh_sup, zh_sup); polyUpper_sup = polyHorner_sup * (zh_sup * zhSquareh_sup); zhSquareHalfh_sup = zhSquareh_sup * -0.5; zhSquareHalfl_sup = zhSquarel_sup * -0.5; Add12(t1h_sup, t1l_sup, polyUpper_sup, -1 * (zh_sup * zl_sup)); Add22(&t2h_sup, &t2l_sup, zh_sup, zl_sup, zhSquareHalfh_sup, zhSquareHalfl_sup); Add22(&ph_sup, &pl_sup, t2h_sup, t2l_sup, t1h_sup, t1l_sup); /* Reconstruction Read logih and logim in the tables (already done) Compute log(x) = E * log(2) + log(1+z) - log(ri) i.e. log(x) = ed * (log2h + log2m) + (ph + pl) + (logih + logim) + delta Carry out everything in double double precision */ /* We store log2 as log2h + log2m + log2l where log2h and log2m have 12 trailing zeros Multiplication of ed (double E) and log2h is thus correct The overall accuracy of log2h + log2m + log2l is 53 * 3 - 24 = 135 which is enough for the accurate phase The accuracy suffices also for the quick phase: 53 * 2 - 24 = 82 Nevertheless the storage with trailing zeros implies an overlap of the tabulated triple double values. We have to take it into account for the accurate phase basic procedures for addition and multiplication The condition on the next Add12 is verified as log2m is smaller than log2h and both are scaled by ed */ Add12(log2edh_sup, log2edl_sup, log2h * ed_sup, log2m * ed_sup); /* Add logih and logim to ph and pl We must use conditioned Add22 as logih can move over ph */ Add22Cond(&logTabPolyh_sup, &logTabPolyl_sup, logih_sup, logim_sup, ph_sup, pl_sup); /* Add log2edh + log2edl to logTabPolyh + logTabPolyl */ Add22Cond(&logh_sup, &logm_sup, log2edh_sup, log2edl_sup, logTabPolyh_sup, logTabPolyl_sup); /* Change logarithm base from natural base to base 2 by multiplying */ Mul22(&logb2h_sup, &logb2m_sup, log2invh, log2invl, logh_sup, logm_sup); /* Rounding test and eventual return or call to the accurate function */ if(E_sup==0) roundcst_sup = RDROUNDCST1; else roundcst_sup = RDROUNDCST2; TEST_AND_COPY_RU(roundable, restemp_sup,logb2h_sup, logb2m_sup, roundcst_sup); #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x_inf); #endif if((roundable==0)) { log2_td_accurate(&logb2h_sup, &logb2m_sup, &logb2l_sup, E_sup, ed_sup, index_sup, zh_sup, zl_sup, logih_sup, logim_sup); RoundUpwards3(&restemp_sup,logb2h_sup, logb2m_sup, logb2l_sup); } ASSIGN_LOW(res,restemp_inf); ASSIGN_UP(res,restemp_sup); return res; } } #endif interval-3.2.0/src/crlibm/log2-td.h0000644000000000000000000013170513316017127015156 0ustar 00000000000000/* * This function computes log2, correctly rounded, * using experimental techniques based on triple double arithmetics * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" /*File generated by maple/log2-td.mpl*/ #define L 7 #define MAXINDEX 53 #define INDEXMASK 127 #define two52 4.50359962737049600000000000000000000000000000000000e+15 #define log2h 6.93147180559890330187045037746429443359375000000000e-01 #define log2m 5.49792301870850242169664946507035702127907939029683e-14 #define log2l -1.31246984177852556920995753667322295879593697972250e-27 #define log2invh 1.44269504088896338700465094007086008787155151367188e+00 #define log2invl 2.03552737409310331110210900522069120325603861485809e-17 #define ROUNDCST1 1.00787401574803160796292764473221714405939530505554e+00 #define ROUNDCST2 1.00787401574803160796292764473221714405939530505554e+00 #define RDROUNDCST1 4.33680868994201773602981120347976684570312500000000e-19 #define RDROUNDCST2 4.33680868994201773602981120347976684570312500000000e-19 #define c3 3.33333333333333370340767487505218014121055603027344e-01 #define c4 -2.49999999990904886448817023847368545830249786376953e-01 #define c5 1.99999999978980019799124079327157232910394668579102e-01 #define c6 -1.66669050883027802800739891608827747404575347900391e-01 #define c7 1.42860109897981618631845890377007890492677688598633e-01 #define accPolyC3h 3.33333333333333314829616256247390992939472198486328e-01 #define accPolyC3l 1.85037170770859413132312241283212169118117639547054e-17 #define accPolyC4h -2.50000000000000000000000000000000000000000000000000e-01 #define accPolyC4l 4.62199018306924685334006418421322154174127637249391e-33 #define accPolyC5h 2.00000000000000011102230246251565404236316680908203e-01 #define accPolyC5l -1.11022302443127785678379338452126964515833173338601e-17 #define accPolyC6h -1.66666666666666657414808128123695496469736099243164e-01 #define accPolyC6l -9.25185854591372488017120157358742564605503054108327e-18 #define accPolyC7h 1.42857142857142849212692681248881854116916656494141e-01 #define accPolyC7l 7.92868209382438390589949095717120486682310988838960e-18 #define accPolyC8h -1.25000000000000000000000000000000000000000000000000e-01 #define accPolyC8l 3.42769668947376590645174407718339199260639267364101e-21 #define accPolyC9h 1.11111111111111521276839653182832989841699600219727e-01 #define accPolyC9l 4.33331955380787609416227741118274520376899199903317e-18 #define accPolyC10 -1.00000000000000699440505513848620466887950897216797e-01 #define accPolyC11 9.09090908567022348840680479042930528521537780761719e-02 #define accPolyC12 -8.33333332642126056732934102910803630948066711425781e-02 #define accPolyC13 7.69261287585959879775643344146374147385358810424805e-02 #define accPolyC14 -7.14319092953022982683819464000407606363296508789062e-02 typedef struct rri_tag {float ri; double logih; double logim; double logil;} rri; static const rri argredtable[128] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* r[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logih[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logim[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logil[0] */ } , { 9.92248058319091796875000000000000000000000000000000e-01, /* r[1] */ 7.78214416734525436109004559170898573938757181167603e-03, /* logih[1] */ -1.28191618904143681948935996668824218266800862156024e-20, /* logim[1] */ 1.17655068600225378123891861200215069271455859581641e-37, /* logil[1] */ } , { 9.84615325927734375000000000000000000000000000000000e-01, /* r[2] */ 1.55042461406118062261505485821544425562024116516113e-02, /* logih[2] */ -3.27761516207149627029928635703400435929630184221293e-19, /* logim[2] */ 2.95200020707030964072253388818190769795416371257942e-37, /* logil[2] */ } , { 9.77099180221557617187500000000000000000000000000000e-01, /* r[3] */ 2.31671170235356708999585606534310500137507915496826e-02, /* logih[3] */ 5.57833156048330069504471566938468802334954100224869e-19, /* logim[3] */ 4.08416064054113313191746248503653555682943539201798e-35, /* logil[3] */ } , { 9.69696998596191406250000000000000000000000000000000e-01, /* r[4] */ 3.07716288644317437217523547587916254997253417968750e-02, /* logih[4] */ 1.04316437964092669923942103072089812062131860035492e-18, /* logim[4] */ -8.26837774892530079043982861155759865584698067912967e-36, /* logil[4] */ } , { 9.62406039237976074218750000000000000000000000000000e-01, /* r[5] */ 3.83188391564273991840572364253603154793381690979004e-02, /* logih[5] */ 1.54512636366303706650320890230224472259662656606095e-18, /* logim[5] */ 8.30977110244055528389241824578843983429633068152463e-35, /* logil[5] */ } , { 9.55223917961120605468750000000000000000000000000000e-01, /* r[6] */ 4.58094969157468376308450785927561810240149497985840e-02, /* logih[6] */ -3.30123051072550842868548428055668582607719074881820e-18, /* logim[6] */ 1.64164772626574162996727598513545022472742050176492e-34, /* logil[6] */ } , { 9.48148131370544433593750000000000000000000000000000e-01, /* r[7] */ 5.32445322139413548812036935942160198464989662170410e-02, /* logih[7] */ 2.23755385085953619415254057336256700540433618368589e-18, /* logim[7] */ -9.41330315099866735037984721876103977945647219756033e-35, /* logil[7] */ } , { 9.41176414489746093750000000000000000000000000000000e-01, /* r[8] */ 6.06246814210813916856679384181916248053312301635742e-02, /* logih[8] */ 2.64247317995478646334926909653435556549332769494295e-18, /* logim[8] */ 1.55075207452234839722600788456166299408429635417895e-34, /* logil[8] */ } , { 9.34306621551513671875000000000000000000000000000000e-01, /* r[9] */ 6.79506060291548280583029395529592875391244888305664e-02, /* logih[9] */ 5.65862161871167282533541105359923619273100535513035e-18, /* logim[9] */ -3.57889357320249912090032102867532919048871786355064e-34, /* logil[9] */ } , { 9.27536249160766601562500000000000000000000000000000e-01, /* r[10] */ 7.52234026111362058530929175503842998296022415161133e-02, /* logih[10] */ 1.00828755349783911736541446332784521904773238841865e-18, /* logim[10] */ 7.77966415828014771486738038255868010153689429282538e-36, /* logil[10] */ } , { 9.20863270759582519531250000000000000000000000000000e-01, /* r[11] */ 8.24437111205913314426751981045526918023824691772461e-02, /* logih[11] */ -4.27419767632228646217014766651675738804062364961374e-18, /* logim[11] */ 3.58539257549786746072726449331073277906948658046759e-34, /* logil[11] */ } , { 9.14285659790039062500000000000000000000000000000000e-01, /* r[12] */ 8.96122182943336897942288032936630770564079284667969e-02, /* logih[12] */ -5.42674234758262048883730612286095846547194397615989e-18, /* logim[12] */ -7.94903110897686868047461590865098481976776339992810e-35, /* logil[12] */ } , { 9.07801389694213867187500000000000000000000000000000e-01, /* r[13] */ 9.67296581235191493819414176869031507521867752075195e-02, /* logih[13] */ 1.17499431052084706890372286741885325822732164697539e-18, /* logim[13] */ -7.47188021694240554877009439429630012902672969107896e-35, /* logil[13] */ } , { 9.01408433914184570312500000000000000000000000000000e-01, /* r[14] */ 1.03796812308095232069149460585322231054306030273438e-01, /* logih[14] */ -1.46116759252442942691327623497388991415382979093093e-18, /* logim[14] */ -5.84766064918572844473631496354606243606272630720064e-35, /* logil[14] */ } , { 8.95104885101318359375000000000000000000000000000000e-01, /* r[15] */ 1.10814377516161077785739053069846704602241516113281e-01, /* logih[15] */ -5.75514509579248124656596649605847554012818793702281e-18, /* logim[15] */ 3.29977719536339952907783192540462408052319847426319e-34, /* logil[15] */ } , { 8.88888835906982421875000000000000000000000000000000e-01, /* r[16] */ 1.17783095261030007483427084480354096740484237670898e-01, /* logih[16] */ -1.19709798867727449215060005668653850880775796697715e-18, /* logim[16] */ 8.04222018353684236067064017226062133396406008492921e-35, /* logil[16] */ } , { 8.82758617401123046875000000000000000000000000000000e-01, /* r[17] */ 1.24703482226247538977581541530526010319590568542480e-01, /* logih[17] */ 2.28663295749049514726834658528273231115811065734312e-18, /* logim[17] */ -3.51123005875932392272239647660221882537057244586168e-35, /* logil[17] */ } , { 8.76712322235107421875000000000000000000000000000000e-01, /* r[18] */ 1.31576365239299886145118989588809199631214141845703e-01, /* logih[18] */ 1.11230010175930229418362785876222391520299564865730e-17, /* logim[18] */ 7.27451645836749926637643602480531900716806359121297e-34, /* logil[18] */ } , { 8.70748281478881835937500000000000000000000000000000e-01, /* r[19] */ 1.38402343348215994822680841025430709123611450195312e-01, /* logih[19] */ -7.69528416335144553864151614176326744245393995127969e-18, /* logim[19] */ 1.14202629230472885861778260955781649682548331183808e-34, /* logil[19] */ } , { 8.64864826202392578125000000000000000000000000000000e-01, /* r[20] */ 1.45182054547982469783207193358975928276777267456055e-01, /* logih[20] */ 8.24244856152552570070228105635897158979868211170798e-18, /* logim[20] */ -6.13072808770694892835379995250538817854995507648779e-34, /* logil[20] */ } , { 8.59060406684875488281250000000000000000000000000000e-01, /* r[21] */ 1.51916037369229123266123337998578790575265884399414e-01, /* logih[21] */ -1.04296908000297145574171199957656893307239877379000e-17, /* logim[21] */ -5.53636436435840586444373230094200986769217138540854e-34, /* logil[21] */ } , { 8.53333353996276855468750000000000000000000000000000e-01, /* r[22] */ 1.58605005962251938145257668111298698931932449340820e-01, /* logih[22] */ -8.86065192248216377790637508171938194510660992474042e-19, /* logim[22] */ -5.87995214834401673695486864800931832452468264932844e-35, /* logil[22] */ } , { 8.47682118415832519531250000000000000000000000000000e-01, /* r[23] */ 1.65249573826629747586025587224867194890975952148438e-01, /* logih[23] */ -9.66125475305916070790888958698289394696700966750453e-18, /* logim[23] */ 1.22853647999759344001960461047755491313341721869856e-34, /* logil[23] */ } , { 8.42105269432067871093750000000000000000000000000000e-01, /* r[24] */ 1.71850249476078659194300257695431355386972427368164e-01, /* logih[24] */ -6.02245395887480538795512923412250309472746231920746e-18, /* logim[24] */ 1.52961687917434402329553899350235008490821862631877e-34, /* logil[24] */ } , { 8.36601257324218750000000000000000000000000000000000e-01, /* r[25] */ 1.78407717077464861299418430462537799030542373657227e-01, /* logih[25] */ -1.24324832026190372515095573175819374097319572461178e-17, /* logim[25] */ -5.99222696564577786410580709003476847421843326905428e-34, /* logil[25] */ } , { 8.31168889999389648437500000000000000000000000000000e-01, /* r[26] */ 1.84922267713498816865680396404059138149023056030273e-01, /* logih[26] */ 9.96243711860796179875713739627414673019270693540839e-18, /* logim[26] */ -1.99546782893888540832510298706525540082513642365204e-34, /* logil[26] */ } , { 8.25806498527526855468750000000000000000000000000000e-01, /* r[27] */ 1.91394796188954025017991966706176754087209701538086e-01, /* logih[27] */ -8.22643020277300444045205706293674132131812201700538e-18, /* logim[27] */ 5.69056030867564774930537188285078930441778787828211e-34, /* logil[27] */ } , { 8.20512771606445312500000000000000000000000000000000e-01, /* r[28] */ 1.97825802934566419288842098467284813523292541503906e-01, /* logih[28] */ 1.28212649590622342007825921152819823725126964367518e-17, /* logim[28] */ 4.34712978477783827374998481132430084872238812357849e-34, /* logil[28] */ } , { 8.15286636352539062500000000000000000000000000000000e-01, /* r[29] */ 2.04215526527529805944638496839615982025861740112305e-01, /* logih[29] */ 2.73382699896480606605004885268461286375739934002155e-18, /* logim[29] */ 1.88415596219599490517606146615135776386751947516623e-34, /* logil[29] */ } , { 8.10126543045043945312500000000000000000000000000000e-01, /* r[30] */ 2.10564817536124687658016796376614365726709365844727e-01, /* logih[30] */ 2.68952644992466202072392146799884466396384136175691e-18, /* logim[30] */ -1.58883120037037559046153789501260274259127656480088e-34, /* logil[30] */ } , { 8.05031418800354003906250000000000000000000000000000e-01, /* r[31] */ 2.16873972759550226463431954471161589026451110839844e-01, /* logih[31] */ -1.23625140584833845652640860288020787431726668393088e-17, /* logim[31] */ -1.28369360755661214950804825668450767372141502246786e-34, /* logil[31] */ } , { 7.99999952316284179687500000000000000000000000000000e-01, /* r[32] */ 2.23143610918856316605030087885097600519657135009766e-01, /* logih[32] */ -9.09120001124270523314725361445863555491966823753373e-18, /* logim[32] */ 1.15945802868784933647836819275496182741822080543604e-34, /* logil[32] */ } , { 7.95031070709228515625000000000000000000000000000000e-01, /* r[33] */ 2.29374082438394522043267897970508784055709838867188e-01, /* logih[33] */ -1.08890120418598083770448590672876580941469212582837e-17, /* logim[33] */ 4.74877924128943438272197143958394008126523960202900e-34, /* logil[33] */ } , { 7.90123462677001953125000000000000000000000000000000e-01, /* r[34] */ 2.35566063862186342303672859088692348450422286987305e-01, /* logih[34] */ -2.39433728738216998660812173360881116827035967139939e-18, /* logim[34] */ -9.62471867414270770251397101906428335828045927610883e-35, /* logil[34] */ } , { 7.85276055335998535156250000000000000000000000000000e-01, /* r[35] */ 2.41719960170209802186036540661007165908813476562500e-01, /* logih[35] */ 2.39578119451184969695376143676233310543075971208880e-18, /* logim[35] */ 1.86231935097448741662637615288316997021879162207127e-34, /* logil[35] */ } , { 7.80487775802612304687500000000000000000000000000000e-01, /* r[36] */ 2.47836201157484947721343360171886160969734191894531e-01, /* logih[36] */ -1.24321923457726137680465119406863072977770725701004e-17, /* logim[36] */ -2.09577513970149680056365167860895085898294691979404e-34, /* logil[36] */ } , { 7.75757551193237304687500000000000000000000000000000e-01, /* r[37] */ 2.53915241645931488712051304901251569390296936035156e-01, /* logih[37] */ -6.31336333527435824035156315376733999545148217960567e-18, /* logim[37] */ 4.63496313971202069379055986715253908538961883067566e-35, /* logil[37] */ } , { 7.71084308624267578125000000000000000000000000000000e-01, /* r[38] */ 2.59957561689829752538116736104711890220642089843750e-01, /* logih[38] */ -7.05748899290965383754297836711168798219001736647281e-18, /* logim[38] */ 4.27245447011230141916526741370315150982259792796987e-34, /* logil[38] */ } , { 7.66467094421386718750000000000000000000000000000000e-01, /* r[39] */ 2.65963511244235673025571031757863238453865051269531e-01, /* logih[39] */ -2.24162125724264292804912034054420308588570407662844e-17, /* logim[39] */ 4.90471140265143981765909599584287898945638617268867e-34, /* logil[39] */ } , { 7.61904716491699218750000000000000000000000000000000e-01, /* r[40] */ 2.71933775088288309795814257086021825671195983886719e-01, /* logih[40] */ 7.83390223779535346513505580003968001040971161798700e-19, /* logim[40] */ -3.02585215101390470982866376614279464778757620082138e-35, /* logil[40] */ } , { 7.57396459579467773437500000000000000000000000000000e-01, /* r[41] */ 2.77868437964940373507971571598318405449390411376953e-01, /* logih[41] */ -2.69368711734232128278453248569958166651302969280381e-17, /* logim[41] */ 1.27334496810554064003001771076892864921428144153570e-33, /* logil[41] */ } , { 7.52941131591796875000000000000000000000000000000000e-01, /* r[42] */ 2.83768232735291170421021433867281302809715270996094e-01, /* logih[42] */ -2.03265852251844689554711830689719609838328388091381e-17, /* logim[42] */ 3.99265876662456660849597520210659365811534845502505e-34, /* logil[42] */ } , { 7.48538017272949218750000000000000000000000000000000e-01, /* r[43] */ 2.89633285132462114930262941925320774316787719726562e-01, /* logih[43] */ -7.21962253363417273270454867455071277489833577725373e-18, /* logim[43] */ -2.16150227221931053192432009592422674631830770048369e-34, /* logil[43] */ } , { 7.44186043739318847656250000000000000000000000000000e-01, /* r[44] */ 2.95464216619126196494704572614864446222782135009766e-01, /* logih[44] */ -1.47072146829197428851717511710908602721304319475328e-17, /* logim[44] */ 4.88114627787723832872543510409367916590649903129304e-34, /* logil[44] */ } , { 7.39884376525878906250000000000000000000000000000000e-01, /* r[45] */ 3.01261352929903802877475982313626445829868316650391e-01, /* logih[45] */ 1.87070681938931680167624656750430985298856099421569e-17, /* logim[45] */ 1.51413799416501325421897094776870076323182009328971e-33, /* logil[45] */ } , { 7.35632181167602539062500000000000000000000000000000e-01, /* r[46] */ 3.07025039020202172856954803137341514229774475097656e-01, /* logih[46] */ -5.38102227896180596526923200171118043417676846319102e-18, /* logim[46] */ 2.06712483430759996475892191286335029882052180959917e-34, /* logil[46] */ } , { 7.31428623199462890625000000000000000000000000000000e-01, /* r[47] */ 3.12755639223383730129768309780047275125980377197266e-01, /* logih[47] */ -7.57930782773895721056011815787401170737920404028723e-18, /* logim[47] */ 8.39475110593319988799512618628582752750846924050440e-35, /* logil[47] */ } , { 7.27272748947143554687500000000000000000000000000000e-01, /* r[48] */ 3.18453701316212645089365196326980367302894592285156e-01, /* logih[48] */ 2.71147705440665649189983820006370647423267349507715e-17, /* logim[48] */ 4.61673001741568050305139864943649666789926072891368e-34, /* logil[48] */ } , { 7.23163843154907226562500000000000000000000000000000e-01, /* r[49] */ 3.24119466791566834817928111078799702227115631103516e-01, /* logih[49] */ -6.22349090807112113628215383245238541760656175683922e-18, /* logim[49] */ -2.94864944946984528585289533414905600786096792764282e-34, /* logil[49] */ } , { 7.19101071357727050781250000000000000000000000000000e-01, /* r[50] */ 3.29753359015631464234985514849540777504444122314453e-01, /* logih[50] */ -2.38987037434306035496609341036867889075145964580121e-17, /* logim[50] */ -1.22161021411351376080765213758661026982900357467596e-33, /* logil[50] */ } , { 7.15083837509155273437500000000000000000000000000000e-01, /* r[51] */ 3.35355487904429983014864546930766664445400238037109e-01, /* logih[51] */ -2.15530481136091842439480783176785939188081961777809e-17, /* logim[51] */ 5.65377778536716902900522531845470344712374772157319e-34, /* logil[51] */ } , { 7.11111068725585937500000000000000000000000000000000e-01, /* r[52] */ 3.40926646575239744585417156486073508858680725097656e-01, /* logih[52] */ 1.74672070296268393919501631375949801326271042364782e-17, /* logim[52] */ 1.28757784323920807504216254145051967795248381758825e-33, /* logil[52] */ } , { 1.41436457633972167968750000000000000000000000000000e+00, /* r[53] */ -3.46680367578929504723816990008344873785972595214844e-01, /* logih[53] */ -2.63487075436177288054440686474043695042741778901884e-17, /* logim[53] */ -1.38972774108545698123375234719775474495262622652200e-33, /* logil[53] */ } , { 1.40659332275390625000000000000000000000000000000000e+00, /* r[54] */ -3.41170697798120592381110327551141381263732910156250e-01, /* logih[54] */ 1.93668606486849623510457675345565515553170548397263e-17, /* logim[54] */ -6.31924577586791945681481090971933602378723267089765e-34, /* logil[54] */ } , { 1.39890718460083007812500000000000000000000000000000e+00, /* r[55] */ -3.35691349380139503200126682713744230568408966064453e-01, /* logih[55] */ 8.91843232308579533655667936963342665384096382048557e-18, /* logim[55] */ -7.43852632990846244963757376301756885994340719135686e-34, /* logil[55] */ } , { 1.39130425453186035156250000000000000000000000000000e+00, /* r[56] */ -3.30241619815349218836075806393637321889400482177734e-01, /* logih[56] */ -1.69271534756955752333877800530082817995576241189249e-17, /* logim[56] */ -2.05124125474152062675126703058085713735683777118919e-34, /* logil[56] */ } , { 1.38378381729125976562500000000000000000000000000000e+00, /* r[57] */ -3.24821643615624322531942880232236348092555999755859e-01, /* logih[57] */ 1.93287622140617006961244731990086787828970688523722e-17, /* logim[57] */ -1.40211415833516824405184666805315188814704601258065e-33, /* logil[57] */ } , { 1.37634420394897460937500000000000000000000000000000e+00, /* r[58] */ -3.19430856448034428130000605960958637297153472900391e-01, /* logih[58] */ 5.58442737360353866559969930374464901851229137435661e-18, /* logim[58] */ -2.25313306148742433454599602113064828727792769150620e-34, /* logil[58] */ } , { 1.36898398399353027343750000000000000000000000000000e+00, /* r[59] */ -3.14068847182749744106899925100151449441909790039062e-01, /* logih[59] */ 1.74087330539322720259314067705480812845274240645592e-17, /* logim[59] */ 2.87763442397890459672608687761118393908121210479900e-34, /* logil[59] */ } , { 1.36170220375061035156250000000000000000000000000000e+00, /* r[60] */ -3.08735537528966208498104606405831873416900634765625e-01, /* logih[60] */ 2.31380218279209479391607966489385619371870731511261e-17, /* logim[60] */ 5.75649697670342883220331709767832654878804183961435e-34, /* logil[60] */ } , { 1.35449743270874023437500000000000000000000000000000e+00, /* r[61] */ -3.03430487161918061023158088573836721479892730712891e-01, /* logih[61] */ 5.88591784280850309549180895879864991445414905765635e-18, /* logim[61] */ 3.80740105286783019924475997846877792541810370319751e-34, /* logil[61] */ } , { 1.34736847877502441406250000000000000000000000000000e+00, /* r[62] */ -2.98153415159913837140237546918797306716442108154297e-01, /* logih[62] */ -8.81391967432414632609646763074561636922040597203571e-18, /* logim[62] */ -2.02736910549706342663167850737697734462522018249963e-34, /* logil[62] */ } , { 1.34031414985656738281250000000000000000000000000000e+00, /* r[63] */ -2.92904026677480888718463347686338238418102264404297e-01, /* logih[63] */ 1.79356774462556308958502912313675336181211584010969e-17, /* logim[63] */ 1.02350086185905899058999882149766002774623879978153e-34, /* logil[63] */ } , { 1.33333325386047363281250000000000000000000000000000e+00, /* r[64] */ -2.87682012847134349620148441317724063992500305175781e-01, /* logih[64] */ -2.60715355783435444041951693925565689223533295668838e-17, /* logim[64] */ -9.83372234709377378449141028490939682198507140512540e-34, /* logil[64] */ } , { 1.32642483711242675781250000000000000000000000000000e+00, /* r[65] */ -2.82487230428967117656924301627441309392452239990234e-01, /* logih[65] */ 2.49452771019268745755792758464310261659699707675018e-17, /* logim[65] */ -1.40230272425562150522506576584140991296902734870694e-33, /* logil[65] */ } , { 1.31958770751953125000000000000000000000000000000000e+00, /* r[66] */ -2.77319345020877350282972884087939746677875518798828e-01, /* logih[66] */ 7.44521346975934828880026635948320543669274837358637e-18, /* logim[66] */ -5.41922476182319969711469733445405189836277342215443e-34, /* logil[66] */ } , { 1.31282043457031250000000000000000000000000000000000e+00, /* r[67] */ -2.72177826311169102080356196893262676894664764404297e-01, /* logih[67] */ -1.94604737767255604321061638736698666324990178271015e-17, /* logim[67] */ 4.93318792723831633917605655356651628446409622108869e-34, /* logil[67] */ } , { 1.30612254142761230468750000000000000000000000000000e+00, /* r[68] */ -2.67062856029558426396164350080653093755245208740234e-01, /* logih[68] */ 1.42676910305707233200559864526771082234384991613068e-17, /* logim[68] */ 9.40874014190123375853921812584677628111272401841540e-34, /* logil[68] */ } , { 1.29949235916137695312500000000000000000000000000000e+00, /* r[69] */ -2.61973695252477101202970288795768283307552337646484e-01, /* logih[69] */ -1.59130185496344773949627658712806321021374170989957e-17, /* logim[69] */ 2.05966526658843352548575822504612882857523370085076e-34, /* logil[69] */ } , { 1.29292941093444824218750000000000000000000000000000e+00, /* r[70] */ -2.56910505054635363020310023784986697137355804443359e-01, /* logih[70] */ -2.32939629151451727444770801596466641031683815428509e-17, /* logim[70] */ -1.43942742464573220634874496721239465737503205324375e-33, /* logil[70] */ } , { 1.28643226623535156250000000000000000000000000000000e+00, /* r[71] */ -2.51872701711453261808060233306605368852615356445312e-01, /* logih[71] */ -2.58573188266130078596915247890597291360969537163785e-17, /* logim[71] */ 3.36064630885731507350249551263037246653963144676932e-34, /* logil[71] */ } , { 1.27999997138977050781250000000000000000000000000000e+00, /* r[72] */ -2.46860055579783743695543307694606482982635498046875e-01, /* logih[72] */ -1.36174299951708605118822966558244798958741114531493e-17, /* logim[72] */ -8.23883896198784591738914635896001757021238114385808e-35, /* logil[72] */ } , { 1.27363181114196777343750000000000000000000000000000e+00, /* r[73] */ -2.41872513137422084916750009142560884356498718261719e-01, /* logih[73] */ -2.91827950997726014268071786281330008614392694540440e-18, /* logim[73] */ 8.66387628958027677722140876839269007945711340420961e-35, /* logil[73] */ } , { 1.26732683181762695312500000000000000000000000000000e+00, /* r[74] */ -2.36909825309450927655063878773944452404975891113281e-01, /* logih[74] */ 4.97049401191734143236484721843489954792294974449682e-18, /* logim[74] */ 2.12212094628219632031384179435720857347529888567725e-34, /* logil[74] */ } , { 1.26108384132385253906250000000000000000000000000000e+00, /* r[75] */ -2.31971542737545860513037609962339047342538833618164e-01, /* logih[75] */ 1.20064411563385414488688519726171456939870706105353e-17, /* logim[75] */ -5.20241965000144345106493348505238495111737026311766e-34, /* logil[75] */ } , { 1.25490188598632812500000000000000000000000000000000e+00, /* r[76] */ -2.27057391030699523559732710964453872293233871459961e-01, /* logih[76] */ -9.55134517665639461592830714479938653876650013848813e-18, /* logim[76] */ -7.00052160915705629865262646818211330004502638341784e-34, /* logil[76] */ } , { 1.24878048896789550781250000000000000000000000000000e+00, /* r[77] */ -2.22167466272476882283015697794326115399599075317383e-01, /* logih[77] */ 1.12308837854924459441805420173945034636561801020789e-17, /* logim[77] */ 1.05992689326800868505291338111574353445179905470698e-34, /* logil[77] */ } , { 1.24271845817565917968750000000000000000000000000000e+00, /* r[78] */ -2.17301285003207084178811214769666548818349838256836e-01, /* logih[78] */ -1.37599098464784711367545798871014398359913153389606e-17, /* logim[78] */ -5.44676947016522950876420214713413739910691265570885e-34, /* logil[78] */ } , { 1.23671507835388183593750000000000000000000000000000e+00, /* r[79] */ -2.12458734101899110457978281374380458146333694458008e-01, /* logih[79] */ 3.12575020468223244847667531342710056704202576314513e-18, /* logim[79] */ 1.27082738610098894087384580413567050181540844264548e-35, /* logil[79] */ } , { 1.23076915740966796875000000000000000000000000000000e+00, /* r[80] */ -2.07639305173597937814733427330793347209692001342773e-01, /* logih[80] */ -1.20531726306040366742269494142059745690218464556184e-17, /* logim[80] */ 3.33883514126655983920316543317695602289579500921493e-34, /* logil[80] */ } , { 1.22488045692443847656250000000000000000000000000000e+00, /* r[81] */ -2.02843253050716987306856253781006671488285064697266e-01, /* logih[81] */ -1.66453566992001313940518505696243672056063400746100e-18, /* logim[81] */ 2.78446239404510241881587234176263335863162887428131e-35, /* logil[81] */ } , { 1.21904754638671875000000000000000000000000000000000e+00, /* r[82] */ -1.98069854157447239328959653903439175337553024291992e-01, /* logih[82] */ -3.74277289637934596837745314540095849706853736054736e-18, /* logim[82] */ 2.20940287174632344749918330821286328950105212564345e-34, /* logil[82] */ } , { 1.21327018737792968750000000000000000000000000000000e+00, /* r[83] */ -1.93319348256398265695210625381150748580694198608398e-01, /* logih[83] */ -4.63045754803609100012916107813305239709411987466506e-18, /* logim[83] */ 3.81311992624323390610440652445847060246376140730432e-34, /* logil[83] */ } , { 1.20754718780517578125000000000000000000000000000000e+00, /* r[84] */ -1.88591184708711112616441596401273272931575775146484e-01, /* logih[84] */ 7.43216311628945500204739783937941202296964434266492e-18, /* logim[84] */ -4.02931080995428730719681936637527024502063366412999e-34, /* logil[84] */ } , { 1.20187783241271972656250000000000000000000000000000e+00, /* r[85] */ -1.83885194019779485419263664880418218672275543212891e-01, /* logih[85] */ 4.12613043545869607985270580107985887836449099592842e-18, /* logim[85] */ -1.13080344207561908198013613253456946184091830340475e-34, /* logil[85] */ } , { 1.19626164436340332031250000000000000000000000000000e+00, /* r[86] */ -1.79201397792742966874612875471939332783222198486328e-01, /* logih[86] */ 1.25197515140082668570664893296659406065442168045883e-17, /* logim[86] */ 2.08673445558311131685127966451011169090072111640797e-34, /* logil[86] */ } , { 1.19069766998291015625000000000000000000000000000000e+00, /* r[87] */ -1.74539412626609380385644954003510065376758575439453e-01, /* logih[87] */ 8.52219781255028950312107624449830634785785378861392e-18, /* logim[87] */ 5.46720442033771639415150684633589460164820712880324e-34, /* logil[87] */ } , { 1.18518519401550292968750000000000000000000000000000e+00, /* r[88] */ -1.69899044245978042555478282338299322873353958129883e-01, /* logih[88] */ 4.86800738580472456380134000450154397097303177737598e-19, /* logim[88] */ -4.48365665383134519709151659261825733866549119396251e-36, /* logil[88] */ } , { 1.17972350120544433593750000000000000000000000000000e+00, /* r[89] */ -1.65280090007780350314092743246874306350946426391602e-01, /* logih[89] */ 1.05991222445546499578510819426998369466676418510398e-18, /* logim[89] */ 2.15535973016890499002202117947684925307171077322261e-36, /* logil[89] */ } , { 1.17431187629699707031250000000000000000000000000000e+00, /* r[90] */ -1.60682338849634120947484916541725397109985351562500e-01, /* logih[90] */ 5.38493323815703006679696841052856196024573538758454e-18, /* logim[90] */ 1.60200163876329179080224417109933041789065267300895e-34, /* logil[90] */ } , { 1.16894984245300292968750000000000000000000000000000e+00, /* r[91] */ -1.56105775199027185795586092353914864361286163330078e-01, /* logih[91] */ 1.32405772531609804709122583998125231935523184710352e-17, /* logim[91] */ 4.88933388697666736600942679327919927438390701656817e-35, /* logil[91] */ } , { 1.16363644599914550781250000000000000000000000000000e+00, /* r[92] */ -1.51549968907714105448292229993967339396476745605469e-01, /* logih[92] */ 1.77181633478899593214922561799512844823326841018122e-18, /* logim[92] */ 5.44951453107128861626798538797020344311568819287008e-35, /* logil[92] */ } , { 1.15837097167968750000000000000000000000000000000000e+00, /* r[93] */ -1.47014683357163111754317696977523155510425567626953e-01, /* logih[93] */ 4.46701777108311388441189058844554903695616000674812e-18, /* logim[93] */ -1.53168389834566630100313932781112142055948393405761e-34, /* logil[93] */ } , { 1.15315318107604980468750000000000000000000000000000e+00, /* r[94] */ -1.42500086821669674774781810810964088886976242065430e-01, /* logih[94] */ -2.21668083020505832726646787146199970227457581911830e-18, /* logim[94] */ -4.73140768447350921077611938776759805597533720242102e-36, /* logil[94] */ } , { 1.14798212051391601562500000000000000000000000000000e+00, /* r[95] */ -1.38005723310861472263866289722500368952751159667969e-01, /* logih[95] */ -9.06035372834454229539393713977175584764482079542462e-18, /* logim[95] */ -6.58482110068426815722709702700082916058774211791842e-34, /* logil[95] */ } , { 1.14285707473754882812500000000000000000000000000000e+00, /* r[96] */ -1.33531333019876075063336884340969845652580261230469e-01, /* logih[96] */ 3.66452824974217778950176131406293356640863401093569e-18, /* logim[96] */ 6.15050085774566840615703784135477182311292227710416e-35, /* logil[96] */ } , { 1.13777780532836914062500000000000000000000000000000e+00, /* r[97] */ -1.29077066489528990977930789085803553462028503417969e-01, /* logih[97] */ 7.97904258955058431558707127373439732289437010877585e-19, /* logim[97] */ -4.72584148771245137732808879600361038781792271619664e-35, /* logil[97] */ } , { 1.13274335861206054687500000000000000000000000000000e+00, /* r[98] */ -1.24642441481986290807704165217728586867451667785645e-01, /* logih[98] */ -1.12998120773332791412288663337308123303520797473827e-18, /* logim[98] */ 5.04751909879024305911295754405025108738663901055449e-35, /* logil[98] */ } , { 1.12775325775146484375000000000000000000000000000000e+00, /* r[99] */ -1.20227386019965673535914163494453532621264457702637e-01, /* logih[99] */ -4.10132123403305460439841682733159064509468253505934e-18, /* logim[99] */ 1.89802934268459828223199224893946334512039168636632e-34, /* logil[99] */ } , { 1.12280702590942382812500000000000000000000000000000e+00, /* r[100] */ -1.15831822975702269928888199501670897006988525390625e-01, /* logih[100] */ -4.33848450767153009712329850176816190393287866962401e-18, /* logim[100] */ -3.16979691573058896647113947407157157214490081484725e-34, /* logil[100] */ } , { 1.11790394783020019531250000000000000000000000000000e+00, /* r[101] */ -1.11455456757806464773707944004854653030633926391602e-01, /* logih[101] */ -5.25227837292521929481451677551514755953859335394548e-18, /* logim[101] */ -1.35455162271740897316919848287529722248286557667632e-34, /* logil[101] */ } , { 1.11304354667663574218750000000000000000000000000000e+00, /* r[102] */ -1.07098197023655139492603893813793547451496124267578e-01, /* logih[102] */ 3.47169710366632825350486634041554320998659998614468e-18, /* logim[102] */ 4.16291803858237783591365989446195611338780307382474e-35, /* logil[102] */ } , { 1.10822510719299316406250000000000000000000000000000e+00, /* r[103] */ -1.02759733026446364867467764270259067416191101074219e-01, /* logih[103] */ 5.14131173582414775653668171432178439238499706689565e-18, /* logim[103] */ -2.03511710633920722432014459953905354472733979743122e-34, /* logil[103] */ } , { 1.10344839096069335937500000000000000000000000000000e+00, /* r[104] */ -9.84401771213754411826712953370588365942239761352539e-02, /* logih[104] */ 4.43863133643792238822177111529042861410430977956950e-18, /* logim[104] */ 3.12055863098469149547827014037274497005231280699218e-34, /* logil[104] */ } , { 1.09871244430541992187500000000000000000000000000000e+00, /* r[105] */ -9.41389890512167593072945237508974969387054443359375e-02, /* logih[105] */ 2.37342936135295683496202513568031672884920488134173e-19, /* logim[105] */ 2.33721773003055253003147894270712826153088420940698e-35, /* logil[105] */ } , { 1.09401702880859375000000000000000000000000000000000e+00, /* r[106] */ -8.98562695172144959565585509153606835752725601196289e-02, /* logih[106] */ 6.27446602451052736319026996501069657057280086335290e-19, /* logim[106] */ -3.52284010127094716016693656249620808330731317587528e-35, /* logil[106] */ } , { 1.08936166763305664062500000000000000000000000000000e+00, /* r[107] */ -8.55918986704354706196440361054555978626012802124023e-02, /* logih[107] */ -5.03513826084130895904008327416965851388338774947593e-18, /* logim[107] */ 6.86424026896698901114373288904478288437409959196820e-35, /* logil[107] */ } , { 1.08474564552307128906250000000000000000000000000000e+00, /* r[108] */ -8.13455314205279167438789045263547450304031372070312e-02, /* logih[108] */ 1.86223784192593707654359268192644483006930996779864e-18, /* logim[108] */ -9.08215611660981343459991418247070342987317386688394e-35, /* logil[108] */ } , { 1.08016872406005859375000000000000000000000000000000e+00, /* r[109] */ -7.71172549156562414651716608204878866672515869140625e-02, /* logih[109] */ 4.37349590112793692636976332290601524356283649435490e-18, /* logim[109] */ -2.43638510650083687411626047741666976256819270953612e-34, /* logil[109] */ } , { 1.07563018798828125000000000000000000000000000000000e+00, /* r[110] */ -7.29067112034412351251333461732428986579179763793945e-02, /* logih[110] */ 6.30693084361487082247322771068486204374546343933133e-18, /* logim[110] */ 3.44825082371128400572272238979928316738696119124015e-34, /* logil[110] */ } , { 1.07112979888916015625000000000000000000000000000000e+00, /* r[111] */ -6.87139782297249979148290321973036043345928192138672e-02, /* logih[111] */ -4.40922228882126717948257852084234011599535648658716e-18, /* logim[111] */ 2.00071285755297414487130516445636815235532199087333e-34, /* logil[111] */ } , { 1.06666660308837890625000000000000000000000000000000e+00, /* r[112] */ -6.45384615329246263959461771264614071696996688842773e-02, /* logih[112] */ 6.47055724777502681297997296903095954212491541204973e-18, /* logim[112] */ -3.53995576621708408093066388957026321212073337996708e-34, /* logil[112] */ } , { 1.06224060058593750000000000000000000000000000000000e+00, /* r[113] */ -6.03804513842609302809449900450999848544597625732422e-02, /* logih[113] */ 2.15703432342306119511642925211564389619524247753812e-18, /* logim[113] */ -3.99051054966201464148223117427430962485432571249835e-35, /* logil[113] */ } , { 1.05785131454467773437500000000000000000000000000000e+00, /* r[114] */ -5.62397891033892469159205518280941760167479515075684e-02, /* logih[114] */ 3.28339677990388790029372693220459728960401288179580e-18, /* logim[114] */ 1.51915205677141595589208947882243470550543557886170e-35, /* logil[114] */ } , { 1.05349802970886230468750000000000000000000000000000e+00, /* r[115] */ -5.21160840267197236763685452842764789238572120666504e-02, /* logih[115] */ -2.76876652450490527514912306264172616345243137067863e-19, /* logim[115] */ 4.97747635693761803951848478678221385327287067714555e-36, /* logil[115] */ } , { 1.04918026924133300781250000000000000000000000000000e+00, /* r[116] */ -4.80091633070045681330739739678392652422189712524414e-02, /* logih[116] */ -1.43903217358996287866324353045636173989420593009940e-18, /* logim[116] */ 9.24533961563047616614044310774847027299245259235749e-35, /* logil[116] */ } , { 1.04489803314208984375000000000000000000000000000000e+00, /* r[117] */ -4.39193047153486545997047585387917933985590934753418e-02, /* logih[117] */ -1.76247347066130256555880115492006953917590179181782e-18, /* logim[117] */ 2.95067167680037492936848210009098107643918346324819e-35, /* logil[117] */ } , { 1.04065036773681640625000000000000000000000000000000e+00, /* r[118] */ -3.98458712942959952796329048396728467196226119995117e-02, /* logih[118] */ 3.12956491324511750770873688790894657687633404551217e-18, /* logim[118] */ 9.08530842942513514982993220469010912494881545842223e-35, /* logil[118] */ } , { 1.03643727302551269531250000000000000000000000000000e+00, /* r[119] */ -3.57891329972944774451271143789199413731694221496582e-02, /* logih[119] */ -2.94786708868720304892365707065135221787713948130908e-19, /* logim[119] */ 1.84384763058385810856389175018656477977822636794864e-35, /* logil[119] */ } , { 1.03225803375244140625000000000000000000000000000000e+00, /* r[120] */ -3.17486685122574663342476242178236134350299835205078e-02, /* logih[120] */ -3.03821748520802146852642560679641488082417537178322e-18, /* logim[120] */ 6.90127669441551609256721347857289051065660383455449e-35, /* logil[120] */ } , { 1.02811241149902343750000000000000000000000000000000e+00, /* r[121] */ -2.77245107619511835239656249996187398210167884826660e-02, /* logih[121] */ 1.56537436220084983093655029081028016172956628311065e-18, /* logim[121] */ -4.26959324792631463690822650182944301609062827136870e-35, /* logil[121] */ } , { 1.02399992942810058593750000000000000000000000000000e+00, /* r[122] */ -2.37164576994431455791989549197751330211758613586426e-02, /* logih[122] */ -1.57190014657555079881764699090245893269914973184857e-19, /* logim[122] */ 4.62721637019171363059082221740445258999073602747011e-36, /* logil[122] */ } , { 1.01992034912109375000000000000000000000000000000000e+00, /* r[123] */ -1.97245351501005340699723689112943247891962528228760e-02, /* logih[123] */ 1.34458916305708123412045028332259969564528051018263e-18, /* logim[123] */ -6.02768376061644464555810636396264987280148524662430e-35, /* logil[123] */ } , { 1.01587295532226562500000000000000000000000000000000e+00, /* r[124] */ -1.57482973634926158579272481574662378989160060882568e-02, /* logih[124] */ -1.00208727697080412925749596659626020152032796409604e-18, /* logim[124] */ 7.75790823155383991507800579878754988160969197338737e-35, /* logil[124] */ } , { 1.01185774803161621093750000000000000000000000000000e+00, /* r[125] */ -1.17879957989121472716753658005472971126437187194824e-02, /* logih[125] */ 2.12843993900806841444093729096134188145078357457959e-19, /* logim[125] */ -7.36236149534638490756917054603187520349493909791838e-36, /* logil[125] */ } , { 1.00787401199340820312500000000000000000000000000000e+00, /* r[126] */ -7.84317373573558719590526067122482345439493656158447e-03, /* logih[126] */ -2.76470798179560918828283984091643257584228907545928e-19, /* logim[126] */ 1.46121103426200283031313413564673422143931331178612e-35, /* logil[126] */ } , { 1.00392150878906250000000000000000000000000000000000e+00, /* r[127] */ -3.91383971648977691676352108629544090945273637771606e-03, /* logih[127] */ -4.28019276224719221462393891683495367484578724177817e-19, /* logim[127] */ -2.25272542183557712010826889962617244762256960750126e-35, /* logil[127] */ } }; interval-3.2.0/src/crlibm/log_accurate.c0000644000000000000000000000672413316017127016333 0ustar 00000000000000/* * Correctly rounded logarithm * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: David Defour * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "log_accurate.h" /* * 1) First reduction: exponent extraction * E * x = 2^ .(1+f) with 0 <= f < 1 * * log(x) = E.log(2) + log(1+f) where: * - log(2) is tabulated * - log(1+f) need to be evaluated * * * 2) Avoiding accuracy problem when E=-1 by testing * * if (1+f >= sqrt(2)) then * 1+f = (1+f)/2; E = E+1; * and, * log(x) = (E+1).log(2) + log((1+f)/2) * * so now: sqrt(2)/2 <= (1+f) < sqrt(2) * * * 3) Second reduction: tabular reduction * -4 * wi = 1 + i. 2^ * 1 * log(1+f) = log(wi) + log ( 1 + --- . (1 + f - wi) ) * wi * * then |(1+f-wi)/wi| <= 2^-5 if we use rounded to nearest. * * 4) Computation: * a) Table lookup of: * - ti = log(wi) * - inv_wi = 1/(wi) * b) Polynomial evaluation of: * - P(R) ~ log(1 + R), where R = (1+f-wi) * inv_wi * * -5 * with |R| < 2^ * * * 5) Reconstruction: * log(x) = E.log(2) + t_i + P(R) * */ void scs_log(scs_ptr res, db_number y, int E){ scs_t R, sc_ln2_times_E, res1, addi; scs_ptr ti, inv_wi; db_number z, wi; int i; #if EVAL_PERF crlibm_second_step_taken++; #endif /* to normalize y.d and round to nearest */ /* + (1-trunc(sqrt(2.)/2 * 2^(4))*2^(-4) )+2.^(-(4+1))*/ z.d = y.d + norm_number.d; i = (z.i[HI] & 0x000fffff); i = i >> 16; /* 0<= i <=11 */ wi.d = ((double)(11+i))*0.0625; /* (1+f-w_i) */ y.d -= wi.d; /* Table reduction */ ti = table_ti_ptr[i]; inv_wi = table_inv_wi_ptr[i]; /* R = (1+f-w_i)/w_i */ scs_set_d(R, y.d); scs_mul(R, R, inv_wi); /* * Polynomial evaluation of log(1 + R) with an error less than 2^(-130) */ scs_mul(res1, constant_poly_ptr[0], R); for(i=1; i<20; i++){ scs_add(addi, constant_poly_ptr[i], res1); scs_mul(res1, addi, R); } if(E==0){ scs_add(res, res1, ti); }else{ /* sc_ln2_times_E = E*log(2) */ scs_set(sc_ln2_times_E, sc_ln2_ptr); if (E >= 0){ scs_mul_ui(sc_ln2_times_E, (unsigned int) E); }else{ scs_mul_ui(sc_ln2_times_E, (unsigned int) -E); sc_ln2_times_E->sign = -1; } scs_add(addi, res1, ti); scs_add(res, addi, sc_ln2_times_E); } } interval-3.2.0/src/crlibm/log_accurate.h0000644000000000000000000002052413316017127016332 0ustar 00000000000000/* * Correctly rounded logarithm * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" /* * Constant to compute the natural logarithm. */ #ifdef WORDS_BIGENDIAN static const db_number norm_number = {{0x3FD60000, 0x00000000}}; /* 11*2^(-5) */ #else static const db_number norm_number = {{0x00000000, 0x3FD60000}}; /* 11*2^(-5) */ #endif #define SQRT_2 1.4142135623730950489e0 static const scs sc_ln2={{0x2c5c85fd, 0x3d1cf79a, 0x2f278ece, 0x1803f2f6, 0x2bd03cd0, 0x3267298b, 0x18b62834, 0x175b8baa}, DB_ONE, -1, 1 }; #define sc_ln2_ptr (scs_ptr)(&sc_ln2) static const scs table_ti[13]= /* ~-3.746934e-01 */ {{{0x17fafa3b, 0x360546fb, 0x1e6fdb53, 0x0b1225e6, 0x15f38987, 0x26664702, 0x3cb1bf6d, 0x118a64f9}, DB_ONE, -1, -1 } , /* ~-2.876821e-01 */ {{0x12696211, 0x0d36e49e, 0x03beb767, 0x1b02aa70, 0x2a30f490, 0x3732bb37, 0x2425c6da, 0x1fc53d0e}, DB_ONE, -1, -1 } , /* ~-2.076394e-01 */ {{0x0d49f69e, 0x115b3c6d, 0x395f53bd, 0x0b901b99, 0x2e77188a, 0x3e3d1ab5, 0x1147dede, 0x05483ae4}, DB_ONE, -1, -1 } , /* ~-1.335314e-01 */ {{0x088bc741, 0x04fc8f7b, 0x319c5a0f, 0x38e5bd03, 0x31dda8fe, 0x30f08645, 0x2fa1d5c5, 0x02c6529d}, DB_ONE, -1, -1 } , /* ~-6.453852e-02 */ {{0x0421662d, 0x19e3a068, 0x228ff66f, 0x3503372c, 0x04bf1b16, 0x0ff1b85c, 0x006c21b2, 0x21a9efd6}, DB_ONE, -1, -1 } , /* ZERO */ {{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {{0, 0}}, 0, 1 } , /* ~6.062462e-02 */ {{0x03e14618, 0x008b1533, 0x02f992e2, 0x37759978, 0x2634d1d3, 0x13375edb, 0x2e4634ea, 0x1dcf0aef}, DB_ONE, -1, 1 } , /* ~1.177830e-01 */ {{0x0789c1db, 0x22af2e5e, 0x27aa1fff, 0x21fe9e15, 0x176e53af, 0x04015c6b, 0x021a0541, 0x006df1d7}, DB_ONE, -1, 1 } , /* ~1.718503e-01 */ {{0x0aff9838, 0x14f27a79, 0x039f1050, 0x0e424775, 0x3f35571c, 0x355ff008, 0x1ca13efc, 0x3c2c8490}, DB_ONE, -1, 1 } , /* ~2.231436e-01 */ {{0x0e47fbe3, 0x33534435, 0x212ec0f7, 0x25ff7344, 0x2571d97a, 0x274129e2, 0x12b111db, 0x2c051568}, DB_ONE, -1, 1 } , /* ~2.719337e-01 */ {{0x11675cab, 0x2ae98380, 0x39cc7d57, 0x041b8b82, 0x0fc19f41, 0x0a43c91d, 0x1523ef69, 0x164b69f6}, DB_ONE, -1, 1 } , /* ~3.184537e-01 */ {{0x14618bc2, 0x0717b09f, 0x10b7b37b, 0x0cf1cd10, 0x15dcb349, 0x0c00c397, 0x2c39cc9b, 0x274c94a8}, DB_ONE, -1, 1 } , {{0x1739d7f6, 0x2ef401a7, 0x0e24c53f, 0x2b4fbde5, 0x2ab77843, 0x1cea5975, 0x1eeef249, 0x384d2344}, DB_ONE, -1, 1 } }; #define table_ti_ptr (scs_ptr)&table_ti static const scs table_inv_wi[13]= /* ~1.454545e+00 */ {{{0x00000001, 0x1d1745d1, 0x1d1745d1, 0x1d1745d1, 0x1d1745d1, 0x1d1745d1, 0x1d183e2a, 0x36835582}, DB_ONE, 0, 1 } , /* ~1.333333e+00 */ {{0x00000001, 0x15555555, 0x15555555, 0x15555555, 0x15555555, 0x15555555, 0x15549b7e, 0x1a416c6b}, DB_ONE, 0, 1 } , /* ~1.230769e+00 */ {{0x00000001, 0x0ec4ec4e, 0x313b13b1, 0x0ec4ec4e, 0x313b13b1, 0x0ec4ec4e, 0x313a6825, 0x3ab28b77}, DB_ONE, 0, 1 } , /* ~1.142857e+00 */ {{0x00000001, 0x09249249, 0x09249249, 0x09249249, 0x09249249, 0x09249249, 0x09238b74, 0x26f620a6}, DB_ONE, 0, 1 } , /* ~1.066667e+00 */ {{0x00000001, 0x04444444, 0x11111111, 0x04444444, 0x11111111, 0x04444444, 0x1111d60e, 0x1f0c9d58}, DB_ONE, 0, 1 } , /* ~1.000000e+00 */ {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, DB_ONE, 0, 1 } , /* ~9.411765e-01 */ {{0x3c3c3c3c, 0x0f0f0f0f, 0x03c3c3c3, 0x30f0f0f0, 0x3c3c3c3c, 0x0f0f923d, 0x16e0e0a4, 0x3a84202f}, DB_ONE, -1, 1 } , /* ~8.888889e-01 */ {{0x38e38e38, 0x38e38e38, 0x38e38e38, 0x38e38e38, 0x38e38e38, 0x38e3946a, 0x2e0ee2c9, 0x0d6e0fbd}, DB_ONE, -1, 1 } , /* ~8.421053e-01 */ {{0x35e50d79, 0x10d79435, 0x39435e50, 0x35e50d79, 0x10d79435, 0x3943324d, 0x0637ea85, 0x131a67ba}, DB_ONE, -1, 1 } , /* ~8.000000e-01 */ {{0x33333333, 0x0ccccccc, 0x33333333, 0x0ccccccc, 0x33333333, 0x0ccccccc, 0x33333333, 0x0ccccccc}, DB_ONE, -1, 1 } , /* ~7.619048e-01 */ {{0x30c30c30, 0x30c30c30, 0x30c30c30, 0x30c30c30, 0x30c30c30, 0x30c2f1a4, 0x160958a1, 0x2b03bc88}, DB_ONE, -1, 1 } , /* ~7.272727e-01 */ {{0x2e8ba2e8, 0x2e8ba2e8, 0x2e8ba2e8, 0x2e8ba2e8, 0x2e8ba2e8, 0x2e8bcb74, 0x2d78b525, 0x00a1db67}, DB_ONE, -1, 1 } , /* ~6.956522e-01 */ {{0x2c8590b2, 0x0590b216, 0x10b21642, 0x321642c8, 0x1642c859, 0x02c8590b, 0x08590b21, 0x190b2164}, DB_ONE, -1, 1 } }; #define table_inv_wi_ptr (scs_ptr)&table_inv_wi static const scs constant_poly[20]= /*0 ~-5.023367e-02 */ {{{0x0337074b, 0x275aac5c, 0x2cf4a893, 0x38013cc3, 0x149a3416, 0x0e067307, 0x12745608, 0x1658e0d5}, DB_ONE, -1, -1 } , /*1 ~5.286469e-02 */ {{0x03622298, 0x252ff65c, 0x03001550, 0x2f457908, 0x32f78ecc, 0x17442a4e, 0x1d806366, 0x2c50350e}, DB_ONE, -1, 1 } , /*2 ~-5.555504e-02 */ {{0x038e36bb, 0x30665a9c, 0x119434c7, 0x3fdec8cb, 0x37dd3adb, 0x2663cd45, 0x230e43e9, 0x32b9663c}, DB_ONE, -1, -1 } , /*3 ~5.882305e-02 */ {{0x03c3c1bb, 0x38c473ae, 0x192b9c18, 0x242b7c4e, 0x3da8edc8, 0x04454ffe, 0x2cf133c6, 0x0c926fd0}, DB_ONE, -1, 1 } , /*4 ~-6.250000e-02 */ {{0x04000000, 0x2b72bb0a, 0x038f5efc, 0x34665092, 0x2461b6c9, 0x172f7050, 0x1218b5c1, 0x104862d7}, DB_ONE, -1, -1 } , /*5 ~6.666667e-02 */ {{0x04444444, 0x374f3324, 0x1531bcf1, 0x1d7d23fc, 0x26ff9670, 0x38fc33ae, 0x15bf1cfb, 0x2c9f1c2d}, DB_ONE, -1, 1 } , /*6 ~-7.142857e-02 */ {{0x04924924, 0x2489e5b6, 0x288b19c5, 0x2893519b, 0x2c3f35c0, 0x0b8bfdce, 0x3541ab49, 0x1de415bc}, DB_ONE, -1, -1 } , /*7 ~7.692308e-02 */ {{0x04ec4ec4, 0x3b0ce4bd, 0x14d14046, 0x0243ade9, 0x083cc34f, 0x393e6a5a, 0x2c1855f2, 0x259d599f}, DB_ONE, -1, 1 } , /*8 ~-8.333333e-02 */ {{0x05555555, 0x1555565b, 0x064b42af, 0x13bc7961, 0x1396754b, 0x33d85415, 0x2ba548d4, 0x039c4ff6}, DB_ONE, -1, -1 } , /*9 ~9.090909e-02 */ {{0x05d1745d, 0x05d1751c, 0x24facd05, 0x07540f86, 0x014f2ec1, 0x3bb3fa8b, 0x02e1da4c, 0x3304817c}, DB_ONE, -1, 1 } , /*10 ~-1.000000e-01 */ {{0x06666666, 0x19999999, 0x21667ee1, 0x0f5f75ea, 0x353af37f, 0x2578daa1, 0x07c76f47, 0x16541534}, DB_ONE, -1, -1 } , /*11 ~1.111111e-01 */ {{0x071c71c7, 0x071c71c7, 0x03e7af88, 0x2fca5d74, 0x0bb43f38, 0x050edb70, 0x3631b696, 0x1fc3e0d3}, DB_ONE, -1, 1 } , /*12 ~-1.250000e-01 */ {{0x08000000, 0x00000000, 0x00003ac6, 0x36c11384, 0x2d596ab4, 0x09257878, 0x0597dc26, 0x2d60813a}, DB_ONE, -1, -1 } , /*13 ~1.428571e-01 */ {{0x09249249, 0x09249249, 0x0924b1db, 0x0d002ac1, 0x0eafd708, 0x2b4df21d, 0x0458da93, 0x2d11460c}, DB_ONE, -1, 1 } , /*14 ~-1.666667e-01 */ {{0x0aaaaaaa, 0x2aaaaaaa, 0x2aaaaaa9, 0x0bb6630e, 0x2e44a5cf, 0x39f32e04, 0x105732b9, 0x01a76208}, DB_ONE, -1, -1 } , /*15 ~2.000000e-01 */ {{0x0ccccccc, 0x33333333, 0x0ccccccc, 0x0bbbe6e8, 0x253269ea, 0x0ec2a630, 0x10defc5c, 0x238aef3b}, DB_ONE, -1, 1 } , /*16 ~-2.500000e-01 */ {{0x10000000, 0x00000000, 0x00000000, 0x0001195c, 0x3654cd5a, 0x16ca3471, 0x343d2da0, 0x235273f2}, DB_ONE, -1, -1 } , /*17 ~3.333333e-01 */ {{0x15555555, 0x15555555, 0x15555555, 0x1555a1e0, 0x2eb2094a, 0x07dde891, 0x230e2bfa, 0x28aae6ab}, DB_ONE, -1, 1 } , /*18 ~-5.000000e-01 */ {{0x1fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x029bd81b, 0x360f63df, 0x28d28bd3, 0x3c15f394}, DB_ONE, -1, -1 } , /*19 ~1.000000e+00 */ {{0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x39e04b7e, 0x08e4e337, 0x1a1e2ed3, 0x23e85705}, DB_ONE, -1, 1 } }; #define constant_poly_ptr (scs_ptr)&constant_poly interval-3.2.0/src/crlibm/log_fast.c0000644000000000000000000002265213316017127015477 0ustar 00000000000000/* * Correctly rounded logarithm * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Daramy Catherine, Florent de Dinechin * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "crlibm.h" #include "crlibm_private.h" #include "log_fast.h" /* switches on various printfs. Default 0 */ #define DEBUG 0 /* * 1) First reduction: exponent extraction * E * x = 2^ .(y) with 1 <= y < 2 * * log(x) = E.log(2) + log(y) where: * - log(2) is tabulated * - log(y) need to be evaluated * * * 2) Avoiding accuracy problem when E=-1 by testing * * if (ny >= sqrt(2)) then * y = z/2; E = E+1; * and, * log(x) = (E+1).log(2) + log(y/2) * * so now: 11/16 <= sqrt(2)/2 <= y < sqrt(2) <= 23/16 * * * 3) Second reduction: tabular reduction * * The interval 1/sqrt(2) .. sqrt(2) is divided in 8 intervals. * So, find the interval X_i where y is. * And compute z = y - middle(X_i); * * 4) Computation: * * Polynomial evaluation of: * - P(z) ~ log(z+middle(X_i)) * * -4 -5 * with |z| < 2^ or 2^ depending the considered interval. * * * 5) Reconstruction: * log(x) = E.log(2) + P(z) * */ /* * Function used to evaluate log and pow functions */ void log_quick(double *pres_hi, double *pres_lo, int* prndcstindex, db_number * py, int E) { double ln2_times_E_HI, ln2_times_E_LO, res_hi, res_lo; double z, res, P_hi, P_lo; int k, i; res=(double)E; if(E<0) E=-E; /* find the interval including y.d */ i = ((((*py).i[HI] & 0x001F0000)>>16)-6) ; if (i < 10) i = i>>1; else i = ((i-1)>>1); z = (*py).d - (middle[i]).d; /* (exact thanks to Sterbenz Lemma) */ /* Compute ln2_times_E = E*log(2) in double-double */ Add12( ln2_times_E_HI, ln2_times_E_LO, res*ln2hi.d, res*ln2lo.d); /* Now begin the polynomial evaluation of log(1 + z) */ res = (Poly_h[i][DEGREE]).d; for(k=DEGREE-1; k>1; k--){ res *= z; res += (Poly_h[i][k]).d; } if(E <= EMIN_FASTPATH) { /* Slow path */ if(E==0) { *prndcstindex = 0 ; /* In this case we start with a double-double multiplication to get enough relative accuracy */ Mul12(&P_hi, &P_lo, res, z); Add22(&res_hi, &res_lo, (Poly_h[i][1]).d, (Poly_l[i][1]).d, P_hi, P_lo); Mul22(&P_hi, &P_lo, res_hi, res_lo, z, 0.); Add22(pres_hi, pres_lo, (Poly_h[i][0]).d, (Poly_l[i][0]).d, P_hi, P_lo); } else { if(E > EMIN_MEDIUMPATH) *prndcstindex = 2; else *prndcstindex =1; P_hi=res*z; Add12(res_hi, res_lo, (Poly_h[i][1]).d, (Poly_l[i][1]).d + P_hi); Mul22(&P_hi, &P_lo, res_hi, res_lo, z, 0.); Add22(&res_hi, &res_lo, (Poly_h[i][0]).d, (Poly_l[i][0]).d, P_hi, P_lo); /* Add E*log(2) */ Add22(pres_hi, pres_lo, ln2_times_E_HI, ln2_times_E_LO, res_hi, res_lo); } } else { /* Fast path */ *prndcstindex = 3 ; res = z*((Poly_h[i][1]).d + z*res); #if 1 Add12(P_hi,P_lo, ln2_times_E_HI, (Poly_h[i][0]).d ); Add12(*pres_hi, *pres_lo, P_hi, (res + ((Poly_l[i][0]).d + (ln2_times_E_LO + P_lo)))); #else Add12(*pres_hi, *pres_lo, ln2_times_E_HI, (Poly_h[i][0]).d + (res + ((Poly_l[i][0]).d + ln2_times_E_LO))); #endif } } /************************************************************* ************************************************************* * ROUNDED TO NEAREST * ************************************************************* *************************************************************/ double log_rn(double x){ db_number y; double res_hi,res_lo,roundcst; int E,rndcstindex; E=0; y.d=x; /* Filter cases */ if (y.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((y.i[HI] & 0x7fffffff)|y.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (y.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; y.d *= two52.d; /* make x a normal number */ } if (y.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* reduce to y.d such that sqrt(2)/2 < y.d < sqrt(2) */ E += (y.i[HI]>>20)-1023; /* extract the exponent */ y.i[HI] = (y.i[HI] & 0x000fffff) | 0x3ff00000; /* do exponent = 0 */ if (y.d > SQRT_2){ y.d *= 0.5; E++; } /* Call the actual computation */ log_quick(&res_hi, &res_lo, &rndcstindex, &y, E); roundcst = rncst[rndcstindex]; /* Test for rounding to the nearest */ if(res_hi == (res_hi + (res_lo * roundcst))) return res_hi; else { scs_t res; #if DEBUG printf("Going for Accurate Phase for x=%1.50e\n",x); #endif scs_log(res, y, E); scs_get_d(&res_hi, res); return res_hi; } } /************************************************************* ************************************************************* * ROUNDED TOWARD -INFINITY * ************************************************************* *************************************************************/ double log_rd(double x){ db_number y; double res_hi,res_lo,roundcst; int E,rndcstindex; scs_t res; E=0; y.d=x; /* Filter cases */ if (y.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((y.i[HI] & 0x7fffffff)|y.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (y.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; y.d *= two52.d; /* make x as normal number = x's mantissa */ } if (y.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* The only double whose log is exactly a double */ if(x==1.0) return 0.0; E += (y.i[HI]>>20)-1023; /* extract the exponent */ y.i[HI] = (y.i[HI] & 0x000fffff) | 0x3ff00000; /* do exponent = 0 */ if (y.d > SQRT_2){ y.d *= 0.5; E++; } log_quick(&res_hi, &res_lo, &rndcstindex, &y, E); roundcst = epsilon[rndcstindex]; TEST_AND_RETURN_RD(res_hi, res_lo, roundcst); /* if the previous block didn't return a value, launch accurate phase */ #if DEBUG printf("Going for Accurate Phase"); #endif scs_log(res, y, E); scs_get_d_minf(&res_hi, res); return res_hi; } /************************************************************* ************************************************************* * ROUNDED TOWARD +INFINITY * ************************************************************* *************************************************************/ double log_ru(double x){ db_number y; double res_hi,res_lo,roundcst; int E,rndcstindex; scs_t res; E=0; y.d=x; /* Filter cases */ if (y.i[HI] < 0x00100000){ /* x < 2^(-1022) */ if (((y.i[HI] & 0x7fffffff)|y.i[LO])==0){ return -1.0/0.0; } /* log(+/-0) = -Inf */ if (y.i[HI] < 0){ return (x-x)/0; /* log(-x) = Nan */ } /* Subnormal number */ E = -52; y.d *= two52.d; /* make x as normal number = x's mantissa */ } if (y.i[HI] >= 0x7ff00000){ return x+x; /* Inf or Nan */ } /* The only double whose log is exactly a double */ if(x==1.0) return 0.0; E += (y.i[HI]>>20)-1023; /* extract the exponent */ y.i[HI] = (y.i[HI] & 0x000fffff) | 0x3ff00000; /* do exponent = 0 */ if (y.d > SQRT_2){ y.d *= 0.5; E++; } log_quick(&res_hi, &res_lo, &rndcstindex, &y, E); roundcst = epsilon[rndcstindex]; TEST_AND_RETURN_RU(res_hi, res_lo, roundcst); /* if the previous block didn't return a value, launch accurate phase */ #if DEBUG printf("Going for Accurate Phase"); #endif scs_log(res, y, E); scs_get_d_pinf(&res_hi, res); return res_hi; } /************************************************************* ************************************************************* * ROUNDED TOWARD ZERO * ************************************************************* *************************************************************/ double log_rz(double x){ if(x>1) return log_rd(x); else return log_ru(x); } interval-3.2.0/src/crlibm/log_fast.h0000644000000000000000000004116413316017127015503 0ustar 00000000000000/* * Correctly rounded logarithm * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "crlibm.h" #include "crlibm_private.h" /*File generated by maple/coef_log.mw*/ #define SQRT_2 1.4142135623730950489e0 #define DEGREE 12 #define EMIN_MEDIUMPATH 23.000 #define EMIN_FASTPATH 185.000 /* Constants for rounding */ static const double epsilon[4] = { /* Case E=0 */ 4.47385432225115274522995672974873440655535693998277e-18, /* Middle case */ 8.40963020519242390613590856552459545441732156457476e-19, /* Case E>EminMedPath */ 3.19013236586914638175957676953204491380730158561523e-20, /* And for the fast path */ 1.65439555368591958127629148820687373633319579538065e-19 }; static const double rncst[4] = { /* Case E=0 */ 1.08596671427669422271833354898262768983840942382813e+00, /* Middle case */ 1.01526872993599659444896587956463918089866638183594e+00, /* Case E>EminMedPath */ 1.00057496390146027920309279579669237136840820312500e+00, /* And for the fast path */ 1.00298612635768380485501438670326024293899536132813e+00 }; #ifdef WORDS_BIGENDIAN static const db_number ln2hi = {{0x3FE62E42,0xFEFA3800}} /* +6.9314718056e-01 */; static const db_number ln2lo = {{0x3D2EF357,0x93C76730}} /* +5.4979230187e-14 */; static const db_number two52 = {{0x43300000,0x00000000}} /* +4.5035996274e+15 */; static const db_number middle[8] = { {{0x3FE7504F,0x333F9DE3}} /* +7.2855339059e-01 */ , {{0x3FE90000,0x00000000}} /* +7.8125000000e-01 */ , {{0x3FEB0000,0x00000000}} /* +8.4375000000e-01 */ , {{0x3FED0000,0x00000000}} /* +9.0625000000e-01 */ , {{0x3FF00000,0x00000000}} /* +1.0000000000e+00 */ , {{0x3FF20000,0x00000000}} /* +1.1250000000e+00 */ , {{0x3FF40000,0x00000000}} /* +1.2500000000e+00 */ , {{0x3FF5D04F,0x333F9DE9}} /* +1.3633567812e+00 */ }; static const db_number Poly_h[8][13] = { /* polynomial 1 */ { {{0xBFD444B8,0x73F60B09}} /* -3.1669436764e-01 */ , {{0x3FF5F619,0x980C433A}} /* +1.3725830020e+00 */ , {{0xBFEE24CC,0x824C9A57}} /* -9.4199204873e-01 */ , {{0x3FEB954C,0x47881604}} /* +8.6197484942e-01 */ , {{0xBFEC6529,0xC58FCD22}} /* -8.8734901987e-01 */ , {{0x3FEF2E06,0x1AC1D834}} /* +9.7436814524e-01 */ , {{0xBFF1D4FE,0xF5D42E1A}} /* -1.1145009616e+00 */ , {{0x3FF4FAB7,0x67F441DC}} /* +1.3112100659e+00 */ , {{0xBFF93248,0xEA47B471}} /* -1.5747765686e+00 */ , {{0x3FFEBDCE,0x85276A57}} /* +1.9213395311e+00 */ , {{0xC002FCE1,0x0ABAD697}} /* -2.3734761084e+00 */ , {{0x4007BFE9,0x8C0B7AF7}} /* +2.9687071744e+00 */ , {{0xC00DE4D4,0xF57FD2EC}} /* -3.7367343120e+00 */ }, /* polynomial 2 */ { {{0xBFCF991C,0x6CB3B379}} /* -2.4686007793e-01 */ , {{0x3FF47AE1,0x47AE147B}} /* +1.2800000000e+00 */ , {{0xBFEA36E2,0xEB1C432D}} /* -8.1920000000e-01 */ , {{0x3FE65E9F,0x80F29213}} /* +6.9905066667e-01 */ , {{0xBFE5798E,0xE2308C3F}} /* -6.7108864000e-01 */ , {{0x3FE5FD7F,0xE1793910}} /* +6.8719476736e-01 */ , {{0xBFE774CC,0xAC3CC49E}} /* -7.3300775185e-01 */ , {{0x3FE9BC1F,0x779F31B6}} /* +8.0421422351e-01 */ , {{0xBFECD2B2,0x9C89806A}} /* -9.0071993421e-01 */ , {{0x3FF065A0,0xF663DD55}} /* +1.0248117089e+00 */ , {{0xBFF2E3A7,0x64D28253}} /* -1.1805795611e+00 */ , {{0x3FF613D4,0x162168A9}} /* +1.3798409333e+00 */ , {{0xBFF9EC69,0x1E7E75E1}} /* -1.6202174369e+00 */ }, /* polynomial 3 */ { {{0xBFC5BF40,0x6B543DB2}} /* -1.6989903680e-01 */ , {{0x3FF2F684,0xBDA12F68}} /* +1.1851851852e+00 */ , {{0xBFE67980,0xE0BF08C7}} /* -7.0233196159e-01 */ , {{0x3FE1C1FA,0x5F678885}} /* +5.5492895731e-01 */ , {{0xBFDF91BD,0x1B62B9D2}} /* -4.9327018427e-01 */ , {{0x3FDDEEAF,0x8242EF01}} /* +4.6769321175e-01 */ , {{0xBFDD9015,0xA36B029B}} /* -4.6191922149e-01 */ , {{0x3FDE0836,0x7F176341}} /* +4.6925127422e-01 */ , {{0xBFDF24F6,0x26663631}} /* -4.8663095236e-01 */ , {{0x3FE067BA,0x19D8F153}} /* +5.1266198204e-01 */ , {{0xBFE17FB2,0xECA216B7}} /* -5.4683824747e-01 */ , {{0x3FE2ECE6,0x2FABC4B9}} /* +5.9141835509e-01 */ , {{0xBFE492F3,0x21A51E4E}} /* -6.4293819972e-01 */ }, /* polynomial 4 */ { {{0xBFB9335E,0x5D594989}} /* -9.8440072813e-02 */ , {{0x3FF1A7B9,0x611A7B96}} /* +1.1034482759e+00 */ , {{0xBFE37B48,0x24872744}} /* -6.0879904875e-01 */ , {{0x3FDCA99C,0x29F8DE8E}} /* +4.4785217379e-01 */ , {{0xBFD7B881,0x3D37E454}} /* -3.7063628176e-01 */ , {{0x3FD4F08E,0x55D1F3A8}} /* +3.2718237286e-01 */ , {{0xBFD3413F,0x346E99D3}} /* -3.0085735436e-01 */ , {{0x3FD23625,0x15433E66}} /* +2.8455473973e-01 */ , {{0xBFD19561,0x9976A7ED}} /* -2.7474250781e-01 */ , {{0x3FD13F21,0x5935F4CB}} /* +2.6947816574e-01 */ , {{0xBFD120AC,0x8299A6A4}} /* -2.6761925463e-01 */ , {{0x3FD13CDB,0x325D4F09}} /* +2.6933936995e-01 */ , {{0xBFD1720B,0x858B6D5D}} /* -2.7258575479e-01 */ }, /* polynomial 5 */ { {{0x00000000,0x00000000}} /* +0.0000000000e-01 */ , {{0x3FF00000,0x00000000}} /* +1.0000000000e+00 */ , {{0xBFE00000,0x00000000}} /* -5.0000000000e-01 */ , {{0x3FD55555,0x55555582}} /* +3.3333333333e-01 */ , {{0xBFD00000,0x000000A9}} /* -2.5000000000e-01 */ , {{0x3FC99999,0x99958511}} /* +1.9999999999e-01 */ , {{0xBFC55555,0x554BF922}} /* -1.6666666665e-01 */ , {{0x3FC24924,0xA3AEF673}} /* +1.4285715096e-01 */ , {{0xBFC00000,0x1CE3E886}} /* -1.2500001345e-01 */ , {{0x3FBC7184,0x13CEB1B9}} /* +1.1110711559e-01 */ , {{0xBFB99941,0xE1BDC076}} /* -9.9994771588e-02 */ , {{0x3FB78146,0xBC144107}} /* +9.1816349905e-02 */ , {{0xBFB595CF,0x0AA58754}} /* -8.4317150211e-02 */ }, /* polynomial 6 */ { {{0x3FBE2707,0x6E2AF2E6}} /* +1.1778303566e-01 */ , {{0x3FEC71C7,0x1C71C71C}} /* +8.8888888889e-01 */ , {{0xBFD948B0,0xFCD6E9E0}} /* -3.9506172840e-01 */ , {{0x3FCDF756,0x80FEB690}} /* +2.3411065386e-01 */ , {{0xBFC3FA39,0xAB547A1A}} /* -1.5607376924e-01 */ , {{0x3FBC6990,0x98A29957}} /* +1.1098579146e-01 */ , {{0xBFB50BD3,0x6791851B}} /* -8.2211697374e-02 */ , {{0x3FB00902,0xA288F0A9}} /* +6.2637486154e-02 */ , {{0xBFA8F192,0x5F283335}} /* -4.8718046299e-02 */ , {{0x3FA3B540,0xE7508F6E}} /* +3.8492229687e-02 */ , {{0xBF9F8850,0xBFE2263F}} /* -3.0793439590e-02 */ , {{0x3F99B300,0x12EF8724}} /* +2.5096894413e-02 */ , {{0xBF94F85D,0x99AF0E14}} /* -2.0478689675e-02 */ }, /* polynomial 7 */ { {{0x3FCC8FF7,0xC79A9A22}} /* +2.2314355131e-01 */ , {{0x3FE99999,0x9999999A}} /* +8.0000000000e-01 */ , {{0xBFD47AE1,0x47AE147B}} /* -3.2000000000e-01 */ , {{0x3FC5D867,0xC3ECE2B2}} /* +1.7066666667e-01 */ , {{0xBFBA36E2,0xEB1C436A}} /* -1.0240000000e-01 */ , {{0x3FB0C6F7,0xA0B52722}} /* +6.5535999999e-02 */ , {{0xBFA65E9F,0x80EFFFCD}} /* -4.3690666665e-02 */ , {{0x3F9EADA7,0x96E552E6}} /* +2.9959314904e-02 */ , {{0xBF95798E,0xEF8F2073}} /* -2.0971520778e-02 */ , {{0x3F8E8A9C,0x71A5F85C}} /* +1.4912817210e-02 */ , {{0xBF85FD5B,0xDA92B978}} /* -1.0737149818e-02 */ , {{0x3F801A73,0xDB58E5DE}} /* +7.8629542651e-03 */ , {{0xBF77A54B,0x588CDC6F}} /* -5.7728713226e-03 */ }, /* polynomial 8 */ { {{0x3FD3D638,0x05AA02DB}} /* +3.0994988015e-01 */ , {{0x3FE778B2,0xD84B7B4A}} /* +7.3348371739e-01 */ , {{0xBFD13748,0x582A4354}} /* -2.6899918184e-01 */ , {{0x3FC0D63A,0x08B6E75D}} /* +1.3153767992e-01 */ , {{0xBFB28638,0xBDFF0D07}} /* -7.2360559831e-02 */ , {{0x3FA5BD59,0x0841B395}} /* +4.2460233934e-02 */ , {{0xBF9A937C,0x93FDD519}} /* -2.5953241856e-02 */ , {{0x3F90B55A,0xB37AD191}} /* +1.6316811757e-02 */ , {{0xBF857265,0xA500F702}} /* -1.0472101305e-02 */ , {{0x3F7BF747,0x97F62E2F}} /* +6.8276211381e-03 */ , {{0xBF727615,0x37BCA347}} /* -4.5071438615e-03 */ , {{0x3F68B6F6,0x340868F6}} /* +3.0169304521e-03 */ , {{0xBF60A0BF,0x5B164CA3}} /* -2.0297753733e-03 */ } }; static const db_number Poly_l[8][2] = { /* polynomial 1 */ { {{0xBC531A78,0xC9731542}} /* -4.1423907624e-18 */ , {{0x3C6DA901,0xD7E733C1}} /* +1.2863054535e-17 */ , }, /* polynomial 2 */ { {{0xBC6F6650,0x792F85DD}} /* -1.3617434188e-17 */ , {{0xBC7EB9DF,0xF7DDA2CA}} /* -2.6650620715e-17 */ , }, /* polynomial 3 */ { {{0x3C21F5B3,0xE8EE7A2B}} /* +4.8680071630e-19 */ , {{0x3C92F660,0x2CEA2030}} /* +6.5789058301e-17 */ , }, /* polynomial 4 */ { {{0x3C5478A8,0x527726CF}} /* +4.4390095748e-18 */ , {{0x3C71A77F,0xA4B8A6F9}} /* +1.5312656901e-17 */ , }, /* polynomial 5 */ { {{0x00000000,0x00000000}} /* +0.0000000000e-01 */ , {{0xBC03E91A,0xAAF9039B}} /* -1.3491922402e-19 */ , }, /* polynomial 6 */ { {{0xBC3615B0,0xDBC40302}} /* -1.1972156066e-18 */ , {{0x3C8C55D6,0x047FA77E}} /* +4.9153904729e-17 */ , }, /* polynomial 7 */ { {{0xBC64F68B,0x97A41961}} /* -9.0912813346e-18 */ , {{0xBC89A0B0,0x9DE4BE41}} /* -4.4456964079e-17 */ , }, /* polynomial 8 */ { {{0xBC3B294D,0xE20C7AD0}} /* -1.4724194439e-18 */ , {{0xBC818759,0xCA7AB225}} /* -3.0407471421e-17 */ , } }; #else static const db_number ln2hi = {{0xFEFA3800,0x3FE62E42}} /* +6.9314718056e-01 */; static const db_number ln2lo = {{0x93C76730,0x3D2EF357}} /* +5.4979230187e-14 */; static const db_number two52 = {{0x00000000,0x43300000}} /* +4.5035996274e+15 */; static const db_number middle[8] = { {{0x333F9DE3,0x3FE7504F}} /* +7.2855339059e-01 */ , {{0x00000000,0x3FE90000}} /* +7.8125000000e-01 */ , {{0x00000000,0x3FEB0000}} /* +8.4375000000e-01 */ , {{0x00000000,0x3FED0000}} /* +9.0625000000e-01 */ , {{0x00000000,0x3FF00000}} /* +1.0000000000e+00 */ , {{0x00000000,0x3FF20000}} /* +1.1250000000e+00 */ , {{0x00000000,0x3FF40000}} /* +1.2500000000e+00 */ , {{0x333F9DE9,0x3FF5D04F}} /* +1.3633567812e+00 */ }; static const db_number Poly_h[8][13] = { /* polynomial 1 */ { {{0x73F60B09,0xBFD444B8}} /* -3.1669436764e-01 */ , {{0x980C433A,0x3FF5F619}} /* +1.3725830020e+00 */ , {{0x824C9A57,0xBFEE24CC}} /* -9.4199204873e-01 */ , {{0x47881604,0x3FEB954C}} /* +8.6197484942e-01 */ , {{0xC58FCD22,0xBFEC6529}} /* -8.8734901987e-01 */ , {{0x1AC1D834,0x3FEF2E06}} /* +9.7436814524e-01 */ , {{0xF5D42E1A,0xBFF1D4FE}} /* -1.1145009616e+00 */ , {{0x67F441DC,0x3FF4FAB7}} /* +1.3112100659e+00 */ , {{0xEA47B471,0xBFF93248}} /* -1.5747765686e+00 */ , {{0x85276A57,0x3FFEBDCE}} /* +1.9213395311e+00 */ , {{0x0ABAD697,0xC002FCE1}} /* -2.3734761084e+00 */ , {{0x8C0B7AF7,0x4007BFE9}} /* +2.9687071744e+00 */ , {{0xF57FD2EC,0xC00DE4D4}} /* -3.7367343120e+00 */ }, /* polynomial 2 */ { {{0x6CB3B379,0xBFCF991C}} /* -2.4686007793e-01 */ , {{0x47AE147B,0x3FF47AE1}} /* +1.2800000000e+00 */ , {{0xEB1C432D,0xBFEA36E2}} /* -8.1920000000e-01 */ , {{0x80F29213,0x3FE65E9F}} /* +6.9905066667e-01 */ , {{0xE2308C3F,0xBFE5798E}} /* -6.7108864000e-01 */ , {{0xE1793910,0x3FE5FD7F}} /* +6.8719476736e-01 */ , {{0xAC3CC49E,0xBFE774CC}} /* -7.3300775185e-01 */ , {{0x779F31B6,0x3FE9BC1F}} /* +8.0421422351e-01 */ , {{0x9C89806A,0xBFECD2B2}} /* -9.0071993421e-01 */ , {{0xF663DD55,0x3FF065A0}} /* +1.0248117089e+00 */ , {{0x64D28253,0xBFF2E3A7}} /* -1.1805795611e+00 */ , {{0x162168A9,0x3FF613D4}} /* +1.3798409333e+00 */ , {{0x1E7E75E1,0xBFF9EC69}} /* -1.6202174369e+00 */ }, /* polynomial 3 */ { {{0x6B543DB2,0xBFC5BF40}} /* -1.6989903680e-01 */ , {{0xBDA12F68,0x3FF2F684}} /* +1.1851851852e+00 */ , {{0xE0BF08C7,0xBFE67980}} /* -7.0233196159e-01 */ , {{0x5F678885,0x3FE1C1FA}} /* +5.5492895731e-01 */ , {{0x1B62B9D2,0xBFDF91BD}} /* -4.9327018427e-01 */ , {{0x8242EF01,0x3FDDEEAF}} /* +4.6769321175e-01 */ , {{0xA36B029B,0xBFDD9015}} /* -4.6191922149e-01 */ , {{0x7F176341,0x3FDE0836}} /* +4.6925127422e-01 */ , {{0x26663631,0xBFDF24F6}} /* -4.8663095236e-01 */ , {{0x19D8F153,0x3FE067BA}} /* +5.1266198204e-01 */ , {{0xECA216B7,0xBFE17FB2}} /* -5.4683824747e-01 */ , {{0x2FABC4B9,0x3FE2ECE6}} /* +5.9141835509e-01 */ , {{0x21A51E4E,0xBFE492F3}} /* -6.4293819972e-01 */ }, /* polynomial 4 */ { {{0x5D594989,0xBFB9335E}} /* -9.8440072813e-02 */ , {{0x611A7B96,0x3FF1A7B9}} /* +1.1034482759e+00 */ , {{0x24872744,0xBFE37B48}} /* -6.0879904875e-01 */ , {{0x29F8DE8E,0x3FDCA99C}} /* +4.4785217379e-01 */ , {{0x3D37E454,0xBFD7B881}} /* -3.7063628176e-01 */ , {{0x55D1F3A8,0x3FD4F08E}} /* +3.2718237286e-01 */ , {{0x346E99D3,0xBFD3413F}} /* -3.0085735436e-01 */ , {{0x15433E66,0x3FD23625}} /* +2.8455473973e-01 */ , {{0x9976A7ED,0xBFD19561}} /* -2.7474250781e-01 */ , {{0x5935F4CB,0x3FD13F21}} /* +2.6947816574e-01 */ , {{0x8299A6A4,0xBFD120AC}} /* -2.6761925463e-01 */ , {{0x325D4F09,0x3FD13CDB}} /* +2.6933936995e-01 */ , {{0x858B6D5D,0xBFD1720B}} /* -2.7258575479e-01 */ }, /* polynomial 5 */ { {{0x00000000,0x00000000}} /* +0.0000000000e-01 */ , {{0x00000000,0x3FF00000}} /* +1.0000000000e+00 */ , {{0x00000000,0xBFE00000}} /* -5.0000000000e-01 */ , {{0x55555582,0x3FD55555}} /* +3.3333333333e-01 */ , {{0x000000A9,0xBFD00000}} /* -2.5000000000e-01 */ , {{0x99958511,0x3FC99999}} /* +1.9999999999e-01 */ , {{0x554BF922,0xBFC55555}} /* -1.6666666665e-01 */ , {{0xA3AEF673,0x3FC24924}} /* +1.4285715096e-01 */ , {{0x1CE3E886,0xBFC00000}} /* -1.2500001345e-01 */ , {{0x13CEB1B9,0x3FBC7184}} /* +1.1110711559e-01 */ , {{0xE1BDC076,0xBFB99941}} /* -9.9994771588e-02 */ , {{0xBC144107,0x3FB78146}} /* +9.1816349905e-02 */ , {{0x0AA58754,0xBFB595CF}} /* -8.4317150211e-02 */ }, /* polynomial 6 */ { {{0x6E2AF2E6,0x3FBE2707}} /* +1.1778303566e-01 */ , {{0x1C71C71C,0x3FEC71C7}} /* +8.8888888889e-01 */ , {{0xFCD6E9E0,0xBFD948B0}} /* -3.9506172840e-01 */ , {{0x80FEB690,0x3FCDF756}} /* +2.3411065386e-01 */ , {{0xAB547A1A,0xBFC3FA39}} /* -1.5607376924e-01 */ , {{0x98A29957,0x3FBC6990}} /* +1.1098579146e-01 */ , {{0x6791851B,0xBFB50BD3}} /* -8.2211697374e-02 */ , {{0xA288F0A9,0x3FB00902}} /* +6.2637486154e-02 */ , {{0x5F283335,0xBFA8F192}} /* -4.8718046299e-02 */ , {{0xE7508F6E,0x3FA3B540}} /* +3.8492229687e-02 */ , {{0xBFE2263F,0xBF9F8850}} /* -3.0793439590e-02 */ , {{0x12EF8724,0x3F99B300}} /* +2.5096894413e-02 */ , {{0x99AF0E14,0xBF94F85D}} /* -2.0478689675e-02 */ }, /* polynomial 7 */ { {{0xC79A9A22,0x3FCC8FF7}} /* +2.2314355131e-01 */ , {{0x9999999A,0x3FE99999}} /* +8.0000000000e-01 */ , {{0x47AE147B,0xBFD47AE1}} /* -3.2000000000e-01 */ , {{0xC3ECE2B2,0x3FC5D867}} /* +1.7066666667e-01 */ , {{0xEB1C436A,0xBFBA36E2}} /* -1.0240000000e-01 */ , {{0xA0B52722,0x3FB0C6F7}} /* +6.5535999999e-02 */ , {{0x80EFFFCD,0xBFA65E9F}} /* -4.3690666665e-02 */ , {{0x96E552E6,0x3F9EADA7}} /* +2.9959314904e-02 */ , {{0xEF8F2073,0xBF95798E}} /* -2.0971520778e-02 */ , {{0x71A5F85C,0x3F8E8A9C}} /* +1.4912817210e-02 */ , {{0xDA92B978,0xBF85FD5B}} /* -1.0737149818e-02 */ , {{0xDB58E5DE,0x3F801A73}} /* +7.8629542651e-03 */ , {{0x588CDC6F,0xBF77A54B}} /* -5.7728713226e-03 */ }, /* polynomial 8 */ { {{0x05AA02DB,0x3FD3D638}} /* +3.0994988015e-01 */ , {{0xD84B7B4A,0x3FE778B2}} /* +7.3348371739e-01 */ , {{0x582A4354,0xBFD13748}} /* -2.6899918184e-01 */ , {{0x08B6E75D,0x3FC0D63A}} /* +1.3153767992e-01 */ , {{0xBDFF0D07,0xBFB28638}} /* -7.2360559831e-02 */ , {{0x0841B395,0x3FA5BD59}} /* +4.2460233934e-02 */ , {{0x93FDD519,0xBF9A937C}} /* -2.5953241856e-02 */ , {{0xB37AD191,0x3F90B55A}} /* +1.6316811757e-02 */ , {{0xA500F702,0xBF857265}} /* -1.0472101305e-02 */ , {{0x97F62E2F,0x3F7BF747}} /* +6.8276211381e-03 */ , {{0x37BCA347,0xBF727615}} /* -4.5071438615e-03 */ , {{0x340868F6,0x3F68B6F6}} /* +3.0169304521e-03 */ , {{0x5B164CA3,0xBF60A0BF}} /* -2.0297753733e-03 */ } }; static const db_number Poly_l[8][2] = { /* polynomial 1 */ { {{0xC9731542,0xBC531A78}} /* -4.1423907624e-18 */ , {{0xD7E733C1,0x3C6DA901}} /* +1.2863054535e-17 */ , }, /* polynomial 2 */ { {{0x792F85DD,0xBC6F6650}} /* -1.3617434188e-17 */ , {{0xF7DDA2CA,0xBC7EB9DF}} /* -2.6650620715e-17 */ , }, /* polynomial 3 */ { {{0xE8EE7A2B,0x3C21F5B3}} /* +4.8680071630e-19 */ , {{0x2CEA2030,0x3C92F660}} /* +6.5789058301e-17 */ , }, /* polynomial 4 */ { {{0x527726CF,0x3C5478A8}} /* +4.4390095748e-18 */ , {{0xA4B8A6F9,0x3C71A77F}} /* +1.5312656901e-17 */ , }, /* polynomial 5 */ { {{0x00000000,0x00000000}} /* +0.0000000000e-01 */ , {{0xAAF9039B,0xBC03E91A}} /* -1.3491922402e-19 */ , }, /* polynomial 6 */ { {{0xDBC40302,0xBC3615B0}} /* -1.1972156066e-18 */ , {{0x047FA77E,0x3C8C55D6}} /* +4.9153904729e-17 */ , }, /* polynomial 7 */ { {{0x97A41961,0xBC64F68B}} /* -9.0912813346e-18 */ , {{0x9DE4BE41,0xBC89A0B0}} /* -4.4456964079e-17 */ , }, /* polynomial 8 */ { {{0xE20C7AD0,0xBC3B294D}} /* -1.4724194439e-18 */ , {{0xCA7AB225,0xBC818759}} /* -3.0407471421e-17 */ , } }; #endif interval-3.2.0/src/crlibm/maple/acos-td.mpl0000644000000000000000000004412313316017127016674 0ustar 00000000000000####################################################################### # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # To use: # restart; read "exp-td.mpl"; Digits := 145: interface(quiet=true): read "common-procedures.mpl": read "triple-double.mpl": read "gal.mpl": mkdir("TEMPACOS"): with(orthopoly,T): truncPoly := proc(p,k) local i, q: q := 0: convert(q,polynom): for i from 0 to min(degree(p,x),k) do q := q + coeff(p,x,i) * x^i: od: return (q): end: intervals := 10: for i from 1 to intervals do epsAccurate[i] := 0.5: epsQuick[i] := 0.5: polyAccurate[i] := 1: polyQuick[i] := 1: od: epsAccurateSpecial := 0.5: epsQuickExtra := 0.5: lowestIntervalMax := 0.185: highestIntervalMin := 0.78: polyAccurateTDCoeffsLowest := 13: polyAccurateDDCoeffsLowest := 12: polyAccurateDCoeffsLowest := 16: polyAccurateDegreeLowest := polyAccurateTDCoeffsLowest + polyAccurateDDCoeffsLowest + polyAccurateDCoeffsLowest: polyQuickDDCoeffsLowest := 12: polyQuickDCoeffsLowest := 10: polyQuickDegreeLowest := polyQuickDDCoeffsLowest + polyQuickDCoeffsLowest: polyAccurateTDCoeffsMiddle := 7: polyAccurateDDCoeffsMiddle := 9: polyAccurateDCoeffsMiddle := 19: polyAccurateDegreeMiddle := polyAccurateTDCoeffsMiddle + polyAccurateDDCoeffsMiddle + polyAccurateDCoeffsMiddle: polyQuickDDCoeffsMiddle := 7: polyQuickDCoeffsMiddle := 7: polyQuickDegreeMiddle := polyQuickDDCoeffsMiddle + polyQuickDCoeffsMiddle: polyAccurateTDCoeffsHighest := 9: polyAccurateDDCoeffsHighest := 9: polyAccurateDCoeffsHighest := 11: polyAccurateDegreeHighest := polyAccurateTDCoeffsHighest + polyAccurateDDCoeffsHighest + polyAccurateDCoeffsHighest: polyQuickDDCoeffsHighest := 9: polyQuickDCoeffsHighest := 9: polyQuickDegreeHighest := polyQuickDDCoeffsHighest + polyQuickDCoeffsHighest: extrabound := hexa2ieee(["3F500000","00000000"]): polyQuickDegreeExtra := 5: bound[0] := 0: b := nearest(lowestIntervalMax): he := ieeehexa(b): bound[1] := hexa2ieee([he[1],"00000000"]): b := nearest(highestIntervalMin): he := ieeehexa(b): bound[intervals - 1] := hexa2ieee([he[1],"00000000"]): bound[intervals] := 1: linearWidth := (highestIntervalMin - lowestIntervalMax) / (intervals - 2): scaleSum := 0: scale[2] := 1.5: scale[3] := 1.35: scale[4] := 1.18: scale[5] := 1.00: scale[6] := 0.915: scale[7] := 0.74: scale[8] := 0.595: scale[9] := 0.50: for i from 2 to (intervals-1) do scaleSum := scaleSum + scale[i]: od: for i from 2 to (intervals-1) do scale[i] := scale[i] / scaleSum; od: current := lowestIntervalMax: for i from 2 to (intervals-2) do b := nearest(current + (highestIntervalMin - lowestIntervalMax) * scale[i]): current := b: he := ieeehexa(b): bound[i] := hexa2ieee([he[1],"00000000"]): od: printf("Using %d intervals with bounds:\n",intervals): for i from 0 to intervals do printf("bound[%d] = %1.30e\n",i,bound[i]): od: printf("Using an extra bound for truncating the quick poly to deg. %d in interval #0 for small args up to %f (2^(%f))\n", polyQuickDegreeExtra,extrabound,log[2](abs(extrabound))); printf("Computing Gal's accurate table values for interval midpoints\n"): for i from 2 to (intervals-1) do m := nearest((bound[i] + bound[i-1]) / 2): mhe := ieeehexa(m): printf("Interval %d: accurate table research start value %f (%s%s)\n",i,m,mhe[1],mhe[2]): midpointFloat[i] := galDoubleToDoubleDouble(nearest(m),arcsin,2^(-121),2^(15)): od: printf("Using the following floating point midpoints for intervals 2-%d:\n",intervals-2): for i from 2 to (intervals-1) do mhe := ieeehexa(midpointFloat[i]): printf("midpointFloat[%d] = %f (%s%s)\n",i,midpointFloat[i],mhe[1],mhe[2]): od: printf("The reduced argument z is therefore bounded by:\n"): printf("Interval 1: |z| < 2^(%f)\n", log[2](abs(bound[1]))): for i from 2 to (intervals-1) do printf("Interval %d: |z| < 2^(%f)\n",i, log[2](max(abs(midpointFloat[i] - bound[i-1]),abs(midpointFloat[i] - bound[i])))): od: printf("Interval %d: |z| < 2^(%f)\n",intervals, log[2](abs(1 - bound[intervals-1]))): printf("Using a %d degree polynomial for lowest interval (1) (accurate phase)\n", polyAccurateDegreeLowest): printf("with %d triple-double, %d double-double and %d double coefficients\n", polyAccurateTDCoeffsLowest, polyAccurateDDCoeffsLowest, polyAccurateDCoeffsLowest): printf("Using a %d degree polynomial for lowest interval (1) (quick phase)\n", polyQuickDegreeLowest): printf("with %d double-double and %d double coefficients\n", polyQuickDDCoeffsLowest, polyQuickDCoeffsLowest): printf("Using a %d degree polynomial for middle intervals (2-%d) (accurate phase)\n", polyAccurateDegreeMiddle,intervals-2): printf("with %d triple-double, %d double-double and %d double coefficients\n", polyAccurateTDCoeffsMiddle, polyAccurateDDCoeffsMiddle, polyAccurateDCoeffsMiddle): printf("Using a %d degree polynomial for middle intervals (2-%d) (quick phase)\n", polyQuickDegreeMiddle,intervals-2): printf("with %d double-double and %d double coefficients\n", polyQuickDDCoeffsMiddle, polyQuickDCoeffsMiddle): printf("Using a %d degree polynomial for highest interval (%d) (accurate phase)\n", polyAccurateDegreeHighest,intervals): printf("with %d triple-double, %d double-double and %d double coefficients\n", polyAccurateTDCoeffsHighest, polyAccurateDDCoeffsHighest, polyAccurateDCoeffsHighest): printf("Using a %d degree polynomial for highest interval (%d) (quick phase)\n", polyQuickDegreeHighest,intervals): printf("with %d double-double and %d double coefficients\n", polyQuickDDCoeffsHighest, polyQuickDCoeffsHighest): if true then printf("Computing polynomials for interval 1 ([%f;%f])\n",bound[0],bound[1]): f := unapply(convert(series((arcsin(sqrt(x))/sqrt(x) - 1)/x,x=0,300),polynom),x): p := unapply(eval(numapprox[chebyshev](f(x),x=(bound[0])^2..(bound[1])^2,2^(-127))),x): polyAccuExact[1] := truncPoly(subs(X=x^2,p(X))*x^3+x,polyAccurateDegreeLowest): polyAccurate[1] := poly_exact32(polyAccuExact[1],polyAccurateTDCoeffsLowest,polyAccurateDDCoeffsLowest): epsAccurate[1] := numapprox[infnorm]((polyAccurate[1]/arcsin(x))-1, x=bound[0]..bound[1]): epsAccurateSpecial := numapprox[infnorm]((polyAccurate[1]/arcsin(x))-1, x=bound[0]..evalf(sin(2^(-18)))): epsAccurateUnknown := numapprox[infnorm]((polyAccurate[1]/arcsin(x))-1, x=bound[0]..evalf(cos(12867/8192))): polyQuickExact[1] := truncPoly(polyAccuExact[1],polyQuickDegreeLowest): polyQuick[1] := poly_exact2(polyQuickExact[1],polyQuickDDCoeffsLowest): epsQuick[1] := numapprox[infnorm]((polyQuick[1]/arcsin(x))-1, x=bound[0]..bound[1]): polyQuickExtraExact := truncPoly(polyAccuExact[1],polyQuickDegreeExtra): polyQuickExtra := poly_exact2(polyQuickExtraExact,polyQuickDegreeExtra): epsQuickExtra := numapprox[infnorm]((polyQuickExtra/arcsin(x))-1, x=bound[0]..extrabound): end if: for i from 2 to (intervals-1) do printf("Computing polynomials for interval %d ([%f;%f])\n",i,bound[i-1],bound[i]): printf("Reduced argument z will be in interval [%1.8e;%1.8e] ([-2^%f,2^%f]),\n", bound[i-1]-midpointFloat[i],bound[i]-midpointFloat[i], log[2](abs(bound[i-1]-midpointFloat[i])),log[2](abs(bound[i]-midpointFloat[i]))): f := unapply(arcsin(x+midpointFloat[i]),x): fhelp := unapply(convert(series((f(x)-arcsin(midpointFloat[i]))/x,x=0,polyAccurateDegreeMiddle*3),polynom),x): polyAccuExact[i] := numapprox[minimax](fhelp(x), x=bound[i-1]-midpointFloat[i]..bound[i]-midpointFloat[i], [polyAccurateDegreeMiddle,0],1,'err')*x + nearestDD(evalf(arcsin(midpointFloat[i]))): polyAccurate[i] := poly_exact32(polyAccuExact[i],polyAccurateTDCoeffsMiddle,polyAccurateDDCoeffsMiddle): epsAccurate[i] := numapprox[infnorm]((polyAccurate[i]/f(x))-1, x=bound[i-1]-midpointFloat[i]..bound[i]-midpointFloat[i]): polyQuickExact[i] := truncPoly(polyAccuExact[i],polyQuickDegreeMiddle): polyQuick[i] := poly_exact2(polyQuickExact[i],polyQuickDDCoeffsMiddle): epsQuick[i] := numapprox[infnorm]((polyQuick[i]/f(x))-1, x=bound[i-1]-midpointFloat[i]..bound[i]-midpointFloat[i]): od: if true then printf("Computing polynomials for interval %d ([%f;%f])\n",intervals,bound[intervals-1],bound[intervals]): g := unapply(((arcsin(1 - x) - Pi/2)/sqrt(2*x)),x): f := unapply(convert(series(((g(x)+1)/x),x=0,polyAccurateDegreeHighest*4),polynom),x): polyAccuExact[intervals] := numapprox[minimax](f(x),x=(1-bound[intervals]+2^(-53))..(1-bound[intervals-1]), [polyAccurateDegreeHighest-1,0],1,'err')*x-1: polyAccurate[intervals] := poly_exact32(polyAccuExact[intervals],polyAccurateTDCoeffsHighest,polyAccurateDDCoeffsHighest): epsAccurate[intervals] := numapprox[infnorm](((unapply(polyAccurate[intervals],x)(x)/g(x))-1), x=(1-bound[intervals]+2^(-53))..(1-bound[intervals-1])): polyQuickExact[intervals] := truncPoly(polyAccuExact[intervals],polyQuickDegreeHighest): polyQuick[intervals] := poly_exact2(polyQuickExact[intervals],polyQuickDDCoeffsHighest): epsQuick[intervals] := numapprox[infnorm](((unapply(polyQuick[intervals],x)(x)/g(x))-1), x=(1-bound[intervals]+2^(-53))..(1-bound[intervals-1])): printf("Checking if the polynomial for interval %d is exactly -1 in z = %f...\n",intervals,1-bound[intervals]); if (unapply(polyAccurate[intervals],x)(1-bound[intervals]) = -1) then printf(" Check passed!\n"): else printf(" Check failed!\n"): end if: end if: for i from 1 to intervals do printf("Relative error for accurate phase polynomial in interval %d ([%f;%f]) is 2^(%f)\n", i,bound[i-1],bound[i],log[2](abs(epsAccurate[i]))): printf("Relative error for quick phase polynomial in interval %d ([%f;%f]) is 2^(%f)\n", i,bound[i-1],bound[i],log[2](abs(epsQuick[i]))): od: printf("Relative error for accurate phase polynomial #1 in special interval [0;sin(2^(-18))]) is 2^(%f)\n", log[2](abs(epsAccurateSpecial))): printf("Relative error for accurate phase polynomial #1 in \"unknown\" interval [0;cos(12867/8192)]) is 2^(%f)\n", log[2](abs(epsAccurateUnknown))): printf("Relative error for quick phase extra case truncated polynomial #1 in special interval [0;%f]) is 2^(%f)\n", extrabound,log[2](abs(epsQuickExtra))): (PiHalfH, PiHalfM, PiHalfL) := hi_mi_lo(evalf(Pi/2)): (PiH, PiM, PiL) := hi_mi_lo(evalf(Pi)): epsPiDD := evalf(((PiHalfH + PiHalfM) - Pi/2)/(Pi/2)): epsPiTD := evalf(((PiHalfH + PiHalfM + PiHalfL) - Pi/2) / (Pi/2)): printf("Relative error for storing Pi/2 as a double-double is 2^(%f)\n",evalf(log[2](abs(epsPiDD)))): printf("Relative error for storing Pi/2 as a triple-double is 2^(%f)\n",evalf(log[2](abs(epsPiTD)))): # Ce qui suit est pifometrique et doit etre prouve en Gappa ensuite arithmeticalErrorQuick[1] := 2^(-61): arithmeticalErrorQuick[2] := 2^(-61): arithmeticalErrorQuick[3] := 2^(-61): arithmeticalErrorQuick[4] := 2^(-61): arithmeticalErrorQuick[5] := 2^(-61): arithmeticalErrorQuick[6] := 2^(-61): arithmeticalErrorQuick[7] := 2^(-61): arithmeticalErrorQuick[8] := 2^(-61): arithmeticalErrorQuick[9] := 2^(-61): arithmeticalErrorQuick[10] := 2^(-68): arithmeticalErrorQuickExtra := 2^(-80): for i from 1 to intervals do estimatedOverallEpsQuick[i] := abs(epsQuick[i]) + abs(arithmeticalErrorQuick[i]) + abs(epsQuick[i]) * abs(arithmeticalErrorQuick[i]): printf("Relative quick phase overall error bound to show in Gappa for interval %d ([%f;%f]) is 2^(%f)\n", i,bound[i-1],bound[i],log[2](abs(estimatedOverallEpsQuick[i]))): od: estimatedOverallEpsQuickExtra := abs(epsQuickExtra) + abs(arithmeticalErrorQuickExtra) + abs(epsQuickExtra) * abs(arithmeticalErrorQuickExtra): printf("Relative quick phase overall error bound to show for extra truncted poly in interval [0;%f]) is 2^(%f)\n", extrabound,log[2](abs(estimatedOverallEpsQuickExtra))): printf("Write tables...\n"): filename:="TEMPACOS/acos-td.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#include \"crlibm.h\"\n#include \"crlibm_private.h\"\n"): fprintf(fd, "\n/* File generated by maple/acos-td.mpl */\n\n"): printf("Write table with bounds\n"): fprintf(fd, "/* High order words of interval bounds (low order word is 0) */\n"): for i from 1 to (intervals-1) do heb := ieeehexa(bound[i]): fprintf(fd, "\#define BOUND%d 0x%s\n",i,heb[1]): od: heb := ieeehexa(extrabound): fprintf(fd, "\#define EXTRABOUND 0x%s\n",heb[1]): printf("Write additional constants\n"): fprintf(fd, "\n\n/* Pi/2 as a triple-double*/\n"): fprintf(fd, "\#define PIHALFH %1.50e\n",PiHalfH): fprintf(fd, "\#define PIHALFM %1.50e\n",PiHalfM): fprintf(fd, "\#define PIHALFL %1.50e\n",PiHalfL): fprintf(fd, "\n\n/* Pi as a triple-double*/\n"): fprintf(fd, "\#define PIH %1.50e\n",PiH): fprintf(fd, "\#define PIM %1.50e\n",PiM): fprintf(fd, "\#define PIL %1.50e\n",PiL): fprintf(fd, "\#define PIHALFDOUBLERN %1.50e\n",nearest(evalf(Pi/2))): fprintf(fd, "\#define PIHALFDOUBLERU %1.50e\n",roundUp(evalf(Pi/2))): fprintf(fd, "\#define PIHALFDOUBLERD %1.50e\n",roundDown(evalf(Pi/2))): printf("Write table with midpoints and polynomial coefficients\n"): k := 0: for i from 0 to polyAccurateDegreeLowest do (hi,mi,lo) := hi_mi_lo(coeff(polyAccurate[1],x,i)): if ((abs(hi) = 1.0) and (mi = 0) and (lo = 0)) then printf( "Coefficient %d of interval 1 polynomial is exactly %f and will not be stored in the table\n",i,hi): else g := 0; if (hi <> 0) then if (i <= polyQuickDegreeLowest) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dh, quickPolyLowC%dh */",hi,k,i,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dh */",hi,k,i): end if: k := k + 1: end if: if (mi <> 0) then if (i <= polyQuickDDCoeffsLowest) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dm, quickPolyLowC%dl */",mi,k,i,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dm */",mi,k,i): end if: k := k + 1: end if: if (lo <> 0) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dl */",lo,k,i): k := k + 1: end if: end if: od: tbl[k] := sprintf("%1.50e, \t/* %d, RN rounding constant quick poly low*/", compute_rn_constant(estimatedOverallEpsQuick[1]),k): k := k + 1: tbl[k] := sprintf("%1.50e, \t/* %d, RD rounding constant quick poly low*/", estimatedOverallEpsQuick[1],k): k := k + 1: printf("Table for interval 1 written\n"): for l from 2 to (intervals-1) do tbl[k] := sprintf("%1.50e, \t/* %d, midpoint in interval %d*/",midpointFloat[l],k,l): tblidx[l] := k; k := k + 1; for i from 0 to polyAccurateDegreeMiddle do (hi,mi,lo) := hi_mi_lo(coeff(polyAccurate[l],x,i)): if ((abs(hi) = 1.0) and (mi = 0) and (lo = 0)) then printf( "Coefficient %d of interval %d polynomial is exactly %f and will not be stored in the table\n",i,l,hi): else g := 0; if (hi <> 0) then if (i <= polyQuickDegreeMiddle) then tbl[k] := sprintf( "%1.50e, \t/* %d, accPolyMid%dC%dh, quickPolyMid%dC%dh */",hi,k,l,i,l,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyMid%dC%dh */",hi,k,l,i): end if: k := k + 1: end if: if (mi <> 0) then if (i <= polyQuickDDCoeffsMiddle) then tbl[k] := sprintf( "%1.50e, \t/* %d, accPolyMid%dC%dm, quickPolyMid%dC%dl */",mi,k,l,i,l,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyMid%dC%dm */",mi,k,l,i): end if: k := k + 1: end if: if (lo <> 0) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyMid%dC%dl */",lo,k,l,i): k := k + 1: end if: end if: od: tbl[k] := sprintf("%1.50e, \t/* %d, RN rounding constant quick poly middle %d*/", compute_rn_constant(estimatedOverallEpsQuick[l]),k,l): k := k + 1: tbl[k] := sprintf("%1.50e, \t/* %d, RD rounding constant quick poly middle %d*/", estimatedOverallEpsQuick[l],k,l): k := k + 1: printf("Table for interval %d written\n",l): od: tblidx[intervals] := k: for i from 0 to polyAccurateDegreeHighest do (hi,mi,lo) := hi_mi_lo(coeff(polyAccurate[intervals],x,i)): if ((abs(hi) = 1.0) and (mi = 0) and (lo = 0)) then printf( "Coefficient %d of interval %d polynomial is exactly %f and will not be stored in the table\n",i,intervals,hi): else g := 0; if (hi <> 0) then if (i <= polyQuickDegreeHighest) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dh, quickPolyHighC%dh */",hi,k,i,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dh */",hi,k,i): end if: k := k + 1: end if: if (mi <> 0) then if (i <= polyQuickDDCoeffsHighest) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dm, quickPolyHighC%dl */",mi,k,i,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dm */",mi,k,i): end if: k := k + 1: end if: if (lo <> 0) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dl */",lo,k,i): k := k + 1: end if: end if: od: tbl[k] := sprintf("%1.50e, \t/* %d, RN rounding constant quick poly high*/", compute_rn_constant(estimatedOverallEpsQuick[intervals]),k): k := k + 1: tbl[k] := sprintf("%1.50e, \t/* %d, RD rounding constant quick poly high*/", estimatedOverallEpsQuick[intervals],k): k := k + 1: printf("Table for interval %d written\n",intervals): tbllen := k: printf("The whole table has %d entries, so uses %d bytes of memory\n",tbllen,tbllen*8): fprintf(fd,"\n\n/* Indices to the following table */\n"): for i from 2 to intervals do fprintf(fd,"\#define TBLIDX%d %d\n",i,tblidx[i]): od: fprintf(fd, "\n\n/* Table with midpoints and polynomial coefficients */\n"): fprintf(fd, "static const double tbl[%d] = {\n",tbllen): for i from 0 to (tbllen - 1) do fprintf(fd, "%s\n",tbl[i]): od: fprintf(fd, "};\n\n"): fclose(fd): printf("----DONE---\n"): interval-3.2.0/src/crlibm/maple/asin-td.mpl0000644000000000000000000004263713316017127016711 0ustar 00000000000000####################################################################### # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # To use: # restart; read "exp-td.mpl"; Digits := 145: interface(quiet=true): read "common-procedures.mpl": read "triple-double.mpl": read "gal.mpl": mkdir("TEMPASIN"): with(orthopoly,T): truncPoly := proc(p,k) local i, q: q := 0: convert(q,polynom): for i from 0 to min(degree(p,x),k) do q := q + coeff(p,x,i) * x^i: od: return (q): end: intervals := 10: for i from 1 to intervals do epsAccurate[i] := 0.5: epsQuick[i] := 0.5: polyAccurate[i] := 1: polyQuick[i] := 1: od: epsAccurateSpecial := 0.5: epsQuickExtra := 0.5: lowestIntervalMax := 0.185: highestIntervalMin := 0.78: polyAccurateTDCoeffsLowest := 13: polyAccurateDDCoeffsLowest := 12: polyAccurateDCoeffsLowest := 16: polyAccurateDegreeLowest := polyAccurateTDCoeffsLowest + polyAccurateDDCoeffsLowest + polyAccurateDCoeffsLowest: polyQuickDDCoeffsLowest := 12: polyQuickDCoeffsLowest := 10: polyQuickDegreeLowest := polyQuickDDCoeffsLowest + polyQuickDCoeffsLowest: polyAccurateTDCoeffsMiddle := 7: polyAccurateDDCoeffsMiddle := 9: polyAccurateDCoeffsMiddle := 19: polyAccurateDegreeMiddle := polyAccurateTDCoeffsMiddle + polyAccurateDDCoeffsMiddle + polyAccurateDCoeffsMiddle: polyQuickDDCoeffsMiddle := 7: polyQuickDCoeffsMiddle := 7: polyQuickDegreeMiddle := polyQuickDDCoeffsMiddle + polyQuickDCoeffsMiddle: polyAccurateTDCoeffsHighest := 9: polyAccurateDDCoeffsHighest := 9: polyAccurateDCoeffsHighest := 11: polyAccurateDegreeHighest := polyAccurateTDCoeffsHighest + polyAccurateDDCoeffsHighest + polyAccurateDCoeffsHighest: polyQuickDDCoeffsHighest := 9: polyQuickDCoeffsHighest := 9: polyQuickDegreeHighest := polyQuickDDCoeffsHighest + polyQuickDCoeffsHighest: extrabound := hexa2ieee(["3F500000","00000000"]): polyQuickDegreeExtra := 5: bound[0] := 0: b := nearest(lowestIntervalMax): he := ieeehexa(b): bound[1] := hexa2ieee([he[1],"00000000"]): b := nearest(highestIntervalMin): he := ieeehexa(b): bound[intervals - 1] := hexa2ieee([he[1],"00000000"]): bound[intervals] := 1: linearWidth := (highestIntervalMin - lowestIntervalMax) / (intervals - 2): scaleSum := 0: scale[2] := 1.5: scale[3] := 1.35: scale[4] := 1.18: scale[5] := 1.00: scale[6] := 0.915: scale[7] := 0.74: scale[8] := 0.595: scale[9] := 0.50: for i from 2 to (intervals-1) do scaleSum := scaleSum + scale[i]: od: for i from 2 to (intervals-1) do scale[i] := scale[i] / scaleSum; od: current := lowestIntervalMax: for i from 2 to (intervals-2) do b := nearest(current + (highestIntervalMin - lowestIntervalMax) * scale[i]): current := b: he := ieeehexa(b): bound[i] := hexa2ieee([he[1],"00000000"]): od: printf("Using %d intervals with bounds:\n",intervals): for i from 0 to intervals do printf("bound[%d] = %1.30e\n",i,bound[i]): od: printf("Using an extra bound for truncating the quick poly to deg. %d in interval #0 for small args up to %f (2^(%f))\n", polyQuickDegreeExtra,extrabound,log[2](abs(extrabound))); printf("Computing Gal's accurate table values for interval midpoints\n"): for i from 2 to (intervals-1) do m := nearest((bound[i] + bound[i-1]) / 2): mhe := ieeehexa(m): printf("Interval %d: accurate table research start value %f (%s%s)\n",i,m,mhe[1],mhe[2]): midpointFloat[i] := galDoubleToDoubleDouble(nearest(m),arcsin,2^(-121),2^(15)): od: printf("Using the following floating point midpoints for intervals 2-%d:\n",intervals-2): for i from 2 to (intervals-1) do mhe := ieeehexa(midpointFloat[i]): printf("midpointFloat[%d] = %f (%s%s)\n",i,midpointFloat[i],mhe[1],mhe[2]): od: printf("The reduced argument z is therefore bounded by:\n"): printf("Interval 1: |z| < 2^(%f)\n", log[2](abs(bound[1]))): for i from 2 to (intervals-1) do printf("Interval %d: |z| < 2^(%f)\n",i, log[2](max(abs(midpointFloat[i] - bound[i-1]),abs(midpointFloat[i] - bound[i])))): od: printf("Interval %d: |z| < 2^(%f)\n",intervals, log[2](abs(1 - bound[intervals-1]))): printf("Using a %d degree polynomial for lowest interval (1) (accurate phase)\n", polyAccurateDegreeLowest): printf("with %d triple-double, %d double-double and %d double coefficients\n", polyAccurateTDCoeffsLowest, polyAccurateDDCoeffsLowest, polyAccurateDCoeffsLowest): printf("Using a %d degree polynomial for lowest interval (1) (quick phase)\n", polyQuickDegreeLowest): printf("with %d double-double and %d double coefficients\n", polyQuickDDCoeffsLowest, polyQuickDCoeffsLowest): printf("Using a %d degree polynomial for middle intervals (2-%d) (accurate phase)\n", polyAccurateDegreeMiddle,intervals-2): printf("with %d triple-double, %d double-double and %d double coefficients\n", polyAccurateTDCoeffsMiddle, polyAccurateDDCoeffsMiddle, polyAccurateDCoeffsMiddle): printf("Using a %d degree polynomial for middle intervals (2-%d) (quick phase)\n", polyQuickDegreeMiddle,intervals-2): printf("with %d double-double and %d double coefficients\n", polyQuickDDCoeffsMiddle, polyQuickDCoeffsMiddle): printf("Using a %d degree polynomial for highest interval (%d) (accurate phase)\n", polyAccurateDegreeHighest,intervals): printf("with %d triple-double, %d double-double and %d double coefficients\n", polyAccurateTDCoeffsHighest, polyAccurateDDCoeffsHighest, polyAccurateDCoeffsHighest): printf("Using a %d degree polynomial for highest interval (%d) (quick phase)\n", polyQuickDegreeHighest,intervals): printf("with %d double-double and %d double coefficients\n", polyQuickDDCoeffsHighest, polyQuickDCoeffsHighest): if true then printf("Computing polynomials for interval 1 ([%f;%f])\n",bound[0],bound[1]): f := unapply(convert(series((arcsin(sqrt(x))/sqrt(x) - 1)/x,x=0,300),polynom),x): p := unapply(eval(numapprox[chebyshev](f(x),x=(bound[0])^2..(bound[1])^2,2^(-127))),x): polyAccuExact[1] := truncPoly(subs(X=x^2,p(X))*x^3+x,polyAccurateDegreeLowest): polyAccurate[1] := poly_exact32(polyAccuExact[1],polyAccurateTDCoeffsLowest,polyAccurateDDCoeffsLowest): epsAccurate[1] := numapprox[infnorm]((polyAccurate[1]/arcsin(x))-1, x=bound[0]..bound[1]): epsAccurateSpecial := numapprox[infnorm]((polyAccurate[1]/arcsin(x))-1, x=bound[0]..evalf(sin(2^(-18)))): polyQuickExact[1] := truncPoly(polyAccuExact[1],polyQuickDegreeLowest): polyQuick[1] := poly_exact2(polyQuickExact[1],polyQuickDDCoeffsLowest): epsQuick[1] := numapprox[infnorm]((polyQuick[1]/arcsin(x))-1, x=bound[0]..bound[1]): polyQuickExtraExact := truncPoly(polyAccuExact[1],polyQuickDegreeExtra): polyQuickExtra := poly_exact2(polyQuickExtraExact,polyQuickDegreeExtra): epsQuickExtra := numapprox[infnorm]((polyQuickExtra/arcsin(x))-1, x=bound[0]..extrabound): end if: for i from 2 to (intervals-1) do printf("Computing polynomials for interval %d ([%f;%f])\n",i,bound[i-1],bound[i]): printf("Reduced argument z will be in interval [%1.8e;%1.8e] ([-2^%f,2^%f]),\n", bound[i-1]-midpointFloat[i],bound[i]-midpointFloat[i], log[2](abs(bound[i-1]-midpointFloat[i])),log[2](abs(bound[i]-midpointFloat[i]))): f := unapply(arcsin(x+midpointFloat[i]),x): fhelp := unapply(convert(series((f(x)-arcsin(midpointFloat[i]))/x,x=0,polyAccurateDegreeMiddle*3),polynom),x): polyAccuExact[i] := numapprox[minimax](fhelp(x), x=bound[i-1]-midpointFloat[i]..bound[i]-midpointFloat[i], [polyAccurateDegreeMiddle,0],1,'err')*x + nearestDD(evalf(arcsin(midpointFloat[i]))): polyAccurate[i] := poly_exact32(polyAccuExact[i],polyAccurateTDCoeffsMiddle,polyAccurateDDCoeffsMiddle): epsAccurate[i] := numapprox[infnorm]((polyAccurate[i]/f(x))-1, x=bound[i-1]-midpointFloat[i]..bound[i]-midpointFloat[i]): polyQuickExact[i] := truncPoly(polyAccuExact[i],polyQuickDegreeMiddle): polyQuick[i] := poly_exact2(polyQuickExact[i],polyQuickDDCoeffsMiddle): epsQuick[i] := numapprox[infnorm]((polyQuick[i]/f(x))-1, x=bound[i-1]-midpointFloat[i]..bound[i]-midpointFloat[i]): od: if true then printf("Computing polynomials for interval %d ([%f;%f])\n",intervals,bound[intervals-1],bound[intervals]): g := unapply(((arcsin(1 - x) - Pi/2)/sqrt(2*x)),x): f := unapply(convert(series(((g(x)+1)/x),x=0,polyAccurateDegreeHighest*4),polynom),x): polyAccuExact[intervals] := numapprox[minimax](f(x),x=(1-bound[intervals]+2^(-53))..(1-bound[intervals-1]), [polyAccurateDegreeHighest-1,0],1,'err')*x-1: polyAccurate[intervals] := poly_exact32(polyAccuExact[intervals],polyAccurateTDCoeffsHighest,polyAccurateDDCoeffsHighest): epsAccurate[intervals] := numapprox[infnorm](((unapply(polyAccurate[intervals],x)(x)/g(x))-1), x=(1-bound[intervals]+2^(-53))..(1-bound[intervals-1])): polyQuickExact[intervals] := truncPoly(polyAccuExact[intervals],polyQuickDegreeHighest): polyQuick[intervals] := poly_exact2(polyQuickExact[intervals],polyQuickDDCoeffsHighest): epsQuick[intervals] := numapprox[infnorm](((unapply(polyQuick[intervals],x)(x)/g(x))-1), x=(1-bound[intervals]+2^(-53))..(1-bound[intervals-1])): printf("Checking if the polynomial for interval %d is exactly -1 in z = %f...\n",intervals,1-bound[intervals]); if (unapply(polyAccurate[intervals],x)(1-bound[intervals]) = -1) then printf(" Check passed!\n"): else printf(" Check failed!\n"): end if: end if: for i from 1 to intervals do printf("Relative error for accurate phase polynomial in interval %d ([%f;%f]) is 2^(%f)\n", i,bound[i-1],bound[i],log[2](abs(epsAccurate[i]))): printf("Relative error for quick phase polynomial in interval %d ([%f;%f]) is 2^(%f)\n", i,bound[i-1],bound[i],log[2](abs(epsQuick[i]))): od: printf("Relative error for accurate phase polynomial #1 in special interval [0;sin(2^(-18))]) is 2^(%f)\n", log[2](abs(epsAccurateSpecial))): printf("Relative error for quick phase extra case truncated polynomial #1 in special interval [0;%f]) is 2^(%f)\n", extrabound,log[2](abs(epsQuickExtra))): (PiHalfH, PiHalfM, PiHalfL) := hi_mi_lo(evalf(Pi/2)): epsPiDD := evalf(((PiHalfH + PiHalfM) - Pi/2)/(Pi/2)): epsPiTD := evalf(((PiHalfH + PiHalfM + PiHalfL) - Pi/2) / (Pi/2)): printf("Relative error for storing Pi/2 as a double-double is 2^(%f)\n",evalf(log[2](abs(epsPiDD)))): printf("Relative error for storing Pi/2 as a triple-double is 2^(%f)\n",evalf(log[2](abs(epsPiTD)))): # Ce qui suit est pifometrique et doit etre prouve en Gappa ensuite arithmeticalErrorQuick[1] := 2^(-61): arithmeticalErrorQuick[2] := 2^(-61): arithmeticalErrorQuick[3] := 2^(-61): arithmeticalErrorQuick[4] := 2^(-61): arithmeticalErrorQuick[5] := 2^(-61): arithmeticalErrorQuick[6] := 2^(-61): arithmeticalErrorQuick[7] := 2^(-61): arithmeticalErrorQuick[8] := 2^(-61): arithmeticalErrorQuick[9] := 2^(-61): arithmeticalErrorQuick[10] := 2^(-68): arithmeticalErrorQuickExtra := 2^(-80): for i from 1 to intervals do estimatedOverallEpsQuick[i] := abs(epsQuick[i]) + abs(arithmeticalErrorQuick[i]) + abs(epsQuick[i]) * abs(arithmeticalErrorQuick[i]): printf("Relative quick phase overall error bound to show in Gappa for interval %d ([%f;%f]) is 2^(%f)\n", i,bound[i-1],bound[i],log[2](abs(estimatedOverallEpsQuick[i]))): od: estimatedOverallEpsQuickExtra := abs(epsQuickExtra) + abs(arithmeticalErrorQuickExtra) + abs(epsQuickExtra) * abs(arithmeticalErrorQuickExtra): printf("Relative quick phase overall error bound to show for extra truncted poly in interval [0;%f]) is 2^(%f)\n", extrabound,log[2](abs(estimatedOverallEpsQuickExtra))): printf("Write tables...\n"): filename:="TEMPASIN/asin-td.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#include \"crlibm.h\"\n#include \"crlibm_private.h\"\n"): fprintf(fd, "\n/* File generated by maple/asin-td.mpl */\n\n"): printf("Write table with bounds\n"): fprintf(fd, "/* High order words of interval bounds (low order word is 0) */\n"): for i from 1 to (intervals-1) do heb := ieeehexa(bound[i]): fprintf(fd, "\#define BOUND%d 0x%s\n",i,heb[1]): od: heb := ieeehexa(extrabound): fprintf(fd, "\#define EXTRABOUND 0x%s\n",heb[1]): printf("Write additional constants\n"): fprintf(fd, "\n\n/* Pi/2 as a triple-double*/\n"): fprintf(fd, "\#define PIHALFH %1.50e\n",PiHalfH): fprintf(fd, "\#define PIHALFM %1.50e\n",PiHalfM): fprintf(fd, "\#define PIHALFL %1.50e\n",PiHalfL): printf("Write table with midpoints and polynomial coefficients\n"): k := 0: for i from 0 to polyAccurateDegreeLowest do (hi,mi,lo) := hi_mi_lo(coeff(polyAccurate[1],x,i)): if ((abs(hi) = 1.0) and (mi = 0) and (lo = 0)) then printf( "Coefficient %d of interval 1 polynomial is exactly %f and will not be stored in the table\n",i,hi): else g := 0; if (hi <> 0) then if (i <= polyQuickDegreeLowest) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dh, quickPolyLowC%dh */",hi,k,i,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dh */",hi,k,i): end if: k := k + 1: end if: if (mi <> 0) then if (i <= polyQuickDDCoeffsLowest) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dm, quickPolyLowC%dl */",mi,k,i,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dm */",mi,k,i): end if: k := k + 1: end if: if (lo <> 0) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyLowC%dl */",lo,k,i): k := k + 1: end if: end if: od: tbl[k] := sprintf("%1.50e, \t/* %d, RN rounding constant quick poly low*/", compute_rn_constant(estimatedOverallEpsQuick[1]),k): k := k + 1: tbl[k] := sprintf("%1.50e, \t/* %d, RD rounding constant quick poly low*/", estimatedOverallEpsQuick[1],k): k := k + 1: printf("Table for interval 1 written\n"): for l from 2 to (intervals-1) do tbl[k] := sprintf("%1.50e, \t/* %d, midpoint in interval %d*/",midpointFloat[l],k,l): tblidx[l] := k; k := k + 1; for i from 0 to polyAccurateDegreeMiddle do (hi,mi,lo) := hi_mi_lo(coeff(polyAccurate[l],x,i)): if ((abs(hi) = 1.0) and (mi = 0) and (lo = 0)) then printf( "Coefficient %d of interval %d polynomial is exactly %f and will not be stored in the table\n",i,l,hi): else g := 0; if (hi <> 0) then if (i <= polyQuickDegreeMiddle) then tbl[k] := sprintf( "%1.50e, \t/* %d, accPolyMid%dC%dh, quickPolyMid%dC%dh */",hi,k,l,i,l,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyMid%dC%dh */",hi,k,l,i): end if: k := k + 1: end if: if (mi <> 0) then if (i <= polyQuickDDCoeffsMiddle) then tbl[k] := sprintf( "%1.50e, \t/* %d, accPolyMid%dC%dm, quickPolyMid%dC%dl */",mi,k,l,i,l,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyMid%dC%dm */",mi,k,l,i): end if: k := k + 1: end if: if (lo <> 0) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyMid%dC%dl */",lo,k,l,i): k := k + 1: end if: end if: od: tbl[k] := sprintf("%1.50e, \t/* %d, RN rounding constant quick poly middle %d*/", compute_rn_constant(estimatedOverallEpsQuick[l]),k,l): k := k + 1: tbl[k] := sprintf("%1.50e, \t/* %d, RD rounding constant quick poly middle %d*/", estimatedOverallEpsQuick[l],k,l): k := k + 1: printf("Table for interval %d written\n",l): od: tblidx[intervals] := k: for i from 0 to polyAccurateDegreeHighest do (hi,mi,lo) := hi_mi_lo(coeff(polyAccurate[intervals],x,i)): if ((abs(hi) = 1.0) and (mi = 0) and (lo = 0)) then printf( "Coefficient %d of interval %d polynomial is exactly %f and will not be stored in the table\n",i,intervals,hi): else g := 0; if (hi <> 0) then if (i <= polyQuickDegreeHighest) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dh, quickPolyHighC%dh */",hi,k,i,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dh */",hi,k,i): end if: k := k + 1: end if: if (mi <> 0) then if (i <= polyQuickDDCoeffsHighest) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dm, quickPolyHighC%dl */",mi,k,i,i): else tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dm */",mi,k,i): end if: k := k + 1: end if: if (lo <> 0) then tbl[k] := sprintf("%1.50e, \t/* %d, accPolyHighC%dl */",lo,k,i): k := k + 1: end if: end if: od: tbl[k] := sprintf("%1.50e, \t/* %d, RN rounding constant quick poly high*/", compute_rn_constant(estimatedOverallEpsQuick[intervals]),k): k := k + 1: tbl[k] := sprintf("%1.50e, \t/* %d, RD rounding constant quick poly high*/", estimatedOverallEpsQuick[intervals],k): k := k + 1: printf("Table for interval %d written\n",intervals): tbllen := k: printf("The whole table has %d entries, so uses %d bytes of memory\n",tbllen,tbllen*8): fprintf(fd,"\n\n/* Indices to the following table */\n"): for i from 2 to intervals do fprintf(fd,"\#define TBLIDX%d %d\n",i,tblidx[i]): od: fprintf(fd, "\n\n/* Table with midpoints and polynomial coefficients */\n"): fprintf(fd, "static const double tbl[%d] = {\n",tbllen): for i from 0 to (tbllen - 1) do fprintf(fd, "%s\n",tbl[i]): od: fprintf(fd, "};\n\n"): fclose(fd): printf("----DONE---\n"): interval-3.2.0/src/crlibm/maple/atan.mpl0000644000000000000000000002543413316017127016271 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA restart: Digits := 100: with (numapprox):with(orthopoly): read "common-procedures.mpl"; mkdir("TEMPATAN"); #First, quick phase #Approach for the first function: #atan(x) = atan(b(i)) + atan ( (x-bi) / (1+x*b(i) ) ) #We try to have 64 correct bits #Constants #if (x >= xmax) : return arctan(x)/2)=neareast(Pi/2) log[2](evalf(min(solve(arctan(x)=nearest(Pi/2),x)))): xmax:=2^54: #halfPi=Pi/2 (remark that maxvalue < Pi/2 so that atan(x) < Pi/2 halfPi:=nearest(Pi/2): halfPi_to_plus_infinity:=nearest(nearest(Pi/2)*(1+2^(-53))): # invPi, for the atanpi function invpih,invpil := hi_lo(1/Pi); # if (xmin simplify( solve( (x-bi) / (1+x*bi) = e ,x) ): minx := bi -> simplify(solve( (x-bi) /(1+x*bi)=-e ,x)): nextbi := proc (x) evalf( max(solve( minx(bi) = x ,bi) )*(1-marge)); end: allbi := proc (n) local xi,nbi,x,i,j; global b,a, nb_of_ai, nb_of_bi, value_for_dicho; x := e; nbi := 0; i := 0; while(i= 0) do nbi := nearest ( nextbi(x) ); b[i] := evalf( nbi ); a[i] := x; x := evalf(maxx(nbi)); i:=i+1; od; j:=0; while ( 2^j < i ) do j:=j+1 od: nb_of_ai := i; nb_of_bi := i; b[i-1] := nearest(1/e+4): value_for_dicho := 2^j; return i,b[0],b[i-1]; end: allbi(100); #The polynome and its size ( 4 because 4 terms : x^2/3, ...) Q9:= poly_exact(x-1/3*x^3+1/5*x^5 -1/7*x^7+1/9*x^9): deg_poly := 4: coef_poly[0]:=nearest (-1/3): coef_poly[1]:=nearest (1/5): coef_poly[2]:=nearest (-1/7): coef_poly[3]:=nearest (1/9): Q := x^2 * coef_poly[0] + x^4*coef_poly[1] + x^6*coef_poly[2] + x^8 * coef_poly[3]: Qprime := poly_exact( x * coef_poly[0] + x^2*coef_poly[1] + x^3*coef_poly[2] + x^4 * coef_poly[3]): log[2] (infnorm( (arctan(x)-x*(1+Q) )/x,x=2^(-53)..e)); # we can note that arctan(x) = sum((-1)^i*x^(2*i+1)/(2*i+1), i = (0 .. infinity)) # so ( arctan(x) - Q9(x) ) / x = sum((-1)^i*x^(2*i)/(2*i+1), i = (5 .. infinity)) # so abs ( (arctan(x) -Q9(x) )/x ) <= x^10 * sum((-1)^(i+1)*x^(2*i)/(2*i+1+10), i = (0 .. infinity)) # <= x^10 * 1/11 # <= 2^(-66) if x<2^(-6.3) #Conputation of the RN constant #Epsilon = relative error #Delta = absolute error #1st : Error about reduction: EpsilonXminusBi := 2^(-105): # 1 + x*b[i] : Epsilon1A22xbi := 2^(-104): # Xred = (x-b[i]) / ( 1 + x*b[i] ) EpsilonXred := EpsilonXminusBi+Epsilon1A22xbi + 2^(-105): DeltaXred := EpsilonXred * e: log2(EpsilonXred); #Polynomial evaluation : #atan ~= x - x^3/3 + x^5/5 - x^7/7 + x^9/9 # ~= x * ( 1 + Q(x^2) ) # = (xhi+xlo) * ( 1 + Q) # ~= xhi + (xhi*Q + xlo) # Warning : the approx about x !! #calc of Q: EpsilonXred2 := (1+2^(-53) + 2^(-105) )^2 * (1+2^(-53)) -1 : log2(EpsilonXred2); errlist:=errlist_quickphase_horner( degree( x^4 ),0,0,EpsilonXred2, 2**(-53)): rounding_error1:= compute_horner_rounding_error(Qprime,x,e,errlist,true): EpsilonQ := rounding_error1[1]: log2(EpsilonQ); # Since q will be multiplied in x(1+q), its absolute error term is : Qmax:=infnorm(Qprime,x=-e^2..e^2): DeltaQ := e*Qmax*EpsilonQ; log2(DeltaQ); # calc of xi*Q + xlo + atan(b[i])lo #First the truncation of xredlo*q : at most half an ulp of xredhi*q DeltaTruncXredloQ := 2^(-53) * e * Qmax: log2(DeltaTruncXredloQ); #then the sum of atanbilo and xredlo : the largest term is atanbilo DeltaAdd1 := 0.5*ulp(2^(-53)*(Pi/2 + e)): log2(DeltaAdd1); #then compute xredhi*q DeltaXredhiQ := 0.5*ulp(e*Qmax): log2(DeltaXredhiQ); # and the second addition DeltaAdd2 := 0.5*ulp(e*Qmax + 2^(-53)*(Pi/2 + e) ): log2(DeltaAdd2); DeltaAtanlolo := DeltaTruncXredloQ + DeltaAdd1 + DeltaXredhiQ + DeltaAdd2: log2(DeltaAtanlolo); # In the second reconstruction there is one more FP add which is # aligned to the previous: DeltaReconst := DeltaAtanlolo + DeltaAdd2 : log2(DeltaReconst); # error due to the approx of atan by P : < e^11/11 Deltaapprox := infnorm( (arctan(x)-x*(1+Q)), x=0..e): log[2](Deltaapprox); DeltaTotal := Deltaapprox + DeltaQ + DeltaReconst : log2(DeltaTotal); EpsilonTotal := evalf( DeltaTotal / arctan(xx) ): EpsilonFinal := infnorm( EpsilonTotal,xx=2^(-6.3)..1,'xmaxmax'): EpsilonFinal_i_10 := infnorm( EpsilonTotal,xx=a[10]..2^60,'xmaxmax'): log2( EpsilonFinal ); log2( EpsilonFinal_i_10 ); # Computation of e and e_i_30 (which is e when i>30 (ie x>1) E := evalf(compute_rn_constant(EpsilonFinal)); E_i_10 := evalf(compute_rn_constant(EpsilonFinal_i_10)); #An other Constant : when there is no reduction. #We compute the polynom and then atan(x) = x + x.Q Epsilonx2 := 2^(-53): errlist:=errlist_quickphase_horner( degree( Qprime ),0,0,Epsilonx2, 2**(-53)): rounding_error:= compute_horner_rounding_error(Qprime,x,e,errlist,true): epsilon_Q := rounding_error[1]: log[2](epsilon_Q); epsilon_x_Q := 2^(-52): delta_final := 2^(-105)*x + epsilon_Q*x^3 + epsilon_x_Q*x^3 - arctan(x) + x*(1+Q): epsilon_final := infnorm(delta_final/x,x=2^(-10)..e): epsilon_final_m10 := infnorm(delta_final/x,x=2^(-24)..2^(-10)): log[2](epsilon_final); E_no_reduction := evalf(compute_rn_constant(epsilon_final)); E_no_reduction_m10 := evalf(compute_rn_constant(epsilon_final_m10)); # Output #test filename:="TEMPATAN/atan_fast.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "\n/*File generated by maple/atan.mpl */\n"): fprintf(fd, "#ifndef _ATAN_FAST_H\n#define _ATAN_FAST_H\n\n"); fprintf(fd, "#include \"crlibm.h\"\n#include \"crlibm_private.h\"\n"): fprintf(fd,"#ifdef WORDS_BIGENDIAN\n"): fprintf(fd, "static const db_number HALFPI = {{0x3FF921FB,0x54442D18}};"): fprintf(fd, "static const db_number HALFPI_TO_PLUS_INFINITY = {{0x3FF921FB,0x54442D19}};"): fprintf(fd,"\n#else\n"): fprintf(fd, "static const db_number HALFPI = {{0x54442D18,0x3FF921FB}};"): fprintf(fd, "static const db_number HALFPI_TO_PLUS_INFINITY = {{0x54442D19,0x3FF921FB}};"): fprintf(fd,"\n"): fprintf(fd,"#endif\n"): fprintf(fd, "#define MIN_REDUCTION_NEEDED %1.50f\n",e): fprintf(fd, "#define INVPIH %1.50f\n", invpih): fprintf(fd, "#define INVPIL %1.50f\n", invpil): fprintf(fd,"#define nb_of_ai %d\n",nb_of_ai): fprintf(fd,"#define nb_of_bi %d\n",nb_of_bi): # we multiply by 2^(-20) in order to prevent from rounding fprintf(fd, "static const double rncst[4] ={\n"): fprintf(fd, "%1.50f , /* i<10 */ \n",E*(1+2^(-20))) : fprintf(fd, "%1.50f , /* i>10 */ \n",E_i_10*(1+2^(-20))) : fprintf(fd, "%1.50f , /* e > 2^-10 */ \n",E_no_reduction*(1+2^(-20))) : fprintf(fd, "%1.50f , /* e < 2^-10 */ \n };\n",E_no_reduction_m10*(1+2^(-20))) : fprintf(fd, "static const double epsilon[4] ={\n"): fprintf(fd, "%1.50e ,\n",EpsilonFinal *(1+2^(-20))) : fprintf(fd, "%1.50e ,\n",EpsilonFinal_i_10*(1+2^(-20))) : fprintf(fd, "%1.50e ,\n",epsilon_final*(1+2^(-20))) : fprintf(fd, "%1.50e ,\n };\n",epsilon_final_m10*(1+2^(-20))) : fprintf(fd, "#define DEGREE %d\n", deg_poly): fprintf(fd, "static double const coef_poly[%d] = \n{\n",deg_poly): for i from deg_poly-1 to 0 by -1 do fprintf(fd, "/* coef for degree %d */ %1.50f, \n" , 2*i+3, coef_poly[i]): od: fprintf(fd," }; \n"); fprintf(fd,"#define A 0\n"): fprintf(fd,"#define B 1\n"): fprintf(fd,"#define ATAN_BHI 2\n"): fprintf(fd,"#define ATAN_BLO 3\n"): fprintf(fd,"\n#ifdef WORDS_BIGENDIAN\n "): for isbig from 1 to 0 by -1 do if(isbig=0) then fprintf(fd,"#else\n"); fi: if(not (nb_of_ai = nb_of_bi)) then printf("Warning : nb_of_ai != nb_of_bi, this should not work"); fi: fprintf(fd,"\n/* limits of the intervals [a[i],b[i]] */\n"); fprintf(fd, "static db_number const arctan_table[%d][4] = \n{\n" , nb_of_ai ); for i from 0 to nb_of_ai - 1 do fprintf(fd, "{\n/*a[%d] */ ",i); printendian(fd,a[i],isbig); fprintf(fd," ,\n/*b[%d] : */ ",i): printendian(fd,b[i],isbig): fprintf(fd," ,\n/*atan_b[%d]*/ ",i): printendian(fd, arctan(b[i]) ,isbig): fprintf(fd,","); printendian(fd, arctan(b[i])-nearest(arctan(b[i])) ,isbig); fprintf(fd," ,\n}\n,"); od; fprintf(fd,"\n};\n"); od: fprintf(fd,"\n#endif\n\n"): fprintf(fd, "#endif /* def _ATAN_FAST_H */\n"); fclose(fd); # Scs phase #Now we want a precision of 130 bits in order to have correct rounding in all cases. evalf(log[2](e^21/21)); #Test about Rounding : #error on the polynom : P_scs := convert(series(arctan(x),x=0,21),polynom); evalf(log[2](e^21/21)); #Intervals parameters #We choose the same e and the same intervals as in the quick phase. #We have the same b[i]s and a[i]s but we save atan[b[i]] on 4 doubles # Output filename:="TEMPATAN/atan_accurate.h": fd1:=fopen(filename, WRITE, TEXT): fprintf(fd1, "#include \"crlibm.h\"\n#include \"crlibm_private.h\" \n#include \"atan_fast.h\"\n"): fprintf(fd1, "\n/*File generated by maple/atan.mpl */\n"): Write_SCS_poly(fd1, "constant_poly", P_scs); fprintf(fd1,"#define constant_poly_ptr (scs_ptr)&constant_poly\n"); # The 1/Pi SCS constant fprintf(fd, "static const scs InvPiSCS=\n"): WriteSCS(fd, evalf(1/Pi)): fprintf(fd, ";\n#define InvPiSCS_ptr (scs_ptr)(& InvPiSCS)\n\n"): fprintf(fd1,"#ifdef WORDS_BIGENDIAN\n\n"): for isbig from 1 to 0 by -1 do if isbig = 0 then fprintf(fd1, "\n#else\n"): fi: fprintf(fd1,"static const db_number atan_blolo[%d] = {\n",nb_of_ai); for i from 0 to nb_of_ai-1 do fprintf(fd1,"/* %d */ ",i): temp0 := nearest(arctan(b[i])); temp := nearest( arctan(b[i]) - nearest(arctan(b[i]))); temp1 := nearest( arctan(b[i]) - temp -temp0); printendian(fd1,temp1,isbig): fprintf(fd1,", \n"); od: fprintf(fd1,"};\n"): od: fprintf(fd1,"\n#endif /* WORDS_BIGENDIAN */ \n"); fclose(fd1); interval-3.2.0/src/crlibm/maple/check-hints-log-td.sh0000755000000000000000000001043213316017127020547 0ustar 00000000000000#!/bin/sh # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # This will only function if you have a modified version of the gappa tool # # You probably need to edit the path to the gappa executable GAPPA=~/ble/gappa-0.4.5/src/gappa cat log-td.gappa | grep "#MAPLE" | sed -e s/=/:=/ -e "s/;/:/" > log-td.gappa.autocheck.mpl echo "printf(\"You should see only zeros in what follows:\\n\");" >> log-td.gappa.autocheck.mpl sed -f ./TEMPLOG/log-td_1.sed log-td.gappa | $GAPPA 2>&1 | grep simplify >> log-td.gappa.autocheck.mpl echo "printf(\"If you have seen only zeros up to now, everything's fine \\n\");" >> log-td.gappa.autocheck.mpl cat log-td-E0.gappa | grep "#MAPLE" | sed -e s/=/:=/ -e "s/;/:/" > log-td-E0.gappa.autocheck.mpl echo "printf(\"You should see only zeros in what follows:\\n\");" >> log-td-E0.gappa.autocheck.mpl sed -f ./TEMPLOG/log-td_1.sed log-td-E0.gappa | $GAPPA 2>&1 | grep simplify >> log-td-E0.gappa.autocheck.mpl echo "printf(\"If you have seen only zeros up to now, everything's fine \\n\");" >> log-td-E0.gappa.autocheck.mpl cat log-td-E0-logir0.gappa | grep "#MAPLE" | sed -e s/=/:=/ -e "s/;/:/" > log-td-E0-logir0.gappa.autocheck.mpl echo "printf(\"You should see only zeros in what follows:\\n\");" >> log-td-E0-logir0.gappa.autocheck.mpl sed -f ./TEMPLOG/log-td_1.sed log-td-E0-logir0.gappa | $GAPPA 2>&1 | grep simplify >> log-td-E0-logir0.gappa.autocheck.mpl echo "printf(\"If you have seen only zeros up to now, everything's fine \\n\");" >> log-td-E0-logir0.gappa.autocheck.mpl cat log-td-accurate.gappa | grep "#MAPLE" | sed -e s/=/:=/ -e "s/;/:/" > log-td-accurate.gappa.autocheck.mpl echo "printf(\"You should see only zeros in what follows:\\n\");" >> log-td-accurate.gappa.autocheck.mpl sed -f ./TEMPLOG/log-td-accurate_1.sed log-td-accurate.gappa | $GAPPA 2>&1 | grep simplify >> log-td-accurate.gappa.autocheck.mpl echo "printf(\"If you have seen only zeros up to now, everything's fine \\n\");" >> log-td-accurate.gappa.autocheck.mpl cat log-td-accurate-E0.gappa | grep "#MAPLE" | sed -e s/=/:=/ -e "s/;/:/" > log-td-accurate-E0.gappa.autocheck.mpl echo "printf(\"You should see only zeros in what follows:\\n\");" >> log-td-accurate-E0.gappa.autocheck.mpl sed -f ./TEMPLOG/log-td-accurate_1.sed log-td-accurate-E0.gappa | $GAPPA 2>&1 | grep simplify >> log-td-accurate-E0.gappa.autocheck.mpl echo "printf(\"If you have seen only zeros up to now, everything's fine \\n\");" >> log-td-accurate-E0.gappa.autocheck.mpl cat log-td-accurate-E0-logir0.gappa | grep "#MAPLE" | sed -e s/=/:=/ -e "s/;/:/" > log-td-accurate-E0-logir0.gappa.autocheck.mpl echo "printf(\"You should see only zeros in what follows:\\n\");" >> log-td-accurate-E0-logir0.gappa.autocheck.mpl sed -f ./TEMPLOG/log-td-accurate_1.sed log-td-accurate-E0-logir0.gappa | $GAPPA 2>&1 | grep simplify >> log-td-accurate-E0-logir0.gappa.autocheck.mpl echo "printf(\"If you have seen only zeros up to now, everything's fine \\n\");" >> log-td-accurate-E0-logir0.gappa.autocheck.mpl echo "read \"log-td.gappa.autocheck.mpl\";" | maple echo "read \"log-td-E0.gappa.autocheck.mpl\";" | maple echo "read \"log-td-E0-logir0.gappa.autocheck.mpl\";" | maple echo "read \"log-td-accurate.gappa.autocheck.mpl\";" | maple echo "read \"log-td-accurate-E0.gappa.autocheck.mpl\";" | maple echo "read \"log-td-accurate-E0-logir0.gappa.autocheck.mpl\";" | maple interval-3.2.0/src/crlibm/maple/common-procedures.mpl0000644000000000000000000010033413316017127021000 0ustar 00000000000000 ##################################################################### # Useful procedures for IEEE doubles # # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #--------------------------------------------------------------------- log2:=proc(x) evalf( log[2](x)) end proc: #--------------------------------------------------------------------- # ieeedouble converts a number to IEEE double format. # returns sign (-1 or 1), exponent between -1022 and 1023, mantissa as a fraction between 0.5 and 1. ieeedouble:=proc(xx) local x, sgn, logabsx, exponent, mantissa, infmantissa,powermin,powermax,expmin,expmax,expmiddle,powermiddle; Digits := 100; x := evalf(xx); if (x=0) then sgn, exponent, mantissa := 1, -1022, 0 else if (x < 0) then sgn := -1 else sgn := 1 fi: x := abs(x); if x >= 2^(1023)*(2-2^(-53)) then mantissa := infinity; exponent := 1023 else if x <= 2^(-1075) then mantissa := 0; exponent := -1022 else if x <= 2^(-1022) then exponent := -1022 else # x is between 2^(-1022) and 2^(1024) powermin := 2^(-1022); expmin := -1022; powermax := 2^1024; expmax := 1024; while (expmax-expmin > 1) do expmiddle := round((expmax+expmin)/2); powermiddle := 2^expmiddle; if x >= powermiddle then powermin := powermiddle; expmin := expmiddle else powermax := powermiddle; expmax := expmiddle fi od; # now, expmax - expmin = 1 and powermin <= x < powermax, # powermin = 2^expmin and powermax = 2^expmax, so expmin is the exponent of x exponent := expmin; fi; infmantissa := x*2^(52-exponent); if frac(infmantissa) <> 0.5 then mantissa := round(infmantissa) else mantissa := floor(infmantissa); if type(mantissa,odd) then mantissa := mantissa+1 fi fi; mantissa := mantissa*2^(-52); fi; fi; fi; sgn,exponent,mantissa; end: #--------------------------------------------------------------------- # ieeedoubleRU converts a number to IEEE double format rounding upwards. # returns sign (-1 or 1), exponent between -1022 and 1023, mantissa as a fraction between 0.5 and 1. ieeedoubleRU:=proc(xx) local x, sgn, logabsx, exponent, mantissa, infmantissa,powermin,powermax,expmin,expmax,expmiddle,powermiddle; Digits := 100; x := evalf(xx); if (x=0) then sgn, exponent, mantissa := 1, -1022, 0 else if (x < 0) then sgn := -1 else sgn := 1 fi: x := abs(x); if x >= 2^(1023)*(2-2^(-53)) then mantissa := infinity; exponent := 1023 else if x <= 2^(-1075) then mantissa := 0; exponent := -1022 else if x <= 2^(-1022) then exponent := -1022 else # x is between 2^(-1022) and 2^(1024) powermin := 2^(-1022); expmin := -1022; powermax := 2^1024; expmax := 1024; while (expmax-expmin > 1) do expmiddle := round((expmax+expmin)/2); powermiddle := 2^expmiddle; if x >= powermiddle then powermin := powermiddle; expmin := expmiddle else powermax := powermiddle; expmax := expmiddle fi od; # now, expmax - expmin = 1 and powermin <= x < powermax, # powermin = 2^expmin and powermax = 2^expmax, so expmin is the exponent of x exponent := expmin; fi; infmantissa := x*2^(52-exponent); if frac(infmantissa) <> 0 then if (sgn > 0) then mantissa := ceil(infmantissa); else mantissa := floor(infmantissa); fi; else mantissa := infmantissa; fi; mantissa := mantissa*2^(-52); fi; fi; fi; sgn,exponent,mantissa; end: #--------------------------------------------------------------------- # ieeedoubleRD converts a number to IEEE double format rounding downwards. # returns sign (-1 or 1), exponent between -1022 and 1023, mantissa as a fraction between 0.5 and 1. ieeedoubleRD:=proc(xx) local x, sgn, logabsx, exponent, mantissa, infmantissa,powermin,powermax,expmin,expmax,expmiddle,powermiddle; Digits := 100; x := evalf(xx); if (x=0) then sgn, exponent, mantissa := 1, -1022, 0 else if (x < 0) then sgn := -1 else sgn := 1 fi: x := abs(x); if x >= 2^(1023)*(2-2^(-53)) then mantissa := infinity; exponent := 1023 else if x <= 2^(-1075) then mantissa := 0; exponent := -1022 else if x <= 2^(-1022) then exponent := -1022 else # x is between 2^(-1022) and 2^(1024) powermin := 2^(-1022); expmin := -1022; powermax := 2^1024; expmax := 1024; while (expmax-expmin > 1) do expmiddle := round((expmax+expmin)/2); powermiddle := 2^expmiddle; if x >= powermiddle then powermin := powermiddle; expmin := expmiddle else powermax := powermiddle; expmax := expmiddle fi od; # now, expmax - expmin = 1 and powermin <= x < powermax, # powermin = 2^expmin and powermax = 2^expmax, so expmin is the exponent of x exponent := expmin; fi; infmantissa := x*2^(52-exponent); if frac(infmantissa) <> 0 then if (sgn < 0) then mantissa := ceil(infmantissa); else mantissa := floor(infmantissa); fi; else mantissa := infmantissa; fi; mantissa := mantissa*2^(-52); fi; fi; fi; sgn,exponent,mantissa; end: #--------------------------------------------------------------------- # pulp returns the precision of the ulp of x pulp:=proc(x) local flt, ulpy: flt:=ieeedouble(x): ulpy:=-52+flt[2]: end proc: #--------------------------------------------------------------------- # ulp returns the absolute value of the ulp of x ulp:=proc(x) 2**(pulp(x)): end proc: #--------------------------------------------------------------------- # Returns nearest IEEE double: nearest := proc(x) local sgn, exponent, mantissa: sgn,exponent,mantissa := ieeedouble(x): sgn*mantissa*2^(exponent): end: #--------------------------------------------------------------------- # Returns RU IEEE double: roundUp := proc(x) local sgn, exponent, mantissa: sgn,exponent,mantissa := ieeedoubleRU(x): sgn*mantissa*2^(exponent): end: #--------------------------------------------------------------------- # Returns RD IEEE double: roundDown := proc(x) local sgn, exponent, mantissa: sgn,exponent,mantissa := ieeedoubleRD(x): sgn*mantissa*2^(exponent): end: #--------------------------------------------------------------------- # Returns RZ IEEE double: roundToZero := proc(x) if evalf(x) > 0 then roundDown(x) else roundUp(x) fi: end: #--------------------------------------------------------------------- # ieehexa returns a string containing the hexadecimal representation of the double nearest to input x. ieeehexa:= proc(x) local hex2, xx, longint, expo, sgn, frac, resultat: if(x=0) then resultat:=["00000000","00000000"]: elif(x=-0) then resultat:=["80000000","00000000"]: # nice try else xx:=ieeedouble(x): sgn:=xx[1]: expo:=xx[2]: frac:=xx[3]: if (expo = -1023) then longint := (frac)*2^51 : # subnormal else longint := (frac-1)*2^52 + (expo+1023)*2^52: fi: if (sgn=-1) then longint := longint + 2^63: fi: longint := longint + 2^64: # to get all the hexadecimal digits when we'll convert to string hex2:=convert(longint, hex): hex2:=convert(hex2, string): resultat:=[substring(hex2,2..9), substring(hex2,10..18)]: fi: resultat: end proc: ieeehexaString := proc(x) local hex, result: hex := ieeehexa(x): result := cat(hex[1],hex[2]): return result: end proc: #--------------------------------------------------------------------- # reciprocal of the previous hexa2ieee:= proc(hexa) local dec, bin, expo, mantis, sgn, hex1, hex2, hexcat, res: hex1:= op(1, hexa): hex2:= op(2, hexa): hexcat:= cat(hex1, hex2): dec:= convert(hexcat, decimal, hex): if(dec >= 2^63) then dec := dec - 2^63: sgn:= -1: else sgn:= 1: fi: expo:= trunc(dec/(2^52)) - 1023: if(expo=-1023) then mantis:= frac(dec/(2^51)): # denormal else mantis:= 1+frac(dec/(2^52)): fi: res:= evalf(sgn*2^(expo)*mantis): res: end proc: #--------------------------------------------------------------------- # Print a number x in Low or Big Endian representation in opened file "fd": printendian:=proc(fd,x,isbig) local xhl: xhl:=ieeehexa(x): if(isbig=0 or isbig=1) then fprintf(fd,"{{0x%+0.8s,0x%+0.8s}} /* %+0.10e */", xhl[2-isbig], xhl[isbig+1], x): else print("ERROR, isbig must be equal to 0 or 1"): end if: end proc: #--------------------------------------------------------------------- # hi_lo takes an arbitrary precision number x and returns two doubles such that: # x ~ x_hi + x_lo hi_lo:= proc(x) local x_hi, x_lo, res: x_hi:= nearest(evalf(x)): res:=x-x_hi: if (res = 0) then x_lo:=0: else x_lo:=nearest(evalf(res)): end if: x_hi,x_lo: end: #--------------------------------------------------------------------- # same as hi_lo, but returns hexadecimal strings ieeehexa2:=proc(x) local reshi, reslo, hexhi, hexlo: reshi:=nearest(x): hexhi:=ieee2hexa(reshi): reslo:= nearest(x-reshi): hexlo:=ieee2hexa(reslo): reshi, reslo: end proc: #--------------------------------------------------------------------- # Computes the constant for the round-to-nearest test. # epsilon is the overall relative error of the approximation scheme # See the documentation for the explanation of these formulae compute_rn_constant := proc(epsilon) local k, constGenCase, constPowerOf2: k := trunc(-log[2](epsilon)) - 53: (1 + 2**54*epsilon / (1 - epsilon - 2**(-k+1) ) ) / (1-2**(-53)) end proc: #--------------------------------------------------------------------- # Takes a real number, and prints the bits after the 53th of its nearest IEEE floating-point number showHowDifficultToRound:=proc(x) local xb,xs,s,e,m: Digits:=200: s,e,m := ieeedouble(x): xb:=convert(evalf(x*2^(-e)),binary): xs:=convert(xb, string): substring(xs,55..153) end proc: #--------------------------------------------------------------------- # Computes the floating point successor of x succDouble:=proc(x) local s,he,hexcat,hehi,helo,castx,shex,neg; he := ieeehexa(x); hehi:= op(1, he); helo:= op(2, he); hexcat := cat(hehi, helo); neg := 1; castx := convert(hexcat, decimal, hex); if (castx >= 2^(63)) then castx := castx - 2^(63); neg := -1; end if; castx := castx + neg; shex := convert(convert(castx, hex),string); s := neg * hexa2ieee([substring(shex,1..8), substring(shex,9..16)]); s; end proc: ##################################################################### # Stuff about truncated polynomials # Truncate a polynomial #--------------------------------------------------------------------- #poly_exact takes a polynomial in x with arbitrary precision # coefficients, and returns a truncated polynomial where coefficients # are IEEE doubles. poly_exact:=proc(P) local deg,i, coef, coef_t, Q: Q:= 0: convert(Q, polynom): deg:=degree(P,x): for i from 0 to deg do coef:=coeff(P,x,i): coef_t:=nearest(coef): Q:= Q + coef_t*x^i: od: return(Q): end: #--------------------------------------------------------------------- #Like poly_exact, but the n first coefficients are exactly # representable as the sum of two doubles. (to actually get the two # doubles, use procedure hi_lo) poly_exact2:=proc(P,n) local deg,i, coef, coef_hi, coef_lo, Q: Q:= 0: convert(Q, polynom): deg:=degree(P,x): for i from 0 to deg do coef :=coeff(P,x,i): coef_hi, coef_lo:=hi_lo(coef): Q:= Q + coef_hi*x^i: if(i|x*Si|. It prints warnings if it not the case. compute_abs_rounding_error:=proc(poly,xmax, nn) local n, deg, delta, deltap, i, S, P, Snorm, Smin, Smax, prec: deltap:=0: delta:=0: deg:=degree(poly): prec:=53: # precision of the first iterations S:=coeff(poly, x, deg): Smax:=abs(S): Smin:=Smax: if nn<0 then n:=0: else n:=nn: fi:# sometimes called by compute_rel_rounding_error with n=-1 for i from (deg-1) to 0 by -1 do P:= convert(S*x, polynom): Smin := abs(coeff(poly,x,i)) - xmax*Smax : if(Smin<=0) then printf("Warning! in compute_abs_rounding_error, Smin<=0 at iteration %d, consider decreasing xmax\n",i): fi: delta:= evalf(xmax*deltap + 2**(-prec)*xmax*Smax): if i0) then p:=100: else p:=53: fi: if coeff(poly,x, 0) = 0 then deltap, Smin, Smax := compute_abs_rounding_error(poly/x,xmax, n-1): rho := (2^(-p)*(Smax+deltap) +deltap ) / Smin : else deltap, Smin, Smax := compute_abs_rounding_error(poly,xmax, n): rho := deltap / Smin: fi: rho: end proc: #--------------------------------------------------------------------- # OBSOLETE use compute_horner_rounding_error below # Computes the accumulated rounding error during the polynomial evaluation. # P is the polynomial. # xmax is the max value of |x|. # n is the degree when P is computed in double double. The first double-double operation is a multiplication (probably less useful). # returns max absolute error, min of the function, max of the function. # This procedure also checks on the fly that the fast (test-free) versions of the double-double addition can be used, i.e. that for all x, at each Horner step i computing ci+x*Si, we have |ci|>|x*Si|. It prints warnings if it not the case. compute_abs_rounding_error_firstmult:=proc(poly,xmax, nn) local n, deg, delta, deltap, i, S, P, Snorm, Smin, Smax, prec: deltap:=0: delta:=0: deg:=degree(poly): prec:=53: # precision of the first iterations S:=coeff(poly, x, deg): Smax:=abs(S): Smin:=Smax: if nn<0 then n:=0: else n:=nn: fi:# sometimes called by compute_rel_rounding_error with n=-1 for i from (deg-1) to 0 by -1 do if i=n-1 then prec:=100: fi: # from the mult of the n-1-th iteration P:= convert(S*x, polynom): Smin := abs(coeff(poly,x,i)) - xmax*Smax : if(Smin<=0) then printf("Warning! in compute_abs_rounding_error, Smin<=0 at iteration %d, consider decreasing xmax\n",i): fi: delta:= evalf(xmax*deltap + 2**(-prec)*xmax*Smax): if i0) then p:=100: else p:=53: fi: if coeff(poly,x, 0) = 0 then deltap, Smin, Smax := compute_abs_rounding_error_firstmult(poly/x,xmax, n-1): rho := (2^(-p)*(Smax+deltap) +deltap ) / Smin : else deltap, Smin, Smax := compute_abs_rounding_error_firstmult(poly,xmax, n): rho := deltap / Smin: fi: rho: end proc: # Compute a good truncated polynomial approximation for a function # Computes an approximation to a function of x f, as a truncated polynomial of deegree deg with the n first coefficients exactly representable as double-double. # The function f(x) must have as input interval xmin..xmax # returns [ truncated polynomial, relative approx error of trunc. poly. , infinite precision polynomial, rel. error of inf. prec. poly ] poly_trunc_classic:=proc(f,deg,xmin,xmax,n) local pe, repe, pt, ppe, rept, maxpt: pe:=numapprox[minimax]( f, x=xmin..xmax, [deg,0], 1, 'err'): pt := poly_exact2(pe,n): rept := numapprox[infnorm]( 1-pt/f, x=xmin..xmax) : maxpt := numapprox[infnorm]( pt, x=xmin..xmax) : pt,rept, maxpt: end proc: #--------------------------------------------------------------------- # Computes a truncated polynomial of degree deg with the two first coefficients stored as double-doubles. # The function f(x) must have as input interval xmin..xmax # returns [ truncated polynomial, relative error of trunc. poly. , infinite precision polynomial, rel. error of inf. prec. poly ] poly_trunc_f2d_2:=proc(f,deg,xmin,xmax) local pe, repe, pt, c0, c1, c2, ppe, abserr, relerr, maxpt, err: pe:=numapprox[minimax]( f, x=xmin..xmax, [deg,0], 1, 'err'): pt := poly_exact2(pe,2): c0:=coeff(pt,x,0): c1:=coeff(pt,x,1): c2:=coeff(pt,x,2): ppe:=numapprox[minimax]( (f - c0 - c1 * x - c2*x*x) , x=xmin..xmax, [deg,0], 1, 'err'): ppe:=expand(ppe) - coeff(ppe,x,0) - coeff(ppe,x,1)*x- coeff(ppe,x,2)*x*x: pt := poly_exact2(ppe,2) + c0 + c1*x + c2*x*x: abserr := numapprox[infnorm]( pt-f, x=xmin..xmax) : relerr := numapprox[infnorm]( 1-pt/f, x=xmin..xmax) : maxpt := numapprox[infnorm]( pt, x=xmin..xmax) : pt,abserr,relerr,maxpt: end proc: #--------------------------------------------------------------------- # Computes a truncated polynomial of degree deg with the first coefficient stored as double-double. # The function f(x) must have as input interval xmin..xmax # returns [ truncated polynomial, relative error of trunc. poly. , infinite precision polynomial, rel. error of inf. prec. poly ] poly_trunc_f2d_1:=proc(f,deg,xmin,xmax) local pe, repe, pt, c0, c1, ppe, relerr, abserr, maxpt, err: pe:=numapprox[minimax]( f , x=xmin..xmax, [deg,0], 1, 'err'): pt := poly_exact2(pe,1): c0:=coeff(pt,x,0): c1:=coeff(pt,x,1): ppe:=numapprox[minimax]( (f - c0 - c1 * x) , x=xmin..xmax, [deg,0], 1, 'err'): ppe:=ppe - coeff(ppe,x,0) - coeff(ppe,x,1)*x: pt := poly_exact2(ppe,1) + c0 + c1*x: abserr := numapprox[infnorm]( pt-f, x=xmin..xmax) : relerr := numapprox[infnorm]( 1-pt/f, x=xmin..xmax) : maxpt := numapprox[infnorm]( pt, x=xmin..xmax) : pt,abserr,relerr,maxpt: end proc: #--------------------------------------------------------------------- # compute_horner_rounding_error # Computes a bound on the accumulated rounding error caused by the Horner evaluation of a truncated polynomial # It is designed to allow evaluating the error for various schemes: # - with or without an error on x # - using SCS operators # - using double and double-double operators. # Arguments: # P is the polynomial. # xmax is the max value of |x|. # errors is a list of size n where n is the degree of the polynomial. # Each element of this list is a triple (epsx,epsmul,epsadd) where # epsx is the relative error on x at each step, # epsadd is the max relative error on the addition # epsmul is the max relative error on the multiplication. # This allows to handle SCS Horner, as well as evaluation starting in double and ending in double-double. # check_dd is a flag, if set to 1 the procedure also checks on the fly that the fast (test-free) versions # of the double-double addition can be used, i.e. that for all x, at each Horner step i computing ci+x*Si, # we have |ci|>|x*Si|. It prints warnings if it not the case. # returns (epsprimek, deltak, minP, maxP) where (see the doc) # epsprimek is the max rel error of the last multiplication (useful if the coeff of degree 0 is 0) # deltak is the max absolute error of the last addition (useful if the reconstruction adds something to result of the polynomial) # minP min of the evaluated polynomial (useful to compute a relative error out of deltak) # maxP max of the evaluated polynomial. compute_horner_rounding_error:=proc(poly, x, xmax, errors, check_dd) local deg, Sk, maxSk, minSk, epsaddk, epsmulk, deltaaddk, k, ck, epsx, epsmul, epsadd, deltaadd, Pk, maxPk: if assigned(x) then printf("Error in compute_horner_rounding_error, polynomial variable is assigned\n"): return 'procname(args)': fi: deg:=degree(poly,x): if(deg<0) then printf("ERROR: negative degree in compute_abs_rounding_error"): return 'procname(args)': fi: Sk:=coeff(poly, x, deg): maxSk:=abs(Sk): minSk:=maxSk: epsmulk:=0: deltaaddk:=0: epsaddk:=0: for k from (deg) to 1 by -1 do # the errors to consider for this step epsx := errors[k][1]: epsadd := errors[k][2]: epsmul := errors[k][3]: # multiplication operation Pk:= convert(Sk*x, polynom): maxPk:=numapprox[infnorm](Pk, x=-xmax..xmax): ck:=coeff(poly,x,k-1): epsmulk:=evalf( (1+epsx)*(1+epsaddk)*(1+epsmul)-1 + 10^(-Digits+2) ): #addition if(ck=0) then Sk:=Pk: maxSk := maxPk: minSk:=0: deltaaddk:= evalf(epsmulk*maxPk): epsaddk:=epsmulk: else Sk:=convert(Pk+ck , polynom): maxSk:=numapprox[infnorm](Sk, x=-xmax..xmax): minSk:=minimize(abs(Sk), x=-xmax..xmax): if(epsadd=2^(-53)) then # compute deltadd exactly as the max half ulp of the result deltaadd := 0.5*ulp(maxSk+epsmulk*maxSk): else # compute deltaadd out of the relative error deltaadd := epsadd * (maxSk+epsmulk*maxSk): fi: deltaaddk := evalf( epsmulk*maxPk + deltaadd + 10^(-Digits+2) ): epsaddk := deltaaddk/minSk + 10^(-Digits+2) : # warnings if (minSk=0) then printf("Warning! in compute_abs_rounding_error, minSk=0 at iteration %d, consider decreasing xmax\n",k): fi: fi: printf("step %d epsmulk=%1.4e deltaaddk=%1.4e minSk=%1.4e maxSk=%1.4e\n", k, epsmulk, deltaaddk, minSk, maxSk): # if (epsadd=2**(-103)) then # # fast Add22 ? # if abs(coeff(poly,x,k)) < xmax*maxSk # may be improved to xmax*Smax/2 # then printf("WARNING Add22 cannot be used at step %d, use Add22Cond\n" , k ): # printf(" coeff=%1.20e, xmax*Smax=%1.20e" , abs(coeff(poly,x,i)), xmax*maxSk ): # fi: # fi: od: return (epsmulk, deltaaddk, minSk, maxSk) end proc: #--------------------------------------------------------------------- # An helper function to build an errlist for the previous procedure. # Arguments: # n is the degree of the polynomial, # ddadd, ddmul number of (final) double-double operations # depsx error on x in the double steps # ddepsx error on x in the double-double steps (when x is represented by a double-double) errlist_quickphase_horner := proc(n,ddadd, ddmul,depsx, ddepsx) local nddadd, epsadd, nddmul, epsmul, epsx: if n=0 then [] else if ddadd>0 then nddadd:=ddadd-1: epsadd:=2**(-103): else nddadd:=ddadd: epsadd:=2**(-53): fi: if ddmul>0 then nddmul:=ddmul-1: epsmul:=2**(-102): epsx:=ddepsx: else nddmul:=ddmul: epsmul:=2**(-53): epsx:=depsx: fi: [ [epsx,epsadd,epsmul] , op(errlist_quickphase_horner(n-1, nddadd, nddmul, depsx,ddepsx))] fi: end proc: #--------------------------------------------------------------------- # Finding the worst cases for additive range reduction # cut and paste from the web page of Muller's book # Much faster if called with Digits very large and an evalf() on C # but then check WorstCaseForAdditiveRangeReduction:=proc(B,n,emin,emax,C) local epsilonmin,powerofBoverC,e,a,Plast,r,Qlast, Q,P,NewQ,NewP,epsilon, numbermin,expmin,l: epsilonmin := 12345.0 : powerofBoverC := B^(emin-n)/C: for e from emin-n+1 to emax-n+1 do powerofBoverC := B*powerofBoverC: a := floor(powerofBoverC): Plast := a: r := 1/(powerofBoverC-a): a := floor(r): Qlast := 1: Q := a: P := Plast*a+1: while Q < B^n-1 do r := 1/(r-a): a := floor(r): NewQ := Q*a+Qlast: NewP := P*a+Plast: Qlast := Q: Plast := P: Q := NewQ: P := NewP od: epsilon := evalf(C*abs(Plast-Qlast*powerofBoverC)): if epsilon < epsilonmin then epsilonmin := epsilon: numbermin := Qlast: expmin := e fi od: print('mantissa',numbermin): print('exponent',expmin): print('epsilon',epsilonmin): l := evalf(log(epsilonmin)/log(B),10): print(numberofdigits,l): (numbermin, expmin, epsilonmin) end proc: ##################################################################### # Stuff for SCS ##################################################################### # Global parameters # Don�t forget to set all the parameters here SCS_NB_WORDS := 8: SCS_NB_BITS := 30: #--------------------------------------------------------------------- # This procedure convert a decimal number into it SCS representation. # x : input number to convert into it SCS representation real_to_SCS := proc(x) local exception, index, sgn, mantissa, nb, i: if x <> 0 then exception := 1: if x > 0 then sgn := 1: nb := x: elif x < 0 then sgn := -1: nb := -x: end if: index := 0: if nb >= 1 then for i from 0 while nb > (2^(SCS_NB_BITS+1)-1) do index := index+1: nb := nb * 2^(-SCS_NB_BITS): end do: else for i from 0 while nb < 1 do index := index-1: nb := nb * 2^(SCS_NB_BITS): end do: end if: for i from 0 by 1 to (SCS_NB_WORDS-1) do mantissa[i] := trunc(nb): nb := (nb - mantissa[i]) * 2^(SCS_NB_BITS): end do: else for i from 0 by 1 to (SCS_NB_WORDS-1) do mantissa[i] := 0: end do: index := 1: exception := x: sgn := 1: end if: mantissa[SCS_NB_WORDS] := exception: mantissa[SCS_NB_WORDS+1] := index: mantissa[SCS_NB_WORDS+2] := sgn: return mantissa: end proc: #--------------------------------------------------------------------- # Convert an SCS number into a rational number SCS_to_real := proc(tab) local res, i: if (tab[SCS_NB_WORDS] <> 1) then return tab[SCS_NB_WORDS]: end if: res := 0: for i from (SCS_NB_WORDS-1) by -1 while i>=0 do res := 2^(-SCS_NB_BITS)*res + tab[i] end do: res := tab[SCS_NB_WORDS+2]*(res * 2.^(SCS_NB_BITS * tab[SCS_NB_WORDS+1])): return res: end proc: #--------------------------------------------------------------------- # This procedure truncates the coefficients of a polynomial to SCS # numbers, so that we can then evaluate its approximation error # (equivalent to poly_exact for the doubles) poly_exact_SCS:=proc(P) local deg,i, coef, coef_t, Q: Q:= 0: convert(Q, polynom): deg:=degree(P,x): for i from 0 to deg do coef:=coeff(P,x,i): coef_t:=SCS_to_real(real_to_SCS(evalf(coef))): Q:= Q + coef_t*x^i: od: return(Q): end: #--------------------------------------------------------------------- # Write Into file fd the SCSS number stored into the table tab where # tab[0..(SCS_NB_WORDS-1)] store the mantissa # tab[SCS_NB_WORDS] store the exception # tab[SCS_NB_WORDS+1] store the index # tab[SCS_NB_WORDS+2] store the sign # You probably want to use WriteSCS below ! WriteSCS_from_table := proc(fd, tab) local i: fprintf(fd,"{{"): fprintf(fd,"0x%+0.8x, ", tab[0]): for i from 1 by 1 to (SCS_NB_WORDS-2) do fprintf(fd,"0x%+0.8x, ", tab[i]): if (i mod 4 = 3) then fprintf(fd,"\n"): fi: end do: fprintf(fd,"0x%+0.8x},\n", tab[SCS_NB_WORDS-1]): if (tab[SCS_NB_WORDS]=1) then fprintf(fd,"DB_ONE, %3d, %3d ", tab[SCS_NB_WORDS+1], tab[SCS_NB_WORDS+2]): else # the only other possible value is 0 so ... fprintf(fd,"{0x00000000, 0x00000000}, %3d, %3d ", tab[SCS_NB_WORDS+1], tab[SCS_NB_WORDS+2]): end if: fprintf(fd, "} \n"): end proc: #--------------------------------------------------------------------- # Write a real number as an SCS array to a file WriteSCS := proc (fd,x) WriteSCS_from_table(fd , real_to_SCS (x)): end: #--------------------------------------------------------------------- # A procedure to count the non-zero coefficients of a polynomial (to store it) get_nb_terms := proc(poly) local i, deg_poly: deg_poly := degree(poly): for i from deg_poly by -1 while i>=0 do if coeff(poly, x, i)=0 then deg_poly := deg_poly-1: end if: end do: return deg_poly: end proc: #--------------------------------------------------------------------- # Write a polynomial to an array of SCS coefficients # fd : file where to put the result # poly : input polynom # name : name of the array Write_SCS_poly := proc(fd, name, poly) local i, deg: #fclose(fd): try finally fprintf(fd,"static const scs %s [%d]=\n", name, get_nb_terms(poly)+1): deg := degree(poly): fprintf(fd,"/* ~%1.50e */ \n{", coeff(poly, x, deg)): WriteSCS(fd, coeff(poly, x, deg)): for i from (deg-1) by (-1) while i>=0 do if (coeff(poly, x, i)<>0) then fprintf(fd,",\n/* ~%1.50e */ \n", coeff(poly, x, i)): WriteSCS(fd, coeff(poly, x, i), 0): end if: end do: fprintf(fd,"};\n"): end try: end proc: interval-3.2.0/src/crlibm/maple/csh.mpl0000644000000000000000000004365413316017127016127 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA restart: Digits := 150; with (numapprox):with(orthopoly): interface(quiet=true); read "common-procedures.mpl"; mkdir("TEMPCSH"); ####################################################################### # Some values to go to the .testdata # What is the first value that rounds to nearest to +inf ? ieeehexa(arcsinh(hexa2ieee(["7fefffff","ffffffff"]))); # What is the first value that rounds to +inf to +inf ? ###################################################################### #First, some constants variables (used in the polynomial evaluations) n_double_ch := 11: # max degree for cosh's polynomial evaluation n_double_sh := 8: # max degree for sinh's polynomial evaluation b_max := 2**(-9.): # max absolute input for polynomial evaluation ###################################################################### #some constants ... inv_ln_2 := 1/ln(2.): ln2_hi := hexa2ieee(["3FE62E42", "FEFA3800"]): ln2_lo := nearest(ln(2.)-ln2_hi): two_43_44 := 2^43 + 2^44: bias := convert(op(2,ieeehexa(ln(2.)/2.+two_43_44)),'decimal','hex'): #to get maximum index for the second range reduction ... ###################################################################### #Bounds of our evaluation max_input_ch := arccosh(hexa2ieee(["7FEFFFFF","FFFFFFFF"])): k_max_ch := ceil(max_input_ch / ln(2)): max_input_sh := arcsinh(hexa2ieee(["7FEFFFFF","FFFFFFFF"])): k_max_sh := ceil(max_input_sh / ln(2)): #towards +inf, we have cosh(x) = sinh(x) since exp(-x) is too small #so, we are sure of k_max_sh == k_max_ch k_max := k_max_ch; ###################################################################### # When can we ignore exp(-x) in front of exp(x) in the first step ? # We want the same error as in the general case k_max_csh_approx_exp := 35: tempxmax:=(k_max_csh_approx_exp-1)*log(2): eps_csh_approx_exp := exp(-tempxmax)/exp(tempxmax): log2(%); # # When can we ignore exp(-x) in front of exp(x) in the second step ? # The worst case for exp for large arguments requires 115 bits k_max_csh_approx_exp_2 := 65: tempxmax:=(k_max_csh_approx_exp_2-1)*log(2): eps_csh_approx_exp_2 := exp(-tempxmax)/exp(tempxmax): log2(%); # 118 ###################################################################### #The Taylor polynoms poly_ch :=series(cosh(x),x,n_double_ch): poly_ch := convert(poly_ch,polynom)-1; poly_sh :=series(sinh(x),x,n_double_sh): poly_sh := (convert(poly_sh,polynom))/x-1; #################################################################### # secondary functions size_of_table := convert(op(2,ieeehexa(two_43_44+ln(2.)/2.)),decimal,hex); #returns the float which follow immediately the input next_float := proc(value) local hex1,hex2,hexcat,result; hex1:= op(1, value): hex2:= op(2, value): hexcat:= cat(hex1, hex2); result := convert(convert(convert(hexcat,decimal,hex)+1+2**64,hex),string); result := [substring(result,2..9), substring(result,10..18)]; end: #compute the errors done in tabulated values for cosh delta_table_cosh_func := proc() local result, i, value, temp, tmp, maxi; value := ieeehexa(two_43_44-ln(2.)/2.); result := 0; maxi := 0; for i from -size_of_table to size_of_table do tmp := cosh(hexa2ieee(value)-two_43_44): temp := nearest(tmp): result := max(result, abs(tmp - temp - nearest(tmp-temp))); maxi := max(maxi, abs(temp + nearest(tmp-temp))); value:=next_float(value): od: result,maxi; end: #compute the error done in tabulated values for sinh delta_table_sinh_func := proc() local result, i, value, temp, tmp, maxi; value := ieeehexa(two_43_44-ln(2.)/2.); result := 0; maxi := 0; for i from -size_of_table to size_of_table do tmp := sinh(hexa2ieee(value)-two_43_44): temp := nearest(tmp): result := max(result, abs(tmp - temp - nearest(tmp-temp))); maxi := max(maxi, abs(temp + nearest(tmp-temp))); value:=next_float(value): od: result,maxi; end: #return the error on x_hi * y_lo Mul11_Error := proc(x,err_x, y, err_y) (2^(-53) * y + err_y) * (err_x + 1/2*ulp(x)) + x * err_y; end: #return the error on (x_hi * y_hi)_lo + x_lo * y_hi + x_hi * y_lo Mul43_Error := proc(x,err_x, y, err_y) 1/2*ulp(3*2^(-53)* x * y) + 1/2*ulp(2*2^(-53) * x * y) + Mul11_Error(x, err_x, y, err_y) + Mul11_Error(y, err_y, x, err_x); end: cosh_0_35 := proc() local k, delta, maxi,epsilon, mini,cosh_0_35_max, delta_cosh_0_35: epsilon := 0; delta := 0: for k from -35 to -1 do delta_cosh_0_35 := 1/2*2^(-53)*ulp(1/(2^k)*(cosh_max + sinh_max)) + 1/(2^k)*(delta_sinh + delta_cosh): cosh_0_35_max := 1/(2^k)*(cosh_max + sinh_max): delta_cosh_0_35 := 1/2*2^(-53)*ulp(cosh_0_35_max + 2^k * sinh_max) + delta_cosh_0_35 + 2^k * delta_sinh: cosh_0_35_max := cosh_0_35_max + 2^k * sinh_max: delta_cosh_0_35 := 1/2*2^(-53)*ulp(cosh_0_35_max + 2^k * cosh_max) + delta_cosh_0_35 + 2^k * delta_cosh: cosh_0_35_max := cosh_0_35_max + 2^k * cosh_max: maxi := max(evalf(cosh((k-1/2)*ln(2))),evalf(cosh((k+1/2)*ln(2)))): mini := min(evalf(cosh((k-1/2)*ln(2))),evalf(cosh((k+1/2)*ln(2)))): epsilon := max(epsilon, delta_cosh_0_35/mini): delta := max(delta, delta_cosh_0_35): od; for k from 1 to 35 do delta_cosh_0_35 := 1/2*2^(-53)*ulp(1/(2^k)*(cosh_max + sinh_max)) + 1/(2^k)*(delta_sinh + delta_cosh): cosh_0_35_max := 1/(2^k)*(cosh_max + sinh_max): delta_cosh_0_35 := 1/2*2^(-53)*ulp(cosh_0_35_max + 2^k * sinh_max) + delta_cosh_0_35 + 2^k * delta_sinh: cosh_0_35_max := cosh_0_35_max + 2^k * sinh_max: delta_cosh_0_35 := 1/2*2^(-53)*ulp(cosh_0_35_max + 2^k * cosh_max) + delta_cosh_0_35 + 2^k * delta_cosh: cosh_0_35_max := cosh_0_35_max + 2^k * cosh_max: maxi := max(evalf(cosh((k-1/2)*ln(2))),evalf(cosh((k+1/2)*ln(2)))): mini := min(evalf(cosh((k-1/2)*ln(2))),evalf(cosh((k+1/2)*ln(2)))): epsilon := max(epsilon, delta_cosh_0_35/mini): delta := max(delta, delta_cosh_0_35): od; delta, epsilon; end: cosh_35_inf := proc() local k, delta, maxi,epsilon, mini,cosh_0_35_max, delta_cosh_0_35: epsilon := 0; delta := 0: for k from 35 to 1025 do delta_cosh_0_35 := 1/2*2^(-53)*ulp(2^k*(cosh_max + sinh_max)) + 2^k*(delta_sinh + delta_cosh) + 1/(2^k)*(cosh_max + sinh_max + delta_sinh + delta_cosh): cosh_0_35_max := 2^k*(cosh_max + sinh_max): maxi := max(evalf(cosh((k-1/2)*ln(2))),evalf(cosh((k+1/2)*ln(2)))): mini := min(evalf(cosh((k-1/2)*ln(2))),evalf(cosh((k+1/2)*ln(2)))): epsilon := max(epsilon, delta_cosh_0_35/mini): delta := max(delta, delta_cosh_0_35): od; delta, epsilon; end: ############################################################# ###################################################################### #now we can begin the proof ###################################################################### #first, we must compute the error created by the first range reduction # CODY and WAITE Argument reduction ln2 := ln(2.); invln2:= nearest(1/ln2); reminvln2 := evalf(1/ln2 - invln2); expln2:=ieeedouble(ln2)[2]: #get the exponent of ln2 in its IEEE representation bits_ln2_hi_0 := ceil(log2(k_max)); # 1/2 <= ln2/2^(expln2 + 1) < 1 ln2_hi := round(evalf(ln2 * 2^(52 - bits_ln2_hi_0 - expln2)))/2^(52 - bits_ln2_hi_0 - expln2);#this trick is used to get a truncated mantissa for ln2_hi #ln2_hi is a now exactly representable in the IEEE format and bits_ln2_hi_0 last bits of its mantissa are set to 0 #and bits_ln2_hi_0 is exactly the max number of bits to represent k #so the k * ln2_hi-product is exact :) ln2_lo:=nearest(ln2 - ln2_hi): # The error in this case (we need absolute error) delta_repr_ln2 := abs(ln2 - ln2_hi - ln2_lo); delta_round := evalf(1/2 * ulp(ln2_lo)); delta_cody_waite := k_max * (delta_repr_ln2 + delta_round); delta_b := delta_repr_ln2 + delta_round + delta_cody_waite; #we have 2 cases: # * k != 0 and we have an inexact range reduction # * k == 0 and we have no range reduction and then delta_range_reduc = 0 #the second range reduction is exact, so it doesn't introduce new error #after this second range reduction, we have a argument <= 2^(-9) #'mathematical' reductions: # x = k * ln(2) + y # y = a + b #'true' reductions: # x = k * (ln2_hi + ln2_lo) + (b_hi + b_lo) + table_index_float # with table_index_float = table_index * 2^(-8) #we'll use the following mathematical formulaes : #cosh(a + b) = cosh(a) * cosh(b) + sinh(a) * sinh(b) #sinh(a + b) = sinh(a) * cosh(b) + sinh(b) * cosh(a) #sinh(a) and cosh(a) are tabulated as double double # and we use Taylor series to compute approximations of the sums #computation of the absolute error in the tabulated values : delta_ca := delta_table_cosh_func()[1]; delta_sa := delta_table_sinh_func()[1]; ca_max := delta_table_cosh_func()[2]; sa_max := delta_table_sinh_func()[2]; #now we must compute the error done in polynomial evaluation #we use cosh(b) = 1 + sum(b^(2*k)/(2*k!), k > 0) # sinh(b) = b * (1 + sum(b^(2*k)/(2*k+1!), k > 0)) #both used polynoms are even (x�, x^4, x^6, ...) and we can use this fact y_max := b_max ^ 2; delta_y := 1/2*ulp(y_max) + delta_b^2; # remove the first x and compute the polynomial of y = x� poly_ch2 := subs(x=sqrt(y), expand(poly_ch)); poly_sh2 := subs(x=sqrt(y), expand(poly_sh)); errlist_cosh := errlist_quickphase_horner(degree(poly_ch2), 0, 0, 2^(-53), 2^(-70)): errlist_sinh := errlist_quickphase_horner(degree(poly_sh2), 0, 0, 2^(-53), 2^(-70)): #error between effective result and theorical polynomial result rounding_error_tcb := compute_horner_rounding_error(poly_ch2, y, y_max, errlist_cosh, true); rounding_error_tsb := compute_horner_rounding_error(poly_sh2, y, y_max, errlist_sinh, true); #error between therical polynomial result and cosh value approx_error_tcb := infnorm((cosh(x)-1-poly_ch)/(cosh(x)-1),x= -b_max..b_max); approx_error_tsb := infnorm((sinh(x)/x-1-poly_sh)/(sinh(x)/x-1),x= -b_max..b_max); delta_tcb := rounding_error_tcb[2] + approx_error_tcb; delta_tsb := rounding_error_tsb[2] + approx_error_tsb; tsb_max := rounding_error_tsb[4]; tcb_max := rounding_error_tcb[4]; #now we must do the first reconstruction, which correspond to cosh(a + b) = cosh(a) * cosh(b) + sinh(a) * sinh(b) #first case : sinh(a) = 0 = sa (= sa_hi + sa_lo in the C code) # cosh(a) = 1 = ca (= ca_hi + ca_lo in the C code) #there is no error on sa and caj delta_cosh0 := delta_tcb; cosh0_max := 1+tcb_max; delta_sinh0 := delta_b: sinh0_max := b_max: delta_sinh0 := delta_sinh0 + (tsb_max + delta_tsb)*(b_max + delta_b + 1/2*ulp(b_max)) - b_max * tsb_max + 1/2*ulp(sinh0_max + tsb_max*b_max): sinh0_max := sinh0_max + tsb_max*b_max: delta_sinh0 := delta_sinh0 + 2^(-53)*1/2*ulp(sinh0_max + tsb_max*b_max); sinh0_max := sinh0_max + tsb_max*b_max; #second case : sinh(a) <> 0 #there is a delta_table_cosh and delta_table_sinh absolute error on ca and sa. delta_cosh1 := delta_ca: cosh1_max := 2^(-53)*ca_max: delta_cosh1 := 1/2*ulp(cosh1_max + 3*2^(-53)*b_max * sa_max) + delta_cosh1 + Mul43_Error(b_max, delta_b, sa_max, delta_sa): cosh1_max := cosh1_max + 3 * 2^(-53) * b_max * sa_max: delta_cosh1 := 1/2*ulp(cosh1_max + b_max * sa_max * tsb_max) + delta_cosh1 + ((sa_max+1/2*ulp(sa_max)+delta_sa)*(b_max+ulp(b_max)+delta_b)*(tsb_max+delta_tsb)-tsb_max*sa_max*b_max): cosh1_max := cosh1_max + b_max * sa_max * tsb_max: delta_cosh1 := 1/2*ulp(cosh1_max + tcb_max*ca_max) + delta_cosh1 + ((ca_max + 1/2*ulp(ca_max) + delta_ca)*(tcb_max-delta_tcb)-ca_max*tcb_max): cosh11_max := cosh1_max + tcb_max*ca_max: delta_cosh1 := 1/2*ulp(cosh1_max + b_max * sa_max) + delta_cosh1: cosh11_max := cosh1_max + b_max * sa_max: delta_cosh1 := 1/2*2^(-53)*ulp(cosh1_max + ca_max) + delta_cosh1; cosh11_max := cosh1_max + ca_max; cosh_max := max(cosh0_max, cosh1_max); delta_cosh := max(delta_cosh0, delta_cosh1); delta_sinh1 := delta_sa: sinh1_max := 2^(-53)*sa_max: delta_sinh1 := 1/2*ulp(sinh1_max + 3*2^(-53)*ca_max * b_max) + delta_sinh1 + Mul43_Error(ca_max, delta_ca, b_max, delta_b): sinh1_max := sinh1_max + 3*2^(-53)*ca_max * b_max: delta_sinh1 := delta_sinh1 + 1/2*ulp(sinh1_max + sa_max * tcb_max): sinh1_max := sinh1_max + sa_max * tcb_max: delta_sinh1 := 1/2*ulp(sinh1_max + b_max * ca_max * tsb_max) + delta_sinh1 + ((ca_max+1/2*ulp(ca_max)+delta_ca)*(b_max+ulp(b_max)+delta_b)*(tsb_max+delta_tsb)-tsb_max*ca_max*b_max): sinh1_max := sinh1_max + b_max * sa_max * tsb_max: delta_sinh1 := delta_sinh1 + 1/2*2^(-53)*ulp(sinh1_max + b_max * ca_max): sinh1_max := sinh1_max + b_max * ca_max: delta_sinh1 := delta_sinh1 + 2^(-53)*1/2*ulp(sinh1_max + sa_max); sinh1_max := sinh1_max + sa_max; sinh_max := max(sinh1_max, sinh0_max); delta_sinh := max(delta_sinh0, delta_sinh1); #so we have the error done on cosh(y) and sinh(y) #now we must compute the error done on the last reconstruction #there are many cases #we begin by 0 < |k| < 35 epsilon_cosh_0_35 := cosh_0_35()[2]; #|k| > 35 epsilon_cosh_35_inf := cosh_35_inf()[2]; #rounding constant maxepsilon_csh := max(epsilon_cosh_35_inf, epsilon_cosh_0_35, delta_cosh): round_cst_csh := evalf(compute_rn_constant(maxepsilon_csh));; #################################################################################################" #now some functions used to build the .h header file. #################################################################################################" IEEE2db_number_BE := proc(ieee_number) local hex1, hex2, hexcat; hexcat=ieeehexa(ieee_number); hex1:= op(1, ieeehexa(ieee_number)): hex2:= op(2, ieeehexa(ieee_number)): cat(cat("{{0x"||hex1||",0x"||hex2||"}}; /*",sprintf("%.10e",ieee_number)),"*/ \n"); end: IEEE2db_number_LE := proc(ieee_number) local hex1, hex2, hexcat; hexcat=ieeehexa(ieee_number); hex1:= op(2, ieeehexa(ieee_number)): hex2:= op(1, ieeehexa(ieee_number)): cat(cat("{{0x"||hex1||",0x"||hex2||"}}; /*",sprintf("%.10e",ieee_number)),"*/ \n"); end: IEEE2db_number := proc(ieee_number, big_little) if (big_little = 1) then IEEE2db_number_BE(ieee_number): else IEEE2db_number_LE(ieee_number): fi; end: lo_part := proc(ieee_number) if (ieee_number <> 0) then ieee_number - nearest(ieee_number); else 0; end if; end: IEEE2db_db_number_sinh := proc(number,big_little) local hexstring1,hexstring2, hex1,hex2,hex3,hex4; hexstring1 := ieeehexa(number); hexstring2 := ieeehexa(lo_part(number)); if (big_little = 1) then hex1:= op(1, hexstring1): hex2:= op(2, hexstring1): hex3:= op(1, hexstring2): hex4:= op(2, hexstring2): else hex1:= op(2, hexstring1): hex2:= op(1, hexstring1): hex3:= op(2, hexstring2): hex4:= op(1, hexstring2): fi; " {{0x"||hex1||", 0x"||hex2||"}}, {{0x"||hex3||", 0x"||hex4||"}}},\n"; end: IEEE2db_db_number_cosh := proc(number,big_little) local hexstring1,hexstring2, hex1,hex2,hex3,hex4; hexstring1 := ieeehexa(number); hexstring2 := ieeehexa(lo_part(number)); if (big_little = 1) then hex1:= op(1, hexstring1): hex2:= op(2, hexstring1): hex3:= op(1, hexstring2): hex4:= op(2, hexstring2): else hex1:= op(2, hexstring1): hex2:= op(1, hexstring1): hex3:= op(2, hexstring2): hex4:= op(1, hexstring2): fi; " {{{0x"||hex1||", 0x"||hex2||"}}, {{0x"||hex3||", 0x"||hex4||"}},\n"; end: ##################################################################################### #now, we can produce the header file ! round_cst_cosh := 1.0020: round_cst_sinh := round_cst_cosh: filename := "TEMPCSH/csh_fast.h": fd := fopen(filename, WRITE, TEXT): fprintf(fd, "\n /* File generated by maple/csh.mpl */ \n"): fprintf(fd, "\n"): fprintf(fd, " static double maxepsilon_csh = %1.30e ;\n", maxepsilon_csh): fprintf(fd, " static double round_cst_csh = %1.30e ;\n", round_cst_csh): fprintf(fd, "\n"): fprintf(fd, "#ifdef WORDS_BIGENDIAN \n"): for big_little from 1 to 2 do if (big_little = 2) then fprintf(fd, "#else \n"): fi: fprintf(fd, cat( " static db_number const inv_ln_2 = ",IEEE2db_number(inv_ln_2,big_little))): fprintf(fd, cat( " static db_number const ln2_hi = ",IEEE2db_number(ln2_hi,big_little))): fprintf(fd, cat( " static db_number const ln2_lo = ",IEEE2db_number(ln2_lo,big_little))): fprintf(fd, cat( " static db_number const two_43_44 = ", IEEE2db_number(two_43_44,big_little))): fprintf(fd, cat( " static db_number const two_minus_30 = ", IEEE2db_number(2**(-40),big_little))): fprintf(fd, " static int const bias = %d ;\n", bias): fprintf(fd, "\n"); fprintf(fd,"/* some bounds */ \n"): fprintf(fd, cat( " static db_number const max_input_csh = ",IEEE2db_number(max_input_ch,big_little))): fprintf(fd, "\n"): fprintf(fd, cat(cat(" static const db_number cosh_sinh_table[",convert(2*size_of_table+1,string)),"][4] = { \n")); vvalue := ieeehexa(two_43_44-ln(2.)/2.); for i from -size_of_table to size_of_table do fprintf(fd, IEEE2db_db_number_cosh(cosh(hexa2ieee(vvalue)-two_43_44),big_little)); fprintf(fd, IEEE2db_db_number_sinh(sinh(hexa2ieee(vvalue)-two_43_44),big_little)); vvalue:=next_float(vvalue): od: fprintf(fd,"}; \n"); fprintf(fd,"/* the coefficients for the cosh-approximations */ \n"): for i from 1 to (n_double_ch/2) do fprintf(fd, cat(cat(cat( " static const db_number c",convert(2*(i-1),string))," = "),IEEE2db_number(coeff(poly_ch+1,x,2*(i-1)),big_little))): od: fprintf(fd,"/* the coefficients for the sinh-approximations */\n"): for i from 1 to (n_double_sh/2) do fprintf(fd, cat(cat(cat( " static const db_number s",convert(2*i-1,string))," = "),IEEE2db_number(coeff(poly_sh+1,x,2*(i-1)),big_little))): od: od: fprintf(fd, "#endif \n"): fclose(fd): interval-3.2.0/src/crlibm/maple/double-extended.mpl0000644000000000000000000001165113316017127020412 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #--------------------------------------------------------------------- # ieeedouble converts a number to IEEE double extended format. # returns sign (-1 or 1), exponent between -16383 and 16383, mantissa as a fraction between 0.5 and 1. # TODO : use JMM procedure; check subnormals etc ieeedoubleExt:=proc(xx) local x, sign, logabsx, exponent, mantissa, infmantissa; x:=evalf(xx): if (x=0) then sign,exponent,mantissa := 0,0,0; else if (x<0) then sign:=-1: else sign:=1: fi: exponent := floor(log2(sign*x)); if (exponent>16383) then mantissa:=infinity: exponent:=16383: elif (exponent< -16382) then # denorm exponent := -16383 fi: infmantissa := sign*x*2^(63-exponent); if frac(infmantissa) <> 0.5 then mantissa := round(infmantissa) else mantissa := floor(infmantissa); if type(mantissa,odd) then mantissa := mantissa+1 fi; fi; mantissa := mantissa*2^(-63); fi; sign,exponent,mantissa; end: nearestExt := proc(x) local sign, exponent, mantissa; sign, exponent, mantissa := ieeedoubleExt(x); sign*mantissa*2^(exponent); end: ieeehexaExt:= proc(x) local resultat, sign, exponent, mantissa, t; if(x=0) then resultat:=["0000","0000","0000","0000","0000"]; elif(x=-0) then resultat:=["8000","0000","0000","0000","0000"]; else sign,exponent,mantissa := ieeedoubleExt(x); t := 2**80 + (exponent+16383)*2^64 + mantissa*2^63; if (sign=-1) then t := t + 2**79; fi: t := convert(t, hex); t:=convert(t, string): resultat:=[substring(t, 2..5), substring(t, 6..9 ), substring(t, 10..13 ), substring(t, 14..17 ), substring(t, 18..21 )]; end if: resultat; end proc: printDoubleAsShort:=proc(x) local ss; ss:=ieeehexa(x); cat( "DOUBLE_HEX(", substring(ss[1], 1..4), ", " , substring(ss[1], 5..8), ", " , substring(ss[2], 1..4), ", " , substring(ss[2], 5..8)) ; end proc: printDoubleExtAsShort:=proc(x) local ss; ss:=ieeehexaExt(x); cat( "LDOUBLE_HEX(", ss[1], ", ", ss[2], ", ",ss[3], ", ", ss[4], ", ", ss[5], ")"); end proc: printDoubleAsULL:=proc(x) local ss; ss:=ieeehexa(x); cat( "ULL(", ss[1], ss[2], ")"); end proc: printDoubleAsHexInt:=proc(x) local ss; ss:=ieeehexa(x); cat(ss[1], ss[2]); end proc: #--------------------------------------------------------------------- # hi_lo takes an arbitrary precision number x and returns two doubles such that: # x ~ x_hi + x_lo hiloExt:= proc(x) local x_hi, x_lo, res: x_hi:= nearestExt(evalf(x)): res:=x-x_hi: if (res = 0) then x_lo:=0: else x_lo:=nearestExt(evalf(res)): end if; x_hi,x_lo; end: #--------------------------------------------------------------------- # Like poly_exact, but the n first coefficients are exactly representable as the sum of two doubles. # (to actually get the two doubles, use procedure hi_lo) polyExact2Ext:=proc(P,n) local deg,i, coef, coef_hi, coef_lo, Q: Q:= 0: convert(Q, polynom): deg:=degree(P,x): for i from 0 to deg do coef :=coeff(P,x,i): coef_hi, coef_lo:=hiloExt(coef): Q:= Q + coef_hi*x^i: if(i 0) then fprintf(fd,"#define %s%dh %1.50e\n",s,i,hi): end if: if (mi <> 0) then fprintf(fd,"#define %s%dm %1.50e\n",s,i,mi): end if: if (lo <> 0) then fprintf(fd,"#define %s%dl %1.50e\n",s,i,lo): end if: end if: end if: od: end proc: # First, we compute special values ReturnXBound := convert((ieeehexa(2^(-54)))[1],decimal,hex): Largest := 2^(1023) * ((2^(53) - 1) / 2^(52)): Smallest := 2^(-1023) * 1 * 2^(-51): OverflowBound := nearest(log(Largest + 1)): MinusOneBound := nearest(log(2^(-54))): SimpleOverflowBound := convert(ieeehexa(OverflowBound)[1],decimal,hex): DirectIntervalBound := convert((ieeehexa(0.25))[1],decimal,hex): MinusOnePlusOneUlp := -1 + 2^(-53): # Attention: it's 2^(-53) because we are at a binade boundary # Second, we have the computation of the values for the direct interval # The function, that we approximate is directF := unapply(exp(x) - 1,x): # The domain is directA := -2^(-5): directB := 2^(-5): # The polynomials are quickDirectpoly := X -> X+1/2*X^2+(3360682229480701/1180591620717411303424*X^6+3660136839517697/147573952589676412928*X^5+7320130809407439/36893488147419103232*X^4+3202559734508631/2305843009213693952*X^3+4803839602572223/576460752303423488*X^2+6004799503160665/144115188075855872*X+6004799503160661/36028797018963968)*X^3: accuDirectpoly := X -> X+1/2*X^2+(3786738884990361/4951760157141521099596496896*X^12+7100145222887513/618970019642690137449562112*X^11+6212541673969101/38685626227668133590597632*X^10+5047690109993399/2417851639229258349412352*X^9+3785767582868083/151115727451828646838272*X^8+5205430426443615/18889465931478580854784*X^7+29303968161043118891149009244865/10633823966279326983230456482242756608*X^6+65933928362347017505024866986963/2658455991569831745807614120560689152*X^5+65933928362347017505149159875899/332306998946228968225951765070086144*X^4+28846093658526820158502757550845/20769187434139310514121985316880384*X^3+21634570243895115118877068038417/2596148429267413814265248164610048*X^2+27043212804868893898596335048021/649037107316853453566312041152512*X+243583606221817153033947472119380503276473908509/1461501637330902918203684832716283019655932542976)*X^3: # Truncate the quick phase direct interval polynomial to degree specialDegree # for special interval |x| <= specialBound (speed-up) specialDegree := 5: specialBound := 2^(-12): specialPoly := unapply(sum(coeff(quickDirectpoly(x),x,i) * x^i,i=0..specialDegree),x): printf("Special polynomial is the direct polynomial truncated to degree %d used in |x| < 2^(%f)\n", specialDegree, evalf(log[2](specialBound))): # Compute the relative errors errDirectQuick := numapprox[infnorm](quickDirectpoly(x)/directF(x) -1,x=directA..directB): errDirectAccu := numapprox[infnorm](accuDirectpoly(x)/directF(x) -1,x=directA..directB): errSpecialPoly := numapprox[infnorm](specialPoly(x)/directF(x) -1,x=-specialBound..specialBound): errDirectAccuSpecial := numapprox[infnorm](accuDirectpoly(x)/directF(x) -1,x=2^(-12)..2^(-12)): printf("The relative approximation error of the direct interval quick polynomial is 2^(%f)\n", evalf(log[2](abs(errDirectQuick)))): printf("The relative approximation error of the direct interval accurate polynomial is 2^(%f)\n", evalf(log[2](abs(errDirectAccu)))): printf("The relative approximation error of the special interval special polynomial is 2^(%f)\n", evalf(log[2](abs(errSpecialPoly)))): printf("The relative approximation error of the direct interval accurate polynomial in special domain is 2^(%f)\n", evalf(log[2](abs(errDirectAccuSpecial)))): # Third, we have the computation of the values for the common interval # The function, that we approximate is commonF := unapply(exp(x),x): # The domain is commonA := -log(2)*2^(-12) * (1/2 + 2^(-19)): commonB := log(2)*2^(-12) * (1/2 + 2^(-19)): quickCommonpoly := X -> 1+X+1/2*X^2+(6004799504593679/144115188075855872*X+6004799504235425/36028797018963968)*X^3: accuCommonpoly := X -> 1+X+1/2*X^2+(3660068549402285/18446744073709551616*X^4+6405119471061623/4611686018427387904*X^3+4803839602528529/576460752303423488*X^2+54086425609737787796676993069745/1298074214633706907132624082305024*X+54086425609737787797192670135537/324518553658426726783156020576256)*X^3: # Compute the relative errors errCommonQuick := numapprox[infnorm](quickCommonpoly(x)/commonF(x) -1,x=commonA..commonB): errCommonAccu := numapprox[infnorm](accuCommonpoly(x)/commonF(x) -1,x=commonA..commonB): printf("The relative approximation error of the common interval quick polynomial is 2^(%f)\n", evalf(log[2](abs(errCommonQuick)))): printf("The relative approximation error of the common interval accurate polynomial is 2^(%f)\n", evalf(log[2](abs(errCommonAccu)))): epsilonApproxRmAccurate := numapprox[infnorm]( ((1+x)/(exp(x)))-1, x=commonA*2^(-52)..commonB*2^(-52)): epsilonApproxRlAccurate := numapprox[infnorm]( ((1+x)/(exp(x)))-1, x=commonA*2^(-105)..commonB*2^(-105)): printf("The approximation rel error for approximating exp(rm) by 1 + rm is 2^(%2f)\n", log2(abs(epsilonApproxRmAccurate))): printf("The approximation rel error for approximating exp(rl) by 1 + rl is 2^(%2f)\n", log2(abs(epsilonApproxRlAccurate))): # Compute the constants for argument reduction and the tables in the common path MsLog2Div2L := evalf(-log(2)/(2^(12))): msLog2Div2Lh, msLog2Div2Lm, msLog2Div2Ll := hi_mi_lo(MsLog2Div2L): epsMsLog2Div2L := evalf(abs(((msLog2Div2Lh + msLog2Div2Lm + msLog2Div2Ll) - MsLog2Div2L)/MsLog2Div2L)): epsDDMsLog2Div2L := evalf(abs(((msLog2Div2Lh + msLog2Div2Lm) - MsLog2Div2L)/MsLog2Div2L)): printf("The error made by storing MsLog2Div2L as a double-double is 2^(%f)\n",log[2](epsDDMsLog2Div2L)): printf("The error made by storing MsLog2Div2L as a triple-double is 2^(%f)\n",log[2](epsMsLog2Div2L)): gap := -floor(-log[2](abs(msLog2Div2Lm/msLog2Div2Lh))): printf("Information: |msLog2Div2Lm| <= 2^(%f) * |msLog2Div2Lh|\n",gap): log2InvMult2L := nearest(2^(12) / (log(2))): shiftConst := 2^(52) + 2^(51): indexmask1 := 2^((12)/2) - 1: indexmask2 := indexmask1 * 2^((12)/2): for i from 0 to 2^(12/2) - 1 do twoPowerIndex1hi[i], twoPowerIndex1mi[i], twoPowerIndex1lo[i] := hi_mi_lo(evalf(2^(i/(2^12)))): twoPowerIndex2hi[i], twoPowerIndex2mi[i], twoPowerIndex2lo[i] := hi_mi_lo(evalf(2^(i/(2^(12/2))))): od: # Estimate the error of the two quick phases # ATTENTION: C EST PIFOMETRIQUE POUR L INSTANT epsQuickDirectOverall := 2^(-62): epsQuickCommonOverall := 2^(-62): # Write the tables printf("Write tables...\n"): filename:="TEMPEXPM1/expm1.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#include \"crlibm.h\"\n#include \"crlibm_private.h\"\n"): fprintf(fd, "\n/* File generated by maple/expm1.mpl */\n"): fprintf(fd, "\#define log2InvMult2L %1.50e\n",log2InvMult2L): fprintf(fd, "\#define msLog2Div2Lh %1.50e\n",msLog2Div2Lh): fprintf(fd, "\#define msLog2Div2Lm %1.50e\n",msLog2Div2Lm): fprintf(fd, "\#define msLog2Div2Ll %1.50e\n",msLog2Div2Ll): fprintf(fd, "\#define shiftConst %1.50e\n",shiftConst): fprintf(fd, "\#define INDEXMASK1 0x%08x\n",indexmask1): fprintf(fd, "\#define INDEXMASK2 0x%08x\n",indexmask2): fprintf(fd, "\#define RETURNXBOUND 0x%08x\n",ReturnXBound): fprintf(fd, "\#define OVERFLOWBOUND %1.50e\n",OverflowBound): fprintf(fd, "\#define LARGEST %1.50e\n",Largest): fprintf(fd, "\#define SMALLEST %1.50e\n",Smallest): fprintf(fd, "\#define MINUSONEBOUND %1.50e\n",MinusOneBound): fprintf(fd, "\#define SIMPLEOVERFLOWBOUND 0x%08x\n",SimpleOverflowBound): fprintf(fd, "\#define DIRECTINTERVALBOUND 0x%08x\n",DirectIntervalBound): fprintf(fd, "\#define SPECIALINTERVALBOUND 0x%08x\n",convert((ieeehexa(specialBound))[1],decimal,hex)): fprintf(fd, "\#define ROUNDCSTDIRECTRN %1.50e\n",compute_rn_constant(epsQuickDirectOverall)): fprintf(fd, "\#define ROUNDCSTDIRECTRD %1.50e\n",epsQuickDirectOverall): fprintf(fd, "\#define ROUNDCSTCOMMONRN %1.50e\n",compute_rn_constant(epsQuickCommonOverall)): fprintf(fd, "\#define ROUNDCSTCOMMONRD %1.50e\n",epsQuickCommonOverall): fprintf(fd, "\#define MINUSONEPLUSONEULP %1.50e\n",MinusOnePlusOneUlp): fprintf(fd,"\n\n"): printPolynomialIntoFile(fd,"quickDirectpolyC",quickDirectpoly): fprintf(fd,"\n"): printPolynomialIntoFile(fd,"accuDirectpolyC",accuDirectpoly): fprintf(fd,"\n"): printPolynomialIntoFile(fd,"quickCommonpolyC",quickCommonpoly): fprintf(fd,"\n"): printPolynomialIntoFile(fd,"accuCommonpolyC",accuCommonpoly): fprintf(fd,"\n\n"): # Print the tables fprintf(fd, "typedef struct tPi_t_tag {double hi; double mi; double lo;} tPi_t; \n"): fprintf(fd, "static const tPi_t twoPowerIndex1[%d] = {\n", 2^(12/2)): for i from 0 to 2^(12/2)-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50e, /* twoPowerIndex1hi[%d] */ \n", twoPowerIndex1hi[i], i): fprintf(fd, " %1.50e, /* twoPowerIndex1mi[%d] */ \n", twoPowerIndex1mi[i], i): fprintf(fd, " %1.50e, /* twoPowerIndex1lo[%d] */ \n", twoPowerIndex1lo[i], i): fprintf(fd, " } "): if(i<2^(12/2)-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fprintf(fd, "static const tPi_t twoPowerIndex2[%d] = {\n", 2^(12/2)): for i from 0 to 2^(12/2)-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50e, /* twoPowerIndex2hi[%d] */ \n", twoPowerIndex2hi[i], i): fprintf(fd, " %1.50e, /* twoPowerIndex2mi[%d] */ \n", twoPowerIndex2mi[i], i): fprintf(fd, " %1.50e, /* twoPowerIndex2lo[%d] */ \n", twoPowerIndex2lo[i], i): fprintf(fd, " } "): if(i<2^(12/2)-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fprintf(fd, "\n\n"): fclose(fd): printf(" ...done\n"):interval-3.2.0/src/crlibm/maple/gal.mpl0000644000000000000000000000525613316017127016111 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Digits := 120: interface(quiet=true): read "common-procedures.mpl": read "triple-double.mpl": #--------------------------------------------------------------------- # Procedure gal computes a number x and a boolean such that # # if the boolean is true # - |x - xstart| is minimal # - x = roundX(x) (x is a floating point number in format roundX) # - |(roundY(f(x)) - f(x)) / f(x)| <= eps # # and the boolean is false if no such x could be found in iter iterations # # Limitations: # # - floating point numbers xp such that f(xp) = 0 are not considered # # Uses: # # - The successor function succX for floating point numbers roundX(t) gal:=proc(xstart,roundX,f,roundY,epsi,succX,iter) local xleft, xright, i, err, ima, d, x, eps, b; d := Digits; Digits := 120; eps := abs(epsi); xleft := roundX(xstart); xright := roundX(succX(roundX(xstart))); x := 0; i := 0; err := eps * 2; while ((err > eps) and (i < iter)) do i := i + 1; if (type(i,odd)) then x := xright; xright := evalf(roundX(succX(roundX(xright)))); else x := xleft; xleft := evalf(roundX(-succX(roundX(-xleft)))); end if; ima := evalf(f(x)); if (ima <> 0) then err := evalf(abs((ima - roundY(ima))/ima)); end if; end do; b := false; if (i < iter) then b := true; end if; Digits := d; (x,b); end proc: galDoubleToDouble:=proc(xstart,f,epsi,iter) local g,b,xn; (g,b) := gal(xstart,nearest,f,nearest,epsi,succDouble,iter); if (b) then xn := g; else xn = xstart; end if; xn; end proc: galDoubleToDoubleDouble:=proc(xstart,f,epsi,iter) local g,b,xn; (g,b) := gal(xstart,nearest,f,nearestDD,epsi,succDouble,iter); if (b) then xn := g; else xn = xstart; end if; xn; end proc: interval-3.2.0/src/crlibm/maple/log-de.mpl0000644000000000000000000003511313316017127016510 0ustar 00000000000000####################################################################### # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # To use: # restart; read "log-de.mpl"; #TODO output scripts for the Gappa proof out for Paterson/Stockmayer Digits := 100: interface(quiet=true): read "common-procedures.mpl": read "double-extended.mpl": mkdir("TEMPLOG"): log2h,log2l := hiloExt(log(2)): L := 7: # number of bits used to address the table MAXINDEX := round(2^L * (sqrt(2)-1)): for i from 0 to MAXINDEX-1 do center[i] := 1 + i*2^(-L): # center[i] in [1, 2[ # We want it to fit on 11 bits of mantissa r[i] := round(evalf( (1/center[i]) * 2^(11)) ) / 2^(11) ; od: for i from MAXINDEX to 2^L do # y has been divided by two, center[i] in [0.5, 1[ center[i]:=(1 + i*2^(-L)) / 2: # We want it to fit on 11 bits of mantissa, r[i] := round(evalf( (1/center[i]) * 2^(10)) ) / 2^(10) ; od: # Note that we go up to 2^L although the case 2^L is wrapped to zero # in the C code. It could be important for zmax (but it turns out not). for i from 0 to 2^L do (logirh[i], logirl[i]) := hiloExt(-log(r[i])): od: #Computation of ZMax. for i from 0 to MAXINDEX-1 do t_x := center[i] + 2^(-L-1) : zmax[i] := (t_x*r[i]-1) : t_x := center[i] - 2^(-L-1) : zmin[i] := (t_x*r[i]-1) : zabsmax[i] := max(abs(zmin[i]), abs(zmax[i])): od: for i from MAXINDEX to 2^L do t_x := center[i] + 2^(-L-2) : zmax[i] := (t_x*r[i]-1) : t_x := center[i] - 2^(-L-2) : zmin[i] := (t_x*r[i]-1) : zabsmax[i] := max(abs(zmin[i]), abs(zmax[i])): od: zmaxmax:=0: zminmin:=0: for i from 0 to 2^L do if zmax[i] > zmaxmax then zmaxmax := zmax[i]: fi: if zmin[i] < zminmin then zminmin := zmin[i]: fi: od: printf("zminmin = -2^(%2f) zmaxmax = 2^(%2f)\n", log2(-zminmin), log2(zmaxmax) ) : PolyDegreeQuick:=7: #Keep -zmaxmax..zmaxmax to keep c1=1, which is useful in the proof if(1+1=3) then # The polynomial used to be computed here, polyQuick:= polyExact2Ext(x * numapprox[minimax]( log(1+x)/x, x=-zmaxmax..zmaxmax, [PolyDegreeQuick-1,0], 1 , 'deltaApprox'), 0): epsilonApproxQuick := numapprox[infnorm]( 1-polyQuick/log(1+x), x=zminmin..zmaxmax): deltaApproxQuick := numapprox[infnorm]( polyQuick-log(1+x), x=zminmin..zmaxmax): else # magical polynomial given by Sylvain's tool polyQuick := x * (1 + (x * ((-0.50000000000000000000000000000000000000000000000000000000000000e0) + (x * (0.33333333333333342585191871876304503530263900756835937500000000e0 + (x * ((-0.24999999998423708125194764306797878816723823547363281250000000e0) + (x * (0.19999999996748479835773082413652446120977401733398437500000000e0 + (x * ((-0.16666957260954737285452154083031928166747093200683593750000000e0) + (x * 0.14286056338555042088955815415829420089721679687500000000000000e0)))))))))))): # validated infinite norms given by Christoph's tool epsilonApproxQuick := 2^(-64.119667587221): deltaApproxQuick := 2^(-72.230387592107): fi: printf(" rel approximation error for the quick phase is 2^(%2f)\n", log2(epsilonApproxQuick) ) : printf(" abs approximation error for the quick phase is 2^(%2f)\n", log2(deltaApproxQuick) ) : # For the Paterson/Stockmayer method polyQuick0:= x * numapprox[minimax]( log(1+x)/x, x=-zmaxmax..zmaxmax, [PolyDegreeQuick-1,0], 1 , 'deltaApprox'): ## Création des nouveaux coefficients polyQuick0:= x * numapprox[minimax]( log(1+x)/x, x=-zmaxmax..zmaxmax, [PolyDegreeQuick-1,0], 1 , 'deltaApprox'): ## Création des nouveaux coefficients a7 := convert(coeff(polyQuick0,x,7),rational): a6 := convert(coeff(polyQuick0,x,6)/a7,rational): a5 := convert(coeff(polyQuick0,x,5)/a7,rational): a4 := convert(coeff(polyQuick0,x,4)/a7,rational): a3 := convert(coeff(polyQuick0,x,3),rational): a2 := convert(coeff(polyQuick0,x,2),rational): a1 := convert(coeff(polyQuick0,x,1),rational): a0 := convert(coeff(polyQuick0,x,0),rational): alpha0 := a5 - 1: alpha1 := a6: alpha2 := a4 - alpha0 * a6: ## a7_hi,a7_lo := hiloExt(a7): a3_hi,a3_lo := hiloExt(a3): a2_hi,a2_lo := hiloExt(a2): a0_hi,a0_lo := hiloExt(a0): c_hi,c_lo := hiloExt(alpha0): alpha_hi,alpha_lo := hiloExt(alpha1): beta_hi,beta_lo := hiloExt(alpha2): #coef_c := c_hi + c_lo: #coef_alpha := alpha_hi + alpha_lo: #coef_beta := beta_hi + beta_lo: #coef_c7 := a7_hi + a7_lo: #coef_c3 := a3_hi + a3_lo: #coef_c2 := a2_hi + a2_lo: #coef_c0 := a0_hi + a0_lo: coef_c := c_hi: coef_alpha := alpha_hi: coef_beta := beta_hi: coef_c7 := a7_hi: coef_c3 := a3_hi: coef_c2 := a2_hi: coef_c0 := a0_hi: polyQuickPat := ((x^2 + coef_c)*(x + coef_alpha) + (x + coef_beta)) * (coef_c7*x^4) + ((coef_c3 * x + coef_c2)*x^2 + (x)): epsilonApproxQuickPat := numapprox[infnorm]( 1-polyQuickPat/log(1+x), x=zminmin..zmaxmax): printf(" approximation rel error for Paterson/Stockmayer in the quick phase is 2^(%2f)\n", log2(epsilonApproxQuickPat) ) : deltaApproxQuickPat := numapprox[infnorm]( polyQuickPat-log(1+x), x=zminmin..zmaxmax): printf(" approximation abs error for Paterson/Stockmayer in the quick phase is 2^(%2f)\n", log2(deltaApproxQuickPat) ) : PolyDegreeAccurate:=14: printf("Computing the polynomial for accurate phase (this may take some time...)\n"): pe:= x * numapprox[minimax]( log(1+x)/x, x=-zmaxmax..zmaxmax, [PolyDegreeAccurate-1,0], 1 , 'deltaApprox'): MaxDegreeDDE:=8: # polyAccurate := polyExact2Ext(pe, MaxDegreeDDE): deltaApproxAccurate := numapprox[infnorm](polyAccurate-log(1+x), x=-zmaxmax..zmaxmax): epsilonApproxAccurate := numapprox[infnorm]( 1-polyAccurate/log(1+x), x=-zmaxmax..zmaxmax): printf(" approximation error for the accurate phase is 2^(%2f)\n", log2(epsilonApproxAccurate) ) : filename:="TEMPLOG/log-de.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "/*File generated by maple/log-de.mpl*/\n\n"): # some constants fprintf(fd, "#define L %d\n", L): fprintf(fd, "#define MAXINDEX %d\n", MAXINDEX): fprintf(fd, "#define INDEXMASK %d\n", 2^L-1): fprintf(fd, "static const double two64 = %1.25e ;\n", evalf(2^64)): fprintf(fd, "#if 1\n#define ESTRIN\n#else\n#define PATERSON\n#endif\n"): fprintf(fd, "#if defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)\n\n"): fprintf(fd, "#ifdef PATERSON\n"): # polynomial for quick phase fprintf(fd,"static const long double c7 = %1.50e;\n",coef_c7): fprintf(fd,"static const long double c3 = %1.50e;\n",coef_c3): fprintf(fd,"static const long double c2 = %1.50e;\n",coef_c2): fprintf(fd,"static const long double ps_alpha = %1.50e;\n",coef_alpha): fprintf(fd,"static const long double ps_beta = %1.50e;\n",coef_beta): fprintf(fd,"static const long double ps_c = %1.50e;\n",coef_c): fprintf(fd, "#endif/* PATERSON*/\n\n"): fprintf(fd, "#ifdef ESTRIN\n"): fprintf(fd, " /* Coefficients are read directly from the array thanks to the following macros */ \n"): for i from PolyDegreeQuick to 2 by -1 do fprintf(fd, "#define c%d c[%d]\n", i, PolyDegreeQuick-i): od: fprintf(fd, "static const double c[%d] = {\n",PolyDegreeQuick): for i from PolyDegreeQuick to 2 by -1 do fprintf(fd, " /* c%d = */ %1.50eL, \n", i, coeff(polyQuick,x,i)): od: fprintf(fd, "}; \n \n"): fprintf(fd, "#endif/* ESTRIN */\n\n"): for i from PolyDegreeAccurate to 1 by -1 do fprintf(fd, "#define c%dh ch[%d]\n", i, PolyDegreeAccurate-i): od: for i from MaxDegreeDDE-1 to 1 by -1 do fprintf(fd, "#define c%dl cl[%d]\n", i, MaxDegreeDDE-1-i): od: fprintf(fd, "#define PREFETCH_POLY_ACCURATE \n"): fprintf(fd, "\n#else /* not(defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)),\n assuming Itanium, otherwise we shouldn't be there */ \n\n"): fprintf(fd, "#define PREFETCH_POLY_QUICK "): for i from PolyDegreeQuick to 2 by -1 do fprintf(fd, "c%d=c[%d]; ", i, PolyDegreeQuick-i): od: fprintf(fd, "\n#define PREFETCH_POLY_ACCURATE "): for i from PolyDegreeAccurate to 1 by -1 do fprintf(fd, "c%dh=ch[%d]; ", i, PolyDegreeAccurate-i): if i mod 4 =0 then fprintf(fd, "\\\n "): fi: od: fprintf(fd, "\\\n "): for i from MaxDegreeDDE-1 to 1 by -1 do fprintf(fd, "c%dl=cl[%d]; ", i, MaxDegreeDDE-1-i): od: fprintf(fd, "\n#endif /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ \n\n"): # Various constants fprintf(fd, "static const long double log2H = %1.50eL ;\n", log2h): fprintf(fd, "static const long double log2L = %1.50eL ;\n", log2l): # The polynomials # polynomial for quick phase # for i from PolyDegreeQuick to 1 by -1 do # fprintf(fd, "static const long double c%d = %1.50eL ;\n", i, coeff(polyQuick,x,i)): # od: # polynomial for accurate phase fprintf(fd, "static const long double ch[%d] = {\n",PolyDegreeAccurate): for i from PolyDegreeAccurate to 1 by -1 do (ch, cl) := hiloExt(coeff(polyAccurate,x,i)): fprintf(fd, " /* ch%d = */ %1.50eL, \n", i, ch): od: fprintf(fd, "}; \n \n"): fprintf(fd, "static const long double cl[%d] = {\n", MaxDegreeDDE): for i from MaxDegreeDDE-1 to 1 by -1 do (ch, cl) := hiloExt(coeff(polyAccurate,x,i)): fprintf(fd, " /* cl%d = */ %1.50eL, \n", i, cl): od: fprintf(fd, "}; \n \n"): # The tables fprintf(fd, "typedef struct rri_tag {float r; long double logirh; long double logirl; } rri ; \n"): fprintf(fd, "static const rri argredtable[%d] = {\n", 2^L): for i from 0 to 2^L-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50eL, /* r[%d] */ \n", r[i], i): fprintf(fd, " %1.50eL, /* logirh[%d] */ \n", logirh[i], i): fprintf(fd, " %1.50eL, /* logirl[%d] */ \n", logirl[i], i): fprintf(fd, " } "): if(i<2^L-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fclose(fd): printf("\n************ DONE TEMPLOG/log-de.h ************\n"); filename:="TEMPLOG/polynomials.sed": fd:=fopen(filename, WRITE, TEXT): for i from PolyDegreeAccurate to 1 by -1 do (ch, cl) := hiloExt(coeff(polyAccurate,x,i)): fprintf(fd, " s/_c%dh/%1.40e/g\n", i, ch): if(i&2\n"): fprintf(fd, "sed -f $CRLIBMDIR/maple/TEMPLOG/polynomials.sed -f $CRLIBMDIR/maple/TEMPLOG/log-de_0.sed $CRLIBMDIR/gappa/log-de/log-de-acc-index0-E0.gappa | $GAPPA \n"): fprintf(fd, "echo Accurate phase, case E!=0, index=0 1>&2\n"): fprintf(fd, "sed -f $CRLIBMDIR/maple/TEMPLOG/polynomials.sed -f $CRLIBMDIR/maple/TEMPLOG/log-de_0.sed $CRLIBMDIR/gappa/log-de/log-de-acc-index0-E1N.gappa | $GAPPA \n"): fprintf(fd, "for num in `seq 1 %d`; do\n", 2^L-1): fprintf(fd, " echo Accurate phase, case E=0, index=$num 1>&2\n"): fprintf(fd, " sed -f $CRLIBMDIR/maple/TEMPLOG/polynomials.sed -f $CRLIBMDIR/maple/TEMPLOG/log-de_$num.sed $CRLIBMDIR/gappa/log-de/log-de-acc-index1N-E0.gappa | $GAPPA \n"): fprintf(fd, " echo 1>&2\n"): fprintf(fd, "done\n"): fprintf(fd, "for num in `seq 1 %d`; do\n", 2^L-1): fprintf(fd, " echo Accurate phase, case E!=0, index = $num 1>&2 \n"): fprintf(fd, " sed -f $CRLIBMDIR/maple/TEMPLOG/polynomials.sed -f $CRLIBMDIR/maple/TEMPLOG/log-de_$num.sed $CRLIBMDIR/gappa/log-de/log-de-acc-index1N-E1N.gappa | $GAPPA \n"): fprintf(fd, " echo 1>&2\n"): fprintf(fd, "done\n\n"): fprintf(fd, "echo Quick phase, case E=0, index=0 1>&2\n"): fprintf(fd, "sed -f $CRLIBMDIR/maple/TEMPLOG/polynomials.sed -f $CRLIBMDIR/maple/TEMPLOG/log-de_0.sed $CRLIBMDIR/gappa/log-de/log-de-index0-E0.gappa | $GAPPA \n"): fprintf(fd, " echo 1>&2\n"): fprintf(fd, "echo Quick phase, case E!=0, index=0 1>&2 \n"): fprintf(fd, "sed -f $CRLIBMDIR/maple/TEMPLOG/polynomials.sed -f $CRLIBMDIR/maple/TEMPLOG/log-de_0.sed $CRLIBMDIR/gappa/log-de/log-de-index0-E1N.gappa | $GAPPA \n"): fprintf(fd, " echo 1>&2\n"): fprintf(fd, "for num in `seq 1 %d`; do\n", 2^L-1): fprintf(fd, " echo Quick phase, for all E, index=$num 1>&2\n"): fprintf(fd, " sed -f $CRLIBMDIR/maple/TEMPLOG/polynomials.sed -f $CRLIBMDIR/maple/TEMPLOG/log-de_$num.sed $CRLIBMDIR/gappa/log-de/log-de-index1N-E0N.gappa | $GAPPA \n"): fprintf(fd, " echo 1>&2\n"): fprintf(fd, "done\n"): fclose(fd): printf("\n************ DONE TEMPLOG/run-log-de-proof.sh ************\n"): printf("Now you should run \n"): printf(" sh ../../gappa/log-de/run-log-de-proof.sh 2> ../../maple/TEMPLOG/Gappa.out\n"): printf(" (You probably need to edit the path to the gappa executable within run-log-de-proof.sh)\n"): printf("Then look at TEMPLOG/Gappa.out. It shouldn't contain 'some enclosures were not satisfied'.\n If it does, report it !\n"): printf("----DONE---\n") : interval-3.2.0/src/crlibm/maple/log-de.patterson.mpl0000644000000000000000000002765513316017127020542 0ustar 00000000000000####################################################################### # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # To use: # restart; read "log-de.mpl"; Digits := 200: interface(quiet=true): read "common-procedures.mpl": read "double-extended.mpl": mkdir("PATERSON"): log2h,log2l := hiloExt(log(2)): L := 7: # number of bits used to address the table MAXINDEX := round(2^L * (sqrt(2)-1)): for i from 0 to MAXINDEX-1 do center[i] := 1 + i*2^(-L): # center[i] in [1, 2[ # We want it to fit on 11 bits of mantissa r[i] := round(evalf( (1/center[i]) * 2^(11)) ) / 2^(11) ; od: for i from MAXINDEX to 2^L do # y has been divided by two, center[i] in [0.5, 1[ center[i]:=(1 + i*2^(-L)) / 2: # We want it to fit on 11 bits of mantissa, r[i] := round(evalf( (1/center[i]) * 2^(10)) ) / 2^(10) ; od: # Note that we go up to 2^L although the case 2^L is wrapped to zero # in the C code. It could be important for zmax (but it turns out not). for i from 0 to 2^L do (logirh[i], logirl[i]) := hiloExt(-log(r[i])): od: #Computation of ZMax. for i from 0 to MAXINDEX-1 do t_x := center[i] + 2^(-L-1) : zmax[i] := (t_x*r[i]-1) : t_x := center[i] - 2^(-L-1) : zmin[i] := (t_x*r[i]-1) : zabsmax[i] := max(abs(zmin[i]), abs(zmax[i])): od: for i from MAXINDEX to 2^L do t_x := center[i] + 2^(-L-2) : zmax[i] := (t_x*r[i]-1) : t_x := center[i] - 2^(-L-2) : zmin[i] := (t_x*r[i]-1) : zabsmax[i] := max(abs(zmin[i]), abs(zmax[i])): od: zmaxmax:=0: zminmin:=0: for i from 0 to 2^L do if zmax[i] > zmaxmax then zmaxmax := zmax[i]: fi: if zmin[i] < zminmin then zminmin := zmin[i]: fi: od: printf("zminmin = -2^(%2f) zmaxmax = 2^(%2f)\n", log2(-zminmin), log2(zmaxmax) ) : PolyDegreeQuick:=7: #Keep -zmaxmax..zmaxmax to keep c1=1, which is useful in the proof ###### PHASE RAPIDE polyQuick0:= x * numapprox[minimax]( log(1+x)/x, x=-zmaxmax..zmaxmax, [PolyDegreeQuick-1,0], 1 , 'deltaApprox'): ## Création des nouveaux coefficients a7 := convert(coeff(polyQuick0,x,7),rational): a6 := convert(coeff(polyQuick0,x,6)/a7,rational): a5 := convert(coeff(polyQuick0,x,5)/a7,rational): a4 := convert(coeff(polyQuick0,x,4)/a7,rational): a3 := convert(coeff(polyQuick0,x,3),rational): a2 := convert(coeff(polyQuick0,x,2),rational): a1 := convert(coeff(polyQuick0,x,1),rational): a0 := convert(coeff(polyQuick0,x,0),rational): alpha0 := a5 - 1: alpha1 := a6: alpha2 := a4 - alpha0 * a6: ## a7_hi,a7_lo := hiloExt(a7): a3_hi,a3_lo := hiloExt(a3): a2_hi,a2_lo := hiloExt(a2): a0_hi,a0_lo := hiloExt(a0): c_hi,c_lo := hiloExt(alpha0): alpha_hi,alpha_lo := hiloExt(alpha1): beta_hi,beta_lo := hiloExt(alpha2): coef_c := c_hi + c_lo: coef_alpha := alpha_hi + alpha_lo: coef_beta := beta_hi + beta_lo: coef_c7 := a7_hi + a7_lo: coef_c3 := a3_hi + a3_lo: coef_c2 := a2_hi + a2_lo: coef_c0 := a0_hi + a0_lo: polyQuick := ((x^2 + coef_c)*(x + coef_alpha) + (x + coef_beta)) * (coef_c7*x^4) + ((coef_c3 * x + coef_c2)*x^2 + (x)): epsilonApproxQuick := numapprox[infnorm]( 1-polyQuick/log(1+x), x=zminmin..zmaxmax): printf(" approximation rel error for the quick phase is 2^(%2f)\n", log2(epsilonApproxQuick) ) : deltaApproxQuick := numapprox[infnorm]( polyQuick-log(1+x), x=zminmin..zmaxmax): printf(" approximation abs error for the quick phase is 2^(%2f)\n", log2(deltaApproxQuick) ) : ################################################################################################ PolyDegreeAccurate:=14: printf("Computing the polynomial for accurate phase (this may take some time...)\n"): pe:= x * numapprox[minimax]( log(1+x)/x, x=-zmaxmax..zmaxmax, [PolyDegreeAccurate-1,0], 1 , 'deltaApprox'): MaxDegreeDDE:=8: # polyAccurate := polyExact2Ext(pe, MaxDegreeDDE): deltaApproxAccurate := numapprox[infnorm](polyAccurate-log(1+x), x=-zmaxmax..zmaxmax): epsilonApproxAccurate := numapprox[infnorm]( 1-polyAccurate/log(1+x), x=-zmaxmax..zmaxmax): printf(" approximation error for the accurate phase is 2^(%2f)\n", log2(epsilonApproxAccurate) ) : filename:="PATERSON/log-de.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "/*File generated by maple/log-de.mpl*/\n\n"): fprintf(fd, "#if defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)\n\n"): fprintf(fd, "#ifndef PATERSON\n#define PATERSON\n#endif\n"): for i from PolyDegreeAccurate to 1 by -1 do fprintf(fd, "#define c%dh ch[%d]\n", i, PolyDegreeAccurate-i): od: for i from MaxDegreeDDE-1 to 1 by -1 do fprintf(fd, "#define c%dl cl[%d]\n", i, MaxDegreeDDE-1-i): od: fprintf(fd, "#define PREFETCH_POLY_ACCURATE \n"): fprintf(fd, "\n#else /* not(defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64)),\n assuming Itanium, otherwise we shouldn't be there */ \n\n"): fprintf(fd, "\n#define PREFETCH_POLY_ACCURATE "): for i from PolyDegreeAccurate to 1 by -1 do fprintf(fd, "c%dh=ch[%d]; ", i, PolyDegreeAccurate-i): if i mod 4 =0 then fprintf(fd, "\\\n "): fi: od: fprintf(fd, "\\\n "): for i from MaxDegreeDDE-1 to 1 by -1 do fprintf(fd, "c%dl=cl[%d]; ", i, MaxDegreeDDE-1-i): od: fprintf(fd, "\n#endif /* defined(CRLIBM_TYPECPU_X86) || defined(CRLIBM_TYPECPU_AMD64) */ \n\n"): # Various constants fprintf(fd, "#define L %d\n", L): fprintf(fd, "#define MAXINDEX %d\n", MAXINDEX): fprintf(fd, "#define INDEXMASK %d\n", 2^L-1): fprintf(fd, "static const long double log2h = %1.50eL ;\n", log2h): fprintf(fd, "static const long double log2l = %1.50eL ;\n", log2l): fprintf(fd, "static const long double two64 = %1.50eL ;\n", evalf(2^64)): # The polynomials # polynomial for quick phase fprintf(fd,"static const long double c7 = %1.50e;\n",coef_c7): fprintf(fd,"static const long double c3 = %1.50e;\n",coef_c3): fprintf(fd,"static const long double c2 = %1.50e;\n",coef_c2): fprintf(fd,"static const long double ps_alpha = %1.50e;\n",coef_alpha): fprintf(fd,"static const long double ps_beta = %1.50e;\n",coef_beta): fprintf(fd,"static const long double ps_c = %1.50e;\n",coef_c): # polynomial for accurate phase fprintf(fd, "static const long double ch[%d] = {\n",PolyDegreeAccurate): for i from PolyDegreeAccurate to 1 by -1 do (ch, cl) := hiloExt(coeff(polyAccurate,x,i)): fprintf(fd, " /* ch%d = */ %1.50eL, \n", i, ch): od: fprintf(fd, "}; \n \n"): fprintf(fd, "static const long double cl[%d] = {\n", MaxDegreeDDE): for i from MaxDegreeDDE-1 to 1 by -1 do (ch, cl) := hiloExt(coeff(polyAccurate,x,i)): fprintf(fd, " /* cl%d = */ %1.50eL, \n", i, cl): od: fprintf(fd, "}; \n \n"): # The tables fprintf(fd, "typedef struct rri_tag {float r; long double logirh; long double logirl; } rri ; \n"): fprintf(fd, "static const rri argredtable[%d] = {\n", 2^L): for i from 0 to 2^L-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50eL, /* r[%d] */ \n", r[i], i): fprintf(fd, " %1.50eL, /* logirh[%d] */ \n", logirh[i], i): fprintf(fd, " %1.50eL, /* logirl[%d] */ \n", logirl[i], i): fprintf(fd, " } "): if(i<2^L-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fclose(fd): printf("\n************ DONE PATERSON/log-de.h ************\n"); filename:="PATERSON/polynomials.sed": fd:=fopen(filename, WRITE, TEXT): for i from PolyDegreeAccurate to 1 by -1 do (ch, cl) := hiloExt(coeff(polyAccurate,x,i)): fprintf(fd, " s/_c%dh/%1.40e/g\n", i, ch): if(i ../maple/PATERSON/Gappa.out\n"): printf(" (You probably need to edit the path to the gappa executable within run-log-de-proof.sh)\n"): printf("Then look at PATERSON/Gappa.out. It shouldn't contain 'some enclosures were not satisfied'.\n If it does, report it !\n"): printf("----DONE---\n") : interval-3.2.0/src/crlibm/maple/log-td.mpl0000644000000000000000000003352113316017127016530 0ustar 00000000000000####################################################################### # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # To use: # restart; read "log-de.mpl"; Digits := 120: interface(quiet=true): read "common-procedures.mpl": read "triple-double.mpl": mkdir("TEMPLOG"): # We want log2h + log2m + log2l + delta = log(2) such that # log2h and log2m have at least 11 trailing zeros # in order to have an exact multiplication with E, which is lower than 1024 in # magnitude # The resting accuracy is enough for both quick and accurate phases. log2acc := log(2): log2h := round(log2acc * 2**(floor(-log[2](abs(log2acc))) + (53 - 11))) / 2**(floor(-log[2](abs(log2acc))) + (53 - 11)): log2m := round((log2acc - log2h) * 2**(floor(-log[2](abs((log2acc - log2h)))) + (53 - 11))) / 2**(floor(-log[2](abs((log2acc - log2h)))) + (53 - 11)): log2l := log2acc - (log2h + log2m): L := 7: # number of bits used to address the table MAXINDEX := round(2^L * (sqrt(2)-1)): for i from 0 to MAXINDEX-1 do center[i] := 1 + i*2^(-L): # center[i] in [1, 2[ t := evalf(1/center[i]): r[i] := round(t * 2**(floor(-log[2](abs(t))) + 23)) / 2**(floor(-log[2](abs(t))) + 23): (logih[i], logim[i], logil[i]) := hi_mi_lo(evalf(-log(r[i]))): od: for i from MAXINDEX to 2^L do # y has been divided by two, center[i] in [0.5, 1[ center[i]:=(1 + i*2^(-L)) / 2: t := evalf(1/center[i]): r[i] := round(t * 2**(floor(-log[2](abs(t))) + 23)) / 2**(floor(-log[2](abs(t))) + 23): (logih[i], logim[i], logil[i]) := hi_mi_lo(evalf(-log(r[i]))): od: #Computation of ZMax. for i from 0 to MAXINDEX-1 do __x := center[i] + 2^(-L-1) : zmax[i] := (__x*r[i]-1) : __x := center[i] - 2^(-L-1) : zmin[i] := (__x*r[i]-1) : od: for i from MAXINDEX to 2^L do __x := center[i] + 2^(-L-2) : zmax[i] := (__x*r[i]-1) : __x := center[i] - 2^(-L-2) : zmin[i] := (__x*r[i]-1) : od: zmaxmax:=0: zminmin:=0: for i from 0 to 2^L do tabulated_value := logih[i] + logim[i] + logil[i]: poly_approx_min := evalf(log(1+zmin[i])): poly_approx_max := evalf(log(1+zmax[i])): # Test if we have a case where we cancellate a lot # i.e. the polynomial approximation value is greater than half the tabulated value # the tabulated value is not exactly zero and we are of opposite sign if ((abs(poly_approx_min) > 0.75*abs(tabulated_value)) and (tabulated_value <> 0.0) and (poly_approx_min * tabulated_value < 0)) then printf("Polynomial approximation is greater in magnitude in zmin[%d] than half the tabluated value\n",i): printf("The tabulated value is %1.50e\n",tabulated_value): if (tabulated_value <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(tabulated_value)))) fi: printf("The value of polynomial in zmin[%d] is %1.50e\n",i,poly_approx_min): if (poly_approx_min <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(poly_approx_min)))) fi: summe := poly_approx_min + tabulated_value: printf("The exponent of the sum of both is %d\n",floor(log2(abs(summe)))): fi: if ((abs(poly_approx_max) > 0.75*abs(tabulated_value)) and (tabulated_value <> 0.0) and (poly_approx_max * tabulated_value <0)) then printf("Polynomial approximation is greater in magnitude in zmax[%d] than half the tabluated value\n",i): printf("The tabulated value is %1.50e\n",tabulated_value): if (tabulated_value <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(tabulated_value)))) fi: printf("The value of polynomial in zmax[%d] is %1.50e\n",i,poly_approx_max): if (poly_approx_max <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(poly_approx_max)))) fi: summe := poly_approx_max + tabulated_value: printf("The exponent of the sum of both is %d\n",floor(log2(abs(summe)))): fi: if zmax[i] > zmaxmax then zmaxmax := zmax[i]: fi: if zmin[i] < zminmin then zminmin := zmin[i]: fi: od: printf("zminmin = -2^(%2f) zmaxmax = 2^(%2f)\n", log2(-zminmin), log2(zmaxmax) ) : PolyDegreeQuick:=7: printf(" degree of the polynomial used in the quick phase is %d\n",PolyDegreeQuick); DDNumberQuick:=3: printf(" number of double doubles used for the coefficients is %d\n",DDNumberQuick); #Keep -zmaxmax..zmaxmax to keep c1=1, which is useful in the proof #and constrain the first two coefficients to 1 and -1/2 in order to save up a full multiplication and a rounding error polyQuick:= poly_exact2(x*(1+x*(-0.5+x*(numapprox[minimax]((((log(1+x)/x)-1)/x+0.5)/x, x=-zmaxmax..zmaxmax, [PolyDegreeQuick-3,0], 1 , 'deltaApprox')))), DDNumberQuick): #Try to verify the bound for using double double arithmetic. #Idea: compare the maximum absolute value of the polynomial in zmaxmax (the polynomial has its maxima at the limits) #with the maximum value of the first term which is calculated in double precision only p := unapply(polyQuick,x): printf(" using only %d double doubles should be fine since the hi z ulp should affect the result starting from bit %f\n", DDNumberQuick,evalf(53 + log2(p(zmaxmax)) - log2(zmaxmax^(DDNumberQuick)),5)): epsilonApproxQuick := numapprox[infnorm]( 1-polyQuick/log(1+x), x=zminmin..zmaxmax): printf(" approximation rel error for the quick phase is 2^(%2f)\n", log2(epsilonApproxQuick) ) : deltaApproxQuick := numapprox[infnorm]( polyQuick-log(1+x), x=zminmin..zmaxmax): printf(" approximation abs error for the quick phase is 2^(%2f)\n", log2(deltaApproxQuick) ) : PolyDegreeAccurate:=14: printf(" degree of the polynomial used in the accurate phase is %d\n",PolyDegreeAccurate); DDNumberAccu:=7: TDNumberAccu:=3: printf(" number of triple doubles used for the coefficients is %d\n",TDNumberAccu); printf(" number of double doubles used for the coefficients is %d\n",DDNumberAccu); #Keep -zmaxmax..zmaxmax to keep c1=1, which is useful in the proof polyAccurate:= poly_exact32(x*(1+x*(-0.5+x*(numapprox[minimax]((((log(1+x)/x)-1)/x+0.5)/x, x=-zmaxmax..zmaxmax, [PolyDegreeAccurate-3,0], 1 , 'deltaApprox')))), TDNumberAccu, DDNumberAccu): #Try to verify the bound for using double double arithmetic. #Idea: compare the maximum absolute value of the polynomial in zmaxmax (the polynomial has its maxima at the limits) #with the maximum value of the first term which is calculated in double precision only pp := unapply(polyAccurate,x): printf(" using only %d triple doubles should be fine since the mi z ulp should affect the result starting from bit %f\n", TDNumberAccu,evalf(106 + log2(p(zmaxmax)) - log2(zmaxmax^(TDNumberAccu)),5)): printf(" using only %d double doubles should be fine since the hi z ulp should affect the result starting from bit %f\n", DDNumberAccu,evalf(53 + log2(p(zmaxmax)) - log2(zmaxmax^(TDNumberAccu + DDNumberAccu)),5)): epsilonApproxAccurate := numapprox[infnorm]( 1-polyAccurate/log(1+x), x=zminmin..zmaxmax): printf(" approximation rel error for the accurate phase is 2^(%2f)\n", log2(epsilonApproxAccurate) ) : deltaApproxAccurate := numapprox[infnorm]( polyAccurate-log(1+x), x=zminmin..zmaxmax): printf(" approximation abs error for the quick phase is 2^(%2f)\n", log2(deltaApproxAccurate) ) : #------------------------------------------------------------------- # Output filename:="TEMPLOG/log-td.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#include \"crlibm.h\"\n#include \"crlibm_private.h\"\n"): fprintf(fd, "\n/*File generated by maple/log-td.mpl*/\n"): fprintf(fd, "\n\#define L %d\n\n",L): fprintf(fd, "\#define MAXINDEX %d\n\n", MAXINDEX): fprintf(fd, "\#define INDEXMASK %d\n", 2^L-1): fprintf(fd, "\#define two52 %1.50e\n", 2^(52)): fprintf(fd, "\#define log2h %1.50e\n", log2h): fprintf(fd, "\#define log2m %1.50e\n", log2m): fprintf(fd, "\#define log2l %1.50e\n", log2l): epsilon_quick_1 := 2^(-62.5): # The Gappa proof will show this bound epsilon_quick_2 := 2^(-62.5): # The Gappa proof will show this bound fprintf(fd, "\#define ROUNDCST1 %1.50e\n", compute_rn_constant(epsilon_quick_1)): fprintf(fd, "\#define ROUNDCST2 %1.50e\n", compute_rn_constant(epsilon_quick_2)): fprintf(fd, "\#define RDROUNDCST1 %1.50e\n", epsilon_quick_1): fprintf(fd, "\#define RDROUNDCST2 %1.50e\n", epsilon_quick_2): fprintf(fd, "\n\n"): # Print the defines for the define statements for i from 3 to PolyDegreeQuick do fprintf(fd, "\#define c%d %1.50e\n",i,coeff(polyQuick,x,i)): od: fprintf(fd, "\n\n"): for i from 3 to (DDNumberAccu + TDNumberAccu -1) do (hi,lo) := hi_lo(coeff(polyAccurate,x,i)): fprintf(fd, "\#define accPolyC%dh %1.50e\n",i,hi): fprintf(fd, "\#define accPolyC%dl %1.50e\n",i,lo): od: for i from (DDNumberAccu + TDNumberAccu) to PolyDegreeAccurate do fprintf(fd, "\#define accPolyC%d %1.50e\n",i,coeff(polyAccurate,x,i)): od: fprintf(fd, "\n\n"): # Print the table fprintf(fd, "typedef struct rri_tag {float ri; double logih; double logim; double logil;} rri; \n"): fprintf(fd, "static const rri argredtable[%d] = {\n", 2^L): for i from 0 to 2^L-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50e, /* r[%d] */ \n", r[i], i): fprintf(fd, " %1.50e, /* logih[%d] */ \n", logih[i], i): fprintf(fd, " %1.50e, /* logim[%d] */ \n", logim[i], i): fprintf(fd, " %1.50e, /* logil[%d] */ \n", logil[i], i): fprintf(fd, " } "): if(i<2^L-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fclose(fd): for j from 0 to 2^L-1 do filename:=cat("TEMPLOG/log-td_",j,".sed"): fd:=fopen(filename, WRITE, TEXT): fprintf(fd, " s/_log2h/%1.50e/g\n", log2h): fprintf(fd, " s/_log2m/%1.50e/g\n", log2m): fprintf(fd, " s/_log2l/%1.50e/g\n", log2l): fprintf(fd, " s/_logih/%1.50e/g\n", logih[j]): fprintf(fd, " s/_logim/%1.50e/g\n", logim[j]): fprintf(fd, " s/_logil/%1.50e/g\n", logil[j]): fprintf(fd, " s/_zmin/%1.50e/g\n", zmin[j]): fprintf(fd, " s/_zmax/%1.50e/g\n", zmax[j]): for i from 3 to PolyDegreeQuick do fprintf(fd, " s/_c%d/%1.50e/g\n", i, coeff(polyQuick,x,i)): od: fprintf(fd, " s/_epsilonApproxQuick/%1.50e/g\n", epsilonApproxQuick): fclose(fd): od: for j from 0 to 2^L-1 do filename:=cat("TEMPLOG/log-td-accurate_",j,".sed"): fd:=fopen(filename, WRITE, TEXT): fprintf(fd, " s/_log2h/%1.50e/g\n", log2h): fprintf(fd, " s/_log2m/%1.50e/g\n", log2m): fprintf(fd, " s/_log2l/%1.50e/g\n", log2l): fprintf(fd, " s/_logih/%1.50e/g\n", logih[j]): fprintf(fd, " s/_logim/%1.50e/g\n", logim[j]): fprintf(fd, " s/_logil/%1.50e/g\n", logil[j]): fprintf(fd, " s/_zmin/%1.50e/g\n", zmin[j]): fprintf(fd, " s/_zmax/%1.50e/g\n", zmax[j]): for i from 3 to (DDNumberAccu + TDNumberAccu -1) do (hi,lo) := hi_lo(coeff(polyAccurate,x,i)): fprintf(fd, " s/_accPolyC%dh/%1.50e/g\n", i, hi): fprintf(fd, " s/_accPolyC%dl/%1.50e/g\n", i, lo): od: for i from (DDNumberAccu + TDNumberAccu) to PolyDegreeAccurate do fprintf(fd, " s/_accPolyC%d/%1.50e/g\n", i, coeff(polyAccurate,x,i)): od: fprintf(fd, " s/_epsilonApproxAccurate/%1.50e/g\n", epsilonApproxAccurate): fclose(fd): od: # A shell script to use them filename:="run-log-td-proof.sh": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#!/bin/sh\n"): fprintf(fd, "# You probably need to edit the path to the gappa executable\n"): fprintf(fd, "GAPPA=~/sangria/gappa-0.4.7/src/gappa\n"): fprintf(fd, "# Test all the possible table value for E=1\n"): fprintf(fd, "for num in `seq 0 %d`; do\n", 2^L-1): fprintf(fd, " echo $num, E=1:\n"): fprintf(fd, " sed -f ./TEMPLOG/log-td_$num.sed log-td.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fprintf(fd, "# For the case E=0 we first handle the cases 0 and %d using log-td-E0-logir0.gappa\n", 2^L): fprintf(fd, "echo 0 and %d, E=0:\n", 2^L): fprintf(fd, "sed -f log-td_0.sed log-td-E0-logir0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, "# then the other cases where logirh <> 0\n"): fprintf(fd, "for num in `seq 1 %d`; do\n", 2^L-1): fprintf(fd, " echo $num, E=0:\n"): fprintf(fd, " sed -f ./TEMPLOG/log-td_$num.sed log-td-E0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fprintf(fd, "# Accurate phase: Test all the possible table value for E=1\n"): fprintf(fd, "for num in `seq 0 %d`; do\n", 2^L-1): fprintf(fd, " echo Accurate phase: $num, E=1:\n"): fprintf(fd, " sed -f ./TEMPLOG/log-td-accurate_$num.sed log-td-accurate.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fprintf(fd, "# Accurate phase: For the case E=0 we first handle the cases 0 and %d using log-td-accurate-E0-logir0.gappa\n", 2^L): fprintf(fd, "echo 0 and %d, E=0:\n", 2^L): fprintf(fd, "sed -f ./TEMPLOG/log-td-accurate_0.sed log-td-accurate-E0-logir0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, "# Accurate phase: then the other cases where logirh <> 0\n"): fprintf(fd, "for num in `seq 1 %d`; do\n", 2^L-1): fprintf(fd, " echo $num, E=0:\n"): fprintf(fd, " sed -f ./TEMPLOG/log-td-accurate_$num.sed log-td-accurate-E0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fclose(fd): printf("----DONE---\n") : interval-3.2.0/src/crlibm/maple/log.mpl0000644000000000000000000003223613316017127016125 0ustar 00000000000000####################################################################### # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # To use: # restart; read "log.mpl"; Digits := 100: interface(quiet=true): read "common-procedures.mpl": mkdir("TEMPLOG"): deg:=12: # Error, (in mkdir) directory exists and is not empty ####################################################################### # First, quick phase # Approach for the first function: # log(x) = E*log(2) + P(R) # where P(R) is defined over such an interval [11/16; 12/16] ... [21/16; 23/16] # At all, there is 8 intervals, corresponding to 8 polynomials. # Computation of log(2) as a double-double # We want to compute E.log(2) where |E|<1024, and get the result as a double-double. # We store two double constants ln2hi and ln2lo, such that ln2hi has at most 43 non-zero bits in its mantissa, # such that # ln2hi+ln2lo = log(2) (1+2**-101) (see below log2(eps_ln2_cst) ) # and the multiplication of ln2hi by E is exact. Then we use a Fast2Sum to compute E.log2 as a double-double. ln2hi:= round( ln(2.) * (2**43)) / (2**43) : r:=evalf(ln(2) - ln2hi): bits_log2hi:=1+log2(op(2,ieeedouble(ln2hi)[3])): ln2lo:=nearest(ln(2.) - ln2hi): eps_ln2_cst:=abs( (ln2hi+ln2lo-ln(2.)) / ln(2.)): log2(eps_ln2_cst): # Performance parameters # Try adding one or removing one to bitsFastPath. This value is optimal for the Pentium IV bitsFastPath:=7: #idem for MedPath. Look at the proof for explanations. bitsMedPath:=4: minFastPath:=(2^bitsFastPath)+0.5: # such that |Elog(2) + p(z)| > 2^bitsFastPath where |p(z)| < 0.4 EminFastPath:=floor(minFastPath/log(2)): # such that |E| > EminFastPath => |Elog(2) + p(z)| > 2^bitsFastPath evalf((EminFastPath+1)*log(2)-0.4): # just checking minMedPath:=(2^bitsMedPath)+0.5: # such that |Elog(2) + p(z)| > 2^bitsMedPath where |p(z)| < 0.4 EminMedPath:=floor(minMedPath/log(2)): # such that |E| > EminMedPath => |Elog(2) + p(z)| > 2^bitsMedPath evalf((EminMedPath+1)*log(2)-0.4): # just checking # Interval parameters ymin := (1-2^(-50)) * sqrt(2)/2: # sqrt(2)/2 with margin for the FP comparison and for the computation of xmax ymax := (1+2^(-50)) * sqrt(2): # sqrt(2)/2 with margin for the FP comparison and for the computation of xmax Ilist:=[[ymin,12/16],[12/16,13/16],[13/16,14/16],[14/16,15/16],[15/16,17/16],[17/16,19/16],[19/16,21/16],[21/16,ymax]]: Xmax:=[(12/16-ymin)/2, 2**(-5), 2**(-5), 2**(-5), 2**(-4), 2**(-4), 2**(-4), (ymax - 21/16)/2]: midI:=[nearest((ymin+12/16)/2), 25/32, 27/32, 29/32, 1,18/16, 20/16, nearest((21/16+ymax)/2)]: # Computation of the polynomials # This is the function we use on all the intervals poly_log_2 := proc(i,deg) local p, pe, e, pt, delta_approx, epsilon_approx, delta_rounding, minptr, err, maxptr, maxpt, epsilon, miny, epsilonZero, epsilonEgtMed, ptFastPath,epsilonFastPath, minptrFastPath, maxptrFastPath, errlist, epsilon_lastmult, maxEln2_lo, s1, p1, maxres, c0h, c0l, maxP_hi, maxP_lo,delta_rounding_s1,maxp1,delta_rounding_p1: printf("Interval %d : ", i): if(i=5) # special case around 1, we impose that coeff0 = 0 then pe:=x * numapprox[minimax]( (log(1+x)/x), x=-Xmax[i]..Xmax[i], [deg-1,0], 1 , 'delta_approx'): pt := poly_exact2(pe, 2): delta_approx := numapprox[infnorm](pt-log(1+x), x=-Xmax[i]..Xmax[i]): epsilon_approx := numapprox[infnorm]( 1-pt/log(1+x), x=-Xmax[i]..Xmax[i]): maxpt:= numapprox[infnorm]( pt, x=-Xmax[i]..Xmax[i]): else pt, delta_approx, epsilon_approx, maxpt := poly_trunc_f2d_2( log(x+midI[i]) , deg, -Xmax[i], Xmax[i] ): end if: printf(" delta_approx = %3.2f, epsilon_approx = %3.2f, maxpt = %3.2f\n", -log2(delta_approx), -log2(epsilon_approx), maxpt): #delta for E=0 errlist := errlist_quickphase_horner(deg, 2, 2, 0,0): # two dd adds, two dd mul, no error on x epsilon_lastmult, delta_rounding, minptr, maxptr := compute_horner_rounding_error(pt, x, Xmax[i], errlist, true): if i=5 then epsilonZero := (1+epsilon_approx) * (1 + epsilon_lastmult) - 1 : else epsilonZero := (delta_approx + delta_rounding)/minptr: fi: printf(" epsilonZero = %3.2f ", -log2(epsilonZero)): # For 0 maxepsilonEZero then maxepsilonEZero := epsilonEZero : fi : if epsilon > maxepsilon then maxepsilon := epsilon : fi : if epsilonEgtMed > maxepsilonEgtMed then maxepsilonEgtMed := epsilonEgtMed : fi : if epsilonFastPath > maxepsilonFastPath then maxepsilonFastPath := epsilonFastPath : fi : od: rncstEZero := evalf(compute_rn_constant(maxepsilonEZero)): rncst := evalf(compute_rn_constant(maxepsilon)): rncstEgtMed := evalf(compute_rn_constant(maxepsilonEgtMed)): rncstFastPath := evalf(compute_rn_constant(maxepsilonFastPath)): #------------------------------------------------------------------- # Output filename:="TEMPLOG/log_fast.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#include \"crlibm.h\"\n#include \"crlibm_private.h\"\n"): fprintf(fd, "\n/*File generated by maple/log.mpl*/\n"): fprintf(fd, "\n\#define SQRT_2 1.4142135623730950489e0 \n\n"): fprintf(fd, "#define DEGREE %d\n\n", deg): fprintf(fd,"#define EMIN_MEDIUMPATH %4.3f \n",EminMedPath ): fprintf(fd,"#define EMIN_FASTPATH %4.3f \n",EminFastPath ): fprintf(fd,"/* Constants for rounding */\n"): fprintf(fd,"static const double epsilon[4] =\n{\n"): fprintf(fd," /* Case E=0 */\n"): fprintf(fd," %1.50e, \n",maxepsilonEZero): fprintf(fd," /* Middle case */\n"): fprintf(fd," %1.50e, \n",maxepsilon): fprintf(fd," /* Case E>EminMedPath */\n"): fprintf(fd," %1.50e, \n",maxepsilonEgtMed): fprintf(fd," /* And for the fast path */\n"): fprintf(fd," %1.50e \n",maxepsilonFastPath): fprintf(fd,"\n};\n\n"): fprintf(fd,"static const double rncst[4] =\n{\n"): fprintf(fd," /* Case E=0 */\n"): fprintf(fd," %1.50e, \n",rncstEZero): fprintf(fd," /* Middle case */\n"): fprintf(fd," %1.50e, \n",rncst): fprintf(fd," /* Case E>EminMedPath */\n"): fprintf(fd," %1.50e, \n",rncstEgtMed): fprintf(fd," /* And for the fast path */\n"): fprintf(fd," %1.50e \n",rncstFastPath): fprintf(fd,"};\n\n"): # THE POLYNOMIALS npol:=8: n:=2: # the degree from which we want two doubles fprintf(fd,"#ifdef WORDS_BIGENDIAN\n"): for isbig from 1 to 0 by -1 do if(isbig=0) then fprintf(fd,"#else\n"): fi: # Various constants fprintf(fd, "static const db_number ln2hi = "): printendian(fd,ln2hi,isbig): fprintf(fd, ";\n"): fprintf(fd, "static const db_number ln2lo = "): printendian(fd,ln2lo,isbig): fprintf(fd, ";\n"): fprintf(fd, "static const db_number two52 = "): printendian(fd, nearest(2.**52),isbig): fprintf(fd, ";\n"): # Write middle table fprintf(fd, "static const db_number middle[%d] =\n{\n",npol): for i from 1 to 7 do printendian(fd,midI[i],isbig): fprintf(fd," ,\n"): od: printendian(fd,midI[8],isbig): fprintf(fd, "\n};\n\n"): #Write Poly_h fprintf(fd,"static const db_number Poly_h[%d][%d] =\n{\n", npol, deg+1): for k from 1 to 8 do fprintf(fd," /* polynomial %d */\n",k): fprintf(fd,"{\n"): P:=PolyList[k][1]: for j from 0 to deg do coef:=hi_lo(coeff(P,x,j)): printendian(fd, coef[1], isbig): if j 0.75*abs(tabulated_value)) and (tabulated_value <> 0.0) and (poly_approx_min * tabulated_value < 0)) then printf("Polynomial approximation is greater in magnitude in zmin[%d] than half the tabluated value\n",i): printf("The tabulated value is %1.50e\n",tabulated_value): if (tabulated_value <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(tabulated_value)))) fi: printf("The value of polynomial in zmin[%d] is %1.50e\n",i,poly_approx_min): if (poly_approx_min <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(poly_approx_min)))) fi: summe := poly_approx_min + tabulated_value: printf("The exponent of the sum of both is %d\n",floor(log2(abs(summe)))): fi: if ((abs(poly_approx_max) > 0.75*abs(tabulated_value)) and (tabulated_value <> 0.0) and (poly_approx_max * tabulated_value <0)) then printf("Polynomial approximation is greater in magnitude in zmax[%d] than half the tabluated value\n",i): printf("The tabulated value is %1.50e\n",tabulated_value): if (tabulated_value <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(tabulated_value)))) fi: printf("The value of polynomial in zmax[%d] is %1.50e\n",i,poly_approx_max): if (poly_approx_max <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(poly_approx_max)))) fi: summe := poly_approx_max + tabulated_value: printf("The exponent of the sum of both is %d\n",floor(log2(abs(summe)))): fi: if zmax[i] > zmaxmax then zmaxmax := zmax[i]: fi: if zmin[i] < zminmin then zminmin := zmin[i]: fi: od: printf("zminmin = -2^(%2f) zmaxmax = 2^(%2f)\n", log2(-zminmin), log2(zmaxmax) ) : PolyDegreeQuick:=7: printf(" degree of the polynomial used in the quick phase is %d\n",PolyDegreeQuick); DDNumberQuick:=3: printf(" number of double doubles used for the coefficients is %d\n",DDNumberQuick); #Keep -zmaxmax..zmaxmax to keep c1=1, which is useful in the proof #and constrain the first two coefficients to 1 and -1/2 in order to save up a full multiplication and a rounding error polyQuick:= poly_exact2(x*(1+x*(-0.5+x*(numapprox[minimax]((((log(1+x)/x)-1)/x+0.5)/x, x=-zmaxmax..zmaxmax, [PolyDegreeQuick-3,0], 1 , 'deltaApprox')))), DDNumberQuick): #Try to verify the bound for using double double arithmetic. #Idea: compare the maximum absolute value of the polynomial in zmaxmax (the polynomial has its maxima at the limits) #with the maximum value of the first term which is calculated in double precision only p := unapply(polyQuick,x): printf(" using only %d double doubles should be fine since the hi z ulp should affect the result starting from bit %f\n", DDNumberQuick,evalf(53 + log2(p(zmaxmax)) - log2(zmaxmax^(DDNumberQuick)),5)): epsilonApproxQuick := numapprox[infnorm]( 1-polyQuick/log(1+x), x=zminmin..zmaxmax): printf(" approximation rel error for the quick phase is 2^(%2f)\n", log2(epsilonApproxQuick) ) : deltaApproxQuick := numapprox[infnorm]( polyQuick-log(1+x), x=zminmin..zmaxmax): printf(" approximation abs error for the quick phase is 2^(%2f)\n", log2(deltaApproxQuick) ) : PolyDegreeAccurate:=14: printf(" degree of the polynomial used in the accurate phase is %d\n",PolyDegreeAccurate); DDNumberAccu:=7: TDNumberAccu:=3: printf(" number of triple doubles used for the coefficients is %d\n",TDNumberAccu); printf(" number of double doubles used for the coefficients is %d\n",DDNumberAccu); #Keep -zmaxmax..zmaxmax to keep c1=1, which is useful in the proof polyAccurate:= poly_exact32(x*(1+x*(-0.5+x*(numapprox[minimax]((((log(1+x)/x)-1)/x+0.5)/x, x=-zmaxmax..zmaxmax, [PolyDegreeAccurate-3,0], 1 , 'deltaApprox')))), TDNumberAccu, DDNumberAccu): #Try to verify the bound for using double double arithmetic. #Idea: compare the maximum absolute value of the polynomial in zmaxmax (the polynomial has its maxima at the limits) #with the maximum value of the first term which is calculated in double precision only pp := unapply(polyAccurate,x): printf(" using only %d triple doubles should be fine since the mi z ulp should affect the result starting from bit %f\n", TDNumberAccu,evalf(106 + log2(p(zmaxmax)) - log2(zmaxmax^(TDNumberAccu)),5)): printf(" using only %d double doubles should be fine since the hi z ulp should affect the result starting from bit %f\n", DDNumberAccu,evalf(53 + log2(p(zmaxmax)) - log2(zmaxmax^(TDNumberAccu + DDNumberAccu)),5)): epsilonApproxAccurate := numapprox[infnorm]( 1-polyAccurate/log(1+x), x=zminmin..zmaxmax): printf(" approximation rel error for the accurate phase is 2^(%2f)\n", log2(epsilonApproxAccurate) ) : deltaApproxAccurate := numapprox[infnorm]( polyAccurate-log(1+x), x=zminmin..zmaxmax): printf(" approximation abs error for the quick phase is 2^(%2f)\n", log2(deltaApproxAccurate) ) : #Compute now the inverse of ln(10) for the final multiplication of ln(x) with this constant for obtaining log10(x) #Compute also the relative error of the constant stored as a triple double. Log10inv := evalf(1 / log(10)): (log10invh, log10invm, log10invl) := hi_mi_lo(Log10inv): Log10invhml := log10invh + log10invm + log10invl: epsilonLog10invhml := evalf(abs((Log10invhml - Log10inv) / Log10inv)): printf(" Log10inv = 1 / ln(10) stored as a triple-double is exact with a relative error of 2^(%2f)\n", evalf(log[2](epsilonLog10invhml))): #Compute now the constant needed for the unfiltered directed final rounding of the triple-double result #This constant is supposed to be the reciprocal of the critical accuracy of the function. #We suppose this critical accuracy to be 2^(-120) because the worst case (for RD) we know of is x = 403ce41d 8fa665fa #We can easily spend some guard bits since we want simply filter out cases with a theoretical worst case accuracy #of -infty (exact floating point images) and as we know that we are exact to at least 122 bits. wca := 2^(122): #------------------------------------------------------------------- # Output filename:="TEMPLOG/log10-td.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#include \"crlibm.h\"\n#include \"crlibm_private.h\"\n"): fprintf(fd, "\n/*File generated by maple/log10-td.mpl*/\n"): fprintf(fd, "\n\#define L %d\n\n",L): fprintf(fd, "\#define MAXINDEX %d\n\n", MAXINDEX): fprintf(fd, "\#define INDEXMASK %d\n", 2^L-1): fprintf(fd, "\#define two52 %1.50e\n", 2^(52)): fprintf(fd, "\#define log2h %1.50e\n", log2h): fprintf(fd, "\#define log2m %1.50e\n", log2m): fprintf(fd, "\#define log2l %1.50e\n", log2l): fprintf(fd, "\#define log10invh %1.50e\n",log10invh): fprintf(fd, "\#define log10invm %1.50e\n",log10invm): fprintf(fd, "\#define log10invl %1.50e\n",log10invl): fprintf(fd, "\#define WORSTCASEACCURACY %1.50e\n",wca): epsilon_quick_1 := 2^(-61): # The Gappa proof will show this bound epsilon_quick_2 := 2^(-61): # The Gappa proof will show this bound fprintf(fd, "\#define ROUNDCST1 %1.50e\n", compute_rn_constant(epsilon_quick_1)): fprintf(fd, "\#define ROUNDCST2 %1.50e\n", compute_rn_constant(epsilon_quick_2)): fprintf(fd, "\#define RDROUNDCST1 %1.50e\n", epsilon_quick_1): fprintf(fd, "\#define RDROUNDCST2 %1.50e\n", epsilon_quick_2): fprintf(fd, "\n\n"): # Print the defines for the define statements for i from 3 to PolyDegreeQuick do fprintf(fd, "\#define c%d %1.50e\n",i,coeff(polyQuick,x,i)): od: fprintf(fd, "\n\n"): for i from 3 to (DDNumberAccu + TDNumberAccu -1) do (hi,lo) := hi_lo(coeff(polyAccurate,x,i)): fprintf(fd, "\#define accPolyC%dh %1.50e\n",i,hi): fprintf(fd, "\#define accPolyC%dl %1.50e\n",i,lo): od: for i from (DDNumberAccu + TDNumberAccu) to PolyDegreeAccurate do fprintf(fd, "\#define accPolyC%d %1.50e\n",i,coeff(polyAccurate,x,i)): od: fprintf(fd, "\n\n"): # Print the table fprintf(fd, "typedef struct rri_tag {float ri; double logih; double logim; double logil;} rri; \n"): fprintf(fd, "static const rri argredtable[%d] = {\n", 2^L): for i from 0 to 2^L-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50e, /* r[%d] */ \n", r[i], i): fprintf(fd, " %1.50e, /* logih[%d] */ \n", logih[i], i): fprintf(fd, " %1.50e, /* logim[%d] */ \n", logim[i], i): fprintf(fd, " %1.50e, /* logil[%d] */ \n", logil[i], i): fprintf(fd, " } "): if(i<2^L-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fclose(fd): for j from 0 to 2^L-1 do filename:=cat("TEMPLOG/log10-td_",j,".sed"): fd:=fopen(filename, WRITE, TEXT): fprintf(fd, " s/_log2h/%1.50e/g\n", log2h): fprintf(fd, " s/_log2m/%1.50e/g\n", log2m): fprintf(fd, " s/_log2l/%1.50e/g\n", log2l): fprintf(fd, " s/_logih/%1.50e/g\n", logih[j]): fprintf(fd, " s/_logim/%1.50e/g\n", logim[j]): fprintf(fd, " s/_logil/%1.50e/g\n", logil[j]): fprintf(fd, " s/_zmin/%1.50e/g\n", zmin[j]): fprintf(fd, " s/_zmax/%1.50e/g\n", zmax[j]): for i from 3 to PolyDegreeQuick do fprintf(fd, " s/_c%d/%1.50e/g\n", i, coeff(polyQuick,x,i)): od: fprintf(fd, " s/_epsilonApproxQuick/%1.50e/g\n", epsilonApproxQuick): fprintf(fd, " s/_epsilonLog10invhml/%1.50e/g\n", epsilonLog10invhml): fclose(fd): od: for j from 0 to 2^L-1 do filename:=cat("TEMPLOG/log10-td-accurate_",j,".sed"): fd:=fopen(filename, WRITE, TEXT): fprintf(fd, " s/_log2h/%1.50e/g\n", log2h): fprintf(fd, " s/_log2m/%1.50e/g\n", log2m): fprintf(fd, " s/_log2l/%1.50e/g\n", log2l): fprintf(fd, " s/_logih/%1.50e/g\n", logih[j]): fprintf(fd, " s/_logim/%1.50e/g\n", logim[j]): fprintf(fd, " s/_logil/%1.50e/g\n", logil[j]): fprintf(fd, " s/_zmin/%1.50e/g\n", zmin[j]): fprintf(fd, " s/_zmax/%1.50e/g\n", zmax[j]): for i from 3 to (DDNumberAccu + TDNumberAccu -1) do (hi,lo) := hi_lo(coeff(polyAccurate,x,i)): fprintf(fd, " s/_accPolyC%dh/%1.50e/g\n", i, hi): fprintf(fd, " s/_accPolyC%dl/%1.50e/g\n", i, lo): od: for i from (DDNumberAccu + TDNumberAccu) to PolyDegreeAccurate do fprintf(fd, " s/_accPolyC%d/%1.50e/g\n", i, coeff(polyAccurate,x,i)): od: fprintf(fd, " s/_epsilonApproxAccurate/%1.50e/g\n", epsilonApproxAccurate): fprintf(fd, " s/_epsilonLog10invhml/%1.50e/g\n", epsilonLog10invhml): fclose(fd): od: # A shell script to use them filename:="run-log10-td-proof.sh": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#!/bin/sh\n"): fprintf(fd, "# You probably need to edit the path to the gappa executable\n"): fprintf(fd, "GAPPA=~/ble/gappa-0.4.5/src/gappa\n"): fprintf(fd, "# Test all the possible table value for E=1\n"): fprintf(fd, "for num in `seq 0 %d`; do\n", 2^L-1): fprintf(fd, " echo $num, E=1:\n"): fprintf(fd, " sed -f ./TEMPLOG/log10-td_$num.sed log10-td.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fprintf(fd, "# For the case E=0 we first handle the cases 0 and %d using log10-td-E0-logir0.gappa\n", 2^L): fprintf(fd, "echo 0 and %d, E=0:\n", 2^L): fprintf(fd, "sed -f log10-td_0.sed log10-td-E0-logir0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, "# then the other cases where logirh <> 0\n"): fprintf(fd, "for num in `seq 1 %d`; do\n", 2^L-1): fprintf(fd, " echo $num, E=0:\n"): fprintf(fd, " sed -f ./TEMPLOG/log10-td_$num.sed log10-td-E0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fprintf(fd, "# Accurate phase: Test all the possible table value for E=1\n"): fprintf(fd, "for num in `seq 0 %d`; do\n", 2^L-1): fprintf(fd, " echo Accurate phase: $num, E=1:\n"): fprintf(fd, " sed -f ./TEMPLOG/log10-td-accurate_$num.sed log10-td-accurate.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fprintf(fd, "# Accurate phase: For the case E=0 we first handle the cases 0 and %d using log10-td-accurate-E0-logir0.gappa\n", 2^L): fprintf(fd, "echo 0 and %d, E=0:\n", 2^L): fprintf(fd, "sed -f ./TEMPLOG/log10-td-accurate_0.sed log10-td-accurate-E0-logir0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, "# Accurate phase: then the other cases where logirh <> 0\n"): fprintf(fd, "for num in `seq 1 %d`; do\n", 2^L-1): fprintf(fd, " echo $num, E=0:\n"): fprintf(fd, " sed -f ./TEMPLOG/log10-td-accurate_$num.sed log10-td-accurate-E0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fclose(fd): printf("----DONE---\n") : interval-3.2.0/src/crlibm/maple/log2-td.mpl0000644000000000000000000003510113316017127016606 0ustar 00000000000000####################################################################### # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # To use: # restart; read "log2-td.mpl"; Digits := 120: interface(quiet=true): read "common-procedures.mpl": read "triple-double.mpl": mkdir("TEMPLOG"): # We want log2h + log2m + log2l + delta = log(2) such that # log2h and log2m have at least 11 trailing zeros # in order to have an exact multiplication with E, which is lower than 1024 in # magnitude # The resting accuracy is enough for both quick and accurate phases. log2acc := log(2): log2h := round(log2acc * 2**(floor(-log[2](abs(log2acc))) + (53 - 11))) / 2**(floor(-log[2](abs(log2acc))) + (53 - 11)): log2m := round((log2acc - log2h) * 2**(floor(-log[2](abs((log2acc - log2h)))) + (53 - 11))) / 2**(floor(-log[2](abs((log2acc - log2h)))) + (53 - 11)): log2l := log2acc - (log2h + log2m): L := 7: # number of bits used to address the table MAXINDEX := round(2^L * (sqrt(2)-1)): for i from 0 to MAXINDEX-1 do center[i] := 1 + i*2^(-L): # center[i] in [1, 2[ t := evalf(1/center[i]): r[i] := round(t * 2**(floor(-log[2](abs(t))) + 23)) / 2**(floor(-log[2](abs(t))) + 23): (logih[i], logim[i], logil[i]) := hi_mi_lo(evalf(-log(r[i]))): od: for i from MAXINDEX to 2^L do # y has been divided by two, center[i] in [0.5, 1[ center[i]:=(1 + i*2^(-L)) / 2: t := evalf(1/center[i]): r[i] := round(t * 2**(floor(-log[2](abs(t))) + 23)) / 2**(floor(-log[2](abs(t))) + 23): (logih[i], logim[i], logil[i]) := hi_mi_lo(evalf(-log(r[i]))): od: #Computation of ZMax. for i from 0 to MAXINDEX-1 do __x := center[i] + 2^(-L-1) : zmax[i] := (__x*r[i]-1) : __x := center[i] - 2^(-L-1) : zmin[i] := (__x*r[i]-1) : od: for i from MAXINDEX to 2^L do __x := center[i] + 2^(-L-2) : zmax[i] := (__x*r[i]-1) : __x := center[i] - 2^(-L-2) : zmin[i] := (__x*r[i]-1) : od: zmaxmax:=0: zminmin:=0: for i from 0 to 2^L do tabulated_value := logih[i] + logim[i] + logil[i]: poly_approx_min := evalf(log(1+zmin[i])): poly_approx_max := evalf(log(1+zmax[i])): # Test if we have a case where we cancellate a lot # i.e. the polynomial approximation value is greater than half the tabulated value # the tabulated value is not exactly zero and we are of opposite sign if ((abs(poly_approx_min) > 0.75*abs(tabulated_value)) and (tabulated_value <> 0.0) and (poly_approx_min * tabulated_value < 0)) then printf("Polynomial approximation is greater in magnitude in zmin[%d] than half the tabluated value\n",i): printf("The tabulated value is %1.50e\n",tabulated_value): if (tabulated_value <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(tabulated_value)))) fi: printf("The value of polynomial in zmin[%d] is %1.50e\n",i,poly_approx_min): if (poly_approx_min <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(poly_approx_min)))) fi: summe := poly_approx_min + tabulated_value: printf("The exponent of the sum of both is %d\n",floor(log2(abs(summe)))): fi: if ((abs(poly_approx_max) > 0.75*abs(tabulated_value)) and (tabulated_value <> 0.0) and (poly_approx_max * tabulated_value <0)) then printf("Polynomial approximation is greater in magnitude in zmax[%d] than half the tabluated value\n",i): printf("The tabulated value is %1.50e\n",tabulated_value): if (tabulated_value <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(tabulated_value)))) fi: printf("The value of polynomial in zmax[%d] is %1.50e\n",i,poly_approx_max): if (poly_approx_max <> 0.0) then printf("i.e. the value has the exponent %d\n",floor(log2(abs(poly_approx_max)))) fi: summe := poly_approx_max + tabulated_value: printf("The exponent of the sum of both is %d\n",floor(log2(abs(summe)))): fi: if zmax[i] > zmaxmax then zmaxmax := zmax[i]: fi: if zmin[i] < zminmin then zminmin := zmin[i]: fi: od: printf("zminmin = -2^(%2f) zmaxmax = 2^(%2f)\n", log2(-zminmin), log2(zmaxmax) ) : PolyDegreeQuick:=7: printf(" degree of the polynomial used in the quick phase is %d\n",PolyDegreeQuick); DDNumberQuick:=3: printf(" number of double doubles used for the coefficients is %d\n",DDNumberQuick); #Keep -zmaxmax..zmaxmax to keep c1=1, which is useful in the proof #and constrain the first two coefficients to 1 and -1/2 in order to save up a full multiplication and a rounding error polyQuick:= poly_exact2(x*(1+x*(-0.5+x*(numapprox[minimax]((((log(1+x)/x)-1)/x+0.5)/x, x=-zmaxmax..zmaxmax, [PolyDegreeQuick-3,0], 1 , 'deltaApprox')))), DDNumberQuick): #Try to verify the bound for using double double arithmetic. #Idea: compare the maximum absolute value of the polynomial in zmaxmax (the polynomial has its maxima at the limits) #with the maximum value of the first term which is calculated in double precision only p := unapply(polyQuick,x): printf(" using only %d double doubles should be fine since the hi z ulp should affect the result starting from bit %f\n", DDNumberQuick,evalf(53 + log2(p(zmaxmax)) - log2(zmaxmax^(DDNumberQuick)),5)): epsilonApproxQuick := numapprox[infnorm]( 1-polyQuick/log(1+x), x=zminmin..zmaxmax): printf(" approximation rel error for the quick phase is 2^(%2f)\n", log2(epsilonApproxQuick) ) : deltaApproxQuick := numapprox[infnorm]( polyQuick-log(1+x), x=zminmin..zmaxmax): printf(" approximation abs error for the quick phase is 2^(%2f)\n", log2(deltaApproxQuick) ) : PolyDegreeAccurate:=14: printf(" degree of the polynomial used in the accurate phase is %d\n",PolyDegreeAccurate); DDNumberAccu:=7: TDNumberAccu:=3: printf(" number of triple doubles used for the coefficients is %d\n",TDNumberAccu); printf(" number of double doubles used for the coefficients is %d\n",DDNumberAccu); #Keep -zmaxmax..zmaxmax to keep c1=1, which is useful in the proof polyAccurate:= poly_exact32(x*(1+x*(-0.5+x*(numapprox[minimax]((((log(1+x)/x)-1)/x+0.5)/x, x=-zmaxmax..zmaxmax, [PolyDegreeAccurate-3,0], 1 , 'deltaApprox')))), TDNumberAccu, DDNumberAccu): #Try to verify the bound for using double double arithmetic. #Idea: compare the maximum absolute value of the polynomial in zmaxmax (the polynomial has its maxima at the limits) #with the maximum value of the first term which is calculated in double precision only pp := unapply(polyAccurate,x): printf(" using only %d triple doubles should be fine since the mi z ulp should affect the result starting from bit %f\n", TDNumberAccu,evalf(106 + log2(p(zmaxmax)) - log2(zmaxmax^(TDNumberAccu)),5)): printf(" using only %d double doubles should be fine since the hi z ulp should affect the result starting from bit %f\n", DDNumberAccu,evalf(53 + log2(p(zmaxmax)) - log2(zmaxmax^(TDNumberAccu + DDNumberAccu)),5)): epsilonApproxAccurate := numapprox[infnorm]( 1-polyAccurate/log(1+x), x=zminmin..zmaxmax): printf(" approximation rel error for the accurate phase is 2^(%2f)\n", log2(epsilonApproxAccurate) ) : deltaApproxAccurate := numapprox[infnorm]( polyAccurate-log(1+x), x=zminmin..zmaxmax): printf(" approximation abs error for the quick phase is 2^(%2f)\n", log2(deltaApproxAccurate) ) : #Compute now the inverse of ln(2) for the final addition of ln(x) with this constant for obtaining log2(x) #Compute also the relative error of the constant stored as a double double. Log2inv := evalf(1 / log(2)): (log2invh, log2invl) := hi_lo(Log2inv): Log2invhl := log2invh + log2invl: epsilonLog2invhl := evalf(abs((Log2invhl - Log2inv) / Log2inv)): printf(" Log2inv = 1 / ln(2) stored as a double-double is exact with a relative error of 2^(%2f)\n", evalf(log[2](epsilonLog2invhl))): #------------------------------------------------------------------- # Output filename:="TEMPLOG/log2-td.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#include \"crlibm.h\"\n#include \"crlibm_private.h\"\n"): fprintf(fd, "\n/*File generated by maple/log2-td.mpl*/\n"): fprintf(fd, "\n\#define L %d\n\n",L): fprintf(fd, "\#define MAXINDEX %d\n\n", MAXINDEX): fprintf(fd, "\#define INDEXMASK %d\n", 2^L-1): fprintf(fd, "\#define two52 %1.50e\n", 2^(52)): fprintf(fd, "\#define log2h %1.50e\n", log2h): fprintf(fd, "\#define log2m %1.50e\n", log2m): fprintf(fd, "\#define log2l %1.50e\n", log2l): fprintf(fd, "\#define log2invh %1.50e\n",log2invh): fprintf(fd, "\#define log2invl %1.50e\n",log2invl): epsilon_quick_1 := 2^(-61): # The Gappa proof will show this bound epsilon_quick_2 := 2^(-61): # The Gappa proof will show this bound fprintf(fd, "\#define ROUNDCST1 %1.50e\n", compute_rn_constant(epsilon_quick_1)): fprintf(fd, "\#define ROUNDCST2 %1.50e\n", compute_rn_constant(epsilon_quick_2)): fprintf(fd, "\#define RDROUNDCST1 %1.50e\n", epsilon_quick_1): fprintf(fd, "\#define RDROUNDCST2 %1.50e\n", epsilon_quick_2): fprintf(fd, "\n\n"): # Print the defines for the define statements for i from 3 to PolyDegreeQuick do fprintf(fd, "\#define c%d %1.50e\n",i,coeff(polyQuick,x,i)): od: fprintf(fd, "\n\n"): for i from 3 to (DDNumberAccu + TDNumberAccu -1) do (hi,lo) := hi_lo(coeff(polyAccurate,x,i)): fprintf(fd, "\#define accPolyC%dh %1.50e\n",i,hi): fprintf(fd, "\#define accPolyC%dl %1.50e\n",i,lo): od: for i from (DDNumberAccu + TDNumberAccu) to PolyDegreeAccurate do fprintf(fd, "\#define accPolyC%d %1.50e\n",i,coeff(polyAccurate,x,i)): od: fprintf(fd, "\n\n"): # Print the table fprintf(fd, "typedef struct rri_tag {float ri; double logih; double logim; double logil;} rri; \n"): fprintf(fd, "static const rri argredtable[%d] = {\n", 2^L): for i from 0 to 2^L-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50e, /* r[%d] */ \n", r[i], i): fprintf(fd, " %1.50e, /* logih[%d] */ \n", logih[i], i): fprintf(fd, " %1.50e, /* logim[%d] */ \n", logim[i], i): fprintf(fd, " %1.50e, /* logil[%d] */ \n", logil[i], i): fprintf(fd, " } "): if(i<2^L-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fclose(fd): for j from 0 to 2^L-1 do filename:=cat("TEMPLOG/log2-td_",j,".sed"): fd:=fopen(filename, WRITE, TEXT): fprintf(fd, " s/_log2h/%1.50e/g\n", log2h): fprintf(fd, " s/_log2m/%1.50e/g\n", log2m): fprintf(fd, " s/_log2l/%1.50e/g\n", log2l): fprintf(fd, " s/_logih/%1.50e/g\n", logih[j]): fprintf(fd, " s/_logim/%1.50e/g\n", logim[j]): fprintf(fd, " s/_logil/%1.50e/g\n", logil[j]): fprintf(fd, " s/_zmin/%1.50e/g\n", zmin[j]): fprintf(fd, " s/_zmax/%1.50e/g\n", zmax[j]): for i from 3 to PolyDegreeQuick do fprintf(fd, " s/_c%d/%1.50e/g\n", i, coeff(polyQuick,x,i)): od: fprintf(fd, " s/_epsilonApproxQuick/%1.50e/g\n", epsilonApproxQuick): fprintf(fd, " s/_epsilonLog2invhl/%1.50e/g\n", epsilonLog2invhl): fclose(fd): od: for j from 0 to 2^L-1 do filename:=cat("TEMPLOG/log2-td-accurate_",j,".sed"): fd:=fopen(filename, WRITE, TEXT): fprintf(fd, " s/_log2h/%1.50e/g\n", log2h): fprintf(fd, " s/_log2m/%1.50e/g\n", log2m): fprintf(fd, " s/_log2l/%1.50e/g\n", log2l): fprintf(fd, " s/_logih/%1.50e/g\n", logih[j]): fprintf(fd, " s/_logim/%1.50e/g\n", logim[j]): fprintf(fd, " s/_logil/%1.50e/g\n", logil[j]): fprintf(fd, " s/_zmin/%1.50e/g\n", zmin[j]): fprintf(fd, " s/_zmax/%1.50e/g\n", zmax[j]): for i from 3 to (DDNumberAccu + TDNumberAccu -1) do (hi,lo) := hi_lo(coeff(polyAccurate,x,i)): fprintf(fd, " s/_accPolyC%dh/%1.50e/g\n", i, hi): fprintf(fd, " s/_accPolyC%dl/%1.50e/g\n", i, lo): od: for i from (DDNumberAccu + TDNumberAccu) to PolyDegreeAccurate do fprintf(fd, " s/_accPolyC%d/%1.50e/g\n", i, coeff(polyAccurate,x,i)): od: fprintf(fd, " s/_epsilonApproxAccurate/%1.50e/g\n", epsilonApproxAccurate): fprintf(fd, " s/_epsilonLog2invhl/%1.50e/g\n", epsilonLog2invhl): fclose(fd): od: # A shell script to use them filename:="run-log2-td-proof.sh": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#!/bin/sh\n"): fprintf(fd, "# You probably need to edit the path to the gappa executable\n"): fprintf(fd, "GAPPA=~/ble/gappa-0.4.5/src/gappa\n"): fprintf(fd, "# Test all the possible table value for E=1\n"): fprintf(fd, "for num in `seq 0 %d`; do\n", 2^L-1): fprintf(fd, " echo $num, E=1:\n"): fprintf(fd, " sed -f ./TEMPLOG/log2-td_$num.sed log2-td.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fprintf(fd, "# For the case E=0 we first handle the cases 0 and %d using log2-td-E0-logir0.gappa\n", 2^L): fprintf(fd, "echo 0 and %d, E=0:\n", 2^L): fprintf(fd, "sed -f log2-td_0.sed log2-td-E0-logir0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, "# then the other cases where logirh <> 0\n"): fprintf(fd, "for num in `seq 1 %d`; do\n", 2^L-1): fprintf(fd, " echo $num, E=0:\n"): fprintf(fd, " sed -f ./TEMPLOG/log2-td_$num.sed log2-td-E0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fprintf(fd, "# Accurate phase: Test all the possible table value for E=1\n"): fprintf(fd, "for num in `seq 0 %d`; do\n", 2^L-1): fprintf(fd, " echo Accurate phase: $num, E=1:\n"): fprintf(fd, " sed -f ./TEMPLOG/log2-td-accurate_$num.sed log2-td-accurate.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fprintf(fd, "# Accurate phase: For the case E=0 we first handle the cases 0 and %d using log2-td-accurate-E0-logir0.gappa\n", 2^L): fprintf(fd, "echo 0 and %d, E=0:\n", 2^L): fprintf(fd, "sed -f ./TEMPLOG/log2-td-accurate_0.sed log2-td-accurate-E0-logir0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, "# Accurate phase: then the other cases where logirh <> 0\n"): fprintf(fd, "for num in `seq 1 %d`; do\n", 2^L-1): fprintf(fd, " echo $num, E=0:\n"): fprintf(fd, " sed -f ./TEMPLOG/log2-td-accurate_$num.sed log2-td-accurate-E0.gappa | $GAPPA > /dev/null\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fclose(fd): printf("----DONE---\n") : interval-3.2.0/src/crlibm/maple/pow.mpl0000755000000000000000000003266413316017127016161 0ustar 00000000000000####################################################################### # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # To use: # restart; read "exp-td.mpl"; Digits := 120: interface(quiet=true): read "common-procedures.mpl": read "triple-double.mpl": mkdir("TEMPPOW"): # Some constants for special cases tests two52 := 2^(52): two53 := 2^(53): twoM53 := 2^(-53): twoM54 := 2^(-54): twoM1021 := 2^(-1021): two1021 := 2^(1021): twoM1000 := 2^(-1000): two1000 := 2^(1000): two999 := 2^(999): two11 := 2^(11): two64 := 2^(64): twoM64 := 2^(-64): scale := 2^(12): rescale := 2^(-12): shiftConst := 2^(52) + 2^(51): largest := 2^(1023) * ((2^(53) - 1) / 2^(52)): smallest := 2^(-1023) * 1 * 2^(-51): # Logarithm log2_12 for power L := 7: # number of bits used to address the table MAXINDEX := round(2^L * (sqrt(2)-1)): for i from 0 to MAXINDEX-1 do center[i] := 1 + i*2^(-L): # center[i] in [1, 2[ t := evalf(1/center[i]): r[i] := round(t * 2**(floor(-log[2](abs(t))) + 23)) / 2**(floor(-log[2](abs(t))) + 23): (logih[i], logil[i], logill[i]) := hi_mi_lo(evalf(-log[2](r[i]))): od: for i from MAXINDEX to 2^L do # y has been divided by two, center[i] in [0.5, 1[ center[i]:=(1 + i*2^(-L)) / 2: t := evalf(1/center[i]): r[i] := round(t * 2**(floor(-log[2](abs(t))) + 23)) / 2**(floor(-log[2](abs(t))) + 23): (logih[i], logil[i], logill[i]) := hi_mi_lo(evalf(-log[2](r[i]))): od: #Computation of ZMax. for i from 0 to MAXINDEX-1 do __x := center[i] + 2^(-L-1) : zmax[i] := (__x*r[i]-1) : __x := center[i] - 2^(-L-1) : zmin[i] := (__x*r[i]-1) : od: for i from MAXINDEX to 2^L do __x := center[i] + 2^(-L-2) : zmax[i] := (__x*r[i]-1) : __x := center[i] - 2^(-L-2) : zmin[i] := (__x*r[i]-1) : od: zmaxmax:=0: zminmin:=0: for i from 0 to 2^L do if zmax[i] > zmaxmax then zmaxmax := zmax[i]: fi: if zmin[i] < zminmin then zminmin := zmin[i]: fi: od: printf("zminmin = -2^(%2f) zmaxmax = 2^(%2f)\n", log2(-zminmin), log2(zmaxmax) ): pLogExact := unapply(-6497523352912697/36028797018963968*X^8+464105351149111/2251799813685248*X^7-4331547231022885/18014398509481984*X^6+324866042375467/1125899906842624*X^5-6497320848556805/18014398509481984*X^4+8460053188225/17592186044416*X^3-58522663504933901518104329421789/81129638414606681695789005144064*X^2+29261331752466950759073917813481/20282409603651670423947251286016*X,X): pLog := poly_exact2(pLogExact(x),3): epsLog := numapprox[infnorm](pLog/log[2](1+x)-1,x=zminmin..zmaxmax): printf("Relative error of pLog w.r.t log2(1+x) is 2^(%f)\n",log[2](abs(epsLog))): # Exponential exp2_12 for power for i from 0 to 2^6 - 1 do twoPowerIndex1hi[i], twoPowerIndex1lo[i], twoPowerIndex1lolo[i] := hi_mi_lo(evalf(2^(i/(2^6)))): twoPowerIndex2hi[i], twoPowerIndex2lo[i], twoPowerIndex2lolo[i] := hi_mi_lo(evalf(2^(i/(2^(12))))): od: pExpExact := unapply(2772236920359585/288230376151711744*X^4+1999746284130149/36028797018963968*X^3+8655072057804175/36028797018963968*X^2+6243314768165359/9007199254740992*X+1,X): pExp := poly_exact(pExpExact(x)): epsExp := numapprox[infnorm]((pExp/2^x)-1,x=-2^(-12)..2^(-12)): printf("Relative error of pExp w.r.t 2^x is 2^(%f)\n",log[2](abs(epsExp))): log2 := nearest(log(2)): # Exponential exp2_33 for power # Polynomial for approximating 2^x - 1 in x=-2^(-42)..2^(-42) pExpXM := unapply(poly_exact2(x * ((6243314768165359 * 2^(-53) + 29397410857115 * 2^(-100)) + (x * 8655072057804175 * 2^(-55))),2),x): epsExpXM := numapprox[infnorm](pExpXM(x)/(2^x-1)-1,x=-2^(-42)..2^(-42)): printf("The relative error of pExpXM w.r.t. 2^x - 1 is 2^(%f)\n",log[2](abs(epsExpXM))): # Polynomial for approximating 2^x - 1 in x=-2^(-95)..2^(-95) pExpXL := unapply(poly_exact(x * 6243314768165359 * 2^(-53)), x): epsExpXL := numapprox[infnorm](pExpXL(x)/(2^x-1)-1,x=-2^(-95)..2^(-95)): printf("The relative error of pExpXL w.r.t. 2^x - 1 is 2^(%f)\n",log[2](abs(epsExpXL))): # Polynomial for approximating 2^x in x=-2^(-12)..2^(-12) pExpXH := unapply(poly_exact32(x * (506517869649829535567849302923399275789356375957 * 2^(-159) + (x * (38978979294391673005692521213079 * 2^(-107) + (x * (36024226132016099441525232746301 * 2^(-109) + (x * (3121261346907607936312652866425 * 2^(-108) + (x * (55385433661433492776134419224183 * 2^(-115) + (x * (5682899659966205 * 2^(-65) + (x * (4501812434047971 * 2^(-68) + (x * 6240991224781291 * 2^(-72))))))))))))))),2,4),x): epsExpXH := numapprox[infnorm](pExpXH(x)/(2^x-1)-1,x=-2^(-12)..2^(-12)): printf("The relative error of pExpXH w.r.t. 2^x - 1 is 2^(%f)\n",log[2](abs(epsExpXH))): # Logarithm log2_13 for power pLog13 := unapply(poly_exact32(x * (65890661388387311068680317907364672336343222485 * 2^(-155) + (x * ((-263562645553549244274721271629458689351564598207 * 2^(-158)) + (x * (39015109003289267678766993386435 * 2^(-106) + (x * ((-29261331752466950759075245039823 * 2^(-106)) + (x * (11704532700986780303630098000775 * 2^(-105) + (x * ((-78030218006578535357533995772145 * 2^(-108)) + (x * (66883044005638744592219245028355 * 2^(-108) + (x * ((-14630665876233475378839909031845 * 2^(-106)) + (x * (721924538728533 * 2^(-52) + (x * ((-324866042427843 * 2^(-51)) + (x * (4725324253587977 * 2^(-55) + (x * ((-8663094456247059 * 2^(-56)) + (x * (7996693900181249 * 2^(-56) + (x * ((-7425880934468497 * 2^(-56)) + (x * 7091529758988931 * 2^(-56))))))))))))))))))))))))))))),3,6),x): epsLog13 := numapprox[infnorm](pLog13(x)/(log[2](1+x))-1,x=-2^(-8)..2^(-8)): printf("The relative error of pLog13 w.r.t. log2(1+x) is 2^(%f)\n",log[2](abs(epsLog13))): # exp2_30bits for exactness test coeff_0 := 9.99999999947486895024439945700578391551971435546875000000000000000000000000000000e-01: coeff_1 := 6.93147180274189311788290979166049510240554809570312500000000000000000000000000000e-01: coeff_2 := 2.40226513201275415632096610352164134383201599121093750000000000000000000000000000e-01: coeff_3 := 5.55041194035996443556513213479775004088878631591796875000000000000000000000000000e-02: coeff_4 := 9.61801251055323207228564541537707555107772350311279296875000000000000000000000000e-03: coeff_5 := 1.33325640280455024258565721595459763193503022193908691406250000000000000000000000e-03: coeff_6 := 1.54736006782907911617439000728779774362919852137565612792968750000000000000000000e-04: coeff_7 := 1.55294506644329091183710789270122631933190859854221343994140625000000000000000000e-05: pExp2Exact := unapply(coeff_0 + X * (coeff_1 + X * (coeff_2 + X * (coeff_3 + X * (coeff_4 + X * (coeff_5 + X * (coeff_6 + X * coeff_7)))))),X): pExp2 := poly_exact(pExp2Exact(x)): epsExp2 := numapprox[infnorm]((pExp2/2^x)-1,x=-0.5..0.5): printf("Relative error of pExp2 w.r.t 2^x is 2^(%f)\n",log[2](abs(epsExp2))): # Overall accuracy estimate # C'est pifometrique epsOverall := 2^(-62): bi := floor(-log[2](abs(epsOverall))): approxBoundFactor := 2^(-(bi - 54)): epsOverallAccurate := 2^(-120): bi2 := floor(-log[2](abs(epsOverallAccurate))) - 1: approxBoundFactorAccurate := 2^(-(bi2 - 54)): # Print out of the .h file filename:="TEMPPOW/pow.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#include \"crlibm.h\"\n#include \"crlibm_private.h\"\n"): fprintf(fd, "\n/*File generated by maple/pow.mpl*/\n"): fprintf(fd, "\#define APPROXBOUNDFACTOR %1.50e\n", approxBoundFactor): fprintf(fd, "\#define APPROXBOUNDFACTORACCURATE %1.50e\n", approxBoundFactorAccurate): fprintf(fd, "\#define TWO52 %1.50e\n", two52): fprintf(fd, "\#define TWO53 %1.50e\n", two53): fprintf(fd, "\#define TWO11 %1.50e\n", two11): fprintf(fd, "\#define TWOM53 %1.50e\n", twoM53): fprintf(fd, "\#define TWOM54 %1.50e\n", twoM54): fprintf(fd, "\#define TWOM1021 %1.50e\n", twoM1021): fprintf(fd, "\#define TWO1021 %1.50e\n", two1021): fprintf(fd, "\#define TWOM1000 %1.50e\n", twoM1000): fprintf(fd, "\#define TWO999 %1.50e\n", two999): fprintf(fd, "\#define TWO1000 %1.50e\n\n", two1000): fprintf(fd, "\#define TWO64 %1.50e\n", two64): fprintf(fd, "\#define TWOM64 %1.50e\n", twoM64): fprintf(fd, "\#define SCALE %1.50e\n", scale): fprintf(fd, "\#define RESCALE %1.50e\n", rescale): fprintf(fd, "\#define SHIFTCONSTANT %1.50e\n", shiftConst): fprintf(fd, "\#define LARGEST %1.50e\n",largest): fprintf(fd, "\#define SMALLEST %1.50e\n\n",smallest): (log2coeff1dh,log2coeff1dl) := hi_lo(coeff(pLog,x,1)): (log2coeff2dh,log2coeff2dl) := hi_lo(coeff(pLog,x,2)): fprintf(fd, "\#define log2coeff1h %1.50e\n",log2coeff1dh): fprintf(fd, "\#define log2coeff1l %1.50e\n",log2coeff1dl): fprintf(fd, "\#define log2coeff2h %1.50e\n",log2coeff2dh): fprintf(fd, "\#define log2coeff2l %1.50e\n",log2coeff2dl): for i from 3 to 8 do fprintf(fd, "\#define log2coeff%d %1.50e\n",i,coeff(pLog,x,i)): od: fprintf(fd,"\n"): for i from 1 to 4 do fprintf(fd, "\#define exp2coeff%d %1.50e\n",i,coeff(pExp,x,i)): od: fprintf(fd,"\n"): for i from 0 to 7 do fprintf(fd, "\#define exp2InaccuCoeff%d %1.50e\n",i,coeff(pExp2,x,i)): od: fprintf(fd,"\n"): (exp2XMcoeff1dh, exp2XMcoeff1dl) := hi_lo(coeff(pExpXM(x),x,1)): exp2XMcoeff2dh := nearest(coeff(pExpXM(x),x,2)): fprintf(fd, "\#define exp2XMcoeff1h %1.50e\n",exp2XMcoeff1dh): fprintf(fd, "\#define exp2XMcoeff1l %1.50e\n",exp2XMcoeff1dl): fprintf(fd, "\#define exp2XMcoeff2h %1.50e\n\n",exp2XMcoeff2dh): exp2XLcoeff1dh := nearest(coeff(pExpXL(x),x,1)): fprintf(fd, "\#define exp2XLcoeff1h %1.50e\n\n",exp2XLcoeff1dh): (exp2XHcoeff1dh,exp2XHcoeff1dm,exp2XHcoeff1dl) := hi_mi_lo(coeff(pExpXH(x),x,1)): fprintf(fd, "\#define exp2XHcoeff1h %1.50e\n",exp2XHcoeff1dh): fprintf(fd, "\#define exp2XHcoeff1m %1.50e\n",exp2XHcoeff1dm): fprintf(fd, "\#define exp2XHcoeff1l %1.50e\n",exp2XHcoeff1dl): for i from 2 to 5 do (exp2XHcoeffidh,exp2XHcoeffidl) := hi_lo(coeff(pExpXH(x),x,i)): fprintf(fd, "\#define exp2XHcoeff%dh %1.50e\n",i,exp2XHcoeffidh): fprintf(fd, "\#define exp2XHcoeff%dm %1.50e\n",i,exp2XHcoeffidl): od: for i from 6 to 8 do fprintf(fd, "\#define exp2XHcoeff%dh %1.50e\n",i,nearest(coeff(pExpXH(x),x,i))): od: fprintf(fd,"\n"): (log213coeff1dh,log213coeff1dm,log213coeff1dl) := hi_mi_lo(coeff(pLog13(x),x,1)): fprintf(fd, "\#define log213coeff1h %1.50e\n",log213coeff1dh): fprintf(fd, "\#define log213coeff1m %1.50e\n",log213coeff1dm): fprintf(fd, "\#define log213coeff1l %1.50e\n",log213coeff1dl): (log213coeff2dh,log213coeff2dm,log213coeff2dl) := hi_mi_lo(coeff(pLog13(x),x,2)): fprintf(fd, "\#define log213coeff2h %1.50e\n",log213coeff2dh): fprintf(fd, "\#define log213coeff2m %1.50e\n",log213coeff2dm): fprintf(fd, "\#define log213coeff2l %1.50e\n",log213coeff2dl): for i from 3 to 8 do (log213coeffidh, log213coeffidl) := hi_lo(coeff(pLog13(x),x,i)): fprintf(fd, "\#define log213coeff%dh %1.50e\n",i,log213coeffidh): fprintf(fd, "\#define log213coeff%dm %1.50e\n",i,log213coeffidl): od: for i from 9 to 15 do fprintf(fd, "\#define log213coeff%dh %1.50e\n",i,nearest(coeff(pLog13(x),x,i))): od: fprintf(fd, "\n\#define LOG2 %1.50e\n\n", log2): fprintf(fd, "typedef struct rri_tag {float ri; double logih; double logil; double logill;} rri; \n"): fprintf(fd, "static const rri argredtable[%d] = {\n", 2^L): for i from 0 to 2^L-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50e, /* r[%d] */ \n", r[i], i): fprintf(fd, " %1.50e, /* logih[%d] */ \n", logih[i], i): fprintf(fd, " %1.50e, /* logil[%d] */ \n", logil[i], i): fprintf(fd, " %1.50e, /* logill[%d] */ \n", logill[i], i): fprintf(fd, " } "): if(i<2^L-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fprintf(fd, "typedef struct tPi_t_tag {double hi; double lo; double lolo;} tPi_t; \n"): fprintf(fd, "static const tPi_t twoPowerIndex1[%d] = {\n", 2^(6)): for i from 0 to 2^(6)-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50e, /* twoPowerIndex1hi[%d] */ \n", twoPowerIndex1hi[i], i): fprintf(fd, " %1.50e, /* twoPowerIndex1lo[%d] */ \n", twoPowerIndex1lo[i], i): fprintf(fd, " %1.50e, /* twoPowerIndex1lolo[%d] */ \n", twoPowerIndex1lolo[i], i): fprintf(fd, " } "): if(i<2^(6)-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fprintf(fd, "static const tPi_t twoPowerIndex2[%d] = {\n", 2^(6)): for i from 0 to 2^(6)-1 do fprintf(fd, " { \n"): fprintf(fd, " %1.50e, /* twoPowerIndex2hi[%d] */ \n", twoPowerIndex2hi[i], i): fprintf(fd, " %1.50e, /* twoPowerIndex2lo[%d] */ \n", twoPowerIndex2lo[i], i): fprintf(fd, " %1.50e, /* twoPowerIndex2lolo[%d] */ \n", twoPowerIndex2lolo[i], i): fprintf(fd, " } "): if(i<2^(6)-1) then fprintf(fd, ", \n"): fi od: fprintf(fd, "}; \n \n"): fclose(fd): printf("--------- DONE -----------\n");interval-3.2.0/src/crlibm/maple/sqrt.mpl0000644000000000000000000000463113316017127016333 0ustar 00000000000000####################################################################### # This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # To use: # restart; read "sqrt.mpl"; Digits := 120: interface(quiet=true): read "common-procedures.mpl": read "triple-double.mpl": mkdir("TEMPSQRT"): polyDegree := 4: ERecSqrtmMin := 0.707: ERecSqrtmMax := 1.4143: xErrMin := evalf((1/(ERecSqrtmMax^2))): xErrMax := evalf((1/(ERecSqrtmMin^2))): printf("Using a %d degree polynomial for computing the iteration seed\n",polyDegree); polyExact := numapprox[minimax](1/sqrt(x),x=1/2..2,[polyDegree,0],1,'err'): poly := poly_exact(polyExact): eps := numapprox[infnorm]((poly*sqrt(x))-1,x=xErrMin..xErrMax): printf("Relative approximation error eps = 2^(%f)\n",log[2](abs(eps))): printf("Writing tables...\n"); filename:="TEMPSQRT/sqrt.h": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "\n/* File generated by maple/sqrt.mpl */\n"): for i from 0 to polyDegree do fprintf(fd, "\#define SQRTPOLYC%d %1.50e\n",i,coeff(poly,x,i)): od: fprintf(fd, "\#define TWO52 %1.50e\n",evalf(2^(52))): fclose(fd): filename:="TEMPSQRT/sqrt.sed": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "s/_epsilonApprox/%1.50e/g\n",eps): fprintf(fd, "s/_ERecSqrtmMin/%1.50e/g\n",ERecSqrtmMin): fprintf(fd, "s/_ERecSqrtmMax/%1.50e/g\n",ERecSqrtmMax): for i from 0 to polyDegree do fprintf(fd, "s/_SQRTPOLYC%d/%1.50e/g\n",i,coeff(poly,x,i)): od: fclose(fd): printf("... done\n");interval-3.2.0/src/crlibm/maple/trigo.mpl0000644000000000000000000006242113316017127016467 0ustar 00000000000000# This file is part of crlibm, the correctly rounded mathematical library, # which has been developed by the Arénaire project at École normale supérieure # de Lyon. # # Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, # Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, # and Jean-Michel Muller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Digits := 100: interface(quiet=true): read "common-procedures.mpl": with(orthopoly): mkdir("TEMPTRIG"): # - Evaluation scheme : # case 1 : return x # case 2 (or Fast) : compute a simple polynomial # case 3 : do an argument reduction... ######################################################## # Case 1 : Small arguments # return x for sine and tan, return 1 for cos ######################################################## xmax_return_x_for_sin := 2^(-26): xmax_return_1_for_cos_RN := sqrt(2^(-53)): xmax_return_1_for_cos_RDIR:=2^(-26): one_rounded_down := evalf(1-ulp(1/2)): xmax_return_x_for_tan := 2^(-27): ######################################################## # Case 2 : simple polynomial approximation ######################################################## # We want to use the same polynomial in case 2 and 3. # So see after arg red ################################################# # Case 3 : Argument reduction ################################################# ################################################# # CODY and WAITE Argument reduction C := Pi/256: invC:= nearest(1/C): reminvC := evalf(1/C - invC): expC:=ieeedouble(C)[2]: epsinvC := abs(reminvC*C): # There are three sets of constants : # - split redC into two constants, for small values when we are concerned with absolute error # - split redC into three constants, for larger values # - split redC into three doubles, for the cases when we need # good relative precision on the result and fear cancellation # Fastest reduction using two-part Cody and Waite (up to |k|=2^22) bitsCh_0:=34: # 1/2 <= C/2^(expC+1) <1 Ch:= round(evalf( C * 2^(bitsCh_0-expC-1))) / (2^(bitsCh_0-expC-1)): # recompute bitsCh in case we are lucky (and we are for bitsCh_0=32) bitsCh:=1+log2(op(2,ieeedouble(Ch)[3])) : # this means the log of the denominator Cl:=nearest(C - Ch): # Cody and Waite argument reduction will work for |k| /dev/null \n"); maxepstotalTanCase2:=4.59602e-19: # Cut from Gappa output log2(maxepstotalTanCase2): # almost 61 bits ############################################################################### # Computing errors for Case3 : now we have an error due to arg red # First DoSinZero. The notations are those of the paper proof # Approximation error already computed above as epsApproxSinCase3; # polynomial evaluation in double, with an error on y*y of epsilonArgRed errlist:=errlist_quickphase_horner(degree(polyTs2),0,0,eps_ArgRed, 0): (epsRoundingTsSinZero, deltaRoundingTsSinZero, minTs, maxTs):= compute_horner_rounding_error(polyTs2,y,y2maxCase3, errlist, true): # just as in the paper proof maxepsSinZero1 := (1+epsApproxSinCase3)*(1+epsRoundingTsSinZero)*(1+2^(-53))*(1+2^(-53)) - 1: # just as in the paper proof. For x>0 the absolute values are as given epstotalSinZero := ( (x-sin(x))*maxepsSinZero1 + x*eps_ArgRed + 2^(-53)*x^3/3 ) / sin(x): maxepstotalSinZero := numapprox[infnorm]( epstotalSinZero , x=2^(-30)..ymaxCase3): printf("\nMax rel error for DoSinZero is %1.5e, if it's smaller than 2^(-66) (%1.5e) then the proof is OK\n\n", maxepstotalSinZero, 2^(-66)): ##############################SinCosCase3############################ SinCosSize:= 128: # size f the table # The Gappa files in TEMPTRIG for i from 1 to SinCosSize/2 do filename:=cat("TEMPTRIG/SinACosA_",i,".sed"): fd:=fopen(filename, WRITE, TEXT): # The table values s:=hi_lo(sin(i*Pi/(2*SinCosSize))): c:=hi_lo(cos(i*Pi/(2*SinCosSize))): fprintf(fd, " s/_cah/%1.40e/g\n", c[1]): fprintf(fd, " s/_cal/%1.40e/g\n", c[2]): fprintf(fd, " s/_sah/%1.40e/g\n", s[1]): fprintf(fd, " s/_sal/%1.40e/g\n", s[2]): # The polynomial coefficients fprintf(fd, " s/_s3/%1.40e/g\n", coeff(polySin,x,3)): fprintf(fd, " s/_s5/%1.40e/g\n", coeff(polySin,x,5)): fprintf(fd, " s/_s7/%1.40e/g\n", coeff(polySin,x,7)): fprintf(fd, " s/_s9/%1.40e/g\n", coeff(polySin,x,9)): fprintf(fd, " s/_c2/%1.40e/g\n", coeff(polyCos,x,2)): fprintf(fd, " s/_c4/%1.40e/g\n", coeff(polyCos,x,4)): fprintf(fd, " s/_c6/%1.40e/g\n", coeff(polyCos,x,6)): fprintf(fd, " s/_c8/%1.40e/g\n", coeff(polyCos,x,8)): # The approximation errors fprintf(fd, " s/_ymaxCase3/%1.40e/g\n", ymaxCase3*1.00001): fprintf(fd, " s/_delta_ArgRed/%1.40e/g\n", delta_ArgRed*1.00001): fprintf(fd, " s/_delta_approx_Sin_Case3/%1.40e/g\n", deltaApproxSinCase3*1.00001): fprintf(fd, " s/_delta_approx_Cos_Case3/%1.40e/g\n", deltaApproxCosCase3*1.00001): fclose(fd): od: printf("************ DONE TEMPTRIG/*.sed ************\n"): # A shell script to use them filename:="../gappa/run-trigo-proof.sh": fd:=fopen(filename, WRITE, TEXT): fprintf(fd, "#!/bin/sh\n"): fprintf(fd, "# You probably need to edit the path to the gappa executable\n"): fprintf(fd, "for file in ../maple/TEMPTRIG/SinACosA*.sed \n"): fprintf(fd, "do\n"): fprintf(fd, " echo $file:\n"): fprintf(fd, " sed -f $file trigoSinCosCase3.gappa | ~/gappa/src/gappa\n"): fprintf(fd, " echo\n"): fprintf(fd, "done\n"): fclose(fd): printf("************ DONE trigo_test.sh ************\n"): printf("To run the Gappa proof, you should go to the gappa directory and run\n"): printf(" sh run-trigo-proof.sh 2> ../maple/TEMPTRIG/Gappa.out\n"): printf("Then look at maple/TEMPTRIG/Gappa.out. It shouldn't contain 'No proof'.\n This means that everything is OK and the rounding constants in TEMPTRIG/trigo_fast.h are proven upper bounds.\n\n"): # This value has been validated by Gappa (using all the previous) maxepstotalSinCosCase3:=3*2^(-66): rnconstantSinCosCase3 := evalf(compute_rn_constant(maxepstotalSinCosCase3)): # The error of sin, the error of cos, then the error of Div22 maxepstotalTanCase3:= 2.1*maxepstotalSinCosCase3: rnconstantTanCase3 := evalf(compute_rn_constant(maxepstotalTanCase3)): ############################################## ## Compute constants for SCS arg red oldDigits:=Digits: Digits:=1000: # for 2/Pi: n:=round(2^(30*48)*evalf(2/Pi)): digitlist:=[]: for i from 1 to 48 do r:=n mod (2^30): n:=floor(n/(2^30)): hexstring:= convert(convert(r,hex),string): digitlist:=[hexstring, op(digitlist)]: end: digitlist: # for 256/Pi: n:=round(2^(30*47)*evalf(256/Pi)): digitlist:=[]: for i from 1 to 48 do r:=n mod (2^30): n:=floor(n/(2^30)): hexstring:= convert(convert(r,hex),string): digitlist:=[hexstring, op(digitlist)]: end: digitlist: Digits:=oldDigits: # an auxiliary output function: # Outputs the high part of a double, and the double in comment. # As all these high parts are used in code as # if(absxhi < XMAX_COS_CASE2) # we have to remove one LSB to the high part, or, divide var by # (1+2^(-20)) # Now we have absxhi absxhi*(1+2^(-20)) x #include "crlibm.h" #include "crlibm_private.h" #include "triple-double.h" #include "pow.h" /* Some macros for specific operations in power */ #define USE_BUILTINS 0 /* decompose Decomposes a positive double precision variable x (normal or subnormal) such that 2^(resE) * resm = x where resm = 2 * k + 1 for integer k resE is an integer variable pointer resm is a double precision variable pointer x is a double precision variable. */ #if USE_BUILTINS #define decompose(resm,resE,x) \ { \ int __decompose_ex, __decompose_d; \ int64_t __decompose_temp; \ db_number __decompose_xdb; \ \ __decompose_xdb.d = (x); \ __decompose_ex = 0; \ if (!(__decompose_xdb.i[HI] & 0xfff00000)) { \ __decompose_xdb.d = (x) * 0.18014398509481984e17; \ __decompose_ex = -54; \ } \ __decompose_ex += (__decompose_xdb.i[HI] >> 20) - 1023; \ __decompose_xdb.i[HI] &= 0x000fffff; \ __decompose_temp = __decompose_xdb.l | 0x0010000000000000llu; \ __decompose_d = __builtin_ctz(__decompose_temp); \ __decompose_xdb.i[HI] |= (1075 - __decompose_d) << 20; \ *(resE) = __decompose_d - 52 + __decompose_ex; \ *(resm) = __decompose_xdb.d; \ } #else #define decompose(resm,resE,x) \ { \ int __decompose_ex, __decompose_d; \ int64_t __decompose_temp; \ db_number __decompose_xdb, __decompose_tempdb; \ \ __decompose_xdb.d = (x); \ __decompose_ex = 0; \ if (!(__decompose_xdb.i[HI] & 0xfff00000)) { \ __decompose_xdb.d = (x) * 0.18014398509481984e17; \ __decompose_ex = -54; \ } \ __decompose_ex += (__decompose_xdb.i[HI] >> 20) - 1023; \ __decompose_xdb.i[HI] &= 0x000fffff; \ __decompose_temp = __decompose_xdb.l | 0x0010000000000000llu; \ __decompose_temp = (~__decompose_temp & (__decompose_temp - 1)) + 1; \ __decompose_tempdb.d = (double) __decompose_temp; \ __decompose_d = (__decompose_tempdb.i[HI] >> 20) - 1023; \ __decompose_xdb.i[HI] |= (1075 - __decompose_d) << 20; \ *(resE) = __decompose_d - 52 + __decompose_ex; \ *(resm) = __decompose_xdb.d; \ } #endif /* isOddInteger Determines if a given double precision number x is an odd integer */ #define isOddInteger(x) (ABS(((ABS(x) + 0.9007199254740992e16) - 0.9007199254740992e16) - ABS(x)) == 1.0) /* isInteger Determines if a given double precision number x is integer */ #define isInteger(x) ((ABS(x) >= 0.4503599627370496e16) || (((ABS(x) + 0.4503599627370496e16) - 0.4503599627370496e16) == ABS(x))) /* log2_130 Approximates resh + resm + resl = (ed + log2(1 + (xh + xm)) + log2(r[index])) * (1 + eps) where ||eps|| <= 2^(-130) */ static inline void log2_130(double *resh, double *resm, double *resl, int index, double ed, double xh, double xm) { double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h; double p_t_6_0h; double p_t_7_0h; double p_t_8_0h; double p_t_9_0h, p_t_9_0m; double p_t_10_0h, p_t_10_0m; double p_t_11_0h, p_t_11_0m; double p_t_12_0h, p_t_12_0m; double p_t_13_0h, p_t_13_0m; double p_t_14_0h, p_t_14_0m; double p_t_15_0h, p_t_15_0m; double p_t_16_0h, p_t_16_0m, p_t_16_0l; double p_t_17_0h, p_t_17_0m, p_t_17_0l; double p_t_18_0h, p_t_18_0m, p_t_18_0l; double p_t_19_0h, p_t_19_0m, p_t_19_0l; double p_t_20_0h, p_t_20_0m, p_t_20_0l; double p_t_21_0h, p_t_21_0m, p_t_21_0l; double p_t_21_1h, p_t_21_1m, p_t_21_1l; double p_t_22_0h, p_t_22_0m, p_t_22_0l; double p_t_23_0h, p_t_23_0m, p_t_23_0l; double p_resh, p_resm, p_resl; double log2yh, log2ym, log2yl; double log2xh, log2xm, log2xl; double logih, logim, logil; p_t_1_0h = log2_130_p_coeff_13h; p_t_2_0h = p_t_1_0h * xh; p_t_3_0h = log2_130_p_coeff_12h + p_t_2_0h; p_t_4_0h = p_t_3_0h * xh; p_t_5_0h = log2_130_p_coeff_11h + p_t_4_0h; p_t_6_0h = p_t_5_0h * xh; p_t_7_0h = log2_130_p_coeff_10h + p_t_6_0h; p_t_8_0h = p_t_7_0h * xh; Add12(p_t_9_0h,p_t_9_0m,log2_130_p_coeff_9h,p_t_8_0h); Mul22(&p_t_10_0h,&p_t_10_0m,p_t_9_0h,p_t_9_0m,xh,xm); Add122(&p_t_11_0h,&p_t_11_0m,log2_130_p_coeff_8h,p_t_10_0h,p_t_10_0m); MulAdd22(&p_t_12_0h,&p_t_12_0m,log2_130_p_coeff_7h,log2_130_p_coeff_7m,xh,xm,p_t_11_0h,p_t_11_0m); MulAdd22(&p_t_13_0h,&p_t_13_0m,log2_130_p_coeff_6h,log2_130_p_coeff_6m,xh,xm,p_t_12_0h,p_t_12_0m); MulAdd22(&p_t_14_0h,&p_t_14_0m,log2_130_p_coeff_5h,log2_130_p_coeff_5m,xh,xm,p_t_13_0h,p_t_13_0m); Mul22(&p_t_15_0h,&p_t_15_0m,p_t_14_0h,p_t_14_0m,xh,xm); Add23(&p_t_16_0h,&p_t_16_0m,&p_t_16_0l,log2_130_p_coeff_4h,log2_130_p_coeff_4m,p_t_15_0h,p_t_15_0m); Mul233(&p_t_17_0h,&p_t_17_0m,&p_t_17_0l,xh,xm,p_t_16_0h,p_t_16_0m,p_t_16_0l); Add233(&p_t_18_0h,&p_t_18_0m,&p_t_18_0l,log2_130_p_coeff_3h,log2_130_p_coeff_3m,p_t_17_0h,p_t_17_0m,p_t_17_0l); Mul233(&p_t_19_0h,&p_t_19_0m,&p_t_19_0l,xh,xm,p_t_18_0h,p_t_18_0m,p_t_18_0l); Add33(&p_t_20_0h,&p_t_20_0m,&p_t_20_0l,log2_130_p_coeff_2h,log2_130_p_coeff_2m,log2_130_p_coeff_2l,p_t_19_0h,p_t_19_0m,p_t_19_0l); Mul233(&p_t_21_0h,&p_t_21_0m,&p_t_21_0l,xh,xm,p_t_20_0h,p_t_20_0m,p_t_20_0l); Renormalize3(&p_t_21_1h,&p_t_21_1m,&p_t_21_1l,p_t_21_0h,p_t_21_0m,p_t_21_0l); Add33(&p_t_22_0h,&p_t_22_0m,&p_t_22_0l,log2_130_p_coeff_1h,log2_130_p_coeff_1m,log2_130_p_coeff_1l,p_t_21_1h,p_t_21_1m,p_t_21_1l); Mul233(&p_t_23_0h,&p_t_23_0m,&p_t_23_0l,xh,xm,p_t_22_0h,p_t_22_0m,p_t_22_0l); p_resh = p_t_23_0h; p_resm = p_t_23_0m; p_resl = p_t_23_0l; logih = argredtable[index].logih; logim = argredtable[index].logim; logil = argredtable[index].logil; Add33(&log2yh,&log2ym,&log2yl,logih,logim,logil,p_resh,p_resm,p_resl); Add133(&log2xh,&log2xm,&log2xl,ed,log2yh,log2ym,log2yl); Renormalize3(resh,resm,resl,log2xh,log2xm,log2xl); } /* exp2_120 Approximates 2^H * (resh + resm + resl) = 2^(xh + xm + xl) * (1 + eps) where ||eps|| <= 2^(-119.5) */ static inline void exp2_120(int *H, double *resh, double *resm, double *resl, double xh, double xm, double xl) { double xhMult2L, rhMult2L, r; int k, index1, index2; db_number shiftedxhMult2Ldb; double rh, rm, rl; double t1h, t1m, t1l, t2, t3; double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h, p_t_5_0m; double p_t_6_0h, p_t_6_0m; double p_t_7_0h, p_t_7_0m; double p_t_8_0h, p_t_8_0m; double p_t_9_0h, p_t_9_0m, p_t_9_0l; double p_t_10_0h, p_t_10_0m, p_t_10_0l; double p_t_11_0h, p_t_11_0m, p_t_11_0l; double p_resh, p_resm, p_resl; double tbl1h, tbl1m, tbl1l, tbl2h, tbl2m, tbl2l; double tablesh, tablesm, tablesl; double exp2h, exp2m, exp2l; /* Argument reduction Produce exactly 2^H * 2^(i1/2^8) * 2^(i2/2^13) * 2^(rh + rm + rl) */ xhMult2L = xh * two13; shiftedxhMult2Ldb.d = shiftConst + xhMult2L; rhMult2L = xhMult2L - (shiftedxhMult2Ldb.d - shiftConst); r = rhMult2L * twoM13; k = shiftedxhMult2Ldb.i[LO]; *H = k >> 13; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> 5; Add12Cond(t1h, t2, r, xm); Add12Cond(t1m, t1l, t2, xl); Add12(rh, t3, t1h, t1m); Add12(rm, rl, t3, t1l); /* Polynomial approximation of 2^(rh + rm + rl) */ p_t_1_0h = exp2_120_p_coeff_6h; p_t_2_0h = p_t_1_0h * rh; p_t_3_0h = exp2_120_p_coeff_5h + p_t_2_0h; p_t_4_0h = p_t_3_0h * rh; Add12(p_t_5_0h,p_t_5_0m,exp2_120_p_coeff_4h,p_t_4_0h); MulAdd22(&p_t_6_0h,&p_t_6_0m,exp2_120_p_coeff_3h,exp2_120_p_coeff_3m,rh,rm,p_t_5_0h,p_t_5_0m); MulAdd22(&p_t_7_0h,&p_t_7_0m,exp2_120_p_coeff_2h,exp2_120_p_coeff_2m,rh,rm,p_t_6_0h,p_t_6_0m); Mul22(&p_t_8_0h,&p_t_8_0m,p_t_7_0h,p_t_7_0m,rh,rm); Add23(&p_t_9_0h,&p_t_9_0m,&p_t_9_0l,exp2_120_p_coeff_1h,exp2_120_p_coeff_1m,p_t_8_0h,p_t_8_0m); Mul33(&p_t_10_0h,&p_t_10_0m,&p_t_10_0l,rh,rm,rl,p_t_9_0h,p_t_9_0m,p_t_9_0l); Add133(&p_t_11_0h,&p_t_11_0m,&p_t_11_0l,exp2_120_p_coeff_0h,p_t_10_0h,p_t_10_0m,p_t_10_0l); Renormalize3(&p_resh,&p_resm,&p_resl,p_t_11_0h,p_t_11_0m,p_t_11_0l); /* Table access */ tbl1h = twoPowerIndex1[index1].hi; tbl1m = twoPowerIndex1[index1].mi; tbl1l = twoPowerIndex1[index1].lo; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; tbl2l = twoPowerIndex2[index2].lo; /* Reconstruction */ Mul33(&tablesh,&tablesm,&tablesl,tbl1h,tbl1m,tbl1l,tbl2h,tbl2m,tbl2l); Mul33(&exp2h,&exp2m,&exp2l,tablesh,tablesm,tablesl,p_resh,p_resm,p_resl); Renormalize3(resh,resm,resl,exp2h,exp2m,exp2l); } /* pow_120 Approximates 2^H * (resh + resm + resl) = 2^(y * (ed + log2(1 + (zh + zm)) + log2(r[index]))) * (1 + eps) where ||eps|| <= 2^(-118.5) if -1075 <= y * (ed + log2(1 + (zh + zm)) + log2(r[index])) <= 1024 Approximates further (ed + log2(1 + (zh + zm)) + log2(r[index))) by log2xh where log2xh = (ed + log2(1 + (zh + zm)) + log2(r[index))) * (1 + eps2) where |eps2| <= 2^(-52) and log2xh is exact if 2^ed * ((1 + (zh + zm)) * r[index]) is an integer power of 2. */ void pow_120(int *H, double *resh, double *resm, double *resl, double *log2xh, double y, int index, double ed, double zh, double zm) { double ylog2xh, ylog2xm, ylog2xl; double log2xm, log2xl; /* Compute log2(x) */ log2_130(log2xh,&log2xm,&log2xl,index,ed,zh,zm); /* Compute y * log2(x) */ Mul133(&ylog2xh,&ylog2xm,&ylog2xl,y,*log2xh,log2xm,log2xl); /* Compute 2^(y * log2(x)) */ exp2_120(H,resh,resm,resl,ylog2xh,ylog2xm,ylog2xl); } /* pow_round_and_check_rn Checks whether 2^H * (powh + powm + powl) which is an approximate to x^y with a relative error or less than 2^(-118.5), can be rounded correctly to double precision in round-to-nearest-ties-to-even mode or whether the Table Maker's Dilemma occurs or the case is exact. Returns 1 if rounding is possible and affects pow with the rounding Returns 0 if rounding is not possible or if the case is exact If the returned value is 0, it affects G, kh, kl such that 2^G * (kh + kl) is an approximate to x^y with an relative error of 2^(-117) and such that rounding 2^G * kh to double precision is an exact operation. */ static inline int pow_round_and_check_rn(double *pow, int H, double powh, double powm, double powl, int *G, double *kh, double *kl) { double th, tm, tl; int K, K1, K2; db_number twodb, two2db; double twoH1074powh, twoH1074powm, shiftedpowh, delta; double scaledth; double t1m, t1l; /* We start by bringing H and powh + powm + powl to a form such that 1 <= powh + powm + powl < 2 */ if ((powh < 1.0) || ((powh == 1.0) && (powm < 0.0))) { powh *= 2.0; powm *= 2.0; powl *= 2.0; H--; } if ((powh > 2.0) || ((powh == 2.0) && (powm >= 0.0))) { powh *= 0.5; powm *= 0.5; powl *= 0.5; H++; } /* Check now whether we have normal or subnormal rounding The rounding is subnormal iff H <= -1023 In both cases, we bring H, powh + powm + powl to a form 2^K * (th + tm + tl) = 2^H * (powh + powm + powm) * (1 + eps) where (i) |eps| <= 2^(-118 - 53) = 2^(-171) (ii) 2^(-K) * ulp(2^K * th) = 1 (iii) the rounding of 2^K * th to double precision is exact (or produces +inf) */ if (H <= -1023) { /* Subnormal rounding In this case, we can neglect powl because the rounding bit of the RN rounding is in powh */ twodb.i[HI] = (H + (1074 + 1023)) << 20; twodb.i[LO] = 0; twoH1074powh = twodb.d * powh; twoH1074powm = twodb.d * powm; shiftedpowh = two52 + twoH1074powh; th = shiftedpowh - two52; delta = twoH1074powh - th; Add12Cond(tm,tl,delta,twoH1074powm); K = -1074; } else { /* Normal rounding In this case, we have exactly: 2^K * (th + tm + tl) = 2^H * (powh + powm + powm) */ th = powh * two52; tm = powm * two52; tl = powl * two52; K = H - 52; } /* Return results for exactness case test */ *G = K; *kh = th; *kl = tm; /* Compute now delta = ABS(0.5 - ABS(tm + tl)) * (1 + eps) where |eps| <= 2^(-53) The addition 0.5 + (-ABS(tm)) is exact by Sterbenz' lemma */ if (tm > 0.0) { t1m = - tm; t1l = - tl; } else { t1m = tm; t1l = tl; } delta = ABS((0.5 + t1m) - t1l); /* We cannot decide the rounding or have an exact case iff delta <= 2^(-118) * th We can see this in the following drawing: result = round( +-----------------+------+----------...----+------------ 2^K * | th | +/-1 | 0 | delta ) +-----------------+------+----------...----+------------ | <------------- 118 bits -------------> | */ scaledth = th * PRECISEROUNDCST; if (delta > scaledth) { /* We can round exactly to nearest We must correct th to the rounding of th + tm + tl iff tm is greater in absolute value than 0.5 or if tm is equal to 0.5 in absolute value and the sign of tm and tl is equal: | | ...------|--------|--------|------... |------->--> | ^ tm tl ^ th round(th + tm + tl) If tm is negative, we must correct th by decreasing it otherwise we must correct th by increasing it. */ if (ABS(tm) >= 0.5) { if (ABS(tm) == 0.5) { if (tm < 0.0) { if (tl < 0.0) { /* The same sign of tm and tl, tm is negative */ th -= 1.0; } } else { if (tl > 0.0) { /* The same sign of tm and tl, tm is positive */ th += 1.0; } } } else { /* tm > 0.5 */ if (tm < 0.0) { th -= 1.0; } else { th += 1.0; } } } /* Perform now the multiplication 2^K * th Note that we must be able to produce (i) 0 if we have total underflow (ii) a subnormal result (iii) a normal result (iv) +inf if we have overflow in a TMD case We produce K1 + K2 = K with K1 = floor(K/2) and multiply in two steps. */ K1 = K >> 1; K2 = K - K1; twodb.i[HI] = (K1 + 1023) << 20; twodb.i[LO] = 0; two2db.i[HI] = (K2 + 1023) << 20; two2db.i[LO] = 0; *pow = two2db.d * (twodb.d * th); return 1; } /* Otherwise we return 0 because we cannot round */ return 0; } /* pow_exact_case Checks whether x^y is an exact or half-ulp case for rounding into double precision. This means the procedure checks whether x^y can be written on not more than 54 bits. The procedure uses 2^G * (kh + kl) supposing the following properties: * kh + kl holds on at most 54 bits * 2^G * kh is representable in double precision (even in the subnormal range) * 2^G * (kh + kl) approximates x^y with an error eps less than 2^(-117), i.e. 2^G * (kh + kl) = x^y * (1 + eps) where |eps| <= 2^(-117) * log2xh approximates log2(x) with an accuracy equivalent to at least 52 bits In particular log2xh is exact if x is an integer power of 2 Returns 1 if the case is exact or half-ulp Returns 0 otherwise If returning 1, affects pow with 2^G * (kh + kl) rounded to double precision */ int pow_exact_case(double *pow, double x, double y, int G, double kh, double kl, double log2xh) { db_number xdb, ydb, tempdb, shiftedEydb, temp2db; int E, F, G1, G2; double m, n, yh, yl, Eyh, Eyl, ed, Ey; double delta; double nearestEy; double value; /* For testing whether x^y is an exact or half-ulp case, we have two main cases: (i) x is an integer power of 2 (ii) x is not an integer power of 2 We start by testing if x is an integer power of 2. */ xdb.d = x; if ((xdb.i[HI] & 0xfff00000) == 0) { /* x is subnormal, scale by 2^52 */ xdb.d *= 0.4503599627370496e16; } if (((xdb.i[HI] & 0x000fffff) | xdb.i[LO]) == 0) { /* x is an integer power of 2 x^y is exact or midpoint iff log2(x) * y is integer Since we know that x is an integer power of 2, log2xh is equal to this integer. Since the exponent of the double precision number is bounded by the exponent range, we know that log2xh is integer and bounded by 2^11. It is therefore possible to split y into two parts of 21 and 32 bits, to perform the multiplication componentwise. Since the result is bounded by 2^11, it suffices to compute the nearest integer to the higher word product, and to compare the rounding difference to the low word product. This splitting is faster than the usual Dekker splitting. */ ydb.d = y; ydb.i[LO] = 0; yh = ydb.d; yl = y - yh; Eyh = log2xh * yh; Eyl = log2xh * yl; delta = ((0.6755399441055744e16 + Eyh) - 0.6755399441055744e16) - Eyh; /* addition rounds, subtractions exact */ if (delta != Eyl) return 0; } else { /* x is not an integer power of 2 We have clearly an inexact case if y is negative or if y is greater than 35 */ if ((y < 0.0) || (y > 35.0)) return 0; /* Decompose now y into y = 2^F * n Checking F and n, we can then already decide some cases using the fact that the worst-case accuracy for x^n, n in [|0;35|], is less (in bits) than the accuracy of the approximation of x^y we have already in 2^G * (kh + kl). */ decompose(&n,&F,y); if ((n > 35.0) || (F < -5)) return 0; if (F < 0) { /* Here, -5 <= F <= -1, 3 <= n <= 35, n an odd integer We decompose x into 2^E * m where m is an odd integer Let H, sh and sl such that 2^H * (sh + sl) = 2^G * (kh + kl) and sh + sl is an odd integer. If we have E * 2^F * n = H, we can apply the worst case argument because we know the worst case for m^(2^F * n) with m odd integer, -5 <= F <= -1, 3 <= n <= 35 when rounding to 53 bits in both rounding modes. E is bounded in magnitude by 2^11. 2^F * n is equal to y by construction. Since n <= 35, y contains at most 6 significant bits. The arithmetical multiplication E * y is therefore exact and less than or equal to 2^17. We check first whether E * y is an integer. If this is the case, we compute sh + sl = 2^(G - E * y) * (kh + kl). Finally, we check whether sh + sl is an odd integer. */ decompose(&m,&E,x); ed = (double) E; Ey = ed * y; /* Exact */ /* Check whether Ey is an integer using the simple shift technique The addition rounds, the substraction is exact by Sterbenz' lemma. If Ey is an integer, the low order word of shiftedEydb is equal to this integer. */ shiftedEydb.d = 0.6755399441055744e16 + Ey; nearestEy = shiftedEydb.d - 0.6755399441055744e16; if (nearestEy != Ey) return 0; /* Here E * y is integer. Produce now 2^(G - E * y). */ tempdb.i[HI] = (((G - shiftedEydb.i[LO]) + 1023) << 20); tempdb.i[LO] = 0; /* Check now if sh + sl = tempdb.d * (kh + kl) is an odd integer. Since kh and kl are not overlapped, we have two cases: (i) kl is equal to 0, in which case tempdb.d * kh must be an odd integer (ii) kl is not equal to 0, in which case tempdb.d * kl must be an odd integer */ if (kl == 0.0) value = kh; else value = kl; value *= tempdb.d; /* Exact because multiplication by positive integer power of 2 */ if (!isOddInteger(value)) return 0; /* Here the case is exact by the worst-case argument */ } /* Here, we have either F >= 0 or an exact case If F >= 0, we also have an exact case because 2^F * n = y <= 35, y therefore integer and because we can apply the worst case argument. */ } /* Here, the case is exact, affect pow with 2^G * (kh + kl) rounded to nearest in double precision Since kh + kl holds on at most 54 bits, 2^G * kh produces never any rounding error and kh and kl are not overlapping, 2^G * kh is equal to the rounding if (i) kl is equal to 0 (ii) kl is not equal to 0 and the mantissa of 2^G * kh is even If in condition (ii), kl is not equal to 0 and the mantissa of 2^G * kh is not even, we correct it depending on the sign of kl. Remark that G can be such that 2^G is no longer a normal. Produce therefore 2^(floor(G/2)) and 2^(G - floor(G/2)) and multiply in two steps. */ G1 = G >> 1; G2 = G - G1; tempdb.i[HI] = (G1 + 1023) << 20; tempdb.i[LO] = 0; temp2db.i[HI] = (G2 + 1023) << 20; temp2db.i[LO] = 0; tempdb.d *= (kh * temp2db.d); if ((kl != 0.0) && ((tempdb.i[LO] & 1) != 0)) { /* We must correct the rounding to the rounding to nearest ties to even */ if (kl > 0.0) { tempdb.l++; } else { tempdb.l++; } } *pow = tempdb.d; return 1; } double pow_exact_rn(double x, double y, double sign, int index, double ed, double zh, double zm) { int H, G; double powh, powm, powl; double pow; double kh, kl; double log2xh; pow_120(&H, &powh, &powm, &powl, &log2xh, y, index, ed, zh, zm); if (pow_round_and_check_rn(&pow,H,powh,powm,powl,&G,&kh,&kl)) return sign * pow; if (pow_exact_case(&pow,x,y,G,kh,kl,log2xh)) return sign * pow; // printf("Could not decide the rounding to nearest of power.\n"); return -5.0; } double pow_rn(double x, double y) { db_number xdb, ydb, yhdb, shiftedylog2xhMult2Ldb, powdb, twodb; double sign; int E, index; double log2FastApprox, ed, ylog2xFast, f; double yh, yl, ri, logih, logim, yrih, yril, th, zh, zm; double p_t_1_0h; double p_t_2_0h; double p_t_3_0h; double p_t_4_0h; double p_t_5_0h; double p_t_9_0h; double p_t_10_0h; double p_t_11_0h, p_t_11_0m; double p_t_12_0h, p_t_12_0m; double log2zh, log2zm; double log2yh, log2ym; double log2xh, log2xm; double ylog2xh, ylog2xm; double rh, r; int k, index1, index2, H; double tbl1, tbl2h, tbl2m; double ph; double powh, powm; double twoH1074powh, twoH1074powm; double shiftedpowh, nearestintpowh, delta, deltaint; double rest; double lowerTerms; double temp1; double zhSq, zhFour, p35, p46, p36, p7; double xSq; /* Fast rejection of special cases */ xdb.d = x; ydb.d = y; if (((((xdb.i[HI] >> 20) + 1) & 0x3ff) <= 1) || ((((ydb.i[HI] >> 20) + 1) & 0x3ff) <= 1)) { /* Handle special cases before handling NaNs and Infinities */ if (x == 1.0) return 1.0; if (y == 0.0) return 1.0; if (y == 1.0) return x; if (y == 2.0) return x * x; /* Remark: may yield uncorrect rounding on x86 for subnormal results */ if (y == -1.0) return 1 / x; if ((x == 0.0) && ((ydb.i[HI] & 0x7ff00000) != 0x7ff00000)) { /* x = +/-0 and y is neither NaN nor Infinity We have four cases (i) y < 0: (a) y odd integer: return +/- Inf and raise divide-by-zero (b) y not odd integer: return + Ind and raise divide-by-zero (ii) (a) y odd integer: return +/- 0 (b) y not odd integer: return +0 Note that y = 0.0 has already been filtered out. */ if (y < 0.0) { if (isOddInteger(y)) return 1/x; else return 1/(x * x); } else { if (isOddInteger(y)) return x; else return x * x; } } /* Handle NaNs and Infinities Note: the cases (x,y) = (1,NaN) and (x,y) = (NaN,0) have already been handled. */ if ((ydb.i[HI] & 0x7ff00000) == 0x7ff00000) { /* Here y is NaN or Inf */ if (((ydb.i[HI] & 0x000fffff) | ydb.i[LO]) != 0) { /* Here y is NaN, we return NaN */ return y; } /* Here y is +/- Inf There are three main cases: (i) x = -1: return 1 (ii) abs(x) > 1: (a) y = +Inf: return +Inf (b) y = -Inf: return +0 (iii) abs(x) < 1: (a) y = +Inf: return +0 (b) y = -Inf: return +Inf Note: the case x = 1 has already been filtered out */ if (x == -1.0) return 1.0; /* Here x != 1, x != -1 */ if ((ABS(x) > 1.0) ^ ((ydb.i[HI] & 0x80000000) == 0)) { /* abs(x) > 1 and y = -Inf or abs(x) < 1 and y = +Inf */ return 0.0; } else { /* abs(x) > 1 and y = +Inf or abs(x) < 1 and y = -Inf */ return ABS(y); } } /* Here y is neither Inf nor NaN */ if ((xdb.i[HI] & 0x7ff00000) == 0x7ff00000) { /* Here x is NaN or Inf */ if (((xdb.i[HI] & 0x000fffff) | xdb.i[LO]) != 0) { /* Here x is NaN, we return NaN */ return x; } /* Here x is +/- Inf There are two main cases: (i) x is +Inf (ii) x is -Inf */ if ((xdb.i[HI] & 0x80000000) == 0) { /* x is +Inf (a) y > 0: return +Inf (b) y < 0: return +0 Note: y = 0 has already been filtered out */ if (y > 0.0) { return x; } else { return 0.0; } } else { /* x is -Inf There are four cases: (a) y > 0: (*) y is an odd integer: return -Inf (**) y is not an odd integer: return +Inf (b) y < 0: (*) y is an odd integer: return -0 (**) y is not an odd integer: return +0 Note: y = 0 has already been filtered out */ if (y > 0.0) { if (isOddInteger(y)) { return x; } else { return -x; } } else { if (isOddInteger(y)) { return -0.0; } else { return 0.0; } } } } } /* Here both x and y are finite numbers */ /* Test now whether we have the case (-x)^y = (-1)^y * x^y where x is positive */ sign = 1.0; if (x < 0.0) { /* x is negative x^y is defined only if y is integer */ if (!isInteger(y)) { /* y is not integer return NaN and raise invalid exception */ return 0.0/0.0; } /* Here y is integer Remove the sign of x and put (-1)^y in sign */ x = -x; xdb.i[HI] &= 0x7fffffff; if (isOddInteger(y)) { sign = -sign; } } /* Here x is strictly positive and finite */ /* Test now if abs(y) is in a range giving finite, non-trivial results x^y We have x^y = 2^(y * log2(x)) = 2^(y * log2(2^E * m)) = 2^(y * (E + log2(1 + f))) We have overflow iff x^y >= 2^(1024), i.e. y * (E + log2(1 + f)) >= 1024 We have underflow (flush to zero) iff x^y <= 2^(-1076), i.e. y * (E + log2(1 + f)) <= - 1076 We round to 1.0 iff abs(y * (E + log2(1 + f))) <= 2^(-54) We approximate log2(1 + f) as log2(1 + f) = c * f * alpha(f) where c is a constant and 0.853 < alpha(f) < 1.21 So we have surely (i) overflow or underflow if abs(y * (E + c * f)) >= ceil(1076/0.853) = 1261 (ii) trivial rounding to 1.0 if abs(y * (E + c * f)) <= 2^(-55) <= 2^(-54)/1.21 */ /* We start the computation of the logarithm of x */ E = 0; if ((xdb.i[HI] & 0xfff00000) == 0) { /* x is subnormal, make it normal */ xdb.d *= two52; E = -52; } E += (xdb.i[HI]>>20)-1023; /* extract the exponent */ index = (xdb.i[HI] & 0x000fffff); xdb.i[HI] = index | 0x3ff00000; /* do exponent = 0 */ index = (index + (1<<(20-L-1))) >> (20-L); /* reduce such that sqrt(2)/2 < xdb.d < sqrt(2) */ if (index >= MAXINDEX) { /* corresponds to xdb>sqrt(2)*/ xdb.i[HI] -= 0x00100000; E++; } ed = (double) E; /* Continue with the exact range reduction of the logarithm of x */ yhdb.i[HI] = xdb.i[HI]; yhdb.i[LO] = 0; yh = yhdb.d; yl = xdb.d - yh; /* Special handling for y = 3 or y = 4 and x on not more than 21 bits (without subnormals) */ if ((yl == 0) && ((y == 3.0) || (y == 4.0)) && (E > -255)) { if (y == 3.0) return sign * (x * (x * x)); else { xSq = x * x; return sign * (xSq * xSq); } } index = index & INDEXMASK; /* Now we have log2(x) = E + log2(xdb.d) with sqrt(2)/2 < xdb.d < sqrt(2) Compute now f such that 1 + f = xdb.d and approximate log2(1 + f) = logFastCoeff * f */ f = xdb.d - 1.0; log2FastApprox = ed + logFastCoeff * f; ylog2xFast = y * log2FastApprox; if (ABS(ylog2xFast) >= 1261.0) { if (ylog2xFast > 0.0) { /* y * log2(x) is positive, i.e. we overflow */ return (sign * LARGEST) * LARGEST; } else { /* y * log2(x) is negative, i.e. we underflow */ return (sign * SMALLEST) * SMALLEST; } } if (ABS(ylog2xFast) <= twoM55) { /* abs(y * log2(x)) <= 2^(-55), we return 1.0 and set the inexact flag */ return sign * (1.0 + SMALLEST); } /* Now, we may still overflow or underflow but on some inputs only */ /* Read tables: Read one float for ri Read the first two doubles for -log(r_i) (out of three) Organization of the table: one struct entry per index, the struct entry containing r, logih, logim and logil in this order */ ri = argredtable[index].ri; /* Actually we don't need the logarithm entries now Move the following two lines to the eventual reconstruction As long as we don't have any if in the following code, we can overlap memory access with calculations */ logih = argredtable[index].logih; logim = argredtable[index].logim; /* Do range reduction: zh + zm = y * ri - 1.0 correctly Correctness is assured by use of two part yh + yl and 21 bit ri and Add12 Discard zl for higher monome degrees */ yrih = yh * ri; yril = yl * ri; th = yrih - 1.0; Add12Cond(zh, zm, th, yril); /* Polynomial approximation of log2(1 + (zh + zm)) */ zhSq = zh * zh; p35 = log2_70_p_coeff_3h + zhSq * log2_70_p_coeff_5h; p46 = log2_70_p_coeff_4h + zhSq * log2_70_p_coeff_6h; zhFour = zhSq * zhSq; p36 = p35 + zh * p46; p7 = log2_70_p_coeff_7h * zhFour; p_t_9_0h = p36 + p7; p_t_10_0h = p_t_9_0h * zh; Add212(&p_t_11_0h,&p_t_11_0m,log2_70_p_coeff_2h,log2_70_p_coeff_2m,p_t_10_0h); MulAdd22(&p_t_12_0h,&p_t_12_0m,log2_70_p_coeff_1h,log2_70_p_coeff_1m,zh,zm,p_t_11_0h,p_t_11_0m); Mul22(&log2zh,&log2zm,p_t_12_0h,p_t_12_0m,zh,zm); /* Reconstruction */ Add122(&log2yh,&log2ym,ed,logih,logim); Add22(&log2xh,&log2xm,log2yh,log2ym,log2zh,log2zm); /* Produce ylog2xh + ylog2xm approximating y * log2(x) Note: neither y nor y * log2(x) may not be subnormal and non-zero because of the fast overflow/underflow/trivial rounding test. */ Mul12(&ylog2xh,&temp1,y,log2xh); ylog2xm = temp1 + y * log2xm; /* Approximate now 2^(y * log2(x)) We have 2^(ylog2xh + ylog2xm) = 2^ylog2xh * 2^ylog2xm = 2^H * 2^(ylog2xh - H) * 2^ylog2xm = 2^H * 2^(i2/2^8) * 2^(i1/2^13) * 2^(ylog2xh - H - i2/2^8 - i1/2^13) * 2^ylog2xm = 2^H * tbl2[i2] * (1 + tbl1[i1]) * (1 + p(rh)) + delta where rh \approx ylog2xh - H - i1/2^7 - i2/2^13 + ylog2xm */ shiftedylog2xhMult2Ldb.d = shiftConstTwoM13 + ylog2xh; r = ylog2xh - (shiftedylog2xhMult2Ldb.d - shiftConstTwoM13); k = shiftedylog2xhMult2Ldb.i[LO]; H = k >> 13; index1 = k & INDEXMASK1; index2 = (k & INDEXMASK2) >> 5; /* Renormalize reduced argument This operation produces an error 2^(z * (1 + eps)) = 2^z * (1 + eps') where |eps| <= 2^(-53) and |eps'| <= 2^(-65) */ rh = r + ylog2xm; /* Table reads */ tbl1 = twoPowerIndex1[index1].hiM1; tbl2h = twoPowerIndex2[index2].hi; tbl2m = twoPowerIndex2[index2].mi; /* Polynomial approximation */ p_t_1_0h = exp2_p_coeff_3h; p_t_2_0h = p_t_1_0h * rh; p_t_3_0h = exp2_p_coeff_2h + p_t_2_0h; p_t_4_0h = p_t_3_0h * rh; p_t_5_0h = exp2_p_coeff_1h + p_t_4_0h; ph = p_t_5_0h * rh; /* Reconstruction */ lowerTerms = tbl1 + (ph + tbl1 * ph); Add212(&powh,&powm,tbl2h,tbl2m,tbl2h * lowerTerms); /* Here we have 2^H * (powh + powm) = x^y * (1 + eps) with ||eps|| <= 2^(-60) Check first if we overflow or underflow. Check then if we can perform normal rounding or if we must perhaps perform subnormal rounding. We are sure that 0.5 <= powh + powm <= 4.0 */ if (H >= 1025) { /* Here, we surely overflow Return sign * inf */ return (sign * LARGEST) * LARGEST; } if (H <= -1077) { /* Here, we surely underflow Return sign * 0 and set inexact flag */ return (sign * SMALLEST) * SMALLEST; } if (H > -1022) { /* We are sure to be able to perform normal rounding We must still be aware of the fact that the final result may overflow */ if(powh == (powh + (powm * RNROUNDCST))) { powdb.d = powh; if (H < 1023) { powdb.i[HI] += H << 20; return sign * powdb.d; } else { /* May overflow: multiply by 2^H in two steps */ powdb.i[HI] += (H - 3) << 20; return sign * powdb.d * 8.0; } } } else { /* We must perhaps perform subnormal rounding We start by renormalizing the double-double powh + powm such that 1 <= powh + powm < 2 */ if ((powh < 1.0) || ((powh == 1.0) && (powm < 0.0))) { powh *= 2.0; powm *= 2.0; H--; } if ((powh > 2.0) || ((powh == 2.0) && (powm >= 0.0))) { powh *= 0.5; powm *= 0.5; H++; } /* Here we know that 1 <= powh + powm < 2 2^H * (powh + powm) is subnormal or equal to the least normal iff H <= -1023 */ if (H > -1023) { /* We have nevertheless normal rounding */ if(powh == (powh + (powm * RNROUNDCST))) { powdb.d = powh; powdb.i[HI] += H << 20; return sign * powdb.d; } /* Here we have normal rounding but could not decide the rounding */ } else { /* We have surely denormal rounding This means round(2^H * (powh + powm)) = 2^(-1074) * nearestint(2^(+1074) * 2^H * (powh + powm)) We compute the rounding (and test its TMD) of nearestint(2^(H + 1074) * (powh + powm)) by computing first nearestint(2^(H + 1074) * powh) and then the absolute error delta = 2^(H + 1074) * powh - nearestint(2^(H + 1074) * powh) + 2^(H + 1074) * powl We can then refute or correct the rounding by tests on delta. We know that 2^(H + 1074) <= 2^(51) and powh <= 2.0. Thus 2^(H + 1074) * powh <= 2^(52) We can hence compute nearestint using the shift trick. We start by constructing 2^(H + 1074) */ twodb.i[HI] = (H + (1074 + 1023)) << 20; twodb.i[LO] = 0; twoH1074powh = twodb.d * powh; twoH1074powm = twodb.d * powm; shiftedpowh = two52 + twoH1074powh; nearestintpowh = shiftedpowh - two52; deltaint = twoH1074powh - nearestintpowh; /* The next addition produces a very small rounding error we must account for in the rounding test. */ delta = deltaint + twoH1074powm; /* Correct now the rounding */ if (ABS(delta) > 0.5) { /* ABS(delta) > 0.5 */ if (delta > 0.0) { /* nearestintpowh is too small by 1.0 */ nearestintpowh += 1.0; /* exact */ delta -= 1.0; /* exact */ } else { /* nearestintpowh is too great by 1.0 */ nearestintpowh -= 1.0; /* exact */ delta += 1.0; /* exact */ } } /* Perform now the rounding test This test filters out also half-ulp exact cases. Exact cases are not filtered out because C99 allows setting the underflow and/or inexact flags also for exact cases. Compute first rest = abs(0.5 - abs(delta)) * (1 + eps) where abs(eps) <= 2^(-53) We cannot decide the rounding if rest <= 2^(H + 1074) * epsmax * 2 where epsmax is the bound for the approximating polynomials, here epsmax = 2^(-60) as follows by the following drawing 2^52 2^(H + 1074) 2^0 2^(H + 1074) * epsmax +-------------------+----------------+---+------... | | 0 ... 0 | nearestintpowh | 1 | rest +-------------------+----------------+---+------... | | <---- 60 bits approx. ------->| This means that we cannot decide the rounding if rest * 1/epsmax * 0.5 <= 2^(H + 1074) We store 1/epsmax * 0.5 on SUBNORMROUNDCST */ rest = ABS(0.5 - ABS(delta)); if (rest * SUBNORMROUNDCST > twodb.d) { /* Here we could decide the rounding The result to return is sign * 2^(-1074) * nearestintpowh which is either subnormal or equal to the least normal. Since we know that the multiplication does not imply any rounding error, we can perform it using the shift trick and a mask. This trick yields to a 200 cycle speed-up on Athlon. */ twodb.d = nearestintpowh + two52; twodb.i[HI] = (twodb.i[HI] + (1 << 20)) & 0x001fffff; return sign * twodb.d; } } } /* If we are here, we could not decide the rounding or are half-ulp Launch now exacter phases and exact and half-ulp testing */ return pow_exact_rn(x,y,sign,index,ed,zh,zm); } interval-3.2.0/src/crlibm/pow.h0000755000000000000000000053303713316017127014522 0ustar 00000000000000/* * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define L 8 #define MAXINDEX 106 #define INDEXMASK 255 #define two52 4.50359962737049600000000000000000000000000000000000e+15 #define twoM55 0.277555756156289135105907917022705078125e-16 #define logFastCoeff 0.14142135623730951454746218587388284504413604736328125e1 #define LARGEST 0.898846567431157953864652595394512366808988489471153286e308 #define SMALLEST 0.222507385850720138309023271733240406421921598046233183e-307 #define shiftConst 6.75539944105574400000000000000000000000000000000000e+15 #define shiftConstTwoM13 0.824633720832e12 #define two13 8192.0 #define twoM13 0.1220703125e-3 #define INDEXMASK1 0x1f #define INDEXMASK2 0x1fe0 #define RNROUNDCST 1.01587301587301598581442042834326647273327977070694e+00 #define RDROUNDCST 8.67361737988403547205962240695953369140625000000000e-19 #define SUBNORMROUNDCST 0.576460752303423488e18 #define PRECISEROUNDCST 0.300926553810505602039996553528894893521578382533654405506e-35 #define twoM1000 0.933263618503218878990089544723817169617091446371708024622e-301 #define twoM74 0.5293955920339377119177015629247762262821197509765625e-22 #define log2_70_p_coeff_1h 1.44269504088896338700465094007086008787155151367187500000000000000000000000000000e+00 #define log2_70_p_coeff_1m 2.03552810625246160186433312051638360278748036817121624952875436065369285643100739e-17 #define log2_70_p_coeff_2h -7.21347520444481693502325470035430043935775756835937500000000000000000000000000000e-01 #define log2_70_p_coeff_2m -1.12725594936749318924493788526353267792267647960831322695440803727251477539539337e-17 #define log2_70_p_coeff_3h 4.80898346962987777164499902937677688896656036376953125000000000000000000000000000e-01 #define log2_70_p_coeff_4h -3.60673760219944627980481755002983845770359039306640625000000000000000000000000000e-01 #define log2_70_p_coeff_5h 2.88539008191916690471146011987002566456794738769531250000000000000000000000000000e-01 #define log2_70_p_coeff_6h -2.40450377363966349975044067832641303539276123046875000000000000000000000000000000e-01 #define log2_70_p_coeff_7h 2.06097743969525126761510591677506454288959503173828125000000000000000000000000000e-01 #define log2_130_p_coeff_1h 1.44269504088896338700465094007086008787155151367187500000000000000000000000000000e+00 #define log2_130_p_coeff_1m 2.03552737409310331110210900522069120325603861485809498166332787150167860090732574e-17 #define log2_130_p_coeff_1l -1.06146602236896146263026926064664797993065100369094413909960470044754680755528179e-33 #define log2_130_p_coeff_2h -7.21347520444481693502325470035430043935775756835937500000000000000000000000000000e-01 #define log2_130_p_coeff_2m -1.01776368704655165555105450261034560162801930742904749083166393575083930045366287e-17 #define log2_130_p_coeff_2l 5.34511411595447028630249611725927839300757516466699521565482986252038599158936192e-34 #define log2_130_p_coeff_3h 4.80898346962987777164499902937677688896656036376953125000000000000000000000000000e-01 #define log2_130_p_coeff_3m 2.52888083240629533774008911522493092191867953828603166055444262383389286696910858e-17 #define log2_130_p_coeff_4h -3.60673760222240846751162735017715021967887878417968750000000000000000000000000000e-01 #define log2_130_p_coeff_4m -5.08881843525388804036113375504277575334378429174238267496122034572181291878223419e-18 #define log2_130_p_coeff_5h 2.88539008177792655196469695511041209101676940917968750000000000000000000000000000e-01 #define log2_130_p_coeff_5m 2.62755152398073847756639381346527463413965059531741258469494937344279605895280838e-17 #define log2_130_p_coeff_6h -2.40449173481493888582249951468838844448328018188476562500000000000000000000000000e-01 #define log2_130_p_coeff_6m -1.26443692756777278172382591559880426333181716128670549204038309198949718847870827e-17 #define log2_130_p_coeff_7h 2.06099291555566194178439332063135225325822830200195312500000000000000000000000000e-01 #define log2_130_p_coeff_7m 6.87383539895312875323064204102239130058263040989538494862642892258008942008018494e-18 #define log2_130_p_coeff_8h -1.80336880111120451131156983137771021574735641479492187500000000000000000000000000e-01 #define log2_130_p_coeff_9h 1.60299448987662213061966554050741251558065414428710937500000000000000000000000000e-01 #define log2_130_p_coeff_10h -1.44269504079917953998091206813114695250988006591796875000000000000000000000000000e-01 #define log2_130_p_coeff_11h 1.31154094707513962925204964449221733957529067993164062500000000000000000000000000e-01 #define log2_130_p_coeff_12h -1.20226134447525057069583453994709998369216918945312500000000000000000000000000000e-01 #define log2_130_p_coeff_13h 1.10970553702962271280796358041698113083839416503906250000000000000000000000000000e-01 #define exp2_p_coeff_0h 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00 #define exp2_p_coeff_1h 6.93147180559945286226763982995180413126945495605468750000000000000000000000000000e-01 #define exp2_p_coeff_2h 2.40226506988959309651932017004583030939102172851562500000000000000000000000000000e-01 #define exp2_p_coeff_3h 5.55041161373122232669530262683110777288675308227539062500000000000000000000000000e-02 #define exp2_120_p_coeff_0h 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00 #define exp2_120_p_coeff_1h 6.93147180559945286226763982995180413126945495605468750000000000000000000000000000e-01 #define exp2_120_p_coeff_1m 2.31904681384630849473271303648771975481164951834144039022334027322358451783657074e-17 #define exp2_120_p_coeff_2h 2.40226506959100721827482516346208285540342330932617187500000000000000000000000000e-01 #define exp2_120_p_coeff_2m -9.49393125283880586293948324833484500178580834723511897021985816991218598559498787e-18 #define exp2_120_p_coeff_3h 5.55041086648215831189645541599020361900329589843750000000000000000000000000000000e-02 #define exp2_120_p_coeff_3m -3.16600969138004600291955060443412194788085531170366074271704803777538472786545753e-18 #define exp2_120_p_coeff_4h 9.61812910762847687873300372984886053018271923065185546875000000000000000000000000e-03 #define exp2_120_p_coeff_5h 1.33335581474269999902038108530177851207554340362548828125000000000000000000000000e-03 #define exp2_120_p_coeff_6h 1.54035356831810422203327126666749791183974593877792358398437500000000000000000000e-04 #define exp2_82_coeff_0h 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000e+00 #define exp2_82_coeff_1h 6.93147180559945286226763982995180413126945495605468750000000000000000000000000000e-01 #define exp2_82_coeff_1m 2.31846856407130082392820712925655671368021772333137264787694675760576501488685608e-17 #define exp2_82_coeff_2h 2.40226506959100721827482516346208285540342330932617187500000000000000000000000000e-01 #define exp2_82_coeff_3h 5.55041086710304984452868382049928186461329460144042968750000000000000000000000000e-02 #define exp2_82_coeff_4h 9.61812619551964329001059184065525187179446220397949218750000000000000000000000000e-03 typedef struct rri_tag {float ri; double logih; double logim; double logil;} rri; static const rri argredtable[256] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* r[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logih[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logim[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* logil[0] */ } , { 9.96109008789062500000000000000000000000000000000000e-01, /* r[1] */ 5.62446320255523789233276232835123664699494838714600e-03, /* logih[1] */ 3.64310694089194558034258095993109791807285384624700e-19, /* logim[1] */ -1.96284275232340525914596195720627417731891367064553e-35, /* logil[1] */ } , { 9.92248535156250000000000000000000000000000000000000e-01, /* r[2] */ 1.12265674928146846900389732581970747560262680053711e-02, /* logih[2] */ -2.01837061736057419181201412747877981301873905342571e-19, /* logim[2] */ -8.76276359130307718472217510144964999205167740057366e-36, /* logil[2] */ } , { 9.88416671752929687500000000000000000000000000000000e-01, /* r[3] */ 1.68087498900021219128131377829049597494304180145264e-02, /* logih[3] */ 3.96046463581792988288086065543694985501952808182690e-19, /* logim[3] */ -7.50175900227718281636157827566620605518389361772661e-36, /* logil[3] */ } , { 9.84615325927734375000000000000000000000000000000000e-01, /* r[4] */ 2.23678990197825021402078249366240925155580043792725e-02, /* logih[4] */ 2.72546008943383898172980491432198212129681766980967e-19, /* logim[4] */ 8.65193903240721388373038654840463886141894144823057e-36, /* logil[4] */ } , { 9.80842590332031250000000000000000000000000000000000e-01, /* r[5] */ 2.79064695222518803496836170552342082373797893524170e-02, /* logih[5] */ -1.06035466460511973857716476431794431849741915846778e-18, /* logim[5] */ 1.40399476841784981797309256958923855448288750735528e-35, /* logil[5] */ } , { 9.77099418640136718750000000000000000000000000000000e-01, /* r[6] */ 3.34227328145833349481996776830783346667885780334473e-02, /* logih[6] */ -2.30264185180544573536858875991075869298703226281026e-18, /* logim[6] */ -1.54328657939112637118099481931192082521169355752646e-34, /* logil[6] */ } , { 9.73383903503417968750000000000000000000000000000000e-01, /* r[7] */ 3.89191773983389929791876227227476192638278007507324e-02, /* logih[7] */ 2.25448778888568193693198665534250833992067200909314e-18, /* logim[7] */ -1.66706958554093095538277426422752915572221541711786e-35, /* logil[7] */ } , { 9.69696998596191406250000000000000000000000000000000e-01, /* r[8] */ 4.43940763627913639877142770728823961690068244934082e-02, /* logih[8] */ -1.35148268469329738787933054025463561212703774709647e-18, /* logim[8] */ -9.30542106567779590725369440921408781707570437070629e-36, /* logil[8] */ } , { 9.66037750244140625000000000000000000000000000000000e-01, /* r[9] */ 4.98485279527303287716577528954076115041971206665039e-02, /* logih[9] */ 6.99684078718519819164474461192556823314757766482007e-19, /* logim[9] */ -2.43070079250460900406108506315855413208920069880071e-35, /* logil[9] */ } , { 9.62406158447265625000000000000000000000000000000000e-01, /* r[10] */ 5.52822205228920421360427894796885084360837936401367e-02, /* logih[10] */ -2.28041829375459011783136992188608860381451027094727e-18, /* logim[10] */ 2.92509524765364940130250242310369777453156638429065e-35, /* logil[10] */ } , { 9.58801269531250000000000000000000000000000000000000e-01, /* r[11] */ 6.06962756528966682068038096531381597742438316345215e-02, /* logih[11] */ -2.30575104391021062016554403718699744533879233050506e-18, /* logim[11] */ -7.17933773994063224992733787486043953294734193934224e-35, /* logil[11] */ } , { 9.55224037170410156250000000000000000000000000000000e-01, /* r[12] */ 6.60889539816468807309490784973604604601860046386719e-02, /* logih[12] */ -3.43531319808022917726081135288707689815983878236052e-18, /* logim[12] */ -1.33537440950953098282350657111014906210298802453012e-34, /* logil[12] */ } , { 9.51672554016113281250000000000000000000000000000000e-01, /* r[13] */ 7.14628301345319461024274687588331289589405059814453e-02, /* logih[13] */ 2.85019564755822761568469835817513709577072221641996e-18, /* logim[13] */ -9.19067891131942166039810480616019695600822882350246e-37, /* logil[13] */ } , { 9.48147773742675781250000000000000000000000000000000e-01, /* r[14] */ 7.68161667434743566929000735399313271045684814453125e-02, /* logih[14] */ -1.06503850285483291664763275879140215046738161101689e-18, /* logim[14] */ -7.65539408485798958761020119630194135239837477350922e-35, /* logil[14] */ } , { 9.44649696350097656250000000000000000000000000000000e-01, /* r[15] */ 8.21486597674154217507691555510973557829856872558594e-02, /* logih[15] */ 1.05949179068992293701743882962947866868089440388204e-18, /* logim[15] */ -8.01871606400843361947793952324428287361058018241436e-35, /* logil[15] */ } , { 9.41176414489746093750000000000000000000000000000000e-01, /* r[16] */ 8.74629272416674041767947755943168886005878448486328e-02, /* logih[16] */ -1.77710701464998942664649859987232463493014273104014e-18, /* logim[16] */ -1.80956122292284222227087580389487512155443759846534e-35, /* logil[16] */ } , { 9.37728881835937500000000000000000000000000000000000e-01, /* r[17] */ 9.27572269111804487140560127045318949967622756958008e-02, /* logih[17] */ -5.27591334713426660094475417460021043346056467758629e-18, /* logim[17] */ -1.53175520932242863184799310580698131125491486503283e-34, /* logil[17] */ } , { 9.34306144714355468750000000000000000000000000000000e-01, /* r[18] */ 9.80327386445321302677058383778785355389118194580078e-02, /* logih[18] */ -5.93734060789694089615179387615749478380374593921383e-19, /* logim[18] */ 3.22072168497817739835267264564341161078059188303423e-35, /* logil[18] */ } , { 9.30909156799316406250000000000000000000000000000000e-01, /* r[19] */ 1.03287706297326614679477074787428136914968490600586e-01, /* logih[19] */ 1.33325264360904317354548306659732409559419348498273e-18, /* logim[19] */ 3.31890629684034024636090527929623831396401127155796e-36, /* logil[19] */ } , { 9.27536010742187500000000000000000000000000000000000e-01, /* r[20] */ 1.08524800743511784517636442615184932947158813476562e-01, /* logih[20] */ -1.28671557844966439678563543759408610236814325233478e-18, /* logim[20] */ -2.56854731168380358630388572766888073135733818319681e-35, /* logil[20] */ } , { 9.24187660217285156250000000000000000000000000000000e-01, /* r[21] */ 1.13742268163890894450140933713555568829178810119629e-01, /* logih[21] */ -8.77036301522305748474920477842609739773359932085098e-19, /* logim[21] */ 8.57410843683479675757388920826360661070052891897777e-35, /* logil[21] */ } , { 9.20863151550292968750000000000000000000000000000000e-01, /* r[22] */ 1.18941319948589224742008241264557000249624252319336e-01, /* logih[22] */ 4.19531239651888390161555205120491536470911709375714e-18, /* logim[22] */ -2.32937303080172707430415739969539325535648073239647e-34, /* logil[22] */ } , { 9.17562484741210937500000000000000000000000000000000e-01, /* r[23] */ 1.24121688041285385684098230285599129274487495422363e-01, /* logih[23] */ 9.00256823026971617398245077356557223480847847208472e-19, /* logim[23] */ 6.70088260119589436198762199150551511628184558421695e-35, /* logil[23] */ } , { 9.14285659790039062500000000000000000000000000000000e-01, /* r[24] */ 1.29283102936294441720477266244415659457445144653320e-01, /* logih[24] */ 7.73743323061072771474411865735142118226773038589797e-18, /* logim[24] */ 7.00151503950389057387088983272314894406637587361574e-34, /* logil[24] */ } , { 9.11031723022460937500000000000000000000000000000000e-01, /* r[25] */ 1.34426803922212734221375285414978861808776855468750e-01, /* logih[25] */ 2.87442943483450917166131039871184389070859209874820e-18, /* logim[25] */ 1.07418394159169377416152150989201926752424104438080e-34, /* logil[25] */ } , { 9.07801628112792968750000000000000000000000000000000e-01, /* r[26] */ 1.39551019182446001121178369430708698928356170654297e-01, /* logih[26] */ -1.30334047193679924727952135062206194795888829424720e-17, /* logim[26] */ 7.66296121586659828803741925222999984250452285658724e-34, /* logil[26] */ } , { 9.04593467712402343750000000000000000000000000000000e-01, /* r[27] */ 1.44658516929258157412974128419591579586267471313477e-01, /* logih[27] */ 1.38592310231888602734839275401641903151588210621318e-17, /* logim[27] */ 7.04204624169239561960113974223630631428167482568361e-34, /* logil[27] */ } , { 9.01408195495605468750000000000000000000000000000000e-01, /* r[28] */ 1.49747527963535687067775370451272465288639068603516e-01, /* logih[28] */ -4.63121585254300608564541809516560465960812790456487e-18, /* logim[28] */ -2.38375164082682849282198954173370103452053181545581e-34, /* logil[28] */ } , { 8.98245811462402343750000000000000000000000000000000e-01, /* r[29] */ 1.54817791959126344059072266645671334117650985717773e-01, /* logih[29] */ -1.97608219816229633690476653766429513925576435617957e-18, /* logim[29] */ -7.29293250516190589410842756372025648233179264971183e-35, /* logil[29] */ } , { 8.95105361938476562500000000000000000000000000000000e-01, /* r[30] */ 1.59870584354488087797108164522796869277954101562500e-01, /* logih[30] */ 1.38164327179219532318047293404835044148743773120749e-17, /* logim[30] */ 2.60902789861922854258976768649749081077445016828227e-34, /* logil[30] */ } , { 8.91985893249511718750000000000000000000000000000000e-01, /* r[31] */ 1.64907200773063644660965110233519226312637329101562e-01, /* logih[31] */ 6.40258479048132435575035617265253227017927489659503e-18, /* logim[31] */ -3.13994360424306793167722791429686820377012800164626e-36, /* logil[31] */ } , { 8.88889312744140625000000000000000000000000000000000e-01, /* r[32] */ 1.69924313511872926429902008749195374548435211181641e-01, /* logih[32] */ 6.27897206252693367521427657669679268044418008293354e-19, /* logim[32] */ -1.84662823838719713889061260700783214693984580501609e-35, /* logil[32] */ } , { 8.85812759399414062500000000000000000000000000000000e-01, /* r[33] */ 1.74926316686843275061136182557675056159496307373047e-01, /* logih[33] */ -1.28095711942361950784467450834305264934252560279915e-17, /* logim[33] */ 6.15728414357675841500352304615531898144676821521735e-34, /* logil[33] */ } , { 8.82759094238281250000000000000000000000000000000000e-01, /* r[34] */ 1.79908316093213171971143538030446507036685943603516e-01, /* logih[34] */ -4.05669244508450884106169713651948436101460999171934e-18, /* logim[34] */ -2.73456623470470858112008354603047232113150522790287e-34, /* logil[34] */ } , { 8.79725456237792968750000000000000000000000000000000e-01, /* r[35] */ 1.84874735594675820848920011485461145639419555664062e-01, /* logih[35] */ 7.83038695439828504402955103668931677062328445957555e-18, /* logim[35] */ 6.50239128030890104986149271144609240438163759169796e-34, /* logil[35] */ } , { 8.76712799072265625000000000000000000000000000000000e-01, /* r[36] */ 1.89823784958295938007921677126432769000530242919922e-01, /* logih[36] */ -8.81954617013802931471562955085007459413223371703754e-18, /* logim[36] */ 4.68176162545611138840109682829353162004456293635899e-34, /* logil[36] */ } , { 8.73720169067382812500000000000000000000000000000000e-01, /* r[37] */ 1.94756800677670482979664257072727195918560028076172e-01, /* logih[37] */ -2.00670924345318825647424200264947046592235601474052e-18, /* logim[37] */ 1.23510776676180725049881134754892221509956109351828e-34, /* logil[37] */ } , { 8.70748519897460937500000000000000000000000000000000e-01, /* r[38] */ 1.99671979373277602709535472058632876724004745483398e-01, /* logih[38] */ -3.35041803578082878314072229510113791314884693559175e-19, /* logim[38] */ 2.19585849692745582866688760428854814221266519680553e-36, /* logil[38] */ } , { 8.67796897888183593750000000000000000000000000000000e-01, /* r[39] */ 2.04570665922535199765519564607529900968074798583984e-01, /* logih[39] */ -1.04751553531138287440354969580963337427221634013275e-17, /* logim[39] */ -4.69171037663777474441792299191703931076443660125798e-34, /* logil[39] */ } , { 8.64865303039550781250000000000000000000000000000000e-01, /* r[40] */ 2.09452634702868761840122147077636327594518661499023e-01, /* logih[40] */ 1.10703702929617688876102394158665802371341635353943e-17, /* logim[40] */ -7.14976977668988171404204188299765278177460282467036e-34, /* logil[40] */ } , { 8.61952781677246093750000000000000000000000000000000e-01, /* r[41] */ 2.14319255162218030852372407935035880655050277709961e-01, /* logih[41] */ 1.29702313007778250478283769152847492223363745647243e-17, /* logim[41] */ 5.73068113001992288619079890329675696690665640594386e-34, /* logil[41] */ } , { 8.59060287475585937500000000000000000000000000000000e-01, /* r[42] */ 2.19168713942656773197015240839391481131315231323242e-01, /* logih[42] */ -7.04698144913766631623882809355752075602951087972227e-18, /* logim[42] */ -6.81063628416184547095854182554280736255034389907768e-34, /* logil[42] */ } , { 8.56186866760253906250000000000000000000000000000000e-01, /* r[43] */ 2.24002389001174750937650514970300719141960144042969e-01, /* logih[43] */ 9.77089146727803082940117001653944079518215379270970e-18, /* logim[43] */ -5.15654043774815198603423123107750339552695455461599e-34, /* logil[43] */ } , { 8.53333473205566406250000000000000000000000000000000e-01, /* r[44] */ 2.28818454019755312955908266303595155477523803710938e-01, /* logih[44] */ 8.60482840827231531693211061331421783325499374269103e-18, /* logim[44] */ 4.62159649315070967905902800219645706522346592477674e-34, /* logil[44] */ } , { 8.50498199462890625000000000000000000000000000000000e-01, /* r[45] */ 2.33619913235866366596482635031861718744039535522461e-01, /* logih[45] */ -3.17603438795656722833659731362733461077382072175793e-18, /* logim[45] */ -1.14190998511637372945280226124717188573979535104549e-34, /* logil[45] */ } , { 8.47681999206542968750000000000000000000000000000000e-01, /* r[46] */ 2.38404943554491266510808600287418812513351440429688e-01, /* logih[46] */ -4.91919207875165757062252476472896320156113810759041e-18, /* logim[46] */ -1.65774202516213266221949772053971269011961846039958e-34, /* logil[46] */ } , { 8.44884872436523437500000000000000000000000000000000e-01, /* r[47] */ 2.43173327789243498564530909789027646183967590332031e-01, /* logih[47] */ 4.93306440425329257306593810775031695904319815014754e-18, /* logim[47] */ -1.13614580751390656792590805859574652593001401554151e-34, /* logil[47] */ } , { 8.42104911804199218750000000000000000000000000000000e-01, /* r[48] */ 2.47928115382989089354737188841681927442550659179688e-01, /* logih[48] */ -1.37712103635557072032234153365222440536782865715083e-18, /* logim[48] */ 9.75493887073081889286766097804801019201793778479461e-36, /* logil[48] */ } , { 8.39344024658203125000000000000000000000000000000000e-01, /* r[49] */ 2.52665840909102268341257513384334743022918701171875e-01, /* logih[49] */ -2.29689231346274680410439539616369605449817860326088e-17, /* logim[49] */ -5.60202341060166161523536551099252965521444882693529e-34, /* logil[49] */ } , { 8.36601257324218750000000000000000000000000000000000e-01, /* r[50] */ 2.57387928683979749777677170641254633665084838867188e-01, /* logih[50] */ 1.55294884781987048139059464306453784663352757128198e-17, /* logim[50] */ 1.01380707456162023479965432916465584034071816674502e-33, /* logil[50] */ } , { 8.33876609802246093750000000000000000000000000000000e-01, /* r[51] */ 2.62094173563105881097357041653594933450222015380859e-01, /* logih[51] */ -8.55713950348344689585298731473352525543751015890334e-18, /* logim[51] */ 5.48763060317488000144168502344734048354142056565485e-34, /* logil[51] */ } , { 8.31169128417968750000000000000000000000000000000000e-01, /* r[52] */ 2.66786024747041050630969039048068225383758544921875e-01, /* logih[52] */ -1.67542241678008684495879286127707515841429324510332e-17, /* logim[52] */ -1.84450647715786516704590189681050172449564734674026e-34, /* logil[52] */ } , { 8.28478813171386718750000000000000000000000000000000e-01, /* r[53] */ 2.71463291252832750188872523722238838672637939453125e-01, /* logih[53] */ -1.82861289604292083819624352321660587975949022128451e-17, /* logim[53] */ 1.41344704609359941327335627738873295910710446946318e-33, /* logil[53] */ } , { 8.25806617736816406250000000000000000000000000000000e-01, /* r[54] */ 2.76124115053543395248425440513528883457183837890625e-01, /* logih[54] */ 2.16585493379379121431927795059778160498079515320280e-17, /* logim[54] */ 8.60215787486055402643372799849720707717258614661468e-34, /* logil[54] */ } , { 8.23151588439941406250000000000000000000000000000000e-01, /* r[55] */ 2.80769958587697043839170873980037868022918701171875e-01, /* logih[55] */ -7.49945068305251944743518556464975251268962220130981e-18, /* logim[55] */ -3.35683654241982931982204205181485008542845495662437e-34, /* logil[55] */ } , { 8.20512771606445312500000000000000000000000000000000e-01, /* r[56] */ 2.85402304853576316290286740695592015981674194335938e-01, /* logih[56] */ 1.97058866076428412478768008134629487975209602250437e-17, /* logim[56] */ 1.06837698553508766117432923132263183155168973782721e-33, /* logil[56] */ } , { 8.17891120910644531250000000000000000000000000000000e-01, /* r[57] */ 2.90019293012687973121188633740530349314212799072266e-01, /* logih[57] */ 2.56668340633873322360015168072740173815474168247740e-19, /* logim[57] */ 1.32070461247422232763959137046376896815849857773214e-35, /* logil[57] */ } , { 8.15286636352539062500000000000000000000000000000000e-01, /* r[58] */ 2.94620727393795800441722576579195447266101837158203e-01, /* logih[58] */ 8.28856253528690669390956178529769851637375900355867e-18, /* logim[58] */ 9.21060163289173545842870657414802261911841193726753e-35, /* logil[58] */ } , { 8.12698364257812500000000000000000000000000000000000e-01, /* r[59] */ 2.99208104378606787321359661291353404521942138671875e-01, /* logih[59] */ 2.50440287234594231108545303202106361171199143807143e-17, /* logim[59] */ 5.76496224108896237321806536123506494667013214131283e-34, /* logil[59] */ } , { 8.10126304626464843750000000000000000000000000000000e-01, /* r[60] */ 3.03781242627308878390124391444260254502296447753906e-01, /* logih[60] */ 7.26236946156037909713854903168533397481837663535236e-18, /* logim[60] */ -5.13832288823633829539789242568260267295555917557936e-34, /* logil[60] */ } , { 8.07571411132812500000000000000000000000000000000000e-01, /* r[61] */ 3.08338256217685957594198953302111476659774780273438e-01, /* logih[61] */ -3.91862830506871787886277655283277883335703800578341e-18, /* logim[61] */ -1.80287911307734040041601196733261985968717764792270e-34, /* logil[61] */ } , { 8.05031776428222656250000000000000000000000000000000e-01, /* r[62] */ 3.12882364094114129304813332055346108973026275634766e-01, /* logih[62] */ 2.00566095640240859030080760939632903054042270806498e-17, /* logim[62] */ -1.20548577698548841142520422108638918923500554048039e-33, /* logil[62] */ } , { 8.02507400512695312500000000000000000000000000000000e-01, /* r[63] */ 3.17413398435927307517090412147808820009231567382812e-01, /* logih[63] */ 1.92917962412721060884664265681098014687881777581369e-17, /* logim[63] */ -5.60605040615516964419678016739265374372709613799588e-34, /* logil[63] */ } , { 8.00000190734863281250000000000000000000000000000000e-01, /* r[64] */ 3.21927750922101629793559141035075299441814422607422e-01, /* logih[64] */ -3.68777572337715973775586041884209304585818249254945e-18, /* logim[64] */ 2.42378345855852981194379769493259763563573896470280e-34, /* logil[64] */ } , { 7.97508239746093750000000000000000000000000000000000e-01, /* r[65] */ 3.26428670204942816823745488363783806562423706054688e-01, /* logih[65] */ 1.45984677103376311105171213886420877499189566989355e-18, /* logim[65] */ 8.54804091592753412940247017733822117449065792260507e-35, /* logil[65] */ } , { 7.95030593872070312500000000000000000000000000000000e-01, /* r[66] */ 3.30917716530283567699655122851254418492317199707031e-01, /* logih[66] */ -1.10914470017120619152208446527819480613105503270278e-17, /* logim[66] */ 7.68957589367645155571847946740580012038237827888475e-35, /* logil[66] */ } , { 7.92570114135742187500000000000000000000000000000000e-01, /* r[67] */ 3.35389527027655065527511624168255366384983062744141e-01, /* logih[67] */ -2.68905140673031160753055547019515200860581054595347e-17, /* logim[67] */ 1.12312306509581200028305457580071181488591082452267e-33, /* logil[67] */ } , { 7.90122985839843750000000000000000000000000000000000e-01, /* r[68] */ 3.39850862798135311404479352859198115766048431396484e-01, /* logih[68] */ 2.67578448800166743621563940564181619384497916823689e-18, /* logim[68] */ -4.08593208106915232849113978946102464404769851005264e-36, /* logil[68] */ } , { 7.87692070007324218750000000000000000000000000000000e-01, /* r[69] */ 3.44296343246967506690481286568683572113513946533203e-01, /* logih[69] */ 2.61985729966483159298053143855013667206513518139355e-17, /* logim[69] */ -1.43317776294076914943494562393727319237442460573694e-33, /* logil[69] */ } , { 7.85276412963867187500000000000000000000000000000000e-01, /* r[70] */ 3.48727530794102902333975180226843804121017456054688e-01, /* logih[70] */ -2.34058128233080475834922834476410669486100635732851e-17, /* logim[70] */ -1.19495530307809197006632618244668279768915361517721e-33, /* logil[70] */ } , { 7.82875061035156250000000000000000000000000000000000e-01, /* r[71] */ 3.53146008580722203795687619276577606797218322753906e-01, /* logih[71] */ 2.51020933081373096955654998109339846738212697870377e-17, /* logim[71] */ 3.85467771988000503348528260185321311042188078683671e-35, /* logil[71] */ } , { 7.80488014221191406250000000000000000000000000000000e-01, /* r[72] */ 3.57551617657171139086358380154706537723541259765625e-01, /* logih[72] */ 8.26026920265729456320682991301405499549392385594867e-18, /* logim[72] */ -4.82409659516332608730700682966909062399273519559205e-34, /* logil[72] */ } , { 7.78115272521972656250000000000000000000000000000000e-01, /* r[73] */ 3.61944198317473264658872267318656668066978454589844e-01, /* logih[73] */ 9.35251240570409658369637671707393177323119533170476e-18, /* logim[73] */ 7.65402247015393379174811496478109595932454697550257e-34, /* logil[73] */ } , { 7.75757789611816406250000000000000000000000000000000e-01, /* r[74] */ 3.66321816535990496532804172602482140064239501953125e-01, /* logih[74] */ -1.26283763367166791971668084210111644172264929234222e-17, /* logim[74] */ -5.18175152989954334710733729135724747368463044348133e-34, /* logil[74] */ } , { 7.73413658142089843750000000000000000000000000000000e-01, /* r[75] */ 3.70687852887287339065380820102291181683540344238281e-01, /* logih[75] */ -2.26426578076002335190700377100879173906840093029931e-18, /* logim[75] */ 9.39919422448895887884207901501396710115618070243006e-35, /* logil[75] */ } , { 7.71084785461425781250000000000000000000000000000000e-01, /* r[76] */ 3.75038592931745407010879489462240599095821380615234e-01, /* logih[76] */ 1.36478878694725594397668899630117789175518936328670e-17, /* logim[76] */ -7.42102285102582603712767861440251383531360222023193e-34, /* logil[76] */ } , { 7.68768310546875000000000000000000000000000000000000e-01, /* r[77] */ 3.79379226984772721653627058913116343319416046142578e-01, /* logih[77] */ 1.13769630716652922583152930707043643780239195343403e-17, /* logim[77] */ -5.71497157206590541051326347759309167725971873915619e-34, /* logil[77] */ } , { 7.66467094421386718750000000000000000000000000000000e-01, /* r[78] */ 3.83704238729474844671329947232152335345745086669922e-01, /* logih[78] */ -1.37569501553533684673235058090995964600109755003945e-17, /* logim[78] */ -8.19419663933668791519024676445202574794121365195595e-35, /* logil[78] */ } , { 7.64179229736328125000000000000000000000000000000000e-01, /* r[79] */ 3.88017048869009228972970504401018843054771423339844e-01, /* logih[79] */ -3.80701519449449765873708863588277305202153361708738e-18, /* logim[79] */ 1.41209082306365988413846146208806553569817267206609e-34, /* logil[79] */ } , { 7.61904716491699218750000000000000000000000000000000e-01, /* r[80] */ 3.92317508770088307912260461307596415281295776367188e-01, /* logih[80] */ -2.48709304499940275271685524139705487487812483329234e-17, /* logim[80] */ 1.51913530740466505110972004119148045675527858280419e-33, /* logil[80] */ } , { 7.59643554687500000000000000000000000000000000000000e-01, /* r[81] */ 3.96605469112625952377015892125200480222702026367188e-01, /* logih[81] */ -2.05409584188905648894008644042627621347744841311892e-17, /* logim[81] */ 2.22145444790121064274793819131004556765772287126498e-35, /* logil[81] */ } , { 7.57396697998046875000000000000000000000000000000000e-01, /* r[82] */ 4.00878963329971971241150185960577800869941711425781e-01, /* logih[82] */ -2.66817967026326825523345579536420301974049078445688e-19, /* logim[82] */ -1.05363633967249486254042597699490314094813255836572e-35, /* logil[82] */ } , { 7.55162239074707031250000000000000000000000000000000e-01, /* r[83] */ 4.05141468510801738833748686374747194349765777587891e-01, /* logih[83] */ 4.12013026738107642301137843414110630137096547313805e-19, /* logim[83] */ 2.33575446522787458311195104600075869808876514799442e-35, /* logil[83] */ } , { 7.52941131591796875000000000000000000000000000000000e-01, /* r[84] */ 4.09391022129029724663240585869061760604381561279297e-01, /* logih[84] */ 2.56067666045646563728399935742968282460993394682039e-17, /* logim[84] */ -5.13721066726803690112726682214076449553351301368597e-34, /* logil[84] */ } , { 7.50733375549316406250000000000000000000000000000000e-01, /* r[85] */ 4.13627472195328416137982685540919192135334014892578e-01, /* logih[85] */ 2.18808337792321329482011871274589564814328341663075e-17, /* logim[85] */ 1.02540355629315485391150379093592950725836019876557e-33, /* logil[85] */ } , { 7.48538017272949218750000000000000000000000000000000e-01, /* r[86] */ 4.17852504136982216831341929719201289117336273193359e-01, /* logih[86] */ 9.86946871873695851969756471738566369665379660554619e-19, /* logim[86] */ 6.29612486797528483220726516137805747359270884942425e-35, /* logil[86] */ } , { 7.46356010437011718750000000000000000000000000000000e-01, /* r[87] */ 4.22064137361382152313638016494223847985267639160156e-01, /* logih[87] */ -1.05922076934284027175745907413659282941993793826139e-17, /* logim[87] */ -6.12299960012078338449376466647955436587104734540624e-34, /* logil[87] */ } , { 7.44186401367187500000000000000000000000000000000000e-01, /* r[88] */ 4.26264066771658511889597775734728202223777770996094e-01, /* logih[88] */ -8.85513480816040453945742392800672953193458312727256e-18, /* logim[88] */ -5.24714106986727460487580275593262691651180525370791e-34, /* logil[88] */ } , { 7.42029190063476562500000000000000000000000000000000e-01, /* r[89] */ 4.30452153955706073862330640622531063854694366455078e-01, /* logih[89] */ 2.61368823927001457998555167240062922142140611089746e-17, /* logim[89] */ 1.44680766060028701358746313826017052885573936570807e-33, /* logil[89] */ } , { 7.39884376525878906250000000000000000000000000000000e-01, /* r[90] */ 4.34628259883472034541540551799698732793331146240234e-01, /* logih[90] */ -4.65804559835565790738625882506228255266947860929998e-18, /* logim[90] */ 3.50162107860052357002426832774093849420181199400792e-34, /* logil[90] */ } , { 7.37751960754394531250000000000000000000000000000000e-01, /* r[91] */ 4.38792244913736528832970407165703363716602325439453e-01, /* logih[91] */ 6.54435041067844518638349922716293820410138082918974e-18, /* logim[91] */ 1.66288117681168517806253799205003056056005048205360e-34, /* logil[91] */ } , { 7.35631942749023437500000000000000000000000000000000e-01, /* r[92] */ 4.42943968801095711018689371485379524528980255126953e-01, /* logih[92] */ -1.31830993629830820106422084359785358736815996728614e-17, /* logim[92] */ 4.61053576482372100205685418524847218246553128543631e-34, /* logil[92] */ } , { 7.33524322509765625000000000000000000000000000000000e-01, /* r[93] */ 4.47083290703147728795130433354643173515796661376953e-01, /* logih[93] */ 1.69077329042533132659710418879288890988542117042696e-17, /* logim[93] */ 9.64412076794160463494531210530587642610119179701767e-34, /* logil[93] */ } , { 7.31428146362304687500000000000000000000000000000000e-01, /* r[94] */ 4.51211950247995374763121390060405246913433074951172e-01, /* logih[94] */ 5.29157734589489879989241042345888795815986344495564e-18, /* logim[94] */ 4.05922256458861404459677801513180982129072332853957e-35, /* logil[94] */ } , { 7.29344367980957031250000000000000000000000000000000e-01, /* r[95] */ 4.55327935107630421551760946385911665856838226318359e-01, /* logih[95] */ 1.12238496235431997950024540898660473611218791584296e-17, /* logim[95] */ 2.53810412167217662475589577599465754868617140018869e-34, /* logil[95] */ } , { 7.27272987365722656250000000000000000000000000000000e-01, /* r[96] */ 4.59431102689436932084987574853585101664066314697266e-01, /* logih[96] */ -5.65021202083821658568979172094850503702023051443232e-18, /* logim[96] */ 2.66729880996649709196382536663439201060959304794017e-34, /* logil[96] */ } , { 7.25212097167968750000000000000000000000000000000000e-01, /* r[97] */ 4.63525104197631598879070224938914179801940917968750e-01, /* logih[97] */ 1.64015018050273811377058500937130036591871213663913e-17, /* logim[97] */ -2.37668158047196530099123034685246144103569462059140e-35, /* logil[97] */ } , { 7.23163604736328125000000000000000000000000000000000e-01, /* r[98] */ 4.67606023035364859463669517936068587005138397216797e-01, /* logih[98] */ -2.35404459021293530100419612489692369296536941011139e-17, /* logim[98] */ 8.65686412848735892137131700314774245266762617410743e-34, /* logil[98] */ } , { 7.21126556396484375000000000000000000000000000000000e-01, /* r[99] */ 4.71675622850898035309796796354930847883224487304688e-01, /* logih[99] */ -5.00291784895727418193570650071413020227423422230627e-18, /* logim[99] */ -3.48814629702810911815080058632968938255265704317182e-34, /* logil[99] */ } , { 7.19100952148437500000000000000000000000000000000000e-01, /* r[100] */ 4.75733774931740460711893092593527399003505706787109e-01, /* logih[100] */ 2.37354207292015831848317508817743592416645271551013e-17, /* logim[100] */ 3.75220251398787236762445752605220099123667359652946e-34, /* logil[100] */ } , { 7.17086791992187500000000000000000000000000000000000e-01, /* r[101] */ 4.79780350020427681645429629497812129557132720947266e-01, /* logih[101] */ 9.64996639262616277761997731342311958042765881278166e-18, /* logim[101] */ -1.45917791984963879526832989164269922466650870970319e-34, /* logil[101] */ } , { 7.15084075927734375000000000000000000000000000000000e-01, /* r[102] */ 4.83815218320749418356996329748653806746006011962891e-01, /* logih[102] */ -2.26055495552680496488915066271475591152753444344542e-17, /* logim[102] */ 1.15943477520296400421924802163066587581164941504239e-33, /* logil[102] */ } , { 7.13091850280761718750000000000000000000000000000000e-01, /* r[103] */ 4.87840178933420298701406636610045097768306732177734e-01, /* logih[103] */ 9.95061561880808777250662218784807296295756393896643e-18, /* logim[103] */ -2.70730037505675842458176336457886940782026608863071e-34, /* logil[103] */ } , { 7.11111068725585937500000000000000000000000000000000e-01, /* r[104] */ 4.91853182321002724286529428354697301983833312988281e-01, /* logih[104] */ -1.93631103608357505056849606827194505159750296147429e-17, /* logim[104] */ -5.13067202688456219222003091599945986652944064972985e-34, /* logil[104] */ } , { 7.09141731262207031250000000000000000000000000000000e-01, /* r[105] */ 4.95854097106264379846152223763056099414825439453125e-01, /* logih[105] */ -8.97253997785747359550285084120100354068920818555134e-18, /* logim[105] */ 4.48985852964966878119016366112985893401143906248048e-34, /* logil[105] */ } , { 1.41436386108398437500000000000000000000000000000000e+00, /* r[106] */ -5.00153317496815130738241350627504289150238037109375e-01, /* logih[106] */ 6.38652340493840901898261226024177907291121978480765e-18, /* logim[106] */ -1.50115709371786842001778403725543006667379544298665e-34, /* logil[106] */ } , { 1.41046905517578125000000000000000000000000000000000e+00, /* r[107] */ -4.96175014428150595868771688401466235518455505371094e-01, /* logih[107] */ -2.52613980927368683904892283975420623567633947857171e-17, /* logim[107] */ -2.78172233261534782496122526419959911999891480999118e-34, /* logil[107] */ } , { 1.40659332275390625000000000000000000000000000000000e+00, /* r[108] */ -4.92205273809975751841960800447850488126277923583984e-01, /* logih[108] */ 1.38263645220702992115908316962406899116133433250055e-17, /* logim[108] */ -9.13478810114964638432169273750765158178251684940645e-35, /* logil[108] */ } , { 1.40274047851562500000000000000000000000000000000000e+00, /* r[109] */ -4.88248120154341713750056896969908848404884338378906e-01, /* logih[109] */ -9.19124816655229741100591795639860013679834003477893e-18, /* logim[109] */ 3.57736696925483033542993216894623988952660296440587e-34, /* logil[109] */ } , { 1.39890670776367187500000000000000000000000000000000e+00, /* r[110] */ -4.84299753257103948733686138439225032925605773925781e-01, /* logih[110] */ 2.76894400316545187895597055836412754062515893165117e-17, /* logim[110] */ -1.28196249311567885024568784724802925800328520582323e-33, /* logil[110] */ } , { 1.39509582519531250000000000000000000000000000000000e+00, /* r[111] */ -4.80364220108999595559851059078937396407127380371094e-01, /* logih[111] */ 1.60772577856827581149848485565219950146355948388194e-17, /* logim[111] */ -6.33909180037348533226128939381564653515346318497266e-34, /* logil[111] */ } , { 1.39130401611328125000000000000000000000000000000000e+00, /* r[112] */ -4.76437699977644402160592562722740694880485534667969e-01, /* logih[112] */ 3.93777448294044466045455458211156033645576475025704e-18, /* logim[112] */ 3.61421668039083688240729461133241002751658704802140e-35, /* logil[112] */ } , { 1.38753318786621093750000000000000000000000000000000e+00, /* r[113] */ -4.72522279136534217869325402716640383005142211914062e-01, /* logih[113] */ 1.96035568196414967372784793032251967173332695653211e-18, /* logim[113] */ -1.17747583658959694655352427302025069169526418930102e-34, /* logil[113] */ } , { 1.38378334045410156250000000000000000000000000000000e+00, /* r[114] */ -4.68618077280239631043912140739848837256431579589844e-01, /* logih[114] */ -6.21887814563789414007506165242075506645450300833460e-18, /* logim[114] */ 2.85091055480350088234477660182894618899479782600553e-34, /* logil[114] */ } , { 1.38005447387695312500000000000000000000000000000000e+00, /* r[115] */ -4.64725214569437938827434209088096395134925842285156e-01, /* logih[115] */ 1.41770874784515407852341959571636665299319020447279e-17, /* logim[115] */ 7.16277267487504881902108530195699095867171533372599e-34, /* logil[115] */ } , { 1.37634468078613281250000000000000000000000000000000e+00, /* r[116] */ -4.60841812328943278842530162364710122346878051757812e-01, /* logih[116] */ -4.53322590938932589383322662851218023838002020827810e-18, /* logim[116] */ -3.00474404192043520651451236027633906276066461510596e-34, /* logil[116] */ } , { 1.37265396118164062500000000000000000000000000000000e+00, /* r[117] */ -4.56967975515349844606305396155221387743949890136719e-01, /* logih[117] */ -2.33094358634200721377135368497958427964300301497283e-17, /* logim[117] */ 9.88425626506853222061479506529364782400408771511375e-34, /* logil[117] */ } , { 1.36898422241210937500000000000000000000000000000000e+00, /* r[118] */ -4.53105819584143920675245453821844421327114105224609e-01, /* logih[118] */ 2.01510616322289821386139052884185780607827719984300e-18, /* logim[118] */ 6.02181671552856437268832796139799348494799893689780e-35, /* logil[118] */ } , { 1.36533355712890625000000000000000000000000000000000e+00, /* r[119] */ -4.49253451092882338802070307792746461927890777587891e-01, /* logih[119] */ 8.23312641185804722064182220776569229058888742494964e-18, /* logim[119] */ 3.51720183694942905373021695760046871719134069706073e-34, /* logil[119] */ } , { 1.36170196533203125000000000000000000000000000000000e+00, /* r[120] */ -4.45410976339701503157186834869207814335823059082031e-01, /* logih[120] */ -1.08977418015840362022538949472279372016122627370204e-17, /* logim[120] */ 6.97295970316695053124005231434035931338517048339577e-34, /* logil[120] */ } , { 1.35808944702148437500000000000000000000000000000000e+00, /* r[121] */ -4.41578502060277766627649498332175426185131072998047e-01, /* logih[121] */ -2.36601424071700836766138911811129382339795814666297e-18, /* logim[121] */ -8.33576574128057056240434241376128274787476967696058e-35, /* logil[121] */ } , { 1.35449790954589843750000000000000000000000000000000e+00, /* r[122] */ -4.37758166969168582838278780400287359952926635742188e-01, /* logih[122] */ 2.32683708630670947650076997142659873229215752583714e-17, /* logim[122] */ -4.15560143754890940120352265317471333960877272565937e-34, /* logil[122] */ } , { 1.35092353820800781250000000000000000000000000000000e+00, /* r[123] */ -4.33946020947943322809692290320526808500289916992188e-01, /* logih[123] */ -6.30929577529820412721860253954307086992044476041831e-19, /* logim[123] */ 3.79819606716958067883014408281063348020187639876938e-35, /* logil[123] */ } , { 1.34736824035644531250000000000000000000000000000000e+00, /* r[124] */ -4.30144198188556980966268383781425654888153076171875e-01, /* logih[124] */ 1.71683205857569655573934637457594450429113050785555e-17, /* logim[124] */ 7.29043201113051662805038181720083419974138092701628e-34, /* logil[124] */ } , { 1.34383201599121093750000000000000000000000000000000e+00, /* r[125] */ -4.26352807132220124053390009066788479685783386230469e-01, /* logih[125] */ 8.26061049860036128096500446845868042685767901578105e-18, /* logim[125] */ 4.84223346776956637948090236698054613852109689623963e-35, /* logil[125] */ } , { 1.34031486511230468750000000000000000000000000000000e+00, /* r[126] */ -4.22571956634882506254058398553752340376377105712891e-01, /* logih[126] */ 2.21190566670722703461840612616380011243743333737306e-17, /* logim[126] */ 1.14896204572710075326698165510345911361717606050114e-33, /* logil[126] */ } , { 1.33681488037109375000000000000000000000000000000000e+00, /* r[127] */ -4.18799697546823501692614399871672503650188446044922e-01, /* logih[127] */ 3.41599526072994406508033857887135558854814373525867e-18, /* logim[127] */ 1.61801446193077496556464113278472787123475795694267e-34, /* logil[127] */ } , { 1.33333396911621093750000000000000000000000000000000e+00, /* r[128] */ -4.15038187209283260248326996588730253279209136962891e-01, /* logih[128] */ 5.85238726764280271365110933546070366526501739862427e-18, /* logim[128] */ -2.45528134121210933969132173699021927099228584364359e-34, /* logil[128] */ } , { 1.32987022399902343750000000000000000000000000000000e+00, /* r[129] */ -4.11285466532431642772138502550660632550716400146484e-01, /* logih[129] */ 1.83565181086895727239354318438705255980398036076305e-17, /* logim[129] */ -1.44829162356744238484324099870150480074671457391215e-34, /* logil[129] */ } , { 1.32642555236816406250000000000000000000000000000000e+00, /* r[130] */ -4.07543704406910789472817668865900486707687377929688e-01, /* logih[130] */ 7.10235884116823704612718576916821308079422777996548e-18, /* logim[130] */ -3.80158777039570620950910438941465328615623287437883e-34, /* logil[130] */ } , { 1.32299804687500000000000000000000000000000000000000e+00, /* r[131] */ -4.03810931786029114753944213589420542120933532714844e-01, /* logih[131] */ -1.93041149309406226539378039674180224095823991324562e-17, /* logim[131] */ -6.48369386828220195024391999791810414893637949753662e-34, /* logil[131] */ } , { 1.31958770751953125000000000000000000000000000000000e+00, /* r[132] */ -4.00087243804195191732020475683384574949741363525391e-01, /* logih[132] */ 2.89502375830776532785152499054923847834329794887170e-18, /* logim[132] */ 3.93222273610552470790411012589691255020379298257710e-35, /* logil[132] */ } , { 1.31619453430175781250000000000000000000000000000000e+00, /* r[133] */ -3.96372735981224799672872904920950531959533691406250e-01, /* logih[133] */ 3.60172691524424563925914502416059579856197691514466e-18, /* logim[133] */ -1.20158940511610546308573928507645976530296896406609e-34, /* logil[133] */ } , { 1.31282043457031250000000000000000000000000000000000e+00, /* r[134] */ -3.92669600259061335467691833400749601423740386962891e-01, /* logih[134] */ 1.93341846112285731515865124079144232548548539073023e-17, /* logim[134] */ 9.57937519914959684169918849813293673245644163903024e-34, /* logil[134] */ } , { 1.30946350097656250000000000000000000000000000000000e+00, /* r[135] */ -3.88975847627444304421828746853861957788467407226562e-01, /* logih[135] */ 3.58737691022243699966445076948412264467756073807198e-18, /* logim[135] */ -6.34256172069676302574983465348800715277257535337860e-35, /* logil[135] */ } , { 1.30612182617187500000000000000000000000000000000000e+00, /* r[136] */ -3.85289467954024300588855567184509709477424621582031e-01, /* logih[136] */ -1.78035364405942478618622742807600593390557301297535e-17, /* logim[136] */ 1.17850158702046574289759352582101206794867193878284e-33, /* logil[136] */ } , { 1.30279922485351562500000000000000000000000000000000e+00, /* r[137] */ -3.81614766464260513068040836515137925744056701660156e-01, /* logih[137] */ 2.71673376063405867104437219707745590226184712176125e-17, /* logim[137] */ 1.69029691017588123460454883011389181316638787275286e-34, /* logil[137] */ } , { 1.29949188232421875000000000000000000000000000000000e+00, /* r[138] */ -3.77947621599900140942907000862760469317436218261719e-01, /* logih[138] */ -1.23014367483561633748866777916981619679184303004036e-17, /* logim[138] */ 6.08355261096735838824466189133147806184918981423043e-34, /* logil[138] */ } , { 1.29620170593261718750000000000000000000000000000000e+00, /* r[139] */ -3.74290237902951461457234927365789189934730529785156e-01, /* logih[139] */ 5.12028570979627947467233714003700900250465944855234e-18, /* logim[139] */ -7.18774911143147425103526075484104021221318133467838e-35, /* logil[139] */ } , { 1.29292869567871093750000000000000000000000000000000e+00, /* r[140] */ -3.70642713487464359189971219166181981563568115234375e-01, /* logih[140] */ -3.62882160448161069817531404328334713231193347048715e-18, /* logim[140] */ 3.44993361798375847334078483327966754606152885070616e-34, /* logil[140] */ } , { 1.28967285156250000000000000000000000000000000000000e+00, /* r[141] */ -3.67005146822302952269723164135939441621303558349609e-01, /* logih[141] */ 1.65005650962521207026407651865843985133165811425788e-17, /* logim[141] */ 5.91047470268282047973730611955174472735945862101340e-34, /* logil[141] */ } , { 1.28643226623535156250000000000000000000000000000000e+00, /* r[142] */ -3.63375497694418791994053208327386528253555297851562e-01, /* logih[142] */ 7.55315421152055178681914500647362519327258619048632e-18, /* logim[142] */ 4.21306551291527090995179817572489429320996105009542e-34, /* logil[142] */ } , { 1.28320884704589843750000000000000000000000000000000e+00, /* r[143] */ -3.59755993558560860368089606708963401615619659423828e-01, /* logih[143] */ 2.63438906908873597795987370422038765478538518071631e-17, /* logim[143] */ -5.30377956355563946242119261708497493118965065157578e-34, /* logil[143] */ } , { 1.28000068664550781250000000000000000000000000000000e+00, /* r[144] */ -3.56144584146996623363889966640272177755832672119141e-01, /* logih[144] */ 1.84288871644476152525450190682980250615827933483764e-17, /* logim[144] */ -2.68882850166617068062129216508822868733174909720115e-34, /* logil[144] */ } , { 1.27680778503417968750000000000000000000000000000000e+00, /* r[145] */ -3.52541353192291462281815483947866596281528472900391e-01, /* logih[145] */ 6.10296193683269704536448210556558136989473744080234e-18, /* logim[145] */ 2.08807753798353788586668668478566842671399016888175e-34, /* logil[145] */ } , { 1.27363204956054687500000000000000000000000000000000e+00, /* r[146] */ -3.48948545297196932590821916164713911712169647216797e-01, /* logih[146] */ -8.65980325947033784931501249514555272578815826796687e-18, /* logim[146] */ -5.80551069749146700308305149939969738912023055923091e-34, /* logil[146] */ } , { 1.27047157287597656250000000000000000000000000000000e+00, /* r[147] */ -3.45364095084557620740639549694606103003025054931641e-01, /* logih[147] */ -2.20359930641039442061906126368732543917103383835287e-17, /* logim[147] */ 5.25544112497915932563320135615380577517633877609112e-34, /* logil[147] */ } , { 1.26732635498046875000000000000000000000000000000000e+00, /* r[148] */ -3.41788087291514053323027155784075148403644561767578e-01, /* logih[148] */ 1.60590761637741619238785912450262223376577693103413e-17, /* logim[148] */ 6.20932254992098893431701251479794933091514543510527e-34, /* logil[148] */ } , { 1.26419830322265625000000000000000000000000000000000e+00, /* r[149] */ -3.38222783638829349595056328325881622731685638427734e-01, /* logih[149] */ -7.25934908657137387104187166197193711352219562279959e-19, /* logim[149] */ -7.33518955628645774542681475658185145551343791889460e-36, /* logil[149] */ } , { 1.26108360290527343750000000000000000000000000000000e+00, /* r[150] */ -3.34663921581079604194997045851778239011764526367188e-01, /* logih[150] */ 2.58775470575103710441675607573318821075159943052076e-17, /* logim[150] */ 2.52692281388567773158078403820428589058070685814554e-35, /* logil[150] */ } , { 1.25798606872558593750000000000000000000000000000000e+00, /* r[151] */ -3.31115945514659559822945311680086888372898101806641e-01, /* logih[151] */ -1.88333140638890303027893990821579263359866325365640e-17, /* logim[151] */ -2.42862233896785521070263301233188993094792416528478e-34, /* logil[151] */ } , { 1.25490188598632812500000000000000000000000000000000e+00, /* r[152] */ -3.27574572037176436900551834696670994162559509277344e-01, /* logih[152] */ 2.07539785395888161822620697150340485723327148173244e-17, /* logim[152] */ -1.23548121878231629330640725541259206553802467565088e-33, /* logil[152] */ } , { 1.25183296203613281250000000000000000000000000000000e+00, /* r[153] */ -3.24042069523512776818563452252419665455818176269531e-01, /* logih[153] */ -2.19005007906502743142091460775759087075823478365805e-17, /* logim[153] */ -9.37037260965326332974189985014675959956434500415796e-34, /* logil[153] */ } , { 1.24878120422363281250000000000000000000000000000000e+00, /* r[154] */ -3.20520728160823831220938018304877914488315582275391e-01, /* logih[154] */ 8.84664087846507870804592874874264782111036297675925e-18, /* logim[154] */ -2.79501394783314300402799429396176544077241557582655e-34, /* logil[154] */ } , { 1.24574279785156250000000000000000000000000000000000e+00, /* r[155] */ -3.17006233235677392645612826527212746441364288330078e-01, /* logih[155] */ -2.11397414280339689746407608887976410350376395394685e-17, /* logim[155] */ 3.03479113171805714055168835565789961369331896831913e-34, /* logil[155] */ } , { 1.24271774291992187500000000000000000000000000000000e+00, /* r[156] */ -3.13498655898958755727790048695169389247894287109375e-01, /* logih[156] */ 2.26105586296044525095947242798100200767794657136581e-17, /* logim[156] */ 2.60892976305499386383284257219701588877405462281587e-34, /* logil[156] */ } , { 1.23970985412597656250000000000000000000000000000000e+00, /* r[157] */ -3.10002506907223029930520397101645357906818389892578e-01, /* logih[157] */ -2.12074655036622140523873009541587371919611130881289e-17, /* logim[157] */ 7.30831854753703044634898432991347385046726141750071e-34, /* logil[157] */ } , { 1.23671531677246093750000000000000000000000000000000e+00, /* r[158] */ -3.06513440210500087701461779943201690912246704101562e-01, /* logih[158] */ 2.12840943277243056092775928647435125404474364580951e-17, /* logim[158] */ 7.25047508544774410393782565061654912871065991425794e-34, /* logil[158] */ } , { 1.23373413085937500000000000000000000000000000000000e+00, /* r[159] */ -3.03031527860823046705007755008409731090068817138672e-01, /* logih[159] */ -1.17964490716782890686396740199564245489484684608012e-17, /* logim[159] */ -2.32059444003387543097602750801495580204955378385700e-34, /* logil[159] */ } , { 1.23077011108398437500000000000000000000000000000000e+00, /* r[160] */ -2.99561313754444002999122176333912648260593414306641e-01, /* logih[160] */ 2.11014025619190086202004124493478829824043549375509e-17, /* logim[160] */ 5.40038404420639021176237530552511419095691650926683e-34, /* logil[160] */ } , { 1.22781753540039062500000000000000000000000000000000e+00, /* r[161] */ -2.96096179330254616335338369026430882513523101806641e-01, /* logih[161] */ 2.67263979507576883549661537337697767383852090911653e-17, /* logim[161] */ -2.94764943000919117463056963543943525405460259854793e-34, /* logil[161] */ } , { 1.22488021850585937500000000000000000000000000000000e+00, /* r[162] */ -2.92640674438622072628390924364794045686721801757812e-01, /* logih[162] */ 1.71594867435767387701491785234936424743342309564339e-17, /* logim[162] */ -1.31007554480643933015058741413754044981377681619902e-33, /* logil[162] */ } , { 1.22195625305175781250000000000000000000000000000000e+00, /* r[163] */ -2.89192636519142565187934224013588391244411468505859e-01, /* logih[163] */ -2.18230480089953441152115749431697227603316223085319e-19, /* logim[163] */ -8.85466907005428204234103766898640792692944423628476e-36, /* logil[163] */ } , { 1.21904754638671875000000000000000000000000000000000e+00, /* r[164] */ -2.85754396342549343845718112788745202124118804931641e-01, /* logih[164] */ -2.52426324464082956234588408195190742914473546506648e-17, /* logim[164] */ 1.40869584178453690304836821378162094545489911118516e-33, /* logil[164] */ } , { 1.21615219116210937500000000000000000000000000000000e+00, /* r[165] */ -2.82323781162987341719627920610946603119373321533203e-01, /* logih[165] */ -2.26062338879282363134318310278758951570998177822355e-17, /* logim[165] */ -2.68106389298437671467414029735971090503255483828766e-34, /* logil[165] */ } , { 1.21327018737792968750000000000000000000000000000000e+00, /* r[166] */ -2.78900865037392253764636507185059599578380584716797e-01, /* logih[166] */ -5.63339187198014524317590270324119375314418005110616e-18, /* logim[166] */ 5.21040627963337134602368749859442018659641934000068e-35, /* logil[166] */ } , { 1.21040153503417968750000000000000000000000000000000e+00, /* r[167] */ -2.75485722297818480530651186199975199997425079345703e-01, /* logih[167] */ 1.00075444298865318738580890792735678874884353310639e-17, /* logim[167] */ -4.47816459623451897434280578394151285127126954784303e-34, /* logil[167] */ } , { 1.20754623413085937500000000000000000000000000000000e+00, /* r[168] */ -2.72078427549137136232104694499867036938667297363281e-01, /* logih[168] */ 2.72560475587786773498503956757053623040042693331146e-17, /* logim[168] */ 1.45218948063688621997250686619739825113781997475216e-33, /* logil[168] */ } , { 1.20470619201660156250000000000000000000000000000000e+00, /* r[169] */ -2.68681339812479158535296619447763077914714813232422e-01, /* logih[169] */ 5.70669740727466907072711072058064597445179109382518e-19, /* logim[169] */ 3.22286121745779380928448151900341840625477392480707e-35, /* logil[169] */ } , { 1.20187759399414062500000000000000000000000000000000e+00, /* r[170] */ -2.65289971315308126253995624210801906883716583251953e-01, /* logih[170] */ -9.85570591393311591325758586976559232082321294112761e-18, /* logim[170] */ 4.70169173751465081907550999286196624093375291125429e-34, /* logil[170] */ } , { 1.19906234741210937500000000000000000000000000000000e+00, /* r[171] */ -2.61906676236464963647421200221288017928600311279297e-01, /* logih[171] */ 2.11725501817603632855204088733430972661848669245281e-17, /* logim[171] */ -4.34447783947526009842327436452242187031752585481265e-34, /* logil[171] */ } , { 1.19626235961914062500000000000000000000000000000000e+00, /* r[172] */ -2.58533830516213369854483516974141821265220642089844e-01, /* logih[172] */ 6.68433683242387216829190215856985521381580367248536e-18, /* logim[172] */ 1.47308049080021740635607084979003827052572897235269e-34, /* logil[172] */ } , { 1.19347381591796875000000000000000000000000000000000e+00, /* r[173] */ -2.55166914924355725524662830139277502894401550292969e-01, /* logih[173] */ 8.59194265653184494493651707567219919844164634345398e-18, /* logim[173] */ -5.71296827813717896996055631958626046207607829073074e-34, /* logil[173] */ } , { 1.19069862365722656250000000000000000000000000000000e+00, /* r[174] */ -2.51808300544058893954968425532570108771324157714844e-01, /* logih[174] */ -1.41914360009177510586369575931064612468930448614148e-17, /* logim[174] */ -1.62403247278609196179609602276489322075073469608800e-34, /* logil[174] */ } , { 1.18793487548828125000000000000000000000000000000000e+00, /* r[175] */ -2.48455747430406659326251883612712845206260681152344e-01, /* logih[175] */ -1.01487704576317129292387756236812830284397429666783e-17, /* logim[175] */ -2.33655220085162222996740706004887790768032744693521e-34, /* logil[175] */ } , { 1.18518447875976562500000000000000000000000000000000e+00, /* r[176] */ -2.45111637923020875273749652478727512061595916748047e-01, /* logih[176] */ 7.90027454939177726382780718024180385506006420479963e-18, /* logim[176] */ -7.12630269915217131628005874908549382719132579907736e-34, /* logil[176] */ } , { 1.18244743347167968750000000000000000000000000000000e+00, /* r[177] */ -2.41776048972363183375833273203170392662286758422852e-01, /* logih[177] */ -1.37983625208326204093508338414984840931706541381331e-17, /* logim[177] */ 7.20097580628563544454377572306403550061149741436607e-34, /* logil[177] */ } , { 1.17972373962402343750000000000000000000000000000000e+00, /* r[178] */ -2.38449057776214834447614521195646375417709350585938e-01, /* logih[178] */ 1.09262391873895283755849310197040950453513559131684e-17, /* logim[178] */ 5.19474724393747239275281177964830169009947097965027e-34, /* logil[178] */ } , { 1.17701148986816406250000000000000000000000000000000e+00, /* r[179] */ -2.35128403889451498276486063332413323223590850830078e-01, /* logih[179] */ -2.20620458531834175679580996316363151867859051514489e-18, /* logim[179] */ 9.83810838200669124655236613392658820366639819033369e-35, /* logil[179] */ } , { 1.17431259155273437500000000000000000000000000000000e+00, /* r[180] */ -2.31816492140433955126965770432434510439634323120117e-01, /* logih[180] */ 2.57100775389850524221489812836912330014517778962947e-18, /* logim[180] */ 1.00374417119546455021964629408545038692958060180549e-34, /* logil[180] */ } , { 1.17162513732910156250000000000000000000000000000000e+00, /* r[181] */ -2.28511051821717880994100369207444600760936737060547e-01, /* logih[181] */ 9.92032628735403930510124467196382166156697723468760e-18, /* logim[181] */ 6.81523716295691040818680683845702798454513605818654e-35, /* logil[181] */ } , { 1.16894912719726562500000000000000000000000000000000e+00, /* r[182] */ -2.25212144978847061960181008544168435037136077880859e-01, /* logih[182] */ -1.16073487380474294909629845428878875053786683626167e-17, /* logim[182] */ 1.99595089821539122107001863565030748851109328863471e-34, /* logil[182] */ } , { 1.16628646850585937500000000000000000000000000000000e+00, /* r[183] */ -2.21922193282795110480520861528930254280567169189453e-01, /* logih[183] */ -3.05125287362116491328592101654681002471500301574214e-18, /* logim[183] */ 1.83193994791768071092494646800366992102561399372769e-34, /* logil[183] */ } , { 1.16363716125488281250000000000000000000000000000000e+00, /* r[184] */ -2.18641275375243943068781504734943155199289321899414e-01, /* logih[184] */ 8.35804667506368175331097204734558341794896033630962e-18, /* logim[184] */ -6.76361847971404643554720269553322140862967487333475e-34, /* logil[184] */ } , { 1.16099739074707031250000000000000000000000000000000e+00, /* r[185] */ -2.15364729860247627879488163671339862048625946044922e-01, /* logih[185] */ 6.95092875909142621207400674633981711651172609645792e-20, /* logim[185] */ -2.69634411814059745570417391670366760873171411634907e-36, /* logil[185] */ } , { 1.15837097167968750000000000000000000000000000000000e+00, /* r[186] */ -2.12097354617240441143621865194290876388549804687500e-01, /* logih[186] */ 3.94012228039531281835195940112690671816259833936964e-18, /* logim[186] */ 2.35523503821099524557043963050386917863396604377712e-34, /* logil[186] */ } , { 1.15575599670410156250000000000000000000000000000000e+00, /* r[187] */ -2.08836848096523530760038056541816331446170806884766e-01, /* logih[187] */ 7.10684410301031817893241287396550439057323196953174e-18, /* logim[187] */ 4.17638182387052934717199646329356631335921484531446e-34, /* logil[187] */ } , { 1.15315246582031250000000000000000000000000000000000e+00, /* r[188] */ -2.05583273736383437269026330795895773917436599731445e-01, /* logih[188] */ -1.11541224825735129654072863667548382180433494970388e-17, /* logim[188] */ 2.60702460469050167439470691373935621310497497561972e-34, /* logil[188] */ } , { 1.15056228637695312500000000000000000000000000000000e+00, /* r[189] */ -2.02339086834303488737774046057893428951501846313477e-01, /* logih[189] */ -8.06133178191867723913541186137675666224522328881259e-18, /* logim[189] */ 4.69018902441109377621277031182321899995757079990517e-34, /* logil[189] */ } , { 1.14798164367675781250000000000000000000000000000000e+00, /* r[190] */ -1.99099573382730848924992983484116848558187484741211e-01, /* logih[190] */ -7.82936742512703344110788328637397546846483342009157e-18, /* logim[190] */ 5.23473869269106466321035297990759170076861208106171e-34, /* logil[190] */ } , { 1.14541435241699218750000000000000000000000000000000e+00, /* r[191] */ -1.95869586130290290748590109615179244428873062133789e-01, /* logih[191] */ 1.12134985887404327493969118908772924959105352074790e-17, /* logim[191] */ 1.66886450547656745631907524196364853864087335213403e-34, /* logil[191] */ } , { 1.14285659790039062500000000000000000000000000000000e+00, /* r[192] */ -1.92644390011628419134837031378992833197116851806641e-01, /* logih[192] */ -6.69952429363159445722018187914913034715067412521068e-18, /* logim[192] */ 8.89381602231133611911957806790376785637357399200603e-35, /* logil[192] */ } , { 1.14031219482421875000000000000000000000000000000000e+00, /* r[193] */ -1.89428859708889563151501533866394311189651489257812e-01, /* logih[193] */ 5.59630837119075206491413698162738631266398718359305e-18, /* logim[193] */ -4.99136387936431477565418774749623903558226749832454e-35, /* logil[193] */ } , { 1.13777732849121093750000000000000000000000000000000e+00, /* r[194] */ -1.86218239090319481743307505894335918128490447998047e-01, /* logih[194] */ 3.78774956212100823689526329408930405128821433232626e-18, /* logim[194] */ -3.17758760986685144372998527475489364873340117319014e-34, /* logil[194] */ } , { 1.13525581359863281250000000000000000000000000000000e+00, /* r[195] */ -1.83017424763517094765674642076191958039999008178711e-01, /* logih[195] */ 5.87157335095818829027440258888705251018885949838258e-18, /* logim[195] */ -2.54192655149641158852181857283167049817204136167821e-34, /* logil[195] */ } , { 1.13274383544921875000000000000000000000000000000000e+00, /* r[196] */ -1.79821639523964738049954803500440903007984161376953e-01, /* logih[196] */ 8.22302301209080640417647229353398001438134544835098e-19, /* logim[196] */ -2.52039332892153569817641206709892948549663624549042e-35, /* logil[196] */ } , { 1.13024330139160156250000000000000000000000000000000e+00, /* r[197] */ -1.76633367267372942688297143831732682883739471435547e-01, /* logih[197] */ -1.91571353469448596640611671435274648642190311723695e-18, /* logim[197] */ -1.21134793249841109085003066519453210454870699339190e-34, /* logil[197] */ } , { 1.12775421142578125000000000000000000000000000000000e+00, /* r[198] */ -1.73452673591511286055322216270724311470985412597656e-01, /* logih[198] */ 5.21283885301191031368646131342662533975361117947090e-18, /* logim[198] */ -1.01368643659769709343563840800327590720656486827318e-34, /* logil[198] */ } , { 1.12527465820312500000000000000000000000000000000000e+00, /* r[199] */ -1.70277178922613403599939374544192105531692504882812e-01, /* logih[199] */ 1.34546625256560311153005432906921643689472370072641e-17, /* logim[199] */ -2.01787346631624515685039191465892766058891822659738e-34, /* logil[199] */ } , { 1.12280654907226562500000000000000000000000000000000e+00, /* r[200] */ -1.67109383895854723967033805820392444729804992675781e-01, /* logih[200] */ -6.60161109774567977756253155335787084419173665974265e-18, /* logim[200] */ -5.20727010500155857942441424119648973967213145273875e-35, /* logil[200] */ } , { 1.12034988403320312500000000000000000000000000000000e+00, /* r[201] */ -1.63949354721177775751073113497113808989524841308594e-01, /* logih[201] */ -1.59075426091945659534123359515275496742329136677793e-18, /* logim[201] */ -8.80061355388662086427482764107757767132081769249868e-35, /* logil[201] */ } , { 1.11790466308593750000000000000000000000000000000000e+00, /* r[202] */ -1.60797157807325702405520928550686221569776535034180e-01, /* logih[202] */ -1.27882485432659989407998658585334380471532522122288e-17, /* logim[202] */ -1.78908761080882243046115883816432632406586944308380e-34, /* logil[202] */ } , { 1.11546897888183593750000000000000000000000000000000e+00, /* r[203] */ -1.57650392886728163421850013037328608334064483642578e-01, /* logih[203] */ 5.48897678434671628772441349557697552667538441741952e-19, /* logim[203] */ -6.79258603184423299240762713680989948394024184442684e-36, /* logil[203] */ } , { 1.11304283142089843750000000000000000000000000000000e+00, /* r[204] */ -1.54509110639958202604304915439570322632789611816406e-01, /* logih[204] */ -3.59136851163677714278758679380160119258917626559671e-19, /* logim[204] */ -1.56974154580554013761421709836383374626199071205828e-35, /* logil[204] */ } , { 1.11062812805175781250000000000000000000000000000000e+00, /* r[205] */ -1.51375839568216624675400794330926146358251571655273e-01, /* logih[205] */ 1.85511636793595219210186133192591461270305721253330e-18, /* logim[205] */ -1.91794182494587047847453803902174963816836368421214e-34, /* logil[205] */ } , { 1.10822486877441406250000000000000000000000000000000e+00, /* r[206] */ -1.48250646865354079873000614497868809849023818969727e-01, /* logih[206] */ -1.01653072428705486842585428998216576160196054521775e-17, /* logim[206] */ 5.31584010431656413312485980487520698550209333197199e-34, /* logil[206] */ } , { 1.10583114624023437500000000000000000000000000000000e+00, /* r[207] */ -1.45131111540638235712918913122848607599735260009766e-01, /* logih[207] */ -1.37520535926702420814491655344493331500786583007547e-17, /* logim[207] */ -3.12537587519576338142297025257101128398882620659901e-34, /* logil[207] */ } , { 1.10344886779785156250000000000000000000000000000000e+00, /* r[208] */ -1.42019778794149176270877887873211875557899475097656e-01, /* logih[208] */ -3.68499044867024074477140873097095881834850367397794e-18, /* logim[208] */ -1.63017157850342774197009569405883228185646262806831e-34, /* logil[208] */ } , { 1.10107612609863281250000000000000000000000000000000e+00, /* r[209] */ -1.38914217265857425909203470837383065372705459594727e-01, /* logih[209] */ -6.17799701560862884451695448882239750612348592334350e-18, /* logim[209] */ -2.34837262732331600500907295169491998103701955922085e-34, /* logil[209] */ } , { 1.09871292114257812500000000000000000000000000000000e+00, /* r[210] */ -1.35814478782694425529342652225750498473644256591797e-01, /* logih[210] */ -1.10878202856006564968015298269391791178600779503105e-17, /* logim[210] */ -6.34363946747343426901749776771284987530057524263824e-34, /* logil[210] */ } , { 1.09635925292968750000000000000000000000000000000000e+00, /* r[211] */ -1.32720615355253201972374199613113887608051300048828e-01, /* logih[211] */ 5.00671269578839009481340541432441710674698094423168e-18, /* logim[211] */ 5.65638829687757042763410955571684820831086486484696e-35, /* logil[211] */ } , { 1.09401702880859375000000000000000000000000000000000e+00, /* r[212] */ -1.29635194425267469275908638337568845599889755249023e-01, /* logih[212] */ -1.32741790693761805495822031536188642314117707435772e-17, /* logim[212] */ 2.36177367859446952683532192189387042515220366349614e-34, /* logil[212] */ } , { 1.09168434143066406250000000000000000000000000000000e+00, /* r[213] */ -1.26555763872087861932058672209677752107381820678711e-01, /* logih[213] */ 5.61175210355060094496565624276228808645454542333958e-18, /* logim[213] */ 2.47905722889287266912955785312024516940886239709541e-34, /* logil[213] */ } , { 1.08936119079589843750000000000000000000000000000000e+00, /* r[214] */ -1.23482376253153572354115397047280566766858100891113e-01, /* logih[214] */ -5.24860550833652446049807047479312960894536533343032e-18, /* logim[214] */ 1.57303914080610683083254197080760577504337194439462e-34, /* logil[214] */ } , { 1.08704948425292968750000000000000000000000000000000e+00, /* r[215] */ -1.20417615674669478686986678894754732027649879455566e-01, /* logih[215] */ 4.98589250874990455590729277739610886330195529901588e-19, /* logim[215] */ -2.77483656505407014767190386581182627944876838144956e-35, /* logil[215] */ } , { 1.08474540710449218750000000000000000000000000000000e+00, /* r[216] */ -1.17356477685791341092347295216313796117901802062988e-01, /* logih[216] */ -4.43816803292478642713439762323399536218860906455113e-18, /* logim[216] */ 1.57142075014587982329499427592772686845625881951589e-34, /* logil[216] */ } , { 1.08245277404785156250000000000000000000000000000000e+00, /* r[217] */ -1.14304083489448829458190459718025522306561470031738e-01, /* logih[217] */ -2.44497503421640839485178934251442732595447798838524e-18, /* logim[217] */ 9.13177011131237596027512825680515711244107356781889e-35, /* logil[217] */ } , { 1.08016967773437500000000000000000000000000000000000e+00, /* r[218] */ -1.11257954979794640437695818491192767396569252014160e-01, /* logih[218] */ 3.65465035573521902378371256352169641526181202186019e-18, /* logim[218] */ 3.01033668355988911672661379284389721222632837445285e-34, /* logil[218] */ } , { 1.07789421081542968750000000000000000000000000000000e+00, /* r[219] */ -1.08215592727541040640737435296614421531558036804199e-01, /* logih[219] */ -6.38939331108877749140470530072612418291901128036500e-18, /* logim[219] */ -1.57977443005077752334576053495157374607253022139958e-34, /* logil[219] */ } , { 1.07563018798828125000000000000000000000000000000000e+00, /* r[220] */ -1.05182150700728491155011568025656742975115776062012e-01, /* logih[220] */ 9.96668646201815079564771481993512113001566815373477e-19, /* logim[220] */ -8.40901520642174694941917655898657225968386843551730e-35, /* logil[220] */ } , { 1.07337570190429687500000000000000000000000000000000e+00, /* r[221] */ -1.02155135184729670139169854792271507903933525085449e-01, /* logih[221] */ 9.54331694819518742321529152057292821145759268608888e-19, /* logim[221] */ 8.08375441648303398276921573613512412447286382908005e-35, /* logil[221] */ } , { 1.07112884521484375000000000000000000000000000000000e+00, /* r[222] */ -9.91320311358910577492764559792703948915004730224609e-02, /* logih[222] */ -1.15319697956815851305646410589057158513062401209409e-19, /* logim[222] */ -7.40284620248563691684694048738117565554761996111872e-36, /* logil[222] */ } , { 1.06889343261718750000000000000000000000000000000000e+00, /* r[223] */ -9.61180252768258497342301893695548642426729202270508e-02, /* logih[223] */ 6.85171092643411485272954560328117638640557421326159e-18, /* logim[223] */ -1.67824770393390632739991704456259895006309663742546e-34, /* logil[223] */ } , { 1.06666755676269531250000000000000000000000000000000e+00, /* r[224] */ -9.31106082695352110789599464624188840389251708984375e-02, /* logih[224] */ -2.26105242874531783782517748931571159031922191193177e-18, /* logim[224] */ -2.03783945271517638711748368885966194474657481104373e-35, /* logil[224] */ } , { 1.06444931030273437500000000000000000000000000000000e+00, /* r[225] */ -9.01072494463056178348736580119293648749589920043945e-02, /* logih[225] */ -5.44728555823394356142980742937673446468666963750632e-18, /* logim[225] */ 1.97413590011115023111162093321380372124491875850575e-34, /* logil[225] */ } , { 1.06224060058593750000000000000000000000000000000000e+00, /* r[226] */ -8.71105777787103824350012359900574665516614913940430e-02, /* logih[226] */ -4.43564406369389579389284215323972775263708137166154e-18, /* logim[226] */ 1.70779313126122225936135094173405768955565424909277e-34, /* logil[226] */ } , { 1.06004142761230468750000000000000000000000000000000e+00, /* r[227] */ -8.41206480365157827083777419829857535660266876220703e-02, /* logih[227] */ -3.14792226986980839484335841464619768591703354318294e-18, /* logim[227] */ 1.52657062057281535176853536917634594017181918735262e-34, /* logil[227] */ } , { 1.05785179138183593750000000000000000000000000000000e+00, /* r[228] */ -8.11375151493067964247885015538486186414957046508789e-02, /* logih[228] */ -6.15912022353230257795364252670116201168948678312527e-18, /* logim[228] */ -2.16344593340788372463481302845555712130079294383972e-34, /* logil[228] */ } , { 1.05566978454589843750000000000000000000000000000000e+00, /* r[229] */ -7.81586275943592923010072581746499054133892059326172e-02, /* logih[229] */ -3.25085161347353548036706096407758727333265699647547e-18, /* logim[229] */ 1.63920542914931230587405015453230564450059005459335e-34, /* logil[229] */ } , { 1.05349731445312500000000000000000000000000000000000e+00, /* r[230] */ -7.51866364807085019172916418028762564063072204589844e-02, /* logih[230] */ -2.54870557338844162102455061406383024497892883435493e-18, /* logim[230] */ -6.59135720018155570156029431794739322327869508222348e-35, /* logil[230] */ } , { 1.05133438110351562500000000000000000000000000000000e+00, /* r[231] */ -7.22215972120476834561486612074077129364013671875000e-02, /* logih[231] */ -6.64425227252169993584924920404020380947983762424339e-18, /* logim[231] */ 2.91013479660203574471829316747093985065960871705841e-34, /* logil[231] */ } , { 1.04918098449707031250000000000000000000000000000000e+00, /* r[232] */ -6.92635653457482070027850795668200589716434478759766e-02, /* logih[232] */ -4.17058903808438561260436396327171311252509638555115e-18, /* logim[232] */ 3.30755248525805832232280848513964707004463090388921e-34, /* logil[232] */ } , { 1.04703521728515625000000000000000000000000000000000e+00, /* r[233] */ -6.63099684847409387433714300641440786421298980712891e-02, /* logih[233] */ -8.74727269069244478292642836141302714118531385326008e-19, /* logim[233] */ 9.13680180722266849670406326820143717312677461406295e-35, /* logil[233] */ } , { 1.04489707946777343750000000000000000000000000000000e+00, /* r[234] */ -6.33608463694464163484809660076280124485492706298828e-02, /* logih[234] */ 4.88853992059804485610361972971949389543857070116405e-18, /* logim[234] */ 3.59584991557930488620611395470856240222060784881851e-34, /* logil[234] */ } , { 1.04277038574218750000000000000000000000000000000000e+00, /* r[235] */ -6.04215166113879487141957724816165864467620849609375e-02, /* logih[235] */ 3.24424348086874445666593409656049253578069669395260e-18, /* logim[235] */ -1.60277475491901208789005491794898884020948020845008e-34, /* logil[235] */ } , { 1.04065132141113281250000000000000000000000000000000e+00, /* r[236] */ -5.74867630322526829145246551888703834265470504760742e-02, /* logih[236] */ 3.76759687947251899896914839649469366487490379203479e-19, /* logim[236] */ -2.21494568010334432329216609802290865335331834512200e-35, /* logil[236] */ } , { 1.03853988647460937500000000000000000000000000000000e+00, /* r[237] */ -5.45566258253886229856455258868663804605603218078613e-02, /* logih[237] */ -2.65946239302500951789232143661643591976491541288433e-18, /* logim[237] */ -1.53785481060545545279952344255193134903777587882504e-34, /* logil[237] */ } , { 1.03643798828125000000000000000000000000000000000000e+00, /* r[238] */ -5.16338003108584853162454919583979062736034393310547e-02, /* logih[238] */ -2.78795469954967100989074401097287044599854944339982e-18, /* logim[238] */ -1.49163921524354280847709876358289989763104855468257e-34, /* logil[238] */ } , { 1.03434371948242187500000000000000000000000000000000e+00, /* r[239] */ -4.87156827428533376056485337812773650512099266052246e-02, /* logih[239] */ 2.96381531361489610816411758109172878093342204001504e-18, /* logim[239] */ 1.90369184844193639243251585798972318425548902746587e-34, /* logil[239] */ } , { 1.03225898742675781250000000000000000000000000000000e+00, /* r[240] */ -4.58049794824296474526903466539806686341762542724609e-02, /* logih[240] */ 1.62105752345434014647769506007451291849983142737970e-18, /* logim[240] */ -9.20867893989873723178504588707200553003761945783565e-35, /* logil[240] */ } , { 1.03018188476562500000000000000000000000000000000000e+00, /* r[241] */ -4.28990763245113357338134107976657105609774589538574e-02, /* logih[241] */ -6.34003512301982273340105213426264835291352971908960e-19, /* logim[241] */ -3.19233228551439316201562934283596212957829301138982e-35, /* logil[241] */ } , { 1.02811241149902343750000000000000000000000000000000e+00, /* r[242] */ -3.99980141873396699558895761583698913455009460449219e-02, /* logih[242] */ 3.46776145155773436838304619563053637896412152479204e-18, /* logim[242] */ 1.18249199307224204078322468557405538276307569138571e-35, /* logil[242] */ } , { 1.02605247497558593750000000000000000000000000000000e+00, /* r[243] */ -3.71045159850557013103689030231180367991328239440918e-02, /* logih[243] */ -1.51254314986204784019866874830661020957859050088050e-18, /* logim[243] */ -4.62897721796816023188344967819483871559574158072420e-35, /* logil[243] */ } , { 1.02400016784667968750000000000000000000000000000000e+00, /* r[244] */ -3.42159518140385116025115053162153344601392745971680e-02, /* logih[244] */ -4.20171334566300044079146136535848239242167490849902e-19, /* logim[244] */ -1.97864138714387435136379874705706366605172130727980e-35, /* logil[244] */ } , { 1.02195549011230468750000000000000000000000000000000e+00, /* r[245] */ -3.13323630146640427773796488963853335008025169372559e-02, /* logih[245] */ -1.60932497177386839267872885266206616652634543879907e-18, /* logim[245] */ -6.28817851293024240545936211571266012891885359494453e-35, /* logil[245] */ } , { 1.01992034912109375000000000000000000000000000000000e+00, /* r[246] */ -2.84564890448900827124578682969513465650379657745361e-02, /* logih[246] */ -1.32743413787410314281579343321838041020056743726823e-18, /* logim[246] */ 2.04618286866463010251865131532183144563010428890917e-35, /* logil[246] */ } , { 1.01789283752441406250000000000000000000000000000000e+00, /* r[247] */ -2.55856842917966814665575725484814029186964035034180e-02, /* logih[247] */ -1.49154860937761055001848142233043312841087530311649e-18, /* logim[247] */ 2.02599394521852446744073942371740628593627411196085e-35, /* logil[247] */ } , { 1.01587295532226562500000000000000000000000000000000e+00, /* r[248] */ -2.27199905087555366345331009370056563057005405426025e-02, /* logih[248] */ 1.12960205619839265574985374116680854623969773242666e-18, /* logim[248] */ -8.34362880258700413677035364508655979450149223832712e-35, /* logil[248] */ } , { 1.01386070251464843750000000000000000000000000000000e+00, /* r[249] */ -1.98594495836460112336840921898328815586864948272705e-02, /* logih[249] */ -1.65424881469239763312059082975380380550401132087393e-20, /* logim[249] */ -1.17360571247672971463309448698886739285461152534205e-36, /* logil[249] */ } , { 1.01185798645019531250000000000000000000000000000000e+00, /* r[250] */ -1.70068230155151732529983377162352553568780422210693e-02, /* logih[250] */ 1.27516044327499840806046149901955205004460778589711e-19, /* logim[250] */ -8.52710691967735804583223211101678334615958045143104e-37, /* logil[250] */ } , { 1.00986099243164062500000000000000000000000000000000e+00, /* r[251] */ -1.41567193815739632983818907518980267923325300216675e-02, /* logih[251] */ 8.65690356839925383828965885125235491000373622359337e-19, /* logim[251] */ -1.64494399168713442766339462748988626277364551873170e-35, /* logil[251] */ } , { 1.00787353515625000000000000000000000000000000000000e+00, /* r[252] */ -1.13146252970666803122634647138511354569345712661743e-02, /* logih[252] */ 3.15936714773135871052341883744882960982174189853601e-19, /* logim[252] */ 2.39659922006639309827564391487460990569975332009368e-35, /* logil[252] */ } , { 1.00589370727539062500000000000000000000000000000000e+00, /* r[253] */ -8.47786370355218220351556368541423580609261989593506e-03, /* logih[253] */ -9.75735845129809026777533412359789145867559613642986e-20, /* logim[253] */ -6.04717464355893048249602969326230504905195484152609e-37, /* logil[253] */ } , { 1.00392150878906250000000000000000000000000000000000e+00, /* r[254] */ -5.64647714981406870921043505973102583084255456924438e-03, /* logih[254] */ 4.32956569441265152083688702413498400247673690133916e-19, /* logim[254] */ 2.23027666862069486060936208535887094361283857129620e-36, /* logil[254] */ } , { 1.00195693969726562500000000000000000000000000000000e+00, /* r[255] */ -2.82050831346294375231997797470739897107705473899841e-03, /* logih[255] */ 2.66775679488942854129723744389995508483544623376680e-20, /* logim[255] */ -8.80338525383831336492192061402657740638778525161937e-37, /* logil[255] */ } }; typedef struct tPi1_t_tag {double hiM1; double hi; double mi; double lo;} tPi1_t; typedef struct tPi2_t_tag {double hi; double mi; double lo;} tPi2_t; static const tPi1_t twoPowerIndex1[32] = { { 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1MOne[0] */ 1.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1hi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1mi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex1lo[0] */ } , { 8.46162726943132067255332051658456293807830661535263e-05, /* twoPowerIndex1MOne[1] */ 1.00008461627269440441523329354822635650634765625000e+00, /* twoPowerIndex1hi[1] */ -9.12125999627646384986052256665186572875345252060450e-17, /* twoPowerIndex1mi[1] */ 3.36755111543914781718517640651013480155414711472518e-33, /* twoPowerIndex1lo[1] */ } , { 1.69239705302231071594454281381558757857419550418854e-04, /* twoPowerIndex1MOne[2] */ 1.00016923970530213772178740327944979071617126464844e+00, /* twoPowerIndex1hi[2] */ 9.33618533547846199388179470637929281332443150415515e-17, /* twoPowerIndex1mi[2] */ 3.77297954885090084710073756456287936644477196404411e-33, /* twoPowerIndex1lo[2] */ } , { 2.53870298429598856802813511279737213044427335262299e-04, /* twoPowerIndex1MOne[3] */ 1.00025387029842960373571258969604969024658203125000e+00, /* twoPowerIndex1hi[3] */ -4.89064911953409381305925724006739962094640351616807e-18, /* twoPowerIndex1mi[3] */ 8.69701308333596579376838706167199696373572491739592e-35, /* twoPowerIndex1lo[3] */ } , { 3.38508052682312944679093869027042273955885320901871e-04, /* twoPowerIndex1MOne[4] */ 1.00033850805268231809463941317517310380935668945312e+00, /* twoPowerIndex1hi[4] */ -5.14133393131895706530678267769194263660821897510018e-18, /* twoPowerIndex1mi[4] */ 3.65532984508913994275805274025238001612209382982528e-34, /* twoPowerIndex1lo[4] */ } , { 4.23152968666321135839808453837918023054953664541244e-04, /* twoPowerIndex1MOne[5] */ 1.00042315296866624052540828415658324956893920898438e+00, /* twoPowerIndex1hi[5] */ 8.06180631495321395718653515232725600012433502276551e-17, /* twoPowerIndex1mi[5] */ 2.27756032119564512217610282919955584270974037720845e-33, /* twoPowerIndex1lo[5] */ } , { 5.07805046987622405244011680736093694576993584632874e-04, /* twoPowerIndex1MOne[6] */ 1.00050780504698755279946453811135143041610717773438e+00, /* twoPowerIndex1hi[6] */ 6.96242402202057255168575283120383384543281723609229e-17, /* twoPowerIndex1mi[6] */ 5.20646484360987194687938744912769762301408608274186e-34, /* twoPowerIndex1lo[6] */ } , { 5.92464288252267119033733777655470476020127534866333e-04, /* twoPowerIndex1MOne[7] */ 1.00059246428825221464364858547924086451530456542969e+00, /* twoPowerIndex1hi[7] */ 5.24358776284676541346649133871799377889330385550410e-17, /* twoPowerIndex1mi[7] */ -1.16401717083964875595275373190622641096721208508067e-33, /* twoPowerIndex1lo[7] */ } , { 6.77130693066356655063220415513569605536758899688721e-04, /* twoPowerIndex1MOne[8] */ 1.00067713069306640782940576173132285475730895996094e+00, /* twoPowerIndex1hi[8] */ -5.11512329768566763581175858027414623025077801052578e-17, /* twoPowerIndex1mi[8] */ 6.98198098827029289611306311409722598417652045670746e-34, /* twoPowerIndex1lo[8] */ } , { 7.61804262036044053420236199514192776405252516269684e-04, /* twoPowerIndex1MOne[9] */ 1.00076180426203609208357647730736061930656433105469e+00, /* twoPowerIndex1hi[9] */ -4.80106395281352797253594357274293799083867247600929e-17, /* twoPowerIndex1mi[9] */ 1.60659089499355510094934148076620501547799589638472e-33, /* twoPowerIndex1lo[9] */ } , { 8.46484995767533420114869802119983432930894196033478e-04, /* twoPowerIndex1MOne[10] */ 1.00084648499576744917760606767842546105384826660156e+00, /* twoPowerIndex1hi[10] */ 8.42299002458648658027371639395540881533737558365359e-17, /* twoPowerIndex1mi[10] */ 2.36970468083963275494383447607242933566525306383712e-33, /* twoPowerIndex1lo[10] */ } , { 9.31172894867080143919968460153313571936450898647308e-04, /* twoPowerIndex1MOne[11] */ 1.00093117289486710497214971837820485234260559082031e+00, /* twoPowerIndex1hi[11] */ -2.48518461029926794844540008382519256098178534001306e-17, /* twoPowerIndex1mi[11] */ 1.46302367831163072138631641353266395843931006446965e-33, /* twoPowerIndex1lo[11] */ } , { 1.01586795994099100479135522334672714350745081901550e-03, /* twoPowerIndex1MOne[12] */ 1.00101586795994101919404783984646201133728027343750e+00, /* twoPowerIndex1hi[12] */ -2.82452207477616780689379931990767172214919031737312e-17, /* twoPowerIndex1mi[12] */ -1.95728551891328398835983018867545661396300096090192e-33, /* twoPowerIndex1lo[12] */ } , { 1.10057019159562384860717720869160984875634312629700e-03, /* twoPowerIndex1MOne[13] */ 1.00110057019159559565935069258557632565498352050781e+00, /* twoPowerIndex1hi[13] */ 2.82746405249917066780441808454827762565634907210646e-17, /* twoPowerIndex1mi[13] */ 2.84963022949056029094282669604361292342636089091009e-33, /* twoPowerIndex1lo[13] */ } , { 1.18527959043738845452964358884173634578473865985870e-03, /* twoPowerIndex1MOne[14] */ 1.00118527959043746022871346212923526763916015625000e+00, /* twoPowerIndex1hi[14] */ -7.18042456559213166577815896739695813826899291527385e-17, /* twoPowerIndex1mi[14] */ -4.76259460142737667571053552520587169925041399888400e-33, /* twoPowerIndex1lo[14] */ } , { 1.26999615707274501712198411240706263924948871135712e-03, /* twoPowerIndex1MOne[15] */ 1.00126999615707279467358148394851014018058776855469e+00, /* twoPowerIndex1hi[15] */ -4.95925540000318718201054702131568017537484907271764e-17, /* twoPowerIndex1mi[15] */ 1.38114240085784279494535821521711378076084168967947e-33, /* twoPowerIndex1lo[15] */ } , { 1.35471989210820577265170783221037709154188632965088e-03, /* twoPowerIndex1MOne[16] */ 1.00135471989210822485460994357708841562271118164062e+00, /* twoPowerIndex1hi[16] */ -1.89737284167929933536294189134998232481318340155287e-17, /* twoPowerIndex1mi[16] */ -1.14644761608474571162584330231223616391499645510675e-34, /* twoPowerIndex1lo[16] */ } , { 1.43945079615033413172886511688375321682542562484741e-03, /* twoPowerIndex1MOne[17] */ 1.00143945079615037663245402654865756630897521972656e+00, /* twoPowerIndex1hi[17] */ -4.25104299595813332360330451324069867137771018561227e-17, /* twoPowerIndex1mi[17] */ -1.57361794708548262075721650186677311111593370726069e-33, /* twoPowerIndex1lo[17] */ } , { 1.52418886980574446246561315376766287954524159431458e-03, /* twoPowerIndex1MOne[18] */ 1.00152418886980565382316399336559697985649108886719e+00, /* twoPowerIndex1hi[18] */ 9.06044106726912172835402556659442028244667434824268e-17, /* twoPowerIndex1mi[18] */ -9.28795936877474030548429956901821606468166518236870e-34, /* twoPowerIndex1lo[18] */ } , { 1.60893411368110274099751944021363669889979064464569e-03, /* twoPowerIndex1MOne[19] */ 1.00160893411368112637660487962421029806137084960938e+00, /* twoPowerIndex1hi[19] */ -2.36264836237383004793138962370023654775211297571300e-17, /* twoPowerIndex1mi[19] */ 8.71910060549436570048152399632583363263947185973970e-34, /* twoPowerIndex1lo[19] */ } , { 1.69368652838312633464312728648337724735029041767120e-03, /* twoPowerIndex1MOne[20] */ 1.00169368652838319810882694582687690854072570800781e+00, /* twoPowerIndex1hi[20] */ -7.17327634990031997530849131951948428542423257707819e-17, /* twoPowerIndex1mi[20] */ 6.07647560689104755979568262152596670382288431776872e-33, /* twoPowerIndex1lo[20] */ } , { 1.77844611451858400190395581574875905062071979045868e-03, /* twoPowerIndex1MOne[21] */ 1.00177844611451849488048537750728428363800048828125e+00, /* twoPowerIndex1hi[21] */ 8.90494708260750700506643975752906510626799035262348e-17, /* twoPowerIndex1mi[21] */ -1.07254669154255875107094381902285900913374960884151e-33, /* twoPowerIndex1lo[21] */ } , { 1.86321287269429545878363096989005498471669852733612e-03, /* twoPowerIndex1MOne[22] */ 1.00186321287269430868605013529304414987564086914062e+00, /* twoPowerIndex1hi[22] */ -1.33071962467226606689858482393149015112554043251841e-17, /* twoPowerIndex1mi[22] */ -3.85443386097781554341108465500150047004226523597749e-34, /* twoPowerIndex1lo[22] */ } , { 1.94798680351713202930918900079859668039716780185699e-03, /* twoPowerIndex1MOne[23] */ 1.00194798680351704334157147968653589487075805664062e+00, /* twoPowerIndex1hi[23] */ 8.86950831931357794861851693306328605666305931343879e-17, /* twoPowerIndex1mi[23] */ 2.75565261371873441737709070275465061950835621245478e-33, /* twoPowerIndex1lo[23] */ } , { 2.03276790759401642869064197327588772168383002281189e-03, /* twoPowerIndex1MOne[24] */ 1.00203276790759399084151937131537124514579772949219e+00, /* twoPowerIndex1hi[24] */ 2.57269259432211179649018725316354562817431777421067e-17, /* twoPowerIndex1mi[24] */ 6.79751255613789265201334995370535043187556454092516e-34, /* twoPowerIndex1lo[24] */ } , { 2.11755618553192319700184675923537724884226918220520e-03, /* twoPowerIndex1MOne[25] */ 1.00211755618553199909115392074454575777053833007812e+00, /* twoPowerIndex1hi[25] */ -7.60963076154928660009367289085332496679920703482915e-17, /* twoPowerIndex1mi[25] */ 4.75753257695507842037160015079808278438391224582425e-33, /* twoPowerIndex1lo[25] */ } , { 2.20235163793787653077616006669359194347634911537170e-03, /* twoPowerIndex1MOne[26] */ 1.00220235163793791599573523853905498981475830078125e+00, /* twoPowerIndex1hi[26] */ -3.92993778548451720552933864302152846562830407163222e-17, /* twoPowerIndex1mi[26] */ 2.22740945016647607963332576015739728975193247400334e-33, /* twoPowerIndex1lo[26] */ } , { 2.28715426541895461981512838178787205833941698074341e-03, /* twoPowerIndex1MOne[27] */ 1.00228715426541903354973328532651066780090332031250e+00, /* twoPowerIndex1hi[27] */ -7.91320298680023160041154790353287334442969086934633e-17, /* twoPowerIndex1mi[27] */ 4.30154033931455305578282137055178652288667345721532e-33, /* twoPowerIndex1lo[27] */ } , { 2.37196406858228422617762554125420138007029891014099e-03, /* twoPowerIndex1MOne[28] */ 1.00237196406858219965840817167190834879875183105469e+00, /* twoPowerIndex1hi[28] */ 8.46137724799471749932697856411684097253648908880386e-17, /* twoPowerIndex1mi[28] */ -1.15795350476069740873680647805085951983720786847012e-33, /* twoPowerIndex1lo[28] */ } , { 2.45678104803504588835028066284849046496674418449402e-03, /* twoPowerIndex1MOne[29] */ 1.00245678104803515040543970826547592878341674804688e+00, /* twoPowerIndex1hi[29] */ -1.04659436381151501919178287379323678295958386394535e-16, /* twoPowerIndex1mi[29] */ 5.63489769746205416541081978104590942612321060930815e-33, /* twoPowerIndex1lo[29] */ } , { 2.54160520438446958443878820332884060917422175407410e-03, /* twoPowerIndex1MOne[30] */ 1.00254160520438451165148308064090088009834289550781e+00, /* twoPowerIndex1hi[30] */ -4.19488324163994025318330321149973224973566383682287e-17, /* twoPowerIndex1mi[30] */ -1.10867727371575753136248480661711257993643946476249e-33, /* twoPowerIndex1lo[30] */ } , { 2.62643653823783820161485991206973267253488302230835e-03, /* twoPowerIndex1MOne[31] */ 1.00262643653823779743561317445710301399230957031250e+00, /* twoPowerIndex1hi[31] */ 4.09516010415381254633240310888754218841825131705667e-17, /* twoPowerIndex1mi[31] */ 4.18651539196539390512773521751259041499174185767385e-34, /* twoPowerIndex1lo[31] */ } }; static const tPi2_t twoPowerIndex2[256] = { { 1.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex2hi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex2mi[0] */ 0.00000000000000000000000000000000000000000000000000e+00, /* twoPowerIndex2lo[0] */ } , { 1.00271127505020252179690487537300214171409606933594e+00, /* twoPowerIndex2hi[1] */ -3.63661592869226394431650732319448247819940912156384e-17, /* twoPowerIndex2mi[1] */ -6.58076018413558386665763067745208065096307047224855e-34, /* twoPowerIndex2lo[1] */ } , { 1.00542990111280272635951860138447955250740051269531e+00, /* twoPowerIndex2hi[2] */ 9.49918653545503175702165599813853704096085691656846e-17, /* twoPowerIndex2mi[2] */ 2.69197614795285565383714012654266434015814803945559e-33, /* twoPowerIndex2lo[2] */ } , { 1.00815589811841754830368245166027918457984924316406e+00, /* twoPowerIndex2hi[3] */ -3.25205875608430806088583499076669170064325943797327e-17, /* twoPowerIndex2mi[3] */ 2.46355206137317856028163445564386882918089954604456e-33, /* twoPowerIndex2lo[3] */ } , { 1.01088928605170047525518839393043890595436096191406e+00, /* twoPowerIndex2hi[4] */ -1.52347786033685771762884896542837070154735103108242e-17, /* twoPowerIndex2mi[4] */ -1.20527773363982029579667170059568717373235495431222e-33, /* twoPowerIndex2lo[4] */ } , { 1.01363008495148942955665916088037192821502685546875e+00, /* twoPowerIndex2hi[5] */ 9.28359976818356758749022147678502506693759778650960e-18, /* twoPowerIndex2mi[5] */ 4.13890589104247114331738780166693451804305210832799e-34, /* twoPowerIndex2lo[5] */ } , { 1.01637831491095309566219384578289464116096496582031e+00, /* twoPowerIndex2hi[6] */ -5.77217007319966002765782626628372138987895927390512e-17, /* twoPowerIndex2mi[6] */ -3.01819186434481667596632332663816426794401961980022e-34, /* twoPowerIndex2lo[6] */ } , { 1.01913399607773791366582827322417870163917541503906e+00, /* twoPowerIndex2hi[7] */ 3.60190498225966172216609531722640706381960474006480e-17, /* twoPowerIndex2mi[7] */ -3.04390025916336453718381303520593752766892414197373e-33, /* twoPowerIndex2lo[7] */ } , { 1.02189714865411662714222984504885971546173095703125e+00, /* twoPowerIndex2hi[8] */ 5.10922502897344389358977529484899213711118891193073e-17, /* twoPowerIndex2mi[8] */ 7.88422656496927442160138555121324022911581088833303e-34, /* twoPowerIndex2lo[8] */ } , { 1.02466779289713572076436776114860549569129943847656e+00, /* twoPowerIndex2hi[9] */ -7.56160786848777943963602624934464667278197265594918e-17, /* twoPowerIndex2mi[9] */ 3.82829708640966874425497233807001672128855640186408e-33, /* twoPowerIndex2lo[9] */ } , { 1.02744594911876374609960294037591665983200073242188e+00, /* twoPowerIndex2hi[10] */ -4.95607417464537044048053918668002938932966613516228e-17, /* twoPowerIndex2mi[10] */ 1.52647285191522534623240430678753798210498111737407e-33, /* twoPowerIndex2lo[10] */ } , { 1.03023163768604097967340749164577573537826538085938e+00, /* twoPowerIndex2hi[11] */ 3.31983004108081294376648458695381123964530598047240e-17, /* twoPowerIndex2mi[11] */ -6.05948719060829591517581519609021946982655246308260e-34, /* twoPowerIndex2lo[11] */ } , { 1.03302487902122841489926940994337201118469238281250e+00, /* twoPowerIndex2hi[12] */ 7.60083887402708848935418174694583720224989620170520e-18, /* twoPowerIndex2mi[12] */ 4.17547660336499599627565312970423748685953776150432e-34, /* twoPowerIndex2lo[12] */ } , { 1.03582569360195719809780712239444255828857421875000e+00, /* twoPowerIndex2hi[13] */ -7.80678239133763616702426510222438085291507518120348e-17, /* twoPowerIndex2mi[13] */ 4.83798199689382054315888822530184564936218864541054e-34, /* twoPowerIndex2lo[13] */ } , { 1.03863410196137873064969880942953750491142272949219e+00, /* twoPowerIndex2hi[14] */ 5.99627378885251061843052226928644856972739702249617e-17, /* twoPowerIndex2mi[14] */ -3.95663704958043112614113186183111724364471056517376e-33, /* twoPowerIndex2lo[14] */ } , { 1.04145012468831610341624127613613381981849670410156e+00, /* twoPowerIndex2hi[15] */ 3.78483048028757620965705119578257297756469464729973e-17, /* twoPowerIndex2mi[15] */ -2.78990868974053264987416432056918863121352708112718e-33, /* twoPowerIndex2lo[15] */ } , { 1.04427378242741375480306942336028441786766052246094e+00, /* twoPowerIndex2hi[16] */ 8.55188970553796489217080231819249267647451456689049e-17, /* twoPowerIndex2mi[16] */ -4.33079108057472301914865017639792677602990877842667e-33, /* twoPowerIndex2lo[16] */ } , { 1.04710509587928979335913481918396428227424621582031e+00, /* twoPowerIndex2hi[17] */ 7.27707724310431474860740275908141293488900903214077e-17, /* twoPowerIndex2mi[17] */ 4.72214361830876717418601268670474261741247234406534e-34, /* twoPowerIndex2lo[17] */ } , { 1.04994408580068721015265964524587616324424743652344e+00, /* twoPowerIndex2hi[18] */ 5.59293784812700258637018360670823030304395274991437e-17, /* twoPowerIndex2mi[18] */ 5.88211594754600857675576658960991674898106235024158e-33, /* twoPowerIndex2lo[18] */ } , { 1.05279077300462642341472019325010478496551513671875e+00, /* twoPowerIndex2hi[19] */ -9.62948289902693573941616400549765121885820038033846e-17, /* twoPowerIndex2mi[19] */ -1.08761347818786776096507022683126915318078909071327e-33, /* twoPowerIndex2lo[19] */ } , { 1.05564517836055715704901558638084679841995239257812e+00, /* twoPowerIndex2hi[20] */ 1.75932573877209198413667791203269037000656546957040e-18, /* twoPowerIndex2mi[20] */ -1.30396724977978376996223394717384715710429730879060e-34, /* twoPowerIndex2lo[20] */ } , { 1.05850732279451276163229067606152966618537902832031e+00, /* twoPowerIndex2hi[21] */ -7.15265185663778073796145114756001119612383138085358e-17, /* twoPowerIndex2mi[21] */ -5.64149549927303480417353705471376517000863783007238e-33, /* twoPowerIndex2lo[21] */ } , { 1.06137722728926209292410476336954161524772644042969e+00, /* twoPowerIndex2hi[22] */ -1.19735370853656575649342301877145101231593191394554e-17, /* twoPowerIndex2mi[22] */ -3.24019009642435813881917735260705206101901086389479e-34, /* twoPowerIndex2lo[22] */ } , { 1.06425491288446449900106927088927477598190307617188e+00, /* twoPowerIndex2hi[23] */ 5.07875419861123039357382102421174755425792834691388e-17, /* twoPowerIndex2mi[23] */ 1.50895958491701564197395322903064350349289305322861e-33, /* twoPowerIndex2lo[23] */ } , { 1.06714040067682369716806078940862789750099182128906e+00, /* twoPowerIndex2hi[24] */ -7.89985396684158212226333428391940791349522867645719e-17, /* twoPowerIndex2mi[24] */ 2.48773924323047906697979838020484860096229450391065e-33, /* twoPowerIndex2lo[24] */ } , { 1.07003371182024187291403904964681714773178100585938e+00, /* twoPowerIndex2hi[25] */ -9.93716271128891938111903502484820565662793756924256e-17, /* twoPowerIndex2mi[25] */ 2.31962344798684261201922994500766835313211720477486e-34, /* twoPowerIndex2lo[25] */ } , { 1.07293486752597555522470429423265159130096435546875e+00, /* twoPowerIndex2hi[26] */ -3.83966884335882380671154732420037314658136257342221e-18, /* twoPowerIndex2mi[26] */ -1.99249094904898757254369089814013323079830118271091e-34, /* twoPowerIndex2lo[26] */ } , { 1.07584388906279104780594479962019249796867370605469e+00, /* twoPowerIndex2hi[27] */ -1.00027161511441361124926436161855303296586383555652e-17, /* twoPowerIndex2mi[27] */ 6.88586299535442828962527763656910379336185001641212e-34, /* twoPowerIndex2lo[27] */ } , { 1.07876079775711986030728439800441265106201171875000e+00, /* twoPowerIndex2hi[28] */ -6.65666043605659260344452997720816205593857378631714e-17, /* twoPowerIndex2mi[28] */ -3.65812580131923690564246115619834327696213789275798e-33, /* twoPowerIndex2lo[28] */ } , { 1.08168561499321524976835462439339607954025268554688e+00, /* twoPowerIndex2hi[29] */ -4.78262390299708626555704566711052721844264408750016e-17, /* twoPowerIndex2mi[29] */ -2.29832484759747593833858703400029440154531888955339e-33, /* twoPowerIndex2lo[29] */ } , { 1.08461836221330920615457671374315395951271057128906e+00, /* twoPowerIndex2hi[30] */ 3.16615284581634611576111879942615084172431708553659e-17, /* twoPowerIndex2mi[30] */ -7.75514267549291199158161695245488815392525791097983e-34, /* twoPowerIndex2lo[30] */ } , { 1.08755906091776965993744852312374860048294067382812e+00, /* twoPowerIndex2hi[31] */ 5.40934930782029075923173884363871219691387098941733e-18, /* twoPowerIndex2mi[31] */ 3.48154867584145263827432069924110927169603001776988e-34, /* twoPowerIndex2lo[31] */ } , { 1.09050773266525768967483145388541743159294128417969e+00, /* twoPowerIndex2hi[32] */ -3.04678207981247114696551170541257032193091359539676e-17, /* twoPowerIndex2mi[32] */ 2.01705487848848619150139275849815038703452970938356e-33, /* twoPowerIndex2lo[32] */ } , { 1.09346439907288583981426199898123741149902343750000e+00, /* twoPowerIndex2hi[33] */ 1.44139581472692093419513384462869463509260880619035e-17, /* twoPowerIndex2mi[33] */ 4.08630093857659572006798113947020484158367259206261e-34, /* twoPowerIndex2lo[33] */ } , { 1.09642908181637688258547314035240560770034790039062e+00, /* twoPowerIndex2hi[34] */ -5.91993348444931582404791974798026685003551623353440e-17, /* twoPowerIndex2mi[34] */ 1.11454498034154926063604046797188107791920045228203e-33, /* twoPowerIndex2lo[34] */ } , { 1.09940180263022191375910097121959552168846130371094e+00, /* twoPowerIndex2hi[35] */ 7.17045959970192322482531070995357544666158025777059e-17, /* twoPowerIndex2mi[35] */ 2.13409756277809587478782727047623660463701953626949e-33, /* twoPowerIndex2lo[35] */ } , { 1.10238258330784089089604549371870234608650207519531e+00, /* twoPowerIndex2hi[36] */ 5.26603687157069438656191942579725322612448063343618e-17, /* twoPowerIndex2mi[36] */ 6.45805397536721410708490440561131106837447579889036e-34, /* twoPowerIndex2lo[36] */ } , { 1.10537144570174117319538709125481545925140380859375e+00, /* twoPowerIndex2hi[37] */ 8.23928876050021358995335359335922723831311179076842e-17, /* twoPowerIndex2mi[37] */ -1.04774466610247815442874156330747491506292900514778e-33, /* twoPowerIndex2lo[37] */ } , { 1.10836841172367872587756210123188793659210205078125e+00, /* twoPowerIndex2hi[38] */ -8.78681384518052661557648698444116835232371902158176e-17, /* twoPowerIndex2mi[38] */ -1.93068861306745460990089493247099606865877523423866e-33, /* twoPowerIndex2lo[38] */ } , { 1.11137350334481754821069898753194138407707214355469e+00, /* twoPowerIndex2hi[39] */ 5.56394502666969764310655992493514019038185064989534e-17, /* twoPowerIndex2mi[39] */ -1.17769877519864439845431603912093657619994388212320e-33, /* twoPowerIndex2lo[39] */ } , { 1.11438674259589243220602838846389204263687133789062e+00, /* twoPowerIndex2hi[40] */ 1.04102784568455709549461912557590544266030834754874e-16, /* twoPowerIndex2mi[40] */ 1.47570167344000313963428137759389241586071635800536e-33, /* twoPowerIndex2lo[40] */ } , { 1.11740815156736927882263898936798796057701110839844e+00, /* twoPowerIndex2hi[41] */ -7.97680590262822045600561531634368139010993610472575e-17, /* twoPowerIndex2mi[41] */ -3.13386648600120619264244700150043196400877518036064e-33, /* twoPowerIndex2lo[41] */ } , { 1.12043775240960674643986294540809467434883117675781e+00, /* twoPowerIndex2hi[42] */ -6.20108590655417874997850240693143539763038270522938e-17, /* twoPowerIndex2mi[42] */ 5.83820205528528388698845434843840374410554175693809e-33, /* twoPowerIndex2lo[42] */ } , { 1.12347556733301989773110562964575365185737609863281e+00, /* twoPowerIndex2hi[43] */ -9.69973758898704299543613376480429793851537956846792e-17, /* twoPowerIndex2mi[43] */ -2.26554127979727181051674177007680355310974340445620e-33, /* twoPowerIndex2lo[43] */ } , { 1.12652161860824184813623105583246797323226928710938e+00, /* twoPowerIndex2hi[44] */ 5.16585675879545673703180814711785602957687143067887e-17, /* twoPowerIndex2mi[44] */ -5.65916686170716220063974592097473710424342945964456e-34, /* twoPowerIndex2lo[44] */ } , { 1.12957592856628807886920640157768502831459045410156e+00, /* twoPowerIndex2hi[45] */ 6.71280585872625658757968769071561199197683972848295e-17, /* twoPowerIndex2mi[45] */ -1.07820162799000302104084759726971168076450417442143e-33, /* twoPowerIndex2lo[45] */ } , { 1.13263851959871919561351205629762262105941772460938e+00, /* twoPowerIndex2hi[46] */ 3.23735616673800026374280491083711282285071512434226e-17, /* twoPowerIndex2mi[46] */ -2.17410428198276732317664547375555516673086011902827e-33, /* twoPowerIndex2lo[46] */ } , { 1.13570941415780546357439106941455975174903869628906e+00, /* twoPowerIndex2hi[47] */ 5.06659992612615585870979493424241383844326077647274e-17, /* twoPowerIndex2mi[47] */ -1.32541787182048387837370885885176434849571625344055e-33, /* twoPowerIndex2lo[47] */ } , { 1.13878863475669156457570352358743548393249511718750e+00, /* twoPowerIndex2hi[48] */ 8.91281267602540777782023808215740339330966556723006e-17, /* twoPowerIndex2mi[48] */ -2.00741463283249448727846279877956608996968961458494e-33, /* twoPowerIndex2lo[48] */ } , { 1.14187620396956157620138583297375589609146118164062e+00, /* twoPowerIndex2hi[49] */ 4.65109117753141238740817792833606106064264488933295e-17, /* twoPowerIndex2mi[49] */ 1.16876708285186516119099627711493197934208124175159e-33, /* twoPowerIndex2lo[49] */ } , { 1.14497214443180417298151496652280911803245544433594e+00, /* twoPowerIndex2hi[50] */ 4.64128989217001065651476858937308428660295061803434e-17, /* twoPowerIndex2mi[50] */ 2.12613258776789922762135782566899992944567171074898e-34, /* twoPowerIndex2lo[50] */ } , { 1.14807647884017893780139729642542079091072082519531e+00, /* twoPowerIndex2hi[51] */ 6.89774023662719177044119892069339989513569982425983e-17, /* twoPowerIndex2mi[51] */ 4.18470834663834509017799649540704770686179227316921e-33, /* twoPowerIndex2lo[51] */ } , { 1.15118922995298267331065744656370952725410461425781e+00, /* twoPowerIndex2hi[52] */ 3.25071021886382721197741051783883831627922464835734e-17, /* twoPowerIndex2mi[52] */ 8.89091931637927159755660842958283684863470887791663e-34, /* twoPowerIndex2lo[52] */ } , { 1.15431042059021593537693206599215045571327209472656e+00, /* twoPowerIndex2hi[53] */ 1.04171289462732661865012882394503754385710309711063e-16, /* twoPowerIndex2mi[53] */ -5.36004208703313921208161123405733997004096829869921e-33, /* twoPowerIndex2lo[53] */ } , { 1.15744007363375112085179807763779535889625549316406e+00, /* twoPowerIndex2hi[54] */ -9.12387123113440028710214564331695285968225139034901e-17, /* twoPowerIndex2mi[54] */ 4.33323257285343273028953697402398811817365345749781e-33, /* twoPowerIndex2lo[54] */ } , { 1.16057821202749877897986152675002813339233398437500e+00, /* twoPowerIndex2hi[55] */ -3.26104020541739372182753051431941352277362975722267e-17, /* twoPowerIndex2mi[55] */ 7.11357834451307044066628553966351937724582011421575e-35, /* twoPowerIndex2lo[55] */ } , { 1.16372485877757747552152522985124960541725158691406e+00, /* twoPowerIndex2hi[56] */ 3.82920483692409349872159816102110059722238312159091e-17, /* twoPowerIndex2mi[56] */ 7.19709831987676327409679245188515478735702972651365e-34, /* twoPowerIndex2lo[56] */ } , { 1.16688003695248165847431209840578958392143249511719e+00, /* twoPowerIndex2hi[57] */ -8.79187957999916974198229633672296429647404899187201e-17, /* twoPowerIndex2mi[57] */ -2.87626642494823975790958872496361075697324563663418e-33, /* twoPowerIndex2lo[57] */ } , { 1.17004376968325018992800323758274316787719726562500e+00, /* twoPowerIndex2hi[58] */ -1.84774420179000469437829606444460290025923861011560e-18, /* twoPowerIndex2mi[58] */ 9.95026324026540894110632007684038501192747054873613e-35, /* twoPowerIndex2lo[58] */ } , { 1.17321608016363732041043022036319598555564880371094e+00, /* twoPowerIndex2hi[59] */ -7.28756258658499447915217361810881652407443644873380e-17, /* twoPowerIndex2mi[59] */ -5.80514434850720922900022428546053614526438490706197e-33, /* twoPowerIndex2lo[59] */ } , { 1.17639699165028122074261318630306050181388854980469e+00, /* twoPowerIndex2hi[60] */ 5.55420325421807896276684328889766000203735373777665e-17, /* twoPowerIndex2mi[60] */ -1.48842929343368511961710849782815827921712348302943e-33, /* twoPowerIndex2lo[60] */ } , { 1.17958652746287584456297281576553359627723693847656e+00, /* twoPowerIndex2hi[61] */ 1.00923127751003904353623199255548893172824487848155e-16, /* twoPowerIndex2mi[61] */ 2.56907593214680284136128623025833045419367581735075e-33, /* twoPowerIndex2lo[61] */ } , { 1.18278471098434101449470290390308946371078491210938e+00, /* twoPowerIndex2hi[62] */ 1.54297543007907605845327903967313855640292420619590e-17, /* twoPowerIndex2mi[62] */ 7.09719727836492954234152192412259750112212179635692e-34, /* twoPowerIndex2lo[62] */ } , { 1.18599156566099384058077248482732102274894714355469e+00, /* twoPowerIndex2hi[63] */ -9.20950683529310590495224568572832186256763277535644e-18, /* twoPowerIndex2mi[63] */ 4.45938700163758066851795410125927948023388255302655e-34, /* twoPowerIndex2lo[63] */ } , { 1.18920711500272102689734765590401366353034973144531e+00, /* twoPowerIndex2hi[64] */ 3.98201523146564611098029654755651628169309930562261e-17, /* twoPowerIndex2mi[64] */ 1.14195965688545340101163692105448367710482873511510e-33, /* twoPowerIndex2lo[64] */ } , { 1.19243138258315117816721340204821899533271789550781e+00, /* twoPowerIndex2hi[65] */ 4.39755141560972144344381120574300882985513737679934e-17, /* twoPowerIndex2mi[65] */ -2.41829020212771695653773640974975764989760653578657e-33, /* twoPowerIndex2lo[65] */ } , { 1.19566439203982732841780034505063667893409729003906e+00, /* twoPowerIndex2hi[66] */ 4.61660367048148139742806754321229408219716031742605e-17, /* twoPowerIndex2mi[66] */ 1.32248737144550668026460879187484144120719947949532e-33, /* twoPowerIndex2lo[66] */ } , { 1.19890616707438057986223611806053668260574340820312e+00, /* twoPowerIndex2hi[67] */ -9.80919335600842311847819900738643766443372921069732e-17, /* twoPowerIndex2mi[67] */ -5.29087429062105337716063232877224643258346493331853e-33, /* twoPowerIndex2lo[67] */ } , { 1.20215673145270307564658196497475728392601013183594e+00, /* twoPowerIndex2hi[68] */ 6.64498149925230124489270286991048474954122885069094e-17, /* twoPowerIndex2mi[68] */ -3.85685255336907654452995968372311171004938395576078e-33, /* twoPowerIndex2lo[68] */ } , { 1.20541610900512385917693336523370817303657531738281e+00, /* twoPowerIndex2hi[69] */ -3.35727219326752963448211014853517469169774564393197e-17, /* twoPowerIndex2mi[69] */ -4.92549550862177406688591486963370003941067572015491e-34, /* twoPowerIndex2lo[69] */ } , { 1.20868432362658162482205170817906036972999572753906e+00, /* twoPowerIndex2hi[70] */ -4.74672594522898409739364787077500872067787392617061e-17, /* twoPowerIndex2mi[70] */ -2.39731037167046840753848687443925994516005866460984e-33, /* twoPowerIndex2lo[70] */ } , { 1.21196139927680124337427969294367358088493347167969e+00, /* twoPowerIndex2hi[71] */ -4.89061107752111835731723583297106520554917182658748e-17, /* twoPowerIndex2mi[71] */ 3.03773638515966381050119516339532028224866436819777e-33, /* twoPowerIndex2lo[71] */ } , { 1.21524735998046895524282717815367504954338073730469e+00, /* twoPowerIndex2hi[72] */ -7.71263069268148813091257203929615917892526180720328e-17, /* twoPowerIndex2mi[72] */ 4.71720614288499816545262331753743129502653902881319e-33, /* twoPowerIndex2lo[72] */ } , { 1.21854222982740845182547673175577074289321899414062e+00, /* twoPowerIndex2hi[73] */ -9.00672695836383767486750626492663453576309245864756e-17, /* twoPowerIndex2mi[73] */ 5.16504109670658058144743067711083355626699725368541e-34, /* twoPowerIndex2lo[73] */ } , { 1.22184603297275762301410395593848079442977905273438e+00, /* twoPowerIndex2hi[74] */ -1.06110212114026911612338140955143073076587458436915e-16, /* twoPowerIndex2mi[74] */ 1.60374219470078741193166884413586755813454143083569e-33, /* twoPowerIndex2lo[74] */ } , { 1.22515879363714552674480273708468303084373474121094e+00, /* twoPowerIndex2hi[75] */ -8.90353381426998342947457496954569957296479418024787e-17, /* twoPowerIndex2mi[75] */ -3.38239295886914309313127675019861767225893406120572e-33, /* twoPowerIndex2lo[75] */ } , { 1.22848053610687002468182527081808075308799743652344e+00, /* twoPowerIndex2hi[76] */ -1.89878163130252995311948719658078062677878185721429e-17, /* twoPowerIndex2mi[76] */ 6.18469453652103848424687212656185051850860290411013e-34, /* twoPowerIndex2lo[76] */ } , { 1.23181128473407586199073193711228668689727783203125e+00, /* twoPowerIndex2hi[77] */ 7.38938247161005024655390749410851704831793332860224e-17, /* twoPowerIndex2mi[77] */ 5.66416860276341522848933887503853153547313928315175e-33, /* twoPowerIndex2lo[77] */ } , { 1.23515106393693341324535595049383118748664855957031e+00, /* twoPowerIndex2hi[78] */ -1.07552443443078413782534550626319265988634731989314e-16, /* twoPowerIndex2mi[78] */ -1.64465643112359468913735122191038582299186062892515e-33, /* twoPowerIndex2lo[78] */ } , { 1.23849989819981654015634831011993810534477233886719e+00, /* twoPowerIndex2hi[79] */ 2.76770205557396742995282629120281510329639442299790e-17, /* twoPowerIndex2mi[79] */ 2.66724789689442974848682438840669194714548350787063e-35, /* twoPowerIndex2lo[79] */ } , { 1.24185781207348400201340155035723000764846801757812e+00, /* twoPowerIndex2hi[80] */ 4.65802759183693679122616767654141683800114091774588e-17, /* twoPowerIndex2mi[80] */ -2.31439910378785985764079190411324307370918857557275e-33, /* twoPowerIndex2lo[80] */ } , { 1.24522483017525797954760946595342829823493957519531e+00, /* twoPowerIndex2hi[81] */ -4.67724044984672750044476807490179835934784763101964e-17, /* twoPowerIndex2mi[81] */ -6.19614441679121104595267684200368658842294828986636e-34, /* twoPowerIndex2lo[81] */ } , { 1.24860097718920481923987608752213418483734130859375e+00, /* twoPowerIndex2hi[82] */ -8.26181099902196355045651985461180951636054028345939e-17, /* twoPowerIndex2mi[82] */ -3.13508520893426556972542244676107480243422253073214e-33, /* twoPowerIndex2lo[82] */ } , { 1.25198627786631622171853450709022581577301025390625e+00, /* twoPowerIndex2hi[83] */ 4.83416715246989759958838285593793501234849559981127e-17, /* twoPowerIndex2mi[83] */ 1.78566475406016519018652742315549367024352654682538e-33, /* twoPowerIndex2lo[83] */ } , { 1.25538075702469109629078047873917967081069946289062e+00, /* twoPowerIndex2hi[84] */ -6.71138982129687841852821870522008036246320680675952e-18, /* twoPowerIndex2mi[84] */ -5.76846264325028352862497671463784812858487529613818e-35, /* twoPowerIndex2lo[84] */ } , { 1.25878443954971652729568631912115961313247680664062e+00, /* twoPowerIndex2hi[85] */ -8.42178258773059935676825219277948030487309990653640e-17, /* twoPowerIndex2mi[85] */ -3.42668790982954401635344774416743553535666629313219e-33, /* twoPowerIndex2lo[85] */ } , { 1.26219735039425073885865913325687870383262634277344e+00, /* twoPowerIndex2hi[86] */ -3.08446488747384646529907217460461327518172988421553e-17, /* twoPowerIndex2mi[86] */ 2.40882976270348351451454970147527613654722303853330e-33, /* twoPowerIndex2lo[86] */ } , { 1.26561951457880628169050396536476910114288330078125e+00, /* twoPowerIndex2hi[87] */ 4.25057700345086863701776979850140764907451511182054e-17, /* twoPowerIndex2mi[87] */ -2.43502301511662232808349177773715412240431561172854e-33, /* twoPowerIndex2lo[87] */ } , { 1.26905095719173321988648694969015195965766906738281e+00, /* twoPowerIndex2hi[88] */ 2.66793213134218609522998616502989391061315227839969e-18, /* twoPowerIndex2mi[88] */ -5.01723570938719050333027020376949013774930719140568e-35, /* twoPowerIndex2lo[88] */ } , { 1.27249170338940276181460831139702349901199340820312e+00, /* twoPowerIndex2hi[89] */ -1.05779162672124210291083901925683986461541009150905e-17, /* twoPowerIndex2mi[89] */ -2.93131904402812719815315335629352674850210527511727e-34, /* twoPowerIndex2lo[89] */ } , { 1.27594177839639200122689999261638149619102478027344e+00, /* twoPowerIndex2hi[90] */ 9.91543024421429032951245620636467731146795580787420e-17, /* twoPowerIndex2mi[90] */ 4.59759442266878048582159401225601949347063078487755e-33, /* twoPowerIndex2lo[90] */ } , { 1.27940120750566932450453805358847603201866149902344e+00, /* twoPowerIndex2hi[91] */ -9.75909500835606221035467671832651562727399972211988e-17, /* twoPowerIndex2mi[91] */ -1.38251039186524925998756795041289231285031751943997e-33, /* twoPowerIndex2lo[91] */ } , { 1.28287001607877826359072059858590364456176757812500e+00, /* twoPowerIndex2hi[92] */ 1.71359491824356096814175768900864730928374054987756e-17, /* twoPowerIndex2mi[92] */ 7.25131491282819461838977871983760669047046080773478e-34, /* twoPowerIndex2lo[92] */ } , { 1.28634822954602556777103927743155509233474731445312e+00, /* twoPowerIndex2hi[93] */ -3.41695570693618197637835756165078424638638756108411e-17, /* twoPowerIndex2mi[93] */ 3.01980638845024588477534724775904900964451374240343e-33, /* twoPowerIndex2lo[93] */ } , { 1.28983587340666572274017198651563376188278198242188e+00, /* twoPowerIndex2hi[94] */ 8.94925753089759172194875997189204564115016328268090e-17, /* twoPowerIndex2mi[94] */ 1.20830737845688318745384554764993450976718105981461e-33, /* twoPowerIndex2lo[94] */ } , { 1.29333297322908946647146422037621960043907165527344e+00, /* twoPowerIndex2hi[95] */ -2.97459044313275164581312778190571731582573264222880e-17, /* twoPowerIndex2mi[95] */ 1.16237613827319824876464974429153654014369509787634e-33, /* twoPowerIndex2lo[95] */ } , { 1.29683955465100964055125132290413603186607360839844e+00, /* twoPowerIndex2hi[96] */ 2.53825027948883149592910250791940344234383392801619e-17, /* twoPowerIndex2mi[96] */ 1.68678246461832500334243039646153124282288438904092e-34, /* twoPowerIndex2lo[96] */ } , { 1.30035564337965059422685953904874622821807861328125e+00, /* twoPowerIndex2hi[97] */ 5.67872810280221742200488134915364617768988996925235e-17, /* twoPowerIndex2mi[97] */ -2.65697595108343105071012773811939091954697862387724e-33, /* twoPowerIndex2lo[97] */ } , { 1.30388126519193581209776766627328470349311828613281e+00, /* twoPowerIndex2hi[98] */ 8.64767559826787117946355165568051639464066963273840e-17, /* twoPowerIndex2mi[98] */ 8.70201872477350096167517355607069078597678984954289e-34, /* twoPowerIndex2lo[98] */ } , { 1.30741644593467731816360810626065358519554138183594e+00, /* twoPowerIndex2hi[99] */ -7.33664565287886889230365718649852916028408328060276e-17, /* twoPowerIndex2mi[99] */ -2.93367882958631685351818537761286406545337467653224e-33, /* twoPowerIndex2lo[99] */ } , { 1.31096121152476441373835314152529463171958923339844e+00, /* twoPowerIndex2hi[100] */ -7.18153613551945385697245613605196258733040544776187e-17, /* twoPowerIndex2mi[100] */ -2.12629266743969557140434977160228094057588798528197e-34, /* twoPowerIndex2lo[100] */ } , { 1.31451558794935463581055046233814209699630737304688e+00, /* twoPowerIndex2hi[101] */ 2.26754331510458564505142831387082924518590502314377e-17, /* twoPowerIndex2mi[101] */ -7.52544640273480434326029480252966858598400235446401e-34, /* twoPowerIndex2lo[101] */ } , { 1.31807960126606404926974391855765134096145629882812e+00, /* twoPowerIndex2hi[102] */ -5.45795582714915350249059559812768392944707787964569e-17, /* twoPowerIndex2mi[102] */ 3.01605678846279399154010507026593082215688854819315e-34, /* twoPowerIndex2lo[102] */ } , { 1.32165327760315753913289427146082744002342224121094e+00, /* twoPowerIndex2hi[103] */ -2.48063824591302174150388078679826792820566433791932e-17, /* twoPowerIndex2mi[103] */ -7.98826352342197225244683042177702410050087972196938e-34, /* twoPowerIndex2lo[103] */ } , { 1.32523664315974132321684919588733464479446411132812e+00, /* twoPowerIndex2hi[104] */ -2.85873121003886137327027220806882812126373511580572e-17, /* twoPowerIndex2mi[104] */ 7.62021406397260431456821182703024347950927217409368e-34, /* twoPowerIndex2lo[104] */ } , { 1.32882972420595435458778865722706541419029235839844e+00, /* twoPowerIndex2hi[105] */ 4.08908622391016005194851803726881862830375046944341e-17, /* twoPowerIndex2mi[105] */ -8.25755527905788850028602577519818711544066895869934e-34, /* twoPowerIndex2lo[105] */ } , { 1.33243254708316150036750968865817412734031677246094e+00, /* twoPowerIndex2hi[106] */ -5.10158663091674395948874951281987248409217090958003e-17, /* twoPowerIndex2mi[106] */ 1.24161698455614255772408207369534691020717040259615e-33, /* twoPowerIndex2lo[106] */ } , { 1.33604513820414583236129146825987845659255981445312e+00, /* twoPowerIndex2hi[107] */ -5.89186635638880135250424875698763827220081961896780e-17, /* twoPowerIndex2mi[107] */ 4.82773672901544401626262260553683707114055277401310e-33, /* twoPowerIndex2lo[107] */ } , { 1.33966752405330291608720472140703350305557250976562e+00, /* twoPowerIndex2hi[108] */ 8.92728259483173198426255486589831591472085466011828e-17, /* twoPowerIndex2mi[108] */ -7.69657983531899254540849298389093495155758992415150e-34, /* twoPowerIndex2lo[108] */ } , { 1.34329973118683532185002604819601401686668395996094e+00, /* twoPowerIndex2hi[109] */ -5.80258089020143775129607366972124060945118168095697e-17, /* twoPowerIndex2mi[109] */ -5.62848183889096727330900462318018132434931156577971e-33, /* twoPowerIndex2lo[109] */ } , { 1.34694178623294580354752270068274810910224914550781e+00, /* twoPowerIndex2hi[110] */ 3.22406510125467916912928274924363934664289972360091e-17, /* twoPowerIndex2mi[110] */ -2.51832203762622189165076753162586788705235166031733e-33, /* twoPowerIndex2lo[110] */ } , { 1.35059371589203447427962601068429648876190185546875e+00, /* twoPowerIndex2hi[111] */ -8.28711038146241653260111018049835125653080776498248e-17, /* twoPowerIndex2mi[111] */ 2.79728744284194320208556684414100450680158956985147e-33, /* twoPowerIndex2lo[111] */ } , { 1.35425554693689265128853094211081042885780334472656e+00, /* twoPowerIndex2hi[112] */ 7.70094837980298946162338224151128414915778826123523e-17, /* twoPowerIndex2mi[112] */ -2.24074836437395028882100810844688282941385619430371e-33, /* twoPowerIndex2lo[112] */ } , { 1.35792730621290114179089414392365142703056335449219e+00, /* twoPowerIndex2hi[113] */ -9.52963574482518886708763256581296493681255450761483e-17, /* twoPowerIndex2mi[113] */ 3.94129059821951840862728683884868804521606133502020e-33, /* twoPowerIndex2lo[113] */ } , { 1.36160902063822475405174827756127342581748962402344e+00, /* twoPowerIndex2hi[114] */ 1.53378766127066804593191316699398053341331687545086e-18, /* twoPowerIndex2mi[114] */ 2.89261626537731219518175809165487342026413059288117e-36, /* twoPowerIndex2lo[114] */ } , { 1.36530071720401191548432962008519098162651062011719e+00, /* twoPowerIndex2hi[115] */ -1.00053631259747651675482154696825016305954942740907e-16, /* twoPowerIndex2mi[115] */ 3.54928742268818507952779264530371584695776903628456e-33, /* twoPowerIndex2lo[115] */ } , { 1.36900242297459051599162194179370999336242675781250e+00, /* twoPowerIndex2hi[116] */ 9.59379791911884877255545693637832999511204427845953e-17, /* twoPowerIndex2mi[116] */ -4.88674958784947176959607858061848292445663702071206e-33, /* twoPowerIndex2lo[116] */ } , { 1.37271416508766841424460380949312821030616760253906e+00, /* twoPowerIndex2hi[117] */ -4.49596059523484126201398925346079480634909342749196e-17, /* twoPowerIndex2mi[117] */ 1.62562490898807010621996863149362627894393561257459e-33, /* twoPowerIndex2lo[117] */ } , { 1.37643597075453016920221216423669829964637756347656e+00, /* twoPowerIndex2hi[118] */ -6.89858893587180104162314142277078705990308809896903e-17, /* twoPowerIndex2mi[118] */ -9.23154448708427617703494512509845826869729176165562e-34, /* twoPowerIndex2lo[118] */ } , { 1.38016786726023799047879947465844452381134033203125e+00, /* twoPowerIndex2hi[119] */ 1.05103145799699839461846797726451249170514296493641e-16, /* twoPowerIndex2mi[119] */ -5.20959403592477818815879901700610698718705668178631e-34, /* twoPowerIndex2lo[119] */ } , { 1.38390988196383202257777611521305516362190246582031e+00, /* twoPowerIndex2hi[120] */ -6.77051165879478628715737183479431151106043475381389e-17, /* twoPowerIndex2mi[120] */ 5.25954134785524271676320971772030766300829615286373e-34, /* twoPowerIndex2lo[120] */ } , { 1.38766204229852907481301826919661834836006164550781e+00, /* twoPowerIndex2hi[121] */ 8.42298427487541531761909892542259393461447669376914e-17, /* twoPowerIndex2mi[121] */ 4.46434333442928450361645463407705485478297602125654e-33, /* twoPowerIndex2lo[121] */ } , { 1.39142437577192623621158418245613574981689453125000e+00, /* twoPowerIndex2hi[122] */ -4.90617486528898932450860315361961796480813828948749e-17, /* twoPowerIndex2mi[122] */ 9.41947135373105773751136712580396521761942792376029e-34, /* twoPowerIndex2lo[122] */ } , { 1.39519690996620027156893684150418266654014587402344e+00, /* twoPowerIndex2hi[123] */ -9.32933622422549655219151241388008074464471865703576e-17, /* twoPowerIndex2mi[123] */ 3.85009236000292978304841859575059463134595037095756e-33, /* twoPowerIndex2lo[123] */ } , { 1.39897967253831123635166022722842171788215637207031e+00, /* twoPowerIndex2hi[124] */ -9.61421320905132307233280072508933760749140842467170e-17, /* twoPowerIndex2mi[124] */ 3.97465190077505680357285219692652769985214754647576e-33, /* twoPowerIndex2lo[124] */ } , { 1.40277269122020475933254601841326802968978881835938e+00, /* twoPowerIndex2hi[125] */ -5.29578324940798922315924317002369067798815514694702e-17, /* twoPowerIndex2mi[125] */ 3.01901046243343149118437935612420792667881700875337e-33, /* twoPowerIndex2lo[125] */ } , { 1.40657599381901543544870492041809484362602233886719e+00, /* twoPowerIndex2hi[126] */ 7.03491481213642218799944724280847971836007996977941e-18, /* twoPowerIndex2mi[126] */ -1.87515169946872014216649248611672456272335645241101e-34, /* twoPowerIndex2lo[126] */ } , { 1.41038960821727066274888784391805529594421386718750e+00, /* twoPowerIndex2hi[127] */ 4.16654872843506225899503851018795172623979530606656e-17, /* twoPowerIndex2mi[127] */ -2.40474814922300276552970992509731322006163156322473e-33, /* twoPowerIndex2lo[127] */ } , { 1.41421356237309514547462185873882845044136047363281e+00, /* twoPowerIndex2hi[128] */ -9.66729331345291345105469972976694765012981670542977e-17, /* twoPowerIndex2mi[128] */ 4.13867530869941356271900493210877889450985709540127e-33, /* twoPowerIndex2lo[128] */ } , { 1.41804788432041517509674122266005724668502807617188e+00, /* twoPowerIndex2hi[129] */ 2.27443854218552945230015468607785816403034626672752e-17, /* twoPowerIndex2mi[129] */ 6.11983793133626012461813597014932765313298826737750e-34, /* twoPowerIndex2lo[129] */ } , { 1.42189260216916557588717751059448346495628356933594e+00, /* twoPowerIndex2hi[130] */ -1.60778289158902441338409661475962612292273904731179e-17, /* twoPowerIndex2mi[130] */ 7.68807227837949092746953551637615091691382851311989e-34, /* twoPowerIndex2lo[130] */ } , { 1.42574774410549420800009556842269375920295715332031e+00, /* twoPowerIndex2hi[131] */ 9.88069075850060728430483918067849097743150129356283e-17, /* twoPowerIndex2mi[131] */ -5.89890673162487333450312700634529433299513739860251e-34, /* twoPowerIndex2lo[131] */ } , { 1.42961333839197002326670826732879504561424255371094e+00, /* twoPowerIndex2hi[132] */ -1.20316424890536551791763281075597751007148682598677e-17, /* twoPowerIndex2mi[132] */ 3.96492532243389364766543780399018506300743370884771e-35, /* twoPowerIndex2lo[132] */ } , { 1.43348941336778890054404200782300904393196105957031e+00, /* twoPowerIndex2hi[133] */ -5.80245424392682610310488944560210655448170298910740e-17, /* twoPowerIndex2mi[133] */ -1.27850570502833499820846554122319062699206032852878e-33, /* twoPowerIndex2lo[133] */ } , { 1.43737599744898236764356624917127192020416259765625e+00, /* twoPowerIndex2hi[134] */ -4.20403401646755661224775048184723117388682958150796e-17, /* twoPowerIndex2mi[134] */ -7.70667502347783805122329265482919129596484289448427e-34, /* twoPowerIndex2lo[134] */ } , { 1.44127311912862565712600826373090967535972595214844e+00, /* twoPowerIndex2hi[135] */ 5.60250365087898567500720975825924684730592892906837e-18, /* twoPowerIndex2mi[135] */ -1.78220423347129903406970040172107023860560188781295e-34, /* twoPowerIndex2lo[135] */ } , { 1.44518080697704665027458759141154587268829345703125e+00, /* twoPowerIndex2hi[136] */ -3.02375813499398731939978948265280760393682335269040e-17, /* twoPowerIndex2mi[136] */ -1.77301195820250091791088617662298487007284882395542e-33, /* twoPowerIndex2lo[136] */ } , { 1.44909908964203504311285541916731745004653930664062e+00, /* twoPowerIndex2hi[137] */ -6.25940500081930925440932857364551992320704493612607e-17, /* twoPowerIndex2mi[137] */ -2.36452377319288878996205003453964701184928253771460e-33, /* twoPowerIndex2lo[137] */ } , { 1.45302799584905262264555858564563095569610595703125e+00, /* twoPowerIndex2hi[138] */ -5.77994860939610610226179416579990281210592783980168e-17, /* twoPowerIndex2mi[138] */ 4.65449358394055530593548186610866020262848130035371e-33, /* twoPowerIndex2lo[138] */ } , { 1.45696755440144376514410851086722686886787414550781e+00, /* twoPowerIndex2hi[139] */ 5.64867945387699814049307308799040836462273423076302e-17, /* twoPowerIndex2mi[139] */ 5.24967327842642970132560251109596346953497158893017e-33, /* twoPowerIndex2lo[139] */ } , { 1.46091779418064704465507475106278434395790100097656e+00, /* twoPowerIndex2hi[140] */ -5.60037718607521580013156831807759453639536208267684e-17, /* twoPowerIndex2mi[140] */ -4.80948804890004400970317146361816382779746350931714e-33, /* twoPowerIndex2lo[140] */ } , { 1.46487874414640573128565392835298553109169006347656e+00, /* twoPowerIndex2hi[141] */ 9.53076754358715731899854652788308463901335051797481e-17, /* twoPowerIndex2mi[141] */ -3.69846856553667878907707087404919621014972996085084e-34, /* twoPowerIndex2lo[141] */ } , { 1.46885043333698184220281746092950925230979919433594e+00, /* twoPowerIndex2hi[142] */ 8.46588275653362760829764150554853775141300918573480e-17, /* twoPowerIndex2mi[142] */ -3.90998276339861143341660977862311141233961685102469e-33, /* twoPowerIndex2lo[142] */ } , { 1.47283289086936752809720019286032766103744506835938e+00, /* twoPowerIndex2hi[143] */ 6.69177408194058937165142250867005391292400049525410e-17, /* twoPowerIndex2mi[143] */ -8.03669204969698754299165627994407636733379029439982e-34, /* twoPowerIndex2lo[143] */ } , { 1.47682614593949934622685304930200800299644470214844e+00, /* twoPowerIndex2hi[144] */ -3.48399455689279579579151031868718147769491495422105e-17, /* twoPowerIndex2mi[144] */ -1.21157704523090580028169713170353136148082368354920e-34, /* twoPowerIndex2lo[144] */ } , { 1.48083022782247186732718091661809012293815612792969e+00, /* twoPowerIndex2hi[145] */ -9.68695210263061857840747540204704607519762865792956e-17, /* twoPowerIndex2mi[145] */ -1.83093426853584085824897446366702716297781292402913e-33, /* twoPowerIndex2lo[145] */ } , { 1.48484516587275239274390514765400439500808715820312e+00, /* twoPowerIndex2hi[146] */ 1.07800867644074807558776439636082922597575014362313e-16, /* twoPowerIndex2mi[146] */ -5.64322930459841965610869302140803670685265398096703e-33, /* twoPowerIndex2lo[146] */ } , { 1.48887098952439700383365561719983816146850585937500e+00, /* twoPowerIndex2hi[147] */ 6.15536715774287133031442683555328448918198696888232e-17, /* twoPowerIndex2mi[147] */ -4.97910816988088435273822881157670080090569125411939e-33, /* twoPowerIndex2lo[147] */ } , { 1.49290772829126483500772337720263749361038208007812e+00, /* twoPowerIndex2hi[148] */ 1.41929201542840357707378184476885202767753055101956e-17, /* twoPowerIndex2mi[148] */ 2.77326329344780505247628358108799734324783290873618e-34, /* twoPowerIndex2lo[148] */ } , { 1.49695541176723545540028226241702213883399963378906e+00, /* twoPowerIndex2hi[149] */ -2.86166325389915821108552064438047364932070584938283e-17, /* twoPowerIndex2mi[149] */ 1.69686608128918952548566738297292377457978745974095e-33, /* twoPowerIndex2lo[149] */ } , { 1.50101406962642558440279572096187621355056762695312e+00, /* twoPowerIndex2hi[150] */ -6.41376727579023503858812048925241405475211237704851e-17, /* twoPowerIndex2mi[150] */ 2.82195851325152411917232690264483764919093983459578e-33, /* twoPowerIndex2lo[150] */ } , { 1.50508373162340647333223841997096315026283264160156e+00, /* twoPowerIndex2hi[151] */ 7.07471061358284636428966552102679897344999964477370e-17, /* twoPowerIndex2mi[151] */ 5.47182451113168633513345414695618261455556199846033e-33, /* twoPowerIndex2lo[151] */ } , { 1.50916442759342284141155232646269723773002624511719e+00, /* twoPowerIndex2hi[152] */ -1.01645532775429503910501990740249618370059871055172e-16, /* twoPowerIndex2mi[152] */ 2.04191706967403438352422808603561166583202022922508e-34, /* twoPowerIndex2lo[152] */ } , { 1.51325618745260981334865846292814239859580993652344e+00, /* twoPowerIndex2hi[153] */ 8.88449785133871209092649041499311129526944241199989e-17, /* twoPowerIndex2mi[153] */ 2.91936471176098668822594707319785335362070597228113e-33, /* twoPowerIndex2lo[153] */ } , { 1.51735904119821474189677701360778883099555969238281e+00, /* twoPowerIndex2hi[154] */ -4.30869947204334080070359075619950231322291381069658e-17, /* twoPowerIndex2mi[154] */ -2.07710051583928391994432084290324754641836773161677e-33, /* twoPowerIndex2lo[154] */ } , { 1.52147301890881458952264893014216795563697814941406e+00, /* twoPowerIndex2hi[155] */ -5.99638767594568341984511314492633394994506478752408e-18, /* twoPowerIndex2mi[155] */ 3.17143766271956082831607786726725332519992796566057e-34, /* twoPowerIndex2lo[155] */ } , { 1.52559815074453841710067081294255331158638000488281e+00, /* twoPowerIndex2hi[156] */ -1.10249417123425609363148008789604625195179292613569e-16, /* twoPowerIndex2mi[156] */ -2.99382882637137806007903782085057425945683820190483e-33, /* twoPowerIndex2lo[156] */ } , { 1.52973446694728698602716576715465635061264038085938e+00, /* twoPowerIndex2hi[157] */ 3.78579211515721965312581373704701424608681121499690e-17, /* twoPowerIndex2mi[157] */ -1.13571103486415982326219089189691662922640586007719e-33, /* twoPowerIndex2lo[157] */ } , { 1.53388199784095591304833305912325158715248107910156e+00, /* twoPowerIndex2hi[158] */ 8.87522684443844614134710276926299051548575116130438e-17, /* twoPowerIndex2mi[158] */ 5.65828980010215437966290324879670843424190599145086e-33, /* twoPowerIndex2lo[158] */ } , { 1.53804077383165682668675344757502898573875427246094e+00, /* twoPowerIndex2hi[159] */ 1.01746723511613592944060366030036337911942910864054e-16, /* twoPowerIndex2mi[159] */ -6.16113785188921653281369270464531950196652324750545e-33, /* twoPowerIndex2lo[159] */ } , { 1.54221082540794074411394376511452719569206237792969e+00, /* twoPowerIndex2hi[160] */ 7.94983480969762085616103882937991564856794389991833e-17, /* twoPowerIndex2mi[160] */ -9.15995637410036729585390444224530830478731117122757e-34, /* twoPowerIndex2lo[160] */ } , { 1.54639218314102144802291149972006678581237792968750e+00, /* twoPowerIndex2hi[161] */ 1.06839600056572198027549065429961389678954641782420e-16, /* twoPowerIndex2mi[161] */ 5.83718082376326468071834720519101607593932706278383e-33, /* twoPowerIndex2lo[161] */ } , { 1.55058487768499997372373400139622390270233154296875e+00, /* twoPowerIndex2hi[162] */ -1.46007065906893851790690523707186238729906746210228e-17, /* twoPowerIndex2mi[162] */ -4.77975052472883005267659258241957348576642768400574e-34, /* twoPowerIndex2lo[162] */ } , { 1.55478893977708865214992783876368775963783264160156e+00, /* twoPowerIndex2hi[163] */ -8.00316135011603564103663107910618902189361743978666e-17, /* twoPowerIndex2mi[163] */ 3.43160502571587532396871747107270731912475137535806e-33, /* twoPowerIndex2lo[163] */ } , { 1.55900440023783692922165755589958280324935913085938e+00, /* twoPowerIndex2hi[164] */ 3.78120705335752750188190562589679090842557793649900e-17, /* twoPowerIndex2mi[164] */ 5.94230221045385633407443935898656310894518533675204e-35, /* twoPowerIndex2lo[164] */ } , { 1.56323128997135762929815427924040704965591430664062e+00, /* twoPowerIndex2hi[165] */ 7.48477764559073438896405945862770341857979941287485e-17, /* twoPowerIndex2mi[165] */ 4.94341409405079431354025041618045920322070178828810e-33, /* twoPowerIndex2lo[165] */ } , { 1.56746963996555299658552939945366233587265014648438e+00, /* twoPowerIndex2hi[166] */ -1.03520617688497219882501733748772197895029551157134e-16, /* twoPowerIndex2mi[166] */ 2.69762629340863925921698542881054318260398435611831e-33, /* twoPowerIndex2lo[166] */ } , { 1.57171948129234140267840302840340882539749145507812e+00, /* twoPowerIndex2hi[167] */ -3.34298400468720006928343525035325490394427299333229e-17, /* twoPowerIndex2mi[167] */ -2.50544082539015029477640638701507533908898561837361e-33, /* twoPowerIndex2lo[167] */ } , { 1.57598084510788649659218663146020844578742980957031e+00, /* twoPowerIndex2hi[168] */ -1.01369164712783039807957177429288269249745537889645e-17, /* twoPowerIndex2mi[168] */ 5.43913851556220712785038586461119929989856637311730e-34, /* twoPowerIndex2lo[168] */ } , { 1.58025376265282457843852625956060364842414855957031e+00, /* twoPowerIndex2hi[169] */ -5.16340292955446806158689134977166394905402588028521e-17, /* twoPowerIndex2mi[169] */ -1.98856458425291225043917897550918006467398545517999e-33, /* twoPowerIndex2lo[169] */ } , { 1.58453826525249374945758518151706084609031677246094e+00, /* twoPowerIndex2hi[170] */ -1.93377170345857029303925724496164498303135170130746e-17, /* twoPowerIndex2mi[170] */ -9.89372992541829104414473016298122291261880812772281e-35, /* twoPowerIndex2lo[170] */ } , { 1.58883438431716395022874621645314618945121765136719e+00, /* twoPowerIndex2hi[171] */ -5.99495011882447940051706621855722696087552777078266e-18, /* twoPowerIndex2mi[171] */ 3.40432693814393853234442560718610272389282350802004e-34, /* twoPowerIndex2lo[171] */ } , { 1.59314215134226699888131406623870134353637695312500e+00, /* twoPowerIndex2hi[172] */ -1.00944065423119637216151952902063201612012779755882e-16, /* twoPowerIndex2mi[172] */ 4.60848399034962572477662350836868643017178368092553e-33, /* twoPowerIndex2lo[172] */ } , { 1.59746159790862707339442749798763543367385864257812e+00, /* twoPowerIndex2hi[173] */ 2.48683927962209992068662736190579938975994331984811e-17, /* twoPowerIndex2mi[173] */ -1.50139044932662639156159749783676630723204028336974e-33, /* twoPowerIndex2lo[173] */ } , { 1.60179275568269341434302077686879783868789672851562e+00, /* twoPowerIndex2hi[174] */ -6.05491745352778434252262534739031747865810833110836e-17, /* twoPowerIndex2mi[174] */ -7.86094560028510434095753390665330649540069137640692e-34, /* twoPowerIndex2lo[174] */ } , { 1.60613565641677102924234077363507822155952453613281e+00, /* twoPowerIndex2hi[175] */ -1.03545452880599952590528959597961463687339938363058e-16, /* twoPowerIndex2mi[175] */ 1.51213609096324399449109200330291470931948233371206e-33, /* twoPowerIndex2lo[175] */ } , { 1.61049033194925428347232809755951166152954101562500e+00, /* twoPowerIndex2hi[176] */ 2.47071925697978878522451183466139791436957933053447e-17, /* twoPowerIndex2mi[176] */ 1.06968477888935897586507304780358756526593706030066e-33, /* twoPowerIndex2lo[176] */ } , { 1.61485681420486071324660315440269187092781066894531e+00, /* twoPowerIndex2hi[177] */ -7.31666339912512326264416948227914471406433964055342e-17, /* twoPowerIndex2mi[177] */ -1.01595252547599872757692201057811430532632162793873e-33, /* twoPowerIndex2lo[177] */ } , { 1.61923513519486372835842757922364398837089538574219e+00, /* twoPowerIndex2hi[178] */ 2.09413341542290924068018622986227170935043667427799e-17, /* twoPowerIndex2mi[178] */ 1.27693128474282181836038535044586644559852980247542e-35, /* twoPowerIndex2lo[178] */ } , { 1.62362532701732886764034446969162672758102416992188e+00, /* twoPowerIndex2hi[179] */ -3.58451285141447470995906396542340522908345291030162e-17, /* twoPowerIndex2mi[179] */ 2.01654731462508044313244700316326841947169625164993e-33, /* twoPowerIndex2lo[179] */ } , { 1.62802742185734783397776936908485367894172668457031e+00, /* twoPowerIndex2hi[180] */ -6.71295508470708408629558620522800193343463268850872e-17, /* twoPowerIndex2mi[180] */ 1.86124288813399584090278118171650158752835667500490e-33, /* twoPowerIndex2lo[180] */ } , { 1.63244145198727497181323542463360354304313659667969e+00, /* twoPowerIndex2hi[181] */ 9.85281923042999296413676989512408187295863462194442e-17, /* twoPowerIndex2mi[181] */ 5.29569525404258920205362940337854972086009006345576e-33, /* twoPowerIndex2lo[181] */ } , { 1.63686744976696441078445332095725461840629577636719e+00, /* twoPowerIndex2hi[182] */ 7.69832507131987557450420469117071256581189667741842e-17, /* twoPowerIndex2mi[182] */ 4.09860242950305193227828568999385703476733354155568e-33, /* twoPowerIndex2lo[182] */ } , { 1.64130544764400632118395151337608695030212402343750e+00, /* twoPowerIndex2hi[183] */ -9.24756873764070550805453694792420241616904847542502e-17, /* twoPowerIndex2mi[183] */ -5.66841671716411725558391721762496706416420121341510e-33, /* twoPowerIndex2lo[183] */ } , { 1.64575547815396494577555586147354915738105773925781e+00, /* twoPowerIndex2hi[184] */ -1.01256799136747726037875241569662212149731136230039e-16, /* twoPowerIndex2mi[184] */ -6.73838498803664271467304077725442401461793880458369e-34, /* twoPowerIndex2lo[184] */ } , { 1.65021757392061774183389388781506568193435668945312e+00, /* twoPowerIndex2hi[185] */ 9.13327958872990419009159019732303823956193063692260e-18, /* twoPowerIndex2mi[185] */ 3.31329049471088319516103160150508562888797231765374e-34, /* twoPowerIndex2lo[185] */ } , { 1.65469176765619430113929411163553595542907714843750e+00, /* twoPowerIndex2hi[186] */ 9.64329430319602866138745392638249192962312397541490e-17, /* twoPowerIndex2mi[186] */ -4.32763297888919888932772949708066540512036129088577e-33, /* twoPowerIndex2lo[186] */ } , { 1.65917809216161615815110508265206590294837951660156e+00, /* twoPowerIndex2hi[187] */ -7.27554555082305065439455737740507311483946617362319e-17, /* twoPowerIndex2mi[187] */ 3.10484891456420478411627075503167773401278965655170e-33, /* twoPowerIndex2lo[187] */ } , { 1.66367658032673637613640948984539136290550231933594e+00, /* twoPowerIndex2hi[188] */ 5.89099269671309967045155789620226639428173542900082e-17, /* twoPowerIndex2mi[188] */ 2.37785299276765025315795732233641105960161859663372e-33, /* twoPowerIndex2lo[188] */ } , { 1.66818726513058246396781214571092277765274047851562e+00, /* twoPowerIndex2hi[189] */ 4.26917801957061509059398373181907237215463008872616e-17, /* twoPowerIndex2mi[189] */ -1.29778952562173962775902833320678339532997660143370e-33, /* twoPowerIndex2lo[189] */ } , { 1.67271017964159662838596887013409286737442016601562e+00, /* twoPowerIndex2hi[190] */ -5.47671596459956307615994670748846981852905207478754e-17, /* twoPowerIndex2mi[190] */ -6.83184087311466618520328543794554690349915956941633e-34, /* twoPowerIndex2lo[190] */ } , { 1.67724535701787846875276954961009323596954345703125e+00, /* twoPowerIndex2hi[191] */ 8.30394950995073278534724188038576562525621449256837e-17, /* twoPowerIndex2mi[191] */ -3.67907931420049303621015743180896250029187335304385e-33, /* twoPowerIndex2lo[191] */ } , { 1.68179283050742900407215074665145948529243469238281e+00, /* twoPowerIndex2hi[192] */ 8.19901002058149652012724391042374107310082144797238e-17, /* twoPowerIndex2mi[192] */ 5.10351519472809316392686812760480457926425713861784e-33, /* twoPowerIndex2lo[192] */ } , { 1.68635263344839336774327875900780782103538513183594e+00, /* twoPowerIndex2hi[193] */ -7.18146327835801067471572934253931013376714544778519e-17, /* twoPowerIndex2mi[193] */ 3.52898289014887861077288846281933083915589270719972e-33, /* twoPowerIndex2lo[193] */ } , { 1.69092479926930527867057207913603633642196655273438e+00, /* twoPowerIndex2hi[194] */ -9.66967147439488016589832627855454450790922345010565e-17, /* twoPowerIndex2mi[194] */ 1.93673800521759096892309246646768463294752053454796e-33, /* twoPowerIndex2lo[194] */ } , { 1.69550936148933262259674847882706671953201293945312e+00, /* twoPowerIndex2hi[195] */ 7.23841687284516664081325689368355266258278971330115e-17, /* twoPowerIndex2mi[195] */ -4.72142878783650889336226782989306533177552216168780e-33, /* twoPowerIndex2lo[195] */ } , { 1.70010635371852347752508194389520213007926940917969e+00, /* twoPowerIndex2hi[196] */ -8.02371937039770024588528464451482959960563128920877e-18, /* twoPowerIndex2mi[196] */ 4.50894675051846528463958043437010583905518288996850e-34, /* twoPowerIndex2lo[196] */ } , { 1.70471580965805125096323990874225273728370666503906e+00, /* twoPowerIndex2hi[197] */ -2.72888328479728156256649817220242427763035044600143e-17, /* twoPowerIndex2mi[197] */ -4.78966969731514783785812327748180984426830295688131e-34, /* twoPowerIndex2lo[197] */ } , { 1.70933776310046292579158944135997444391250610351562e+00, /* twoPowerIndex2hi[198] */ -9.86877945663293107628372224517314496289872901148114e-17, /* twoPowerIndex2mi[198] */ -6.85025222060857007426626094774522285678578778256981e-34, /* twoPowerIndex2lo[198] */ } , { 1.71397224792992597386387387814465910196304321289062e+00, /* twoPowerIndex2hi[199] */ 6.47397510775336706412073988816560535911210776420163e-17, /* twoPowerIndex2mi[199] */ 2.27573149080872552498096897849055426251128097439426e-33, /* twoPowerIndex2lo[199] */ } , { 1.71861929812247793414314855908742174506187438964844e+00, /* twoPowerIndex2hi[200] */ -1.85138041826311098821086356969536380719870481925638e-17, /* twoPowerIndex2mi[200] */ 6.41562962530571009881963439719259893730039269925891e-34, /* twoPowerIndex2lo[200] */ } , { 1.72327894774627399243627223768271505832672119140625e+00, /* twoPowerIndex2hi[201] */ -9.52212380039379996274889157686297699809734122180713e-17, /* twoPowerIndex2mi[201] */ 2.02866645853394952359480765489840261160247275266736e-33, /* twoPowerIndex2lo[201] */ } , { 1.72795123096183766975286744127515703439712524414062e+00, /* twoPowerIndex2hi[202] */ -1.07509818612046424458879695751780763147087565420428e-16, /* twoPowerIndex2mi[202] */ -1.61412967076299755734407780884081362069739071884994e-34, /* twoPowerIndex2lo[202] */ } , { 1.73263618202231106657507098134374246001243591308594e+00, /* twoPowerIndex2hi[203] */ -1.69805107431541549406538664930124317335159068906677e-18, /* twoPowerIndex2mi[203] */ -2.66402312008479346328768862816128097997745127782773e-35, /* twoPowerIndex2lo[203] */ } , { 1.73733383527370621735030908894259482622146606445312e+00, /* twoPowerIndex2hi[204] */ 3.16438929929295694659064288262436215220581330791541e-17, /* twoPowerIndex2mi[204] */ 2.46812086524635182684409036079744664142196277491485e-33, /* twoPowerIndex2lo[204] */ } , { 1.74204422515515644498407255014171823859214782714844e+00, /* twoPowerIndex2hi[205] */ -1.52595911895078879235703824049564298322445354780003e-18, /* twoPowerIndex2mi[205] */ -8.17523608900014455382082672926541929180458870718501e-35, /* twoPowerIndex2lo[205] */ } , { 1.74676738619916904760032139165559783577919006347656e+00, /* twoPowerIndex2hi[206] */ -1.07522904835075145041783457030040618806351398410292e-16, /* twoPowerIndex2mi[206] */ 8.90461808811939147294432800114435837044658194814041e-34, /* twoPowerIndex2lo[206] */ } , { 1.75150335303187820734649449150310829281806945800781e+00, /* twoPowerIndex2hi[207] */ -5.12445042059672465938775283877530577740069995954300e-17, /* twoPowerIndex2mi[207] */ -1.10691385189430357525360305608492620313871007739409e-33, /* twoPowerIndex2lo[207] */ } , { 1.75625216037329945351075366488657891750335693359375e+00, /* twoPowerIndex2hi[208] */ 2.96014069544887330703087179323550026749650613893620e-17, /* twoPowerIndex2mi[208] */ 1.23348227448930022362949427574612725745479960698002e-33, /* twoPowerIndex2lo[208] */ } , { 1.76101384303758390359462282503955066204071044921875e+00, /* twoPowerIndex2hi[209] */ -7.94325312503922771056589226542000745919657831036441e-17, /* twoPowerIndex2mi[209] */ -1.04403750867744833163298565704167076212852668996068e-33, /* twoPowerIndex2lo[209] */ } , { 1.76578843593327272643023206910584121942520141601562e+00, /* twoPowerIndex2hi[210] */ 9.46131501808326786659595799515277320480429557947658e-17, /* twoPowerIndex2mi[210] */ 1.98867486219252293915985766016443087286320281152529e-33, /* twoPowerIndex2lo[210] */ } , { 1.77057597406355471392203071445692330598831176757812e+00, /* twoPowerIndex2hi[211] */ 5.96179451004055584766584184178983874814969039896383e-17, /* twoPowerIndex2mi[211] */ 2.25217410358405709867930003709735313542997798337535e-33, /* twoPowerIndex2lo[211] */ } , { 1.77537649252652118825324123463360592722892761230469e+00, /* twoPowerIndex2hi[212] */ 6.42973179655657203395602172161574258202382771355994e-17, /* twoPowerIndex2mi[212] */ -3.05903038196122316059732104267589318807211463677414e-33, /* twoPowerIndex2lo[212] */ } , { 1.78019002651542446180599199578864499926567077636719e+00, /* twoPowerIndex2hi[213] */ -5.28462728909161736516945207213792976192807478608583e-17, /* twoPowerIndex2mi[213] */ -8.77486215604854126189970187247268663448961942332927e-34, /* twoPowerIndex2lo[213] */ } , { 1.78501661131893496481382044294150546193122863769531e+00, /* twoPowerIndex2hi[214] */ 1.53304001210313138183913113480738748539708581780129e-17, /* twoPowerIndex2mi[214] */ 5.51980832680936081410203965527728574047454546736523e-34, /* twoPowerIndex2lo[214] */ } , { 1.78985628232140103754943538660882040858268737792969e+00, /* twoPowerIndex2hi[215] */ -4.15435466068335038727327499723453563952032099924980e-17, /* twoPowerIndex2mi[215] */ 6.11515946295708221189397364669019622476882042095523e-35, /* twoPowerIndex2lo[215] */ } , { 1.79470907500310716820024481421569362282752990722656e+00, /* twoPowerIndex2hi[216] */ 1.82274584279120867697625715862678123206602563412216e-17, /* twoPowerIndex2mi[216] */ 1.42176433874694971095041068746172287320972847635154e-33, /* twoPowerIndex2lo[216] */ } , { 1.79957502494053511732374772691400721669197082519531e+00, /* twoPowerIndex2hi[217] */ -2.52688923335889795224096886042608995683536858583738e-17, /* twoPowerIndex2mi[217] */ 1.44522688753239826542123866099361934109399231372306e-33, /* twoPowerIndex2lo[217] */ } , { 1.80445416780662393207990135124418884515762329101562e+00, /* twoPowerIndex2hi[218] */ -5.17722240879331788327618111907586559317876939907178e-17, /* twoPowerIndex2mi[218] */ -3.23967570721982535791533521021663088881060430531174e-34, /* twoPowerIndex2lo[218] */ } , { 1.80934653937103195886493267607875168323516845703125e+00, /* twoPowerIndex2hi[219] */ -9.03264140245002968190484653709605673138415565955571e-17, /* twoPowerIndex2mi[219] */ -1.12019787608951203920985462435640152244227583657230e-33, /* twoPowerIndex2lo[219] */ } , { 1.81425217550039885594514998956583440303802490234375e+00, /* twoPowerIndex2hi[220] */ -9.96953153892034881983229632097342495877571562964276e-17, /* twoPowerIndex2mi[220] */ -5.86224914377491774994695195482808191103744720514440e-33, /* twoPowerIndex2lo[220] */ } , { 1.81917111215860849426917411619797348976135253906250e+00, /* twoPowerIndex2hi[221] */ 7.40267690114583888997332201107850297829481646698022e-17, /* twoPowerIndex2mi[221] */ -4.89675321347547219472440109911293831971254102711009e-33, /* twoPowerIndex2lo[221] */ } , { 1.82410338540705341259240412910003215074539184570312e+00, /* twoPowerIndex2hi[222] */ -1.01596278622770830649733223898080028655802910502598e-16, /* twoPowerIndex2mi[222] */ 4.53871114850207724131140654395208935819981398894467e-34, /* twoPowerIndex2lo[222] */ } , { 1.82904903140489727420003873703535646200180053710938e+00, /* twoPowerIndex2hi[223] */ 6.88919290883569563696897029598215713285030905189271e-17, /* twoPowerIndex2mi[223] */ 3.87648962331697016857882013569485482520267614310710e-33, /* twoPowerIndex2lo[223] */ } , { 1.83400808640934243065601094713201746344566345214844e+00, /* twoPowerIndex2hi[224] */ 3.28310722424562720351405816760294702167288526703081e-17, /* twoPowerIndex2mi[224] */ -6.42508934795304248095271046696049734574532048424330e-34, /* twoPowerIndex2lo[224] */ } , { 1.83898058677589371079363900207681581377983093261719e+00, /* twoPowerIndex2hi[225] */ 6.91896974027251194233158929971981865763925505317250e-18, /* twoPowerIndex2mi[225] */ 8.15206232016177839312277544008762312093325605950960e-35, /* twoPowerIndex2lo[225] */ } , { 1.84396656895862598446456104284152388572692871093750e+00, /* twoPowerIndex2hi[226] */ -5.93974202694996455028254223192510163033537942157969e-17, /* twoPowerIndex2mi[226] */ -1.48362556800548453304632576499694052761575815131607e-33, /* twoPowerIndex2lo[226] */ } , { 1.84896606951045083810925007128389552235603332519531e+00, /* twoPowerIndex2hi[227] */ 9.02758044626108928815754968893534423196214872648843e-17, /* twoPowerIndex2mi[227] */ 3.66962637780002837100397510992219276952101768763175e-33, /* twoPowerIndex2lo[227] */ } , { 1.85397912508338547077357816306175664067268371582031e+00, /* twoPowerIndex2hi[228] */ 9.76188749072759353840331670682321086158335176176729e-17, /* twoPowerIndex2mi[228] */ 4.61481577205566482307976345637533484680898060020057e-33, /* twoPowerIndex2lo[228] */ } , { 1.85900577242882047990235605539055541157722473144531e+00, /* twoPowerIndex2hi[229] */ -9.52870546198994068663058182042478513584534522643660e-17, /* twoPowerIndex2mi[229] */ -3.18046180210394448463313927892837392059725438136108e-33, /* twoPowerIndex2lo[229] */ } , { 1.86404604839778897940050228498876094818115234375000e+00, /* twoPowerIndex2hi[230] */ 6.54091268062057171050111940599879934004515525942762e-17, /* twoPowerIndex2mi[230] */ -5.47450840369931668676283513826314309520282956450186e-33, /* twoPowerIndex2lo[230] */ } , { 1.86909998994123860427407635143026709556579589843750e+00, /* twoPowerIndex2hi[231] */ -9.93850521425506708290021081667794428086842804782007e-17, /* twoPowerIndex2mi[231] */ 2.01996583148501250135094900859003261161238917514540e-33, /* twoPowerIndex2lo[231] */ } , { 1.87416763411029996255763307999586686491966247558594e+00, /* twoPowerIndex2hi[232] */ -6.12276341300414256163658402373731493255704994623650e-17, /* twoPowerIndex2mi[232] */ 5.28588559402507397372575432425046614667899080733482e-33, /* twoPowerIndex2lo[232] */ } , { 1.87924901805656019426749026024481281638145446777344e+00, /* twoPowerIndex2hi[233] */ -1.62263155578358447798931987572415275848558528109557e-17, /* twoPowerIndex2mi[233] */ 9.40055036844163004544204966638003638688147648501487e-34, /* twoPowerIndex2lo[233] */ } , { 1.88434417903233453195355195930460467934608459472656e+00, /* twoPowerIndex2hi[234] */ -8.22659312553371090551493304223608514657111026374334e-17, /* twoPowerIndex2mi[234] */ -5.31443494561164967610191190946004049645366520601710e-33, /* twoPowerIndex2lo[234] */ } , { 1.88945315439093919351876138534862548112869262695312e+00, /* twoPowerIndex2hi[235] */ -9.00516828505912671790149612791654138076908000967551e-17, /* twoPowerIndex2mi[235] */ 4.76098007513107821420081485428133742005900358438723e-33, /* twoPowerIndex2lo[235] */ } , { 1.89457598158696560730618330126162618398666381835938e+00, /* twoPowerIndex2hi[236] */ 3.40340353521652967060147928999507962708632290832738e-17, /* twoPowerIndex2mi[236] */ 1.72475099549343225430579028439403217279441019556785e-33, /* twoPowerIndex2lo[236] */ } , { 1.89971269817655530331990121339913457632064819335938e+00, /* twoPowerIndex2hi[237] */ -3.85973976937851432307271295292856183526693379019865e-17, /* twoPowerIndex2mi[237] */ 8.54252722580247976290671190391307753063293836872304e-34, /* twoPowerIndex2lo[237] */ } , { 1.90486334181767413831209978525293990969657897949219e+00, /* twoPowerIndex2hi[238] */ 6.53385751471827862894642310249671518446001303214235e-17, /* twoPowerIndex2mi[238] */ -4.74812640133837504404873359767131188363298319607458e-33, /* twoPowerIndex2lo[238] */ } , { 1.91002795027038985153922112658619880676269531250000e+00, /* twoPowerIndex2hi[239] */ -5.90968800674406023685750489615373077589386094387626e-17, /* twoPowerIndex2mi[239] */ 1.83214657152134469549465915038517283323758050529819e-33, /* twoPowerIndex2lo[239] */ } , { 1.91520656139714740007207183225546032190322875976562e+00, /* twoPowerIndex2hi[240] */ -1.06199460561959626376283195555328606320260702029334e-16, /* twoPowerIndex2mi[240] */ -3.05776975679132548538006102719337626149343902119718e-33, /* twoPowerIndex2lo[240] */ } , { 1.92039921316304740273039897147100418806076049804688e+00, /* twoPowerIndex2hi[241] */ 7.11668154063031418621133275838618151517201202262489e-17, /* twoPowerIndex2mi[241] */ -4.82668562559464286199698217483008854466173164582353e-33, /* twoPowerIndex2lo[241] */ } , { 1.92560594363612502810667592711979523301124572753906e+00, /* twoPowerIndex2hi[242] */ -9.91496376969374092749319194821921356369769258703312e-17, /* twoPowerIndex2mi[242] */ -3.22132452692376239436249260443042416373307145576578e-33, /* twoPowerIndex2lo[242] */ } , { 1.93082679098762710623304883483797311782836914062500e+00, /* twoPowerIndex2hi[243] */ 6.16714970616910955283771024520843382562539181719792e-17, /* twoPowerIndex2mi[243] */ 9.20187048243808720717080369504670367609474211649437e-34, /* twoPowerIndex2lo[243] */ } , { 1.93606179349229434727419629780342802405357360839844e+00, /* twoPowerIndex2hi[244] */ 1.03323859606763257447769151803649788699571393339738e-16, /* twoPowerIndex2mi[244] */ 6.05301367682062275405664830597304146844867569493449e-33, /* twoPowerIndex2lo[244] */ } , { 1.94131098952864045159572015109006315469741821289062e+00, /* twoPowerIndex2hi[245] */ -6.63802989162148798984357531389107673024275126550005e-17, /* twoPowerIndex2mi[245] */ -3.84589208047361365184351178085214844173829595098042e-33, /* twoPowerIndex2lo[245] */ } , { 1.94657441757923321823398055130382999777793884277344e+00, /* twoPowerIndex2hi[246] */ 6.81102234953387718436390433460451017868586507937427e-17, /* twoPowerIndex2mi[246] */ 4.00132790381313470943337752360672827257448941559276e-33, /* twoPowerIndex2lo[246] */ } , { 1.95185211623097831790119016659446060657501220703125e+00, /* twoPowerIndex2hi[247] */ -2.19901696997935108602521778603883611528020250783493e-17, /* twoPowerIndex2mi[247] */ 2.41215894734058348862039105065931631090122373298988e-34, /* twoPowerIndex2lo[247] */ } , { 1.95714412417540017941064434126019477844238281250000e+00, /* twoPowerIndex2hi[248] */ 8.96076779103666776760155050762912042076490756639488e-17, /* twoPowerIndex2mi[248] */ -9.63267661361827588458686334472185443533033181828620e-34, /* twoPowerIndex2lo[248] */ } , { 1.96245048020892731699404976097866892814636230468750e+00, /* twoPowerIndex2hi[249] */ 1.09768440009135469492530703072443773737110713005320e-16, /* twoPowerIndex2mi[249] */ 2.22935494198572795986893315761753148481994138005007e-33, /* twoPowerIndex2lo[249] */ } , { 1.96777122323317588126201371778734028339385986328125e+00, /* twoPowerIndex2hi[250] */ -1.03149280115311315108805777837120874149571671620808e-16, /* twoPowerIndex2mi[250] */ 4.19326590499492480228618720550851028485481027931040e-33, /* twoPowerIndex2lo[250] */ } , { 1.97310639225523432038755800022045150399208068847656e+00, /* twoPowerIndex2hi[251] */ -7.45161786395603748608029025975637403620995816486529e-18, /* twoPowerIndex2mi[251] */ -5.91616296363099671353015573028401106053667494395426e-34, /* twoPowerIndex2lo[251] */ } , { 1.97845602638795092786949680885300040245056152343750e+00, /* twoPowerIndex2hi[252] */ 4.03887531092781665749784154795462589642365074083484e-17, /* twoPowerIndex2mi[252] */ 3.58120371667786223934924900740488031476290303118010e-34, /* twoPowerIndex2lo[252] */ } , { 1.98382016485021939189437034656293690204620361328125e+00, /* twoPowerIndex2hi[253] */ -2.20345441239106265715861919875136617618161805878720e-17, /* twoPowerIndex2mi[253] */ 1.30241601884067628906145032934477933888241617967293e-33, /* twoPowerIndex2lo[253] */ } , { 1.98919884696726634309982273407513275742530822753906e+00, /* twoPowerIndex2hi[254] */ 8.20513263836919941553211296435337826280802285479647e-18, /* twoPowerIndex2mi[254] */ 4.55959041696793749483275697431418566719882990414142e-34, /* twoPowerIndex2lo[254] */ } , { 1.99459211217094023460560947569319978356361389160156e+00, /* twoPowerIndex2hi[255] */ 1.79097103520026450854305804947681496082855314328245e-17, /* twoPowerIndex2mi[255] */ 3.33253733318286084576384624967661010994920841819939e-34, /* twoPowerIndex2lo[255] */ } }; interval-3.2.0/src/crlibm/rem_pio2_accurate.c0000644000000000000000000001553213316017127017263 0ustar 00000000000000/* * rem_pio2, used in correctly rounded trigonometric functions * * Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat, * Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter, * and Jean-Michel Muller * * Author: Catherine Daramy, David Defour, Florent de Dinechin * * This file is part of crlibm, the correctly rounded mathematical library, * which has been developed by the Arénaire project at École normale supérieure * de Lyon. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * This file include functions to compute y=x-N*pi/2 and return the last two bits of N * in order to know which quadrant we are considering. * * We use an scs representation to compute it by Payne and Hanek methods. For more information * you can read K. C. Ng research report from Sun Microsystems: * "Argument reduction for huge argument: Good to the last bit" (July 13, 1992) * */ #include "rem_pio2_accurate.h" /** * Case X_IND = -1: * 0 * 2 ^ * X : <> |--| |--| |--| 0 0 0 0 0 * 2/Pi : <> |--| |--| |--| |--| ..... * * Case X_IND = 0: * 0 * 2 ^ * X : |--| <> |--| |--| 0 0 0 0 0 * 2/Pi : <> |--| |--| |--| |--| ..... * * Case X_IND = 1: * 0 * 2 ^ * X : |--| |--| <> |--| |--| 0 0 0 0 0 * 2/Pi : <> |--| |--| |--| |--| ..... * * Case ... * * Step 1: * * Compute r = X . 2/Pi where: * - r[0] hold the integer part. (if x>0 or the once complement integer part if x<0 ) * - r[1] to r[SCS_NB_WORDS+2] hold the reduced part * the 3 extra 30 bits are here to prevent possible * cancellation due to a number x too close to a * multiple of Pi/2. * * Step 2: * Compute result = (r[1] ... r[SCS_NB_WORDS]) . Pi/2. * * description of local variables : * - ind : where to start multiplying into 2opi table * */ /* TODO OPTIM better 64-bit multiplication, see in scs_mult */ int rem_pio2_scs(scs_ptr result, const scs_ptr x){ uint64_t r[SCS_NB_WORDS+3], tmp; unsigned int N; /* result r[0],...,r[10] could store till 300 bits of precision */ /* that is really enough for computing the reduced argument */ int sign, i, j, ind; int *two_over_pi_pt; if ((X_EXP != 1)||(X_IND < -1)){ scs_set(result, x); return 0; } /* Compute the product |x| * 2/Pi */ if ((X_IND == -1)){ /* In this case we consider number between ]-1,+1[ */ /* we may use simpler algorithm such as Cody And Waite */ r[0] = 0; r[1] = 0; r[2] = (uint64_t)(two_over_pi[0]) * X_HW[0]; r[3] = ((uint64_t)(two_over_pi[0]) * X_HW[1] +(uint64_t)(two_over_pi[1]) * X_HW[0]); if(X_HW[2] == 0){ for(i=4; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-3]) * X_HW[1] +(uint64_t)(two_over_pi[i-2]) * X_HW[0]); }}else { for(i=4; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-4]) * X_HW[2] +(uint64_t)(two_over_pi[i-3]) * X_HW[1] +(uint64_t)(two_over_pi[i-2]) * X_HW[0]); } } }else { if (X_IND == 0){ r[0] = 0; r[1] = (uint64_t)(two_over_pi[0]) * X_HW[0]; r[2] = ((uint64_t)(two_over_pi[0]) * X_HW[1] +(uint64_t)(two_over_pi[1]) * X_HW[0]); if(X_HW[2] == 0){ for(i=3; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-2]) * X_HW[1] +(uint64_t)(two_over_pi[i-1]) * X_HW[0]); }}else { for(i=3; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-3]) * X_HW[2] +(uint64_t)(two_over_pi[i-2]) * X_HW[1] +(uint64_t)(two_over_pi[i-1]) * X_HW[0]); }} }else { if (X_IND == 1){ r[0] = (uint64_t)(two_over_pi[0]) * X_HW[0]; r[1] = ((uint64_t)(two_over_pi[0]) * X_HW[1] +(uint64_t)(two_over_pi[1]) * X_HW[0]); if(X_HW[2] == 0){ for(i=2; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-1]) * X_HW[1] +(uint64_t)(two_over_pi[ i ]) * X_HW[0]); }}else { for(i=2; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-2]) * X_HW[2] +(uint64_t)(two_over_pi[i-1]) * X_HW[1] +(uint64_t)(two_over_pi[ i ]) * X_HW[0]); }} }else { if (X_IND == 2){ r[0] = ((uint64_t)(two_over_pi[0]) * X_HW[1] +(uint64_t)(two_over_pi[1]) * X_HW[0]); if(X_HW[2] == 0){ for(i=1; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[ i ]) * X_HW[1] +(uint64_t)(two_over_pi[i+1]) * X_HW[0]); }}else { for(i=1; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-1]) * X_HW[2] +(uint64_t)(two_over_pi[ i ]) * X_HW[1] +(uint64_t)(two_over_pi[i+1]) * X_HW[0]); }} }else { ind = (X_IND - 3); two_over_pi_pt = (int*)&(two_over_pi[ind]); if(X_HW[2] == 0){ for(i=0; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi_pt[i+1]) * X_HW[1] +(uint64_t)(two_over_pi_pt[i+2]) * X_HW[0]); }}else { for(i=0; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi_pt[ i ]) * X_HW[2] +(uint64_t)(two_over_pi_pt[i+1]) * X_HW[1] +(uint64_t)(two_over_pi_pt[i+2]) * X_HW[0]); } } } } } } /* Carry propagate */ r[SCS_NB_WORDS+1] += r[SCS_NB_WORDS+2]>>30; for(i=(SCS_NB_WORDS+1); i>0; i--) {tmp=r[i]>>30; r[i-1] += tmp; r[i] -= (tmp<<30);} /* The integer part is in r[0] */ N = (unsigned int)(r[0]); #if 0 printf("r[0] = %d\n", N); #endif /* test if the reduced part is bigger than Pi/4 */ if (r[1] > (uint64_t)(SCS_RADIX)/2){ N += 1; sign = -1; for(i=1; i<(SCS_NB_WORDS+3); i++) { r[i]=((~(unsigned int)(r[i])) & 0x3fffffff);} } else sign = 1; /* Now we get the reduce argument and check for possible * cancellation By Kahan algorithm we will have at most 2 digits * of cancellations r[1] and r[2] in the worst case. */ if (r[1] == 0) if (r[2] == 0) i = 3; else i = 2; else i = 1; for(j=0; j
=G$i)B!$S48HWs_ ;"Lk'#?aM]slemJ_`/7mX)q/]>NImq!ZN<][?Fc+edG^?Q_:G9t@ICg^BZkB>Ii.-_'__>P E)F.MJMZ^cAFf>R00A$0!O^6&6*r`Yq-.*.b%&IYm:)WYC$6)o6J76.Qs5=ri@ >H/;9V9]2#*fu]hnakWBO^:'#W^'p)dW*HIk[D0m%Opg9V#^l*dh!sdR4,CD-b^Sg&_@[$' X3Ej$c(=[Sgt3mfPD.r-+sF6$@$U,o&af88)kbgj^?a,:J2#daY2'KVF,1iF=;/,7%G_uNH N/mh^(O]pYb+Lkas4/L=$+)KZ+jD9PKQ)e4(e2.V9pO;]i!;ZD>)dch]I-of`/=(!p#ZBf) 9=X]knMPA[U?>q0.R;Q'iDSZp'*RJ.tRr@ -mgcc8IQO+X_+;81[r;Z$;;;9otiSE1Ls$e%?JKu?I"@?\#"+n?3d$R34qN,D4;6:[g8g>" -7:Qp#e6XtZ8$nD8G,0j_,*GOYd[;U_)OP7m=t[pMb%!5s9kP,2eD>C0SknP!)=7ob3bc)F Du*HdR8'SXl4k5&:8q6ojh;Rb (6fGQ/AeYX:>15Ku,\[l8HTt)+)?j1"dP$:EN#72-nc!eo*J)Gruj:f%,UHU=*cJg79k";6 8;`FrL=F]4nP(m.T2)`p[iZgHD0I]]Tf^`T(t6*1g4bREao9qAgWD:T;mF]j/f`>7fAH>ur]flD!rfuR;7p3HL8eW>_(]+/#!qa #,6l#(KII3oYf&1(6I=dL%`<8X6P)RRZ",a37H!lXR3[p9C(sNb7i96XUh(IaOg.AsRg!6U EYt^Zic$!;iUZ;*njJZf3_-0JAt-\_[jXjHN2J0uZG`^o9(LcD/kbd-__0/S"N`AlZUE+s9 [dP$2U-;b\8Vp%q9hP>a&*+.:G^f!5#:eC"$Y(R"URIkZpbKo&4[l(1n5dm_+7I'N@.@s[) FIg;Y8d#D%/gOW\oT4'hM9P[7*kk<7PPY8@oucSI;;tdeYR1i=#K)Z?WVAY[P\C+jbl gbeErH1=`urtAQdSqT4qIUnB`^*6MQLUN#'sSD;2N'^N!K0-,XcYG;[ik?$AHdF^U'N7DiGssOD^%e]n(f;\35=p@p:m#GNp4bA;j&j;[BcNoS mWY!dL.@EfR5S!.AU-IDQ"AW\?^YLdVI>s+H+n'aB6gK/=HnRY-pAV=OR]&Yg+JG_Bf]jgV eLI+S#C(JQE-sF#3dBr'?#/NY%ubZ^ThT:-Gd#"KE5IG&#GTD[dBQ-j1&uRId=O^U_+)D&7 e@`^2Mcos1rY:-NINc6pZ>b&4R5s`c9!0juaF^T^#a%]Y?&BF*u@(>n4coH-gY=%nG)j]gk ZEFT#QFeogq8A(L@%LM>Fb]uP'E%ceLdNd'^5J;s=f-\p`,?:Tq7q#4?`BTE9fQo^Dl@%/B.Cp(aAT\N.no?MG^\nj&A^3EB6!IptZp"CibUKctGeoSfPagcAtin4ic 4V+64,bOHKf7a>j\RA42?;nhrp-kk6-PW7)nX*_T(%!$oRRbEIuHM36bk@-%uT-)A2q)-K` b9Ve\R"UnlMEScl?Pd?[2+KuV0`@bXO\r:\'?5?)W2Ph:HQu`tZ(c)e6j^cQ"F#I(Cq3Xjr \G@;QeE2fhp-+J`^,M6nDb\p$2^][1q;FGKPk1K1eE[V7ZnTi." @,oRIo"c!5:@6GTQCBi:jNR;BIW-a/mT&4qB85iOs?\X;Mie)0SbCeZOOfg?jI@]1PF19Uk mlk,FV7t.6-B,U6'L,iG:W3:sg@0fQIt&rB7.14.ZQU=f[E4Y19oqUJuR[XGhF"%Ihpa`j68ZN&nDP.cFUtQ#\gH_ZrWL@>'ibS7dt1$IpF6bn=oY!'cb-Re,\PF 9.9co[/PEp^'\q7hsTrSQrR'.2/d>%i/4;*7-=q!]q=UK0"3QI5j*TQL5O5[H(%t[2 [#SAC=KK,88Z.gWr=PtFBd*`SZN,-W$GF!9h>F5/$0'1=>]f)S&$lAIQnRF#IgY!Xq[k R2I7@Q>t356T\pCn"!tPGnL3A6OAT%6M(Q6P!`.R@,)JF-8`Xe;O1uil(b%rL6E](mV:4q0 r@Xo\',b70BrDO=e_SDd<_*gl?sLY$s&G>RS-]G3EeJaMFQ&`E*j(u^H(I8]:?J,?#/hQYP &R.)+1';lWoXYG#lf>Rl=trnu+`BJENU?05Bm#'t-$/g"W!7Df)V`3JKG&U>(ummV4DdG=L oRiN-i'@-0C;.#K!S85Ra*nOiQ+.c6`W*0,$E.`ZMg(dlYo%A\eCp4j%7KCjN[@>HIi:pC\ a2Q5.)/]N%U)rgd>NH+$t3%CTa&#%RXnp8!lCBlBO$8G%T*akj7aD2)_RagqHEG@M[2m.>* .e=TjCcW@uk_a=u#,&Ue6O68h[iDQ,)g9`o%?cE\#0QR1OR$^Kh?LF1`I\qE<%[VJA2O;"CPa>Z&jFc5l70dm_U[/,"=h 8&S!:3_t\kR1KJ1KYsp1]>s5-/#P%ecchi29g*oH]gCaR(Bg5Ps5@adZ>QQ**2`$(K^e6dT >[sjCDM'&[Xc&s+n7r,6+iUO!7D)hogh['h+U8!)K(NEhluG,h[l^C-41',lXEI**S \)sa"SbDJ%!k#=HTW9pRXf5XMo323`(0X+Y1(Iq"G+4;nJfs"85%-qpcem:p;hU,0:C#dQo bJ`eicE[4^3)qrCa"u)7rL)UO*)\"t>QTbP>4qsDJnbTLPj@QoZKBQ ^W,Nj^[@"Ui1aogo3%&(folH1XG8k\Qo;t%kD&-HmVNJ[d4_LZ!RcXPV9:X,$1i#)H_VW)_0>9LT Bf7.gDr'`Ln`rtT`"%?FZ`GAmMo$4?5d)ORO`oRJ&SI#?1eZEZla"7_?)31f F/=,#.7VlX5'P:2_'2^=q(N=5D(ab"FcFO+ad#Ao>V&@XZ>DCcfJs?gBh&[F/ON20[a)rP' %3dlYFG2D@8$%)9>pWB`kQ]C*8*e+AS:E_2mDq.981D0`S;#DWb+(.MKK*@%iqJt4c\&$NK ;^n'oSq=:2H,!`;i:TH"HuM"4&`7D8J1.!\aDW9R)s`De,;R3$Oq_j5DCC!+3^9Ij60)4TS *HC8gL1]SOle_8BO>seBFgidM0G(n\6J4"CPenW()MX"u:#)96)AoF&C0"b=a]p:KaSCuMqfN5H6#,l^#?#8-[IolT! =:"/HnKJ37Aqb']:/p:V9nlbULKIJn#<65t.ZK(&kY@\-=M9\*:i%f#D[%mb2lKPK%.DL_P $'r3=\0UY!*M]H6pt!&1qeH,^j643B@!EE7'uj;eXfS(T$RA-=pp5n#WdSa!mjB2g.YO-I3 ,MKY0jAM;5L6hYuSD!*RN?<>.J0)3%ca9,uIAMd3Z&%%C01=I9Q8W]4/,Kh5K&([p*\TX1] :dAPrM]bdTo#b;ft-"e^d[4f%++iL1HRkD*cYTgKgr:4m4er&2St6 @8q'9"opJZ[7XE3inciX?;4*mh<%=>mn/848u/Kl@Qd^K?mFI.L4*&X1p=3c/(XC_jThi7D<'f\MM3Q6@Z&NItn]"n4^2!+c;0PZ]Ue@X]b/<[j0 PEe^esLL>')i-C)kCX5h'@?Y7-^iK_YSBn90:U>p^"u]W`2d-tUce*2hQnSbA5m.(^>"&PR b-0/l\jn#b!q9sEose1s6JHjX7eT+$e[o@(5WV=KJo.hu*_G*=8n>SFLi\(FA 2[:8Uf_/N;`Yr3>NNNZ?<(QNOr\H:fLH<9*AqoC<)c:t6RahkN8*art+s!S(]T@"%TZ?A3'/ZqFEmBT@] iLd;06"DAR0?G6/JdQYk1@tppJKX4$XZ/K'`!+]C4qlL3AN>fKN`"mJ6u>#V]'d s_?:M!\cGk)WjK@0H`nBF\ZBi`GA94A[2Vr:'h\BO83MtA;r,Ya6^?&tej`XXZE*EKDiiYI KmZ#0H[3]D'`lIf>A`-6nodsF?@)tbiAgK*_i'QQlaupeZmnRP7?>&_@d+r#kDiSW%OH'FQ 7>?%H"@-Q$E'ab(Df>Vo?*821.IQ@a3TjFdB6JHQ#6jU8"_Vd6";kP0[X%AG$?2kihJ*YZK W0]4J)7>ebGKl)OD%teYj&>*Br;\ZAb+BT&oi>)BWd9Wk8J$k)e]sq5e9R@.$8,@j(UEAM' eL%rg%:!R"o@##M-c:esZ&@-U5+2_2\nD$WLj/,B>Fg%!ZZF4SD+MVeTh>o*2&_%=8NSFn/ lrF&+Z7=QtT[C^'gBo8^"qQEYG$LT"lIlRoPcdYHK=3sPIiKQ.eqcF`^$]_"D#FAG8,<\*1 T/VfF1L7isMa#!2*ClD BcmX:?;-:jECCVKtpap/&#nul$#&MY(1tqFD#8pn95(UJ!' O[Oa0.pE0gsq^C,=!H#UqKkN,N?'iJAI)tBpq1Zj;>dPto,.re?4nR%r8)_Bl.rkJGhnV<\ [BL+G(&GgmHHAi!BLhQ#I4_E"^#adg^G:Eo,QZ=IXEk$%.k=\.^-Mf*_UE%M_^TRG%.rrrd qZr_sG]&:q7g8[-LBfP\h_K6p^C@DXLHB#C0>`)i_gFGALVY'RVoEee3rFKIW"k-m%mFbnb (F"FL=fi8pi(t$9_:hDr=@8'+%:T)]kccF&d]`-=2YHEIYZ9tLNm>5a%p28gLF2Vm$HON0A Z:_O,#DPK9'.-LZ3H)"Eg>R7j_%*YA*^=6fft.IZNR%@;;+>_tI/BG!G>1W,>([CmGV\IW+ b*A$HaC-[*gPp?-C

ek"gBX2>(MshYLT;m='!8q[-h$6j7SK+bQO`BfI1:@$[:60O>+&Qp1g4L7Zn#$_MNC> 7=qF221PV)8hhk%q6=@2a\uk)br]@ig`l'gm0M1=LH9U!0B/B86s/9K+?q3EK8i,f+&rUi& jM`OE)[8aOpqHA6b=\nl)k5J^bi$EOHg6l?Vs.A.ZbaG%&ArP !'F(T44fr=b)+U/9Bn9bI[QTRSco*I5(IF">]4m3maTV0Yo&-8XF_X/'G@AGf:&GJ^_r?Vu -<'c=[U,,8%25YKXR+'c-:[-\$W:^q&e+'Fr7qh--oj4b[_=U&&.2sJl7^^g9hc]99D(F^I Xk1/`V51Pd''`dr\Uh-Lp=,H"qI*&hQ+#gMh%)h;B8CO^7COQXg s]nX9d'e[VaTY&gUDE&D<8CJJA2U=3/c)Hkrne'qqol_J8`jq*5l8@Tp.$Zn=C6/pcf5H>W [[Zq@>rlJ=3-9T5s@_bTB6Gck,2UB2Y0qaQYo8jBS1;EdgtnKM\3W_O+;^\p;Nah_h=EhjS VHD9dFi4#I)+R#+[&2!Re*WI5SYFFKM&L4r@%]frH=)Ptr;&Ap[hI]`:3]RL(J_&$+i?WO> K>C.B/m%'cT<`+#u"mE$+6KG`d;&hk(*^@_k+!p"GVj6ggP^O$=W[Vf([^SGMc[$Zpkkta^oNmm6H@JrZXbb^K!Xrh%&Cra.Y ]UoEoL"W^KI+YuaV<>oi*?;9F1rsI*Fh36%l)!Z#N5@u[W$YUZ041Q#e@X`?M8f:htFe)g\ ]U=L>T2RIt&L-]S/g3rc:+s3LiJ&-i1($>X (a%03OM+MPi(?NJAV!Y?9h&/ZAEdL1"'!0@?d&2n<4VTK=9acJj2E(:$B8H_j_"UAGU^m8j =X:@LgbA=K-LU%b)p]i@eb\Z"Y&9S5:hZpB0#LJ)/%*03X!X6gT#n7+G9`YQ>P6m>C$-5*Q ^t-mb(l"_:%m^EJ/L_'H\qb,ReBLP60ZOSub7$)N%$8jFd*dj>:t9u%3-'DZ?J[c`Zh "&m3-PCJJ;KjLH3$.&<*%tFe15,=@LFCT/.2%Id;NE8IP:;26*'p/0JZ9JNf_-H>.e9_\_. F.m\/-:a*!(L#_9P4neDq"qAs0@L !8bMrI2bl'=,0bXpL7Q=sEW#ME?%>!"?YOMOt.l*;@s"c5_0CJjZ2)ET81_;Z(1I!]p8oE! *$XpCN+HZ]o,rO.U2?s0!i/Ia;Y;F]u2\U(MB8d3p;ZtR!2q*B^o7o::7!*s\DID**!M0e: Ns7:J#,#uPi;j0;Ka74Q3n(D@F0RfJ[!ptU&)_410Uk1dTff[%4O_ac_&s:CW.eXs&)cjg_ "80l]aKfI50/81:t7dlfaW$&5I:GUe,qslXUWY=%J19m_$1J8L_)k/%hp6!F2-$DRF.K:GWLIomQ8bAKE'W*5IOVpL'7T?]`Utpc\&JlV\0h :9prNa!&kK+nZpT6n7SAg?n=fmW(KM7J'k!NP=1"a%KBEF:h.[oQ`rN91M;X8(<&61lk27O`e-?Fc#[]FJF#DWHPYFG8G 1@Xsm!202$M=F<\d=+[EgWa%Y*GGh8-QpQcE-4rP-qH5,Og<98FmUO&\"*Kf/!'`Usq\PLh hHk)T,Oo8+Ca\\b_+9A_i6$"0V'7Id`l`Rt)Ck=)Jb<<#=?KF2Kc!U>< KVu[;h^TGKuIF>!L+4>T8(mmL@q2KEjcFn[MJr;)rZ5X@E9:Z4"XIH>;)!P0;]Y!bjj")*s (dML"]i*mu#Z[MY6Lt=Kc(4!FM5/?hhEI!O<9pb%:ih@CXcpR+Gd!gPn[P@MVaK[Sr2gl]. A#_WNZn@)rY_6Y%&629,=rf^4]E$T?tD%R?(eR29I\)eKs.Aq?rlJ<%O`Z45`jH=;SBAJLkCKY,nJnbRBX:?AO']AD72T\0DH'cc+5BbqO lU+dBBF`uILG<->/g(P=g+* Y9WGT%^!@58O+bB[0OH$V3?=tZUZ8EMk5U_fr)2m9$DX\Q7l:H-1,]sRI+i(X[0R ItMAWhWV\Kt3iH]nKH[`mp;QegC!LiFY%B.nkJGPJ.of2C@O+OkhK)2+>>,/*dTrQhD)aVa jU$%)4];sZ#X:HEq61,cg>HHIcXS?;-3nLJPgTN`u#+(Lca@`I@BY]Y"Wj]U6%2=L#0!\$E=DMn$a4=MqJ/&AS\W^mNr;R,>9?8 $phfN]?QjRod"%>EITEC90r5=T)b,C2m97[@:O4:]>8T^)B9'#Pf7"qhM[cMinH+?t5JTAX4:I]G&F)T^W4qW"&g)*&EgoTh5g*GAPr^QaY (S)3;M"PF3BY^:Wo#3L=WQqMrAh&?tP?fr)WU#7m%PRlRaC9pK\VKlJ8iEH*&R/Yei(c,/6 d_\pdjpG&4_1W.^NGM2#N0gqLN;0:L[8"qILH24+9s2Ebt`YVqkTc+ad(WP/D`u5i8l3Ioo -5f)V'&fa_>_g74-58aB)`fpQ3]Y<0S&n##'1#/-g.0;S7EX=Wb43r-1#F$2^WY>6bPGKcH =<[pcciZf(?(o*;?_LA(T/Eq(5g)/eK`@m*Ig$B,'X!9(^6mBOf?rGUEgqaK5 .9A7!Rg<:A@4*S+R]A&mk[kgH2YSXb$!B$RZ$p]sq+Ot+1^"bd+`+M`QgPNH=l/(7YF[PH59on"adT7>HQk2Z/M1RJ3Zq]L^guq/%aXk]Ia%!T_&LUW"*%Z] gg'WT]cs!j5etR$i,Fi5$,JT=he9MjiFX?R@V+>k75&%k8Xlm/T5SE#Ns2^RsZ6G]HiiV.D oCDkkm7$*gaba3Lu[(gQson]SXR(7br@W`;['uc0cBUkRiAc`VKW%?Gl,i"/)0.m2U374E[ =tq@Z)YRC3:?^8^OPfJ=Zh'B,S*r0d#$SaV]BV.s5X56o@R$d-3mVV4gA*5V08`UVa#3o%j $h^>:$$5?p*VYo9A=54I_J/9iSc@8/GH@kPC4;ji/&]'OT>li9d>P4Uq;aEYe6&j9!CXKn6 dJn.Z?ZT4_-6(.=diX5;?\b]`ef4^7e6eEhSO`LJQ2/1]q8Fugcm; B$@N)rZA\J_1o-GTWXMq=8\MJ`O,"o@X*#f\b`B5NURHSc7H7fs;VPo-6#=YQ)H>KL%Yl:e 2QA&I4"UTobXX/fbO[7,dZ XQ&aE3EVsY$OnGP9;g^PTOOQ?'6h(al5nBgM,6rar?EHG D%7?Ng86'147mQh\BW<-MKEU7rm82:='+3:`%N?Upa<0JY#&h)uc%>4J3.8#bnX"6m6e?!) ?<&Eu4:fN\p92nhWq'9C0Uk*qq#odRA R&7\d2lU(KOJgZOX7Df@G"U,O(2)MQW;db?2'W?H/nn[e@Mj 5W;jBi2.T%*p5r`K:Gj[SQA2siaO6!he9p0&_<`>;q)0T)Jjgg+YR:a!iDj-;Ol'tZe-Jg4 iBGqXoVC&4-dWbOStVlOSo`j`#7]%4#[Pbu8<9c>9k12(M$:=6Id ]4Ts.mQ5UR\8HZ%lb%,)f'g<@46HRUP3"-i?Q+\1$cDJh7i0-a]MBWhEZB9Jb&VkaDJ0tW_ 0fK#jmP:WoA'XAd<*&4:XX=G6',B>B%_[cFrc'Bg3.nRA__IBcYd/17JUV4(M,=o>S#nnH9Q8Fk^&heX6b03f<+IdKQ3)W($=JX=W=6ibObYh8([E^^JEb\INNdoqL3 q'jnsSBcgUg^^Z5?DE!?8,-ij>+1^/FA&d:OF(BRuT%tW(s#/N894@dKg+7NkO6+Ao[@.YO o&;Cc`3(XEb1adtgVA2G-=USY[08:%X)*sto5=aAg)T%k^%7*JoiTr[^d0:^]3.DNL'Lmn@ *[O4AR1^]c98W0s-q-+l'k3,'MNM?u7@:V$iq-E5&U#kIpr++\,\N'UVDC]?d1:ua^^q_i= GF?I*@%(sNtL537qh]>A*eQ'_c0bC_6bi4d,,]b89,.o71_qeU`DgI>7Vn,1e5X\*KXf]6T @7o8)X4a6_%ZrZ*#M:,c6g3SlJCN=Xk_>X-N7a=A(Yc/S0mMQBL639::&Xjn--O'(f%\Od% /ZkYml?,Xb=_QSPFKc^E6OB$E?02("Rn TTj&I;7Zus7\Fi/AfSdWRRKe^,q#L1VNXoX;+f$YfFC1uPmu1jAW4Ia4(@89"%.i>:),uQP m3j[.Y1F]2+=JZ&Dmjm!Xk%ago;)QWDe\R<,/O6WlIA5LS05U_iR_8!N[s#d7>:21&A!WhR &oDe9fO#r^:FR%p(gR?#,FDY*J"Y=.8qklh,KjW1=d"oOhRu22)l5i'AXLQX^YFNNs<`a]R Vo*(0j59.=j6$oGmVdjf!).BPM,>=bG>15<0EU=7hc=_d>ELJ]Nq8?#6pD,cu0)N7GI0e7L e<>^B%_`:o$Q#CX0)S9(NrG=-5R<%_9gq!/;kZp9HF`(<%&RsjQ0H7O;0(mu2pNH%442lJ` %Hh*b&VDcqGAj[%n$fdB;2C>k24=N;'Z4@J1PTaqn+HXp(\7Z7r!.ak,;?k7@BVQ.^OpK;& &EK\#@T/,K^cDb_[QTDZf*G_`hS'&\;(W)2Z8JP(+-teT+s:D"Q:?,P/[u5(ukI)NEgG!(r I6?3h1JUnai]$6I9ESf6*3]^.*;5H7K2]\J)k;>6s2JpKlV-b1UDYA\>45EmrbVj%* ZG#Uon_->1QUV_[DId@2pmD9a$63G.XBS9(iSI04G4Np/QrF7t+1)@&QA4UIg(1`d^uaDo5 5)&m[>Csj4\8Eg!uV0&T$dX#P!Brs+eo_+j)",(;o=U-'[#,dOYVc*f)Xt9a#g__4DE=D@t VT1CC'k=anN$7IJ`pB:L&@d)uES*6?kcgFY-=?,=K4,!fG\f!i4!9+stM/X*S2oB$.V:;u6;U.;BGjcU3gkhC[1G U7UXZGZc"^$4k+(>"F.RVm7EBr_Q"-LfIYl7Z014s=pgOJs]3"d8A)BV33nAW3><90-X`_@ mf@ooLHKSZ$I>>"L0#?2eeUarqVSi,.&0Ab9Pd3HhanHk@gsRB+ZcS6RVLaG7XaR=Z?3e8j 56'Sh(PY`N+WK/h)/VKQZO]AfB8CO^H`rKso%*V:WnWHpY??mercmq-jb:NNo,MrnllW38nm77cD UslQAG,!3tHWL&bJ5!,RA\,Vh[BSb_38):!t6j>-CH3[&:+S^EkE -?u/D?dmS[]DR!Ucc)E4[[.N_t6-i'5P&ZD`8@r`&'g!6>)%'6isl<">DkqUNneO8Aq;q`3 `*(`(7ADM7AJ$7-m^fjA-fN?g( k=r+\7_s!>D(9m($j71>b&K,S\8j28^s?S!phPgh9$tt8h8^i1o/8^V3_kP^%b7B>aENrj% >i-"OLnP-qK$m9KoP\^8.sH]Wb$#Yco6>K^`Wh1\*aE[**!fbB1-bJYt3SD6W=:^P'56S@h (F^!"p>Ym^ECg\a_QrCdpBKeR!@4!26``Cs^j#!cKM6RB$R-aJXZZE+L#`"#JZc-4\_bfT+ &n7`(X(el7kbq'[U1t9cQ9aCL&.m"e2sMFb-f/3#i7S<2>:OB3]iD8[2V+bb*M:T3(*H=5A@-ldn:QVFjg_fJS957=m\_hZOch6sQ`oKU5f+GcgQ50&bjNlP>WQb%8>*CTBBOh:6BRF0Kt,m$5)7d( _WKL(H\,(heTq_6hj4#%0t+BO?C*AHg^C#&%BHOD-lQCBf#TV'&W2N:u(,pg%1Th.69+SGU X/g"hqIVRtuBTPall22>!pcohG9r<$@0iSG=/KG=X:NTAIZj\Z3ChK@t5!,hs)/;d9$3*<* `fJ*FuE.^t??=iT^Hrhg(08>QLJc->@72900'AluYL3Pf-I2I[B5_21)7T`tGh'Q$Ec!QhS dJa*n('%5R!FR&("h6euNW!6b-X^'?;MZG"J2r4&MdH)Gi34m=&2s`j9nR[c@-.u-mLS7l& E+rI@5\_V4qcgD(#`1/iD(3JAf+s"(u_>0iO0V4`Z!e)3!AG=K74m#rZ>SR+b[WiK^_Y;J5 >/o-"9Uqi`JhUGYa!k3!BL8iiXb?[OgF28csT?ioVn'mP!Sp9*=ZbKYU%\n4SFB?K5'E@pV (RBM.;S3n8G'M/'Vc[ekfU[i\k'UggC9OG7)F./R5]'X6J_9[J=V cYR0MP["Q!&!ZBQ]VSI(2h:9*Fn!=fn3-^5UaZNG-/9=k0+sh4Np6),*##=sfH'pdt_J>Qd T%KqL[7TNMAq=9Wq2Knrf`87DaVX(g[ql1M+B#+gO):BlVa>>;HY-D]orVSaNu%^>6lZ"jQKlSc&CY\s^g6r'[s6JO31ph>ElZa>B>"TW:l -pV%q1i(s^h!VoZ5\5Z:0*WO^#,#Q2=D\8@:>L*5h/:9hI`F@#f[%OjCouGMb&8X/EF(N^? 4P)iS"-)2dps G0h!DWGuXC^fb?B#F!\j0VTfH/Hh(#U\Fi"#)@[d.(L4D;dFE? BCghg@+i8,F3f(e]gq;KWqDjL7g`r#5UqetWpn*^/C^eY(%2W?j'"fE2O(_Y7'jO%.M>,E3Mh85[T237:SkWL$29bBO:1X(%?D_n:qd!Ii!&`:5!Rm KLeIai'`5g*:_o,ET\G6pE9"p+n>j^EYfqj7jE[P6\XDDL$'h(LE(>j?3E5TEhGdRmRhNG/ 99>o"=QV@kX'=!0a6_qF#PiF7kjN>0lpDSKHDlN&42*63:ib&F.bg?=@rdB63OJToC"kapH \?N6?CL>oIiRdIm\P6lZFm!-)e'NfA3J:IBp+Klu2e;V)>3B! lG&M#H?Y=P<3%u@KP>sIgPL%&@$- ):^c7to;o"=RIXQp$.b=Qu2T".3/DJ!9\(P^-(h"id+trh4V(R/*VPT&$K%Qri#0W-RO'q= ^\2s.9&lU$=UC#7,5nhQ6QTV>=i%Ziackp:>R9Zth%hqOag7VlT[B*aFLsL9Og5Dm+e0m"= M@L1![NgIMPDB8!d-"o((D#Is+"\a/FiC]J&Npc&JEF'U*@#//N&L<4fZ_#,P$VCp'i7a$0 U.CUOC2b)23#1<@0ao$q8?:N]:?d/Ggc0o3L"&LZ-asYI.,On\86eR-Z0FOhf%-F F,grHiW[?^DF`ILi;P(j.S/S05imFWjjJ*V"6T2n5]6a40)[^%i 7@sX`rH%hs*j.trpT7Rp[J1fnV$'+E$lNQ7i;8-#D@n$"nrLG[h!$,&FghTL$29O:DeT5o` *hAs58DPQ\l%_&dJJ2,1icX6Ll!(L;W"J(o0JM'8sh>&\->61EVWJ,LRGTN_LW`Y7[b"KW\ N1QV;!)3IKCh2OGh[.MXaN:9&2-kVNV](5YPTdV.-q)POC%:pUc@`Ypuu_Q,AQWMSkl,ce+ N/+so.Nm2%?=`$'D[?`VlK4o3K30;B?HpA 1@Y$t%I&qYlOdOcVjA`dn[pR]nmf"@5k#)$dusN#`3k&=b&YrtV`t>t,)b6%7HQC/T%"TSBngnNE';fbC<1@kOOXDSUI&/7 6P(]qdb4;X=/^%&YZS0Lba\*rnV"(CQbmC2oS5#2Ph).q@Cu[J";lo4Fc?%4^99cEM@jBL!>eOR-)8".> u_X#)1G\MAi4:,h>7[I9kItm=A]u<\8r6fTnscAD*8SKMIs_+_5J[1Us'D; +^N[;T98rP`a2QNbWRh"NDJFkp,9ds'W7L#%"1Q_!Mh?Pfj9Hf%olq1%:H%H;W)#JpFmi>> <)L#JD:*J`VkN[9PAR'&$!iu$'!NT6Do4ceVnEQVc2k.t#;)MK50Q";s^?'aUjAn@=kH&cU .k1S$qS`^mQFe7e7re6tXRLY7Lkh8doVbI\j".RYIrDlM@ZTDj_l5`b:ST`l5&r R?>'n&r'P81mpebdC/H>G2^"">H["um[M5`[1-_nLclZ2@2<[JK]0@TP^G\/`,T%#)9;8pN uc>_*1nh*o,OYcbO^,-3R@J1 SI=HL:'>!I-Gg`mM(p2#7+dST"Sbh3!fStT33*c=!7L:(ZjEurM&l 'nbYsoZ:fVT4tYZ-Js56n"f*L'A7AVmZq0nd?FPnL)rb.1e.AV@.N;SH;W)/1\a[(2L.mT` E,FY@>0^R.pq@S@Yt0]k46R1h,Q%&$]U#&(Xf;atKG.B,2e[+UnSDJW%PL+S.9]bY*C@uI= s2Q#j*SJ//IcIp`0Ve#7cUG,u5+]^)48>9"Gk[Vr\rBBEJrLbtGJP]MV60KY1Ar]a"4[uCS*MbN>Ed^iXU.$N]"0 [pg=lsS;RHVZ*`6)TZ=1l#JbYne h-fXh\N#(Z%X@n+RC9.+:e^r[JsXCI4JeRr^sT!T8`@p.cH1C$pX[5Oc0>1&d"L%re2(<5% ^.qrkfOLuGUTO!M7H#KhP^UQVk@h+EQ3UT&PA="9?N)@qS/hJiUUC_&J@5onES_(J4@dRIU \TdJtiOd^!n6S3$H#H.4]iUfuhOE2Fmre06\'F\Q6-XMT`AG=dgAPC5q1%ki!Pd7p!+7nuJ T+']_,qbF$mCiqKg<0f-`YZNp>7P)34,37u+iG4Y&)ph\.`L?";Xd!m##6Ys:%`J:(3jLh%I7>Qp?ilG11TrPkp'*- 2nD_5PUZ^:7F@*@5Y11iYnR'T7nbq%RPNT%<"LEPRsUYL2O%.0VW`d,m5mlkC>rL_a3rZk)9p\H9*@[iW[[GRTDbOli25bR$T@@%k;JH5#1e&%"D`Y#4 C<#qIoldJUK)@S;&WRtN_/rlh?u.ucZ$&UTfioP0\Y7/*7G.JZ6e=S?? *1O.`nB*NDf0FJ]sm_?iS7XRIZLc#3HT/8e9ZmmDUr8VL7"SMK)@Kb+ab1e[eS_VkC.>hRP Y.ddi1W7JT+?h_0AHTiER=VE1S#cpid#Y6O[I[JTrjN7i12J@uYKb3QLpP+lh@9OE*NZaa$ B%j]nFCnt'"-q0+RT][)sd:1_Md:s]f%7u26C+4'cG5j-r.JrNZ[3QFt>+(OeemQR2jqM.r 5>u.J<+mM5rfYAE#Nu3#pAW1s@?L0h)Z$'Hqg%uk*m+m2/NcEmHa$B28is]d_ror7NYBTG@ e6\,CAgtuTV\ikV_0A`\iI".NnQm0SGb5r7r-+:o*`'iP?R=gHVjI!]B?kd`4m)[@W>NK#@ #^:ohYY?mocC_)rdr1NIa,F7Z`]K""Zp"iKO 408:D>KlQH5_JH+S7%Y8"'!;mX%BGdFNacI4Yn.s.X)ZfFG!\BEHTqE6@SHA8L"#$>M:b`& k4ThoS"->qRjo?1u^`/u7*N89SX#dBKun`$& HT$Q+YMHPgt@eIfeDFqnDt.akmlkf)i?"E=!2]%1r%@l65F5iOK:,V\ /G=B;)+=+UHu-ob-Z_(h%k&+f$%X4Qqf\'J>(RDLrcMXqRLV(gu([Yup/Y>isFB'sV6`nRW K@Bbp5Nj["20+Oh:FWY5t1'Tkg$0o4arWfnUK*?gLdD9WYISJgsk)DS$tTu><]d2MK")_]; P;6_'[]^)8k*'rF&L()BoQlI92pJ4U$!L+5C5ooDU*Y1IV1$Ka!m2f-p*jP;XahSUqeFt]u pQ>V#nc^/A#pAdCp!8$\%ttpA!Z<0,*3_d5OsqSq/7$)@*+?Z,dA@p-iZ=eL)^3BDZ:Q!u9 cNY!,dL8nDn[$a!#C-W)hC[#6*(^XKGhTG[P..uDs\p'OqC!)(r5G;Du@Y[!*(02(4fj)Tn 0R *6"r'o!/s[TQYT0@k5BM$4<-^\bI7JC,rD2)Ecf"dukpNj"rq)C%erC/6PU0^\%:HUV@$VMs_/("j8ON,=@MU7 X2CA,`OrNA;*22:1EoC;`\/sW(+*?%DFP13$haKiiA'M"o@H8KGM^2#9SG4fd^o5F?uE"O'0@A X_>S/;7b;\p0HpDHmg*,Z3t%De]#+fH9P)Tol\@[I=L3!j&fO;m/7*+@VB1]ec.\D$L/*#?M0(A1NSrrE*8iH\%7#6:t=C::$TfQi6sI7n!-9N WZuGUnT[.>[bU"4Z.%']ij+pOa%[7,.\4`e.3<@sfr/Z4J/%?UAtOY$PS+jq8 GacZ;u=7q2J@*s.Jf\f%aH<%Y&Zc3m!W)DT-%9J[VGF+P\R?ZB$j8jWF5hgMQ5Efu@)du8W 6-^*6GO_HS5.7"DWpj\(/FeSXPU+D@@!FceFXdp;kSN8X'3]Wr=X;@'u)I_8=;VN elO.:MnV(SR#iDAY[`)W=PV(sS"cD5OmaVODY)iN=%!%?9(mN]MfQ9jAQEHk!P3%u14 *@AjjM"-=FpO6qE-5tMTKr#bahV-::-HF\Age/P)uVg5X"o90oUQ<@l<61>s>j/]d(Yqe=F_=q7Njd6u1T"?5=`=a+Uc 5l9AI@&bX2rT3b'q-#kL+g(h(9%Tt`i0TD]YTMYqDCKXag31l\/S"hFI3\iZI;!<)+m&YRNSXNq"M9_4D9aql2]LW_Jp%+hAFF=Z+sq`&pK,F(#:3n\9GX`A")+JWp`5 o&&CFXk[KR&OPJp/$D'TY8h\gI!6?0j:P7GQ9iA-Tme'AnR$Z8aZPgQ\%R/.NQM&Fatr`-n \]_ARUbjf+2OHe=d;Au@Ms_Q[(AcN>=m%dbjqHB)@e.&qceT_?5WGL[X2dj*0t)ti"j/C)k 5$a*;Eh`VB'TQME0Rc4-.b$Ts@hk-6Z,%6*:k%L)Kga\pYm9*@JF%!'9)-'`k9r%g'Ufp?,3`"&7D:\(B#3#"_@CrB4@MM"*^jH7:4c.g >NDY8C$IH$c>T)5-(YS^*N[FO>`rL'PXf:)1gH7<5'j4Pll.6rlgc`U20bt_aMqCr;XJ%lr _1E-D9G>'OXrM.94l6u/=3&#Ea.;nD4ndq;H^$75(_.(t>`$PW6/6o$i@OsG_7gpQ%E_rei \&"`oDP&r4ro4<*E3F`iNO*lkKKM`bl0uR\Y$8+;mh#+jZM?e6&ZbVKH&n&)km#\rY/iT+X 12reU:]A6,X`:\%#O#iZ'RP\JNa uB GrQjuJ$1Ro@nA^8'@@.Y_UY6`Znc'mjZSEFe#Juu^)YHVT>V^Ae5SYI'*^5#@?V0n)9O_Gc *.`t:?W_-\!]k$Dct"sm#Nea:%R*eEr*=& $in$2NKKq7_R1,(n:6*$>[^ErD5^?SZ$9Lcd"%$\q'C&D2q*,o);+ic1?m5pjK].ba94PBF 8XP0"IK`kj`tZph6c1AQmGAMooNk&Zrtl>\nX:M:Ea'`NkRU/C.(ROp.S6:N]\.^mMq9i[? VV"L1qDQd?J=0%V`'o'h=G^FD7&'bQO@rUl#XI>f8^X<:"\`R4eAkD'E8Am_dW'P S5q9\NQ5Q")'"r<.@&(fo,4(LD`OB7BCm)_(6:*GID+L`(B_4h`H/I&:.Ct=A[L.XG8kt]g Ng?dme>KX#7l='iGlAtITInbaQIU>r8*3)V:Ff&qONYUB=ZdcG.\jQ%tAuV@\6drZU^qFlL oT'h]Hd_iUlqoIij0lg\L[E^Mi`H!'WkTH8V,Q)";7-A4a(A'8G2C;8P#W,mm!.Zni',E5X aG6a6bNEh#SOp3iO7,Z>FHEF`8i7Ic%@)+JVACE#b5`*Rp5`kb^G8+.^Tn]5_RM'3oF6'uI -`G)2d'QS;h-d"3?V^kA;`2bH3o$k9(9CglT@[TUZG[Lso1sn,(1M#)r9iH`"36h&ZlT.f4 SF\g<;oJDp:UC9#5u7+n!b*"a_5_2^k>BT;7l5oE8Q'Z,.n`e4_`DcXLQQt!*&R=S:Xh6J7 oNAe78$V0oi53sIOdHEEi/X_fB#V2:HU%G=C2-?+5OFH!T$uj)pUk.1TaT-.S]$htQ gHB4,rg$%ZKo7LimsV?shVRqL.DI+('P.aFXQ1@D`V=QVQ'@p'!tOQ4@VicjD3U%WpWVSUD uf9q>6R+JmGB:EL9`bV+,ondj+S- k)kV"lfqNdVJJ=@a0TSd7a&1*`6"TYA:'&"\RYN.j19.*[e%*!Hc"'3S*&[iF.A!Ti-1d?2 GqG5HtOD=EVtM?Iig&G3-C[F@DH1hL8d`goC<\`,BS>M9@3>0-W/?84_IjJF^9WWELLG>S6 ug<'E?m44lck(pYG:fiHR$GQsYjXM2jh>VK!Yo)PmR(%si\kWsp@D+kh(-/0Xu5qu6o=nU, g6bO]2UU"S&j]oUe>IBD2lH6!6!hJ:<`&+TTl+5c\h5P20:7_kZ6!u*aD8._G%8qhhX/dFY ?+Tl,2%tT?A@u"Ki1dn&YHNVW?N]58i@2'r>OHo;DiP%?Uj==k^[@KYZ=UZHq0ntR5@u[2+ b(o5P)?Yq1Y]^L-L1m&_d1prFAa9rf<(Vq/+t#dgT+_C$cP-rlK10qs(*^+g@14\p%C+D@= GmiGd?PRX!QI*'ds[4A+Hi?WdZCV_+lb?\< n+D#_FolTd1P@Ockl&9+eES0a;$c)T,^?MZL7E"F2S9Eg=%)G0_Wa1oZb'XJV6QU,Eq.E0c Wp>/pAT/nMu5QL2o/NT$Tma%5D8K@%Ftkj(!9<6L\n22Vplpc]-Xi#UjBA.EUb.pmYiS!.` .57+q]-N)hmPE']Z,D\:uGa:UgV;aTDi:,ogn"*J/H;AV;0*>)X5sm1k%<8*ghQt^!oG%gr @H]_KFUOn-2MY-*+N4SIl5ETmEmBOq7STiC)T&"oO5]q"8+?FJBf5rUg/1H+;uWVM6tZrp/ h][*C4_]$$.F,F:2.*sV\JMY6"htWW#??hj(MGR_>(8`ND$792Q%d.mQQEY_&C4O5Y*r@IW*4&^A%@"* lj61*`L8pj(rKo)@]NiPCj]2EsH+N+bXft3?:J3>[K#?Ha(?,*J9/U(kLC'$Cr]D1q+*,Hq ]h18Bqe]qOZ^CH&Q`d1<'kXTFDL+,]H`d'P!MMMq>RoneOU6OGn1>eN7EG'qiZO2^W).Gd# .!m2fcicA`FW1TUr-LdH-p=%pG9o+#-O=dLlr6"i'-r`cT%Z%NNO\JO98L9VU3VN/PkF#2@ mcZ_X<%[$%6.#q8f&aLb,I%?ueJu=^*L-s%EXsSlGck4.iK%h5MVKBhI[IRKpN7g3=Zf*3gS5Y'$urQh(DibZU!t[MHd5RhX&o"&:t6*7Yo/T PY&&2hnc,);:QMC@+0d[SC5))C#MLhs:)fpD2`CRtGcXOO>q>'H!Il!eCf#7?5EMn/Ii9HZ +?&^0r;6+"hQZD2nY)p^t4]K=Gb8K*4D.aPRa-Q\T%1+,WtcU4U5A)=`)i`c7mqisEM0$rH 8M1"HZlR.1Lo!SfR,f.5sQ[*?gGTK!0WMWU?TRqTNTXPpfPAS,YoNpPOT#0=>Y[C\0cI*L( q5>(12-#H]>KJ%=i;dc$2Tam3d4bqThjjYnmMfHNkFk4(SI?qs@_::mXh'01Qf:;G]h$e-F 6"k*L8[OI7VgHa:e",uagH01foB;hc@in`drt"+3GDbnnio:F'a5hS+P3eXoapkf_3BK*L7@L:D=0X0"GD"K#",LIcJKU`DRf *X`TfVJ@XdZ94o;#f*5B_C8`DW+ZD$82QN&47"@We0qs$.L8+3[0t+\Li*F<8-Vmp4Cg-.> VS?W1*p%�U19gWIE52F6Y8V@m>CU6-cj)T/X<6b2ce#h+QrEsIMC#&n[Qe*f[Dn3eeq`& p@S5j!gRAV>Ei4q'tMHq?LY8Hn$/L1jutTP4U$63ar5"K6<^\ Y%LIc:dON0=OCcGqs30X#(\c.=cBS;$7`V]PIZsb(]r.C43^[$-T/-%[b%1CNc$kRkV6to, Z&r.\]68WLF6mK_)N7\UNN !-j9P2T&c@_bbXad![&f[>4@^`mehEj.!ZLdlXnK6C`iuP_h`.M27qB/[0)Hb^P6OBnf#0_ ^mO`r/jPVQisX*L#d^)9Rk/faLo./]\%E5OF8pdHqCE/8\()!44K%)EJ>$G#.RW$Cdgr9Th 6k;8ibH50_@c/VF6B?`13_tM;3hf?NXt[L7h;T8:H?L)G.lN9)Pn*b%rESUe3J<%GX/P@*" +JG_Y9b7Ei81_NkB[AV:1o7N>gZ],?>/@KV^)L2]VDN+Bq=_F@\m#?aPi%)knC*4^]i85.) q7*.]Y+ed9-#+0FcK/Z(]:Ie*%a'?qb%+#d6%YX1n_/O.E3,&VjHp8Uj+$#8bfNG;WPt1K$ 1[=8!'Hk74aN.?<)4W!>@RWV)9$"*o8>P<;MnF_!@>8GpL9"0G\W4PV/d>!&aWusCb`U3#l j8bQ`:Vd0%$j7[2hsqELR<@BifHl^p.oN!%.]K09Kki5B/$8g9/QQ>/H&4(r^9E8*N3=tN2 TPmVpHuo:bqpGBQ")o8d?fjca+p1Kf][:Q..EGm$+?0REAqXF*9JgjGmD- 0ZZ1DId_/?hcdJpF;S+ZLZknG-/\8==bufA@:?#:WY\$Hq6dnb%c)d6O* 10<]cr1r\<;fW%3bSc.HA?`_alK&u\5^i:<`%UR:[M5\g3!P.AONp-:d&&`]j4H"o`f):K6 VA?Qqr`%f7d4(4\1#,e9f^TAl`\W0*l;mD-/s'#6cqt%%qeLLi1U&\CT`O#'am9_O2jL(K" `[^TA@#SJonh*Dscrf6X.qfN"%jY1@`B:Ln5GSN,6W,M22s`q([=ctWe>BX;b:K`*H"[*dN +L-YqPK].R-^h=t)lW:XdL9^,E4cNFN\3.@GS:o^QaDtAD3AOjt_J;`g/O3HE5M9m<)NikL4,Lo%?qF#N;HFmJ(C0)> .n%lc)V<-qCf6_d#`Dn2Eg=XDF"q,> MipFpG6u=qs\:$'C!6^`6?5)0Io E'p?@g?3ZZV;o,2s4[%JHQ1NZ-dJ(*0Dd*tZ>7Ld?,NB!Q7@dVB"Zl1/R!+4tA ;@#Y@(m$hPc_WB!9!)b#FKZp:s=]FGm=5`;)Q2K5q)sK@0SfO>X`^BM)0kd@=rf:L1j!,A] \B:G@B_F3CXTgc65=s+i&6IhHhI+LhnRIbu4Lm,,Nt%NS*6]L'OG>%OfZ2HEO`aR?2nMN#o3#2;XV5%.kk.)09d5DC%\:1XV(@0:BdKKs@.Y Yaf:2s`7;m[[jLSZ]\6k+kF@,4paL+#H!Q%n:qGp88!"B ]1=TM:TBD1s*[5-AdjTOimH*9:-bBJ>T8q38L&j;%r=k9+a#D13lC[9sD`cO@YhSCaB`s5q+looEhmF#07ap,@sL 8-[o:f1l.H>Ka0X1!A00PUa3L*ja$ODou:Gj,.U4"troTcB@0H\O4k67.Lk-8o@W3+ J78BYN88f%fK/4\fZiV!c^.a@M%^>N@E#DEd)5#ZKFUi6A3,#7th-2"Y=5d-e(&8\4@D!q@ 8]%V5"3DZ9)s5k>*OV/Iu`mkgttY[[eTmq$QP-CU#e*p`9c$Y=MNCC)0=Bh+-gIg4hMKs%i G-NOju\kBIKE''&6LhFKjC@H,UE-mbF(B*^"$79X7dOrITNl8rf-&edKLWFcG*#C.9G26bT Co5DG7*fLj6O&'W8E1=qmXL"I$B^;"c'b\JB'.UEgl[l^LMc,AeN%<)=GCd3Kbf("Y24$Q- >h?^B\\O&k8gD?;21s1mREE2cR^r%oP%Wto(]HRG\q/TRGW_o6`1jo:GkV*A7^[1VR3Vs^H $3Br#]2DL33Lb7m1cT5"(!GL?N6&S>+AW$YmN#gqP`=9EYUTlLUW/NrM$I*j\lX!UpT,'*) _b(gkJS\`Qk#+>t6ZLBhV`;G88F+U:GY8b6QmI;n'eE6C[_0["9UaCeXf"fQ)#T$)+T?0ne &`;>@G&9ERJ<=rdtnt0G3ibQp:(GmJjD224KG1ko)34,8;[(dsY?RPQnD?s!#mKXbH?qCQ! >]*=hG;h+2-KTu+A>R@Q$d`ONDF^Z:@e['Q7[rpUODD$@mdu!YFE`6Eh-&:.GB<49l'aET9"h.-M$hX^KCBVqlf-a@564-1H;0d(Xlg SfscrF/FMYX6/ln<&FIogGa4\W*%LTP--'G_M\I>-g-KMPoo:LFMX)i&(iHY2 0)%-E]-&"K&[,'#Uf#,"PB&8(Xn[W^93Eb:>20_S+"qj=I+(G]^&1]"l(Hot=pe[SDN5_YP`I"+1XODHSRKD_p*I(FXY27.ael#\%P>)o\_ s29=(LRcFlr.g5ji,seZ/WjFd#G?*_(JF^r&r'4qKMPAAbPVPe3;!fKrVoao$0b]u7"$HC& WhAWN!A<4SUPL^dSZ>>\82C@C9r(A"Xg,Fc_[\@?_Gl(LBqrTDrZeLG-fM6o*=lF$=ZpH4) JlercsrLQrO>mCP:>L^ZO;JDf5H%rEcEo#QkO)WG=AW:"If8'*s:Z@?C7h7NE+t7,lTr`)8 H/NQ,IiUmifPMdn;KP%cJ=<@O5+-.9>O[UCt[9kH2,UuH5OSkeItWW`$GVJ@ttn`iMcPt.[ j=&'P&4k/\9]\[S9lh19^Y#fDhqZV_nA$T6RepBi_eSDTtD:\T<`oV9Q?#J8@`THi?^0bg1 r!!B0K>LfaDl9)PgtHs3fM6%iTub_\jRTiT[V%=abNEqLm,iddU!dU2g-%Wd;6/5_FZTJ5_ d0P$D"cU8`n,:6;)DBFG#I\S_;XmnS:3CEMp(1&3F(Er5GcZjFF(Va[qDu#lh>a3mcQI7b! ka2gODEU?KZ.)nZ49?C&7^R@=I*`a63-mrdTFDquF2Ja6EA>R`.A;"MG@NeHJ7CA/s6n7p2 k.S#7-CBq%O22%Dumlp20#;"R`:43o_$ofg]cr:`J&e.i!Md*sWZ6;^]F(IZZ8I2tl+[%/@4;H(usH(O>)m X6.r)7X%@B&,mR<-9ch@%/J$;IYb73JKk$'pW93f%$mB>$"_;G?iabrI&)*[N0p.=B7#9A( am?LK9MVJ[/+knO^/e*p:Aq3EoP?\@*19!P#"38km=>+.*Ea;a0ets?u@FVfZMTNAM*X2 )6EDj:%07M@!RW3;u@ 0jI&2%PiULu;3d9_q34Vl7Y+raRl='pSECdGgRb0/.Z0p58cFI;kaF\pV!,BrOeuhSptG3-:CelCEnm9?b4?V129teGTpf;IB*"Z"E84M,#99V?8\ Gno\Xg;OgPWDJp>*K'h"P+.^jI2902LO!4s*Y]_8jskGHb_Jl>p-KB:fud*hT:oqD!8iC_P >1h'0rr5J?Ra+!88g`s)j+36B,Ra7d`lI*)0^hj<g$$$DBj$ur^9@&+BlX8H1]& \9HH=P"3r'PIdG@*7LS/W@oZ1e(Tr)<4\5NKLq4`tgEUL_0b4d2F:NR.26NaK^3r:h>QNSK QX&KkXF'6:cA:,$HK^.+.TK&J9%C#3f#8KiiaA_ckmqQEK*7Q/S8P!1ZP!A$DZI*ALR5 9F'`ZWRC%IaJEIek2Hif=`AgXjlkQ@7!Z45935s*$HI#K5:Dr+Rd3-XO@Rsga&CU?G1ZY0l rdR`Ucni[dNIK4)KKi'D60MS\9P$Il'p85KkbT#ge6K9iJb2/2&D%na?B@Tj70Miq+f(?o. uePk4%i]N+(O5,*?XM,kE3UQf`#Q/9,SRd4 ;G`I+j_]pQ,aC]'!*C-O$oJG1pt@Mfh#!R)KTarnpI#K/"tn`OM6Smu:b7+RS!q [cWfrNNm$\*L!k<2dYiVQHD5mfWhurIcoML!'A4La$242F3c;mHLFl$WMkbc%']gu-ggT@Q em9%!Jh^;>n"Kt3ri+4"b4t:;].N0"CR`6J!6PtXYcc8i>a"on9u*Z_l.i&;UdU[8D'f,IM "n492K@T6c>@a'4RJ)$jGS7&m)(R$g\[gb:r]5KCE$'l_S',ei_"(+!;$?i3l8an/d]].H, (kTH_TaMm7^b`]Ed"Ei)dXeb^n/>dK^K'QbI-=DQsPJXEbh7O0_ra_%"mR]Nr6c.T1b=L"9 &UmTsUK:m;9;<'!/Xu+JXs$16<"eaU!o,crEG`Dg[3W%p5]m95]aZ3*Ar/)gWn]oF']ZE:$c1se7_GQ=RM/qASH#_!ArtGer:O`S_LDdZj ;3$Op0R]]ZKH2T=sElR#:o=mW#!k9aOk,6d2.?ljoO5H%rWcqkWHm,]%l&45E-8m!\fp4h: oD`AA.(.7_n);3V9W*iU9HSS0GlQrgVB*GD\+^"Q7q5KCDl].L%;T)<5+$?D6RGLJI'L6Nh E>*6X`>ru:":5\#g_aB'l4AR>i2Gf>!\>?E;LXqf'5A^4kQq5.?Xgs;J]<^0t0P;Hn,Iu\U lJ@S*.f,<8N3-:1GS,-J`-)*e=$[-L>`m\'16WeMlZ.ku>%i4KeJ$=);`PnrbX[6Mp]aKa2 YBslsmCN2)'bN&RL#?[orSLIrNCVj;iQ<%Tpbunq4kolZIiRK^=5H6)4i`ZE5\'Djq&^mML S4#R4r:_SKHf^n-"0#Je9d4XOm)L?UtK6?CC-F")RdB0p"m+F.NmVuG7NR)gOJ!TOhiE@t>ep8DYrS7kUMd1A$8$L#Q;,cSlS=:BhM%UM2W#7oKcE-H[.]gsWdfg:]"]/8(LjD=;nBh9PnNkM@ +^4J4h$4HH#;$u9+d72"J0 EKlI+b'^cT*s[g*FZSs,h2b.GkBA2oWZo[@?MMe'(ud8%SpE(6([A0_582"FiJno;%O< +3d1E9DlXB/^;-Nqg>TtM0HU4)=6!ds((*"r-Xj1/iTe70JSH1Ht!7?K$;2Z9Q''G/UkODm sO=(pcE9O!f"#)e=EMj`%2A)ZU'>^7V:9a%Z\J6j:*)X`rOif@JO<*c8$>3BRYepdph$aj` 'LAN3@.=NLLE>rC*te3fj2O3dh]NNj2\-Dg+j(Z6@R,M;*7>W,Ve@gf,p4r$$fiWQACRU;f G\>%%8E6"Ou>`s@Rb=s%['uc:p&3-;nG.%Fj3r*@DG=-W(r\@> `pA2Y$pp)hHKX;(VS-ZMSW/'=*r=&t(1;GS_Nl&hDJ&E6BS`r.'?;P*'0'OdaK[<$8.')29 7J+c[I7*rfobs3Lbg;2lE5h_!::)"QV.:`0;^],C1Q01%LW&2+s-ru.(')XAda!KIp]4;ji /'nN.s+ab4PHrT(O*^S%#o.)TF0/F1I5[jBVJ]@4Obp$%11f=Ic#8hI$+WiL=+-T\H:l#ut GRZsS)Bgmn1J&VM=R@`d[?%'o;_pAUZ6',2*:mr*OE3?kg;Ym2,I<^]LT5\K[MWYh%WY!!M ?FfJRLq;\%o]q`ZabJioRE'S4Am$kME:P'GpbDq-Zd_m:S+D7c6"NB(r\4IlY]Lg;1g;U6:`C"C0G=[\P\.3%)_fS"(4f-t!H8gjX;?G@qW_`3@DWl Dj#==Y8Q;$JPa]2D%P#_;$=V-s_+cnqD+bSG1[/eD1KR5u>;_Y^e3TZBi8bkdVA(kp1i&PK !Ed`XM]i,ro@0=+M*cA"eOqaM15"3oC!]S[0-_W33E)DDD31@2n=NX[,a5*u8%9K]WY?,S4 1-G67)iI4@%pWd;c$C(llA5h5l(T"&W*/;1t#KTq+8$\PfkUB1rFK6-^>`4_P;N-IkUc2*koAM'p-]-j%Pd@J$EQl X"Z$'*4+*[:NAPs(]gm5ZA$K/X1OE.;1!X`lrDBZ$ChPVdg\0Cee`J\>BR&?%3`=52beJ9&Pn&9*hhF0Y[;JgIP>9 o*mWA[(Q3Cq?66r@)s+FJiUS#^"(dgoARnor_*St>M@Of@;0TH>1E[.#Z5V7oQc;]" k0Z,=I7mF"YDm5hNIDY$IRNfHYFmHJ^)_d:EhuP.2-ju6s(_<2CF*I?+X"Ha\/[eO:Y4/^+ bC\O2-]eRkS8_PG3ab2mt19'K/bc"'sCh![t7^,KNA-m5qEn=a`.#R>m?iRTk?(n'eu!2?8 j;'C4.n Q1'gorYkmn*LK3IN5]Wj-Z,5.K,JhCRN=Y)$.GgU&%$":R`6.RoT3)6Pbq1Y*F3jN0(am!L!c`V4AHuSQMCBE01GuQ( 3-=@&]ff6QDPGooQ_nF9CEl36IbBe/Pn3CmUW:nhlF%gS"a/%FF'oqAXd:aa;XUHrnLcR/N b1arDRIMqRcuLN4;A`#X+BOd\e&Dj_uhb@tG,*$O#TfpijEVA4A[darV#8VqTb)RbKU@6ql7U :PTZDQBnAeEA"-l)smjE)n`2!Q5u:KqUKbZQqm`"DOR^nY*dd)1`R/)m])4-c&afJ[j^)Q2NiKK^ak9rE [^K^HIOAO2ZK,/>(idN&/'>I)$_pa`rq\'5o=c! $N=iL-\c`On=nWg^(,]?of9*#RXD'7lSf[G,!Y+hjH+cs6a.ZTK44]?qW4d7nZJX'?Z_cl: 9[Fdtb7LAso:)q,cEdmL`@Pg)oC.DgL"2%g2b;`bOBn^29.*^S3m*C4eh*+@,0RlA; ggJI/*T6ifSS7+J;%EA@!a!qcC+hLYTkLD_Y0Np]:4H[_>A_ID&(l0h/47Xo`jr\#l)rZX: Tir<7+j,5Nb#YdWJZlTNPTD"1fR8u7N:kI7WOd1#]"HY>413q9mmK7L(1#hTSE,hV=;rE]Q s8#']@TQBgR4T;^0VW7?5nWmO/9I.h4?"RSgq*d?Nr2s#/+]K #Q^Lt!)k$Fo;.U4'HL>KV9lWp('([F6Da"tQJRDF%bJQpo7WU1Q[(;Z@Mgp>1I3S@HQa"2G 7^&0&oa:_p;jur7k^AIAjrl\R$c2R+u^C/qn,HB^NcGEf3*;.XCg)%T5clO(OT.0?f*V/ou *+@[ZI];qr5P,7FdBV3P1"kYB^NE7+dsa[WSk8UM^NMoS`SXJRp*\@Q%8JYnoIEiDqWmjH< &E7GG2^L_!KH;MNt%GVHM=c0hjYm"Ql0@?r0B6((ge*6(sC-Cb? _?Ld^4l=Hlu<(QCmoObiXI595hVjA<5,-(qJZ[MDTge@&^:QqZX@=cD3O31EZUPI^>NJN][ PkYt_3*f!=^;Q1AAFT#7nBqlO2'O)KX=KC"gQ+HX'_-O:@faB)F6#O&F0%b$KrO1U$\6SH' >E.M(Ge7:#Qb2qV!I_c@n5rol*PB:=5@8@,G!@.4a^jt1>dduoRE]@8RG@Lc6(u\>oU9&DT 2DT1!j!'d[qrrGBh,S'pl0Jj LI4pG_I2Om7!4Rp&qZmuPIYfna06a5W9%E'sm71_k+n]GV]a'lbi*_0A3I%JAgHQ#AYZu6p S/U?W*S'`L2'1B,?JK`)i,V!i'V'5V^*jO0jI33*qWbn!?RC#i6o$"?j9=!Wn/^-!B`@su, 1s7^LP>ojcbQ`?m9UDU^e6Wso7-cq[e&:uD:UA:F5#;pc"%#h+0[O/D6WpX.PK):Y;:5#q+ \>S=V(YEh1po27;fq[o:fEVo5>fof,rTZ\77m3$*g1qY=B7;EB3J?DZVG6TB461&*&Zi+?J "lcK47pu22>\o[RHNo=gh%sAm,smUMDi/#6Z*8DBML(\ N@sIR6O=''dXD3EB(E,e75eQK@q.A"%!I[V))l\WJ(DR>!)eC?,*W6_S2)-BFkb 3]<8!BmNo9B,Bk0`N!Zffc7#UL1tC')F_bqD&:ef`klPn*m_-/)`H0RD/6DpG8p=ckIPQC[ dUkI44a/?DnG`C^i1jD=F$KNBs/8;m64;Z4-][RhEF$/nMcZD;T8' f!uM2".'72I9$EW'f'fQI.Z?.s<(3NuO)a!$=e*[_&=I;iL/LZ15*d>?QM4g1(3H#G.]DO/ !crc4PV7N42]'5tAIHbRh@mS!gVSj^r4(XM]$1dBO_;!(oH6<*V:k>M;oQgOWus4?j=S>QY (@S]`"5WB&N?nn5p$\VrJJ]P9mEn>m.D@&TG.0Ld#'8#^S$nV'lN6IuR++khX$s)(8`Gip3 9GN4IW*$mpCb(4d`Y_'&?OOh<`"8[pC5LQTQq),c)mCA,2kf"j#J3`FYpH8(O^^5gaIX9E8 4JO-Pg6#03K"=*/Oaon(1Q?3Mp[83OMXab@WY.tEM>0W)Xb8@4PoNZP J/B>8qWuO:[^D8,3B4A0cp_jre)nZPa>8FH;Rt7S-03.4&N3Q]hODi"%Qd49mjh*OEN8\DTiJ\/=";Th'.lYRPu0Fq"fSI?/UakE>1k)MCkf)-^:> 'M_E1te3j0:\]iVf@?Yf=aYQfBi%meu/LN)8j8>&o+H*q-eOPq*%FCkp=gFTG5[BfA[bZVP 8B2B/_(P/N'N<(bD/Mu4i(-9t!H%RsX?&'7fn8=<7pc^5<[ut7c)-Y4/C@1Vs*s9l35XEUT L/dK/pEk#fX-%GA(ss9(GdiFljZTN5;MEkshkIp:dRG"cc$e\;Z7B2rc0%N+bijiCtl#'Y=KU]G6'<9IbeV'P._eH#jV6mi E]opKlgI3_)&7`!hAI`;$)AiiQ"UR&:X-\tb0<<\;;oJhiL_Z\WAa2oaM4Y@G4aa@5%G)oF @O%P_WSj7RDofdA%U]'#84jdgIe#oVb'3=[d@.!&.5\,$1akT'a[Aj0eMA"&p!m22p:8CGjg7m^lD 7QH45W6>A;!Y;R04f93!_Ugj2l9.KF7UX[X8]WaES#r`6A*Ha'0M^IT_0Io8\(8mPE/i7RD &s1HfGb%MAO63Bn'8tg)^bIK]ofW:.+9/'XNHQ#i&K[D]GdNb#N3k9K=9q"gXNT6%'^aG#5 GCN3sqL<+lkb*eidN.&4qg=;2_ol1#D]?I;b\P^'OC1WiZLIDZ0sXpbqX"V#X\Yn[LGVqCa\hc9>tMX'oE@dS-FkZ`+j'N%R.U=6V?QG)e;0,DS8D)1%KD C0o$7mVp,_@L#ujIbCd6BZV,Y#@)%Nl.l0E\J/PPF:=2-hg=tuTqg(KpcXo$2KsrGb5RED' -ESHp&`$m+BJuF.CX]5i:?c#bgMW:2+6Nh*M^DeGPNRLD4n3S_f(4Jgd`&&PZ6Oeqq1d/qs ?P5[:]3Z1[olqmlgCNp[s"XNT$Tma%5D8K@@jY\.UsqLqr'n7umO#5P4MI;&CPD.f)rOpO; kor#^Z,&)m(B#>SjSkp0/LNfY[9OJ$>3a.Mt[GQ!#hp\ng(1l]>?,_'>(]$(.=CG^f>eMKT f2bW[$9%jNkEY;=P5_K,tj/4/AIPVOML>Z"B'FhZ*%PCj\"or+bS$fkM'"*'gU"d2kX1U_t (6o/NSb*(OPSoX1pcL)H]L3`%9H?FXBk].gp?A>[e4PS(H;p@X6,a^r=[jt:0^ i+pK"MperL(JA1$f7Y7YOA4J5i8B!ts7D[(Y@94_)F,*k0_";$MlsZe `2j9(Y_'ER'C%_`rA:t(%6!S*CKG>4n$'HWQ*Ba4od%$S^9 =E"I+!kbE IKR##I]V"J*LG:s&@$"%$!.889/MoY2-H,,.2W R+s>!YY'WuB1P^NaB[?APh=&^2(Gu_9uJtbb__3J>.mTjL=g^*E-[5f.hT:/LKJCb']mFFk /eT.L>[3/gsSrnlHZd&cGE1*TR9.`iXR]u9#0Ye8la":o#^7i8buVFaCPKRnB,"<:OMmnU; \*GR0V)d#DDH:(k3#TjNiebc[j.BJ92!)98>cTL30cF/7MFRFsh( b\_XC"aC/<@j^>N`aN5O$g_bi8/.'+MdA&bhXFiS5b"aFS]XNXAFbgEg:WG#g8P&pq:GDH]=aLgIr5^G*cB,-PJ#K2ZuFQQ>H 1/fF\dfgjm=5I .'I]?W26-LX:C=eO*<46kJqIZr0Ohr34?b##t7!eH0hFK''?-ekL98;KZs1"`_tISHOINL0QUaXXi"/G*rcr#2J-3&:%'^^!8l[dkrl3eM>b 16I%sGf"HUd'nP!`JrFg=cKO96lh3,M2q.F`;uMMSK06Kp51D`Re?+[/Yj)fd'bOuE-=qf= m$Uu+P*%_=Kf%1(J96QSBM`PAfmC%0?thJl\(*oGftfn-3+R[7=&k6Pg$qeEgKp%SO]jNR9 E`13oqg4KVH*JLbYZCc?uUie'%)M./TFiDEa *+agMi>_6Q0$KG#G`ZMA7[t8914KIS-$e51"\30Q..)I+RJtgb\4ZI$<;:`nY^Wgk9J`+i> 9c(*$FT1_=C^]noj>cIe-&&6kg=*K8f#NS-2<:O5je=Q78Ui*;)f&Qi>p4kYkRFqsS$$s7n 3W,@;`R,.G&/l6$^?pRr/$/*C+96b7&AY@S-k#qdV#>fJr4kJPb9/_g Y9.=gVpdn7OgI024eLY5)L3#L_jj 2mt'u.gr^YAbDV:8qN);UcL-:29H%&mY8aC,h,iO.+)G^9U4%B**FLM1AWrD;>T-5,)F5o& D=P'R,aF-0DW_P8n'GOZHf4DU=o_L8\hic7Ih$ElNcIQ" 434Ap'KA`T'ECkCte?42m/'Fbc?,?R>;N7QP2E3T"4GL.F`;ODP.6*p0ooQADeX!YVju?qs7+e1P-=LX$0L#C(TN]"\IHOl[&]BgtooE,>h\,A9i=l%YSiOhT' R7))&uS<.Ok9V#bGT&n7iaoH,r6.KRj@HoaZC-pcc__StTFN`csLN)8kufKNppZJsVB9@g$*T!aRFlfW_BCPKg):/k[j@9]Y&*kt[H,I^!_K4_Fb/KZ:?22RDE!%de`:NMGkGk[KkO\S$rsCPci I2-Yk2FbciA,Xq9X[XI?4^i/YVQ`+#"%Yd+1E+o 4b^=8Z:b"_TAm^hZSgk =GPb`7`EMnQY2DfbMa)Kd%i9Cmo.pOcXQ*Ck8HHAoKUDi];;m sPtc\d.GBLS/d`-sq_E>OU`EFB8Ha=B>\l7,N[&(CZOBJ8tm^GmT62n;(QCT1s:>:3bm/E6 r/KG\Qh0&OPXn"s4Lu7Zg!*\q^5gEK?L_J89p04a4B)q8]#mBR^78E!=+_DMU@#@M3/ P:?gq:kiq'A/@o6n'1Y-O)V9uFU(ch02g6-#"6YJF^e'5E5dUb@tsbfH&(&FXi,'1H3_62q mYAZfA5HbC@Gq/#0B>hW+Q6XBSJK3/=8AB=(Hba4298D5PM.'kNVu3@*bM^>bkZ>r6Z-Ob^ QauV?hI&B,`G?!!h\,"`JGY2X=h*&c5Z([:j:ZO@sq]Gl*];2eou'k?i;V4oRf0idEn\cY+"R'c)ElU/EDhRUn+B8u&GSka%]P7ocV?Wti4PEuDXAG ;Gl:BJ\?_-BClqe7isEp&cm9d:o\OXf[oZ7hip^<)QR 3k(t^)R:JUT@?1UiGVkgWf[1b\naqAUaAORA,KQ$9N?lW/>b*05&o=Cfk nChk#7.J?5'QY8;1/-.jd5B/>Ct1I=PC2IOcBEqK3R75tnNG2sm.3HfPQ^qMd$,O[5uA=J' 1:/HD&GjkFH%8;SEA4*GFYNrm!,$*nbR[P2%1%D*bR&P;plCL,uiE[?!TQ78%IMSi\n%2PM8C0K35Z#/4gmBpk:QMnd;(oB Ri(0qMpeJ?u-:"sgHf8\a7h=n&5HX<&PomGYN)8'f$-e\3>c8gfM7_-Tf+%P:aEZ*3`c<6R2igQfWq21f4Af71WRcbQcFIJSOR58@* LH3ptiL2BY!LtN?ia<\F)@TO^-EC.G[/-OrWp:S;[B")3cF^4EgCD$B'';3EoY3]Sol%Y.HYoJBBf;gn;uo0I\2?\^1(YYC]2:<>^n'@nskIeahJ$'\6 pAC-O\8m*=kTdoURX0e+F_Wao:R\/#*b^r%!LR5Ro&#-PG]MDmj7q J,MrjaU.AUC51DrV]HBiEL=8Le"Z0hDen$VV2T)Ze!r0:.%C6ZbI^g8'P=f?_>a(JZeSd.9 Bn:)N%oCDo[WQmCjC\'k;q+hH^^+7n?$!D4!AO+l_"/'08=$nBL#dq[^+N,(K983pBQ)HOZ OHk!.NIJ`7BaLJ$-�dIZ?_2/k[AAJ5FN06We0h=Xa4cUL\DMfR1`loKe9&$6V_rN=f:&d MtWUOUgOs9810Z-;fCnO]EBQCf:k$(Wk!IA+"`NmHDSL`2$Cck@)8GhUj0C[G];[FW@O>7@Gp"kg#2[7'n*okmqgtV4En%mm"EA!Pag/idgF1o.E'l>'OnMQ+AI-dXBq<'qS]`"G/#(957r)OFEm'a*@+nQXdds14,S3Obu%?mJt%L%q09Z$*i_?8f`#m)q.*C-a8mJ_OF&1D)emVL6.dpK:$ciXa %`5;bUoX!*5'+Z\u)+l,B-qFDf@RK D$`lWT],k0$G_s?7O*ok:mEF(69pr=94>]0EKU!>DNV36#=LnW79-UGKAN*Tep =kANhh>kP*lEp_dUbO#9OHM>W:MZ%soZ.T]R.VfA_0bNUd!8DG)W8#H8lGPV)bkks>9p-5h+2?d-9(dlYo%AET-SOLjEUKCIo^\n$ ul@#Zjb3^r'Y.3dO&HM;7)aQk/+cHnk`mmm0K)p]Dm9K$reH7J"!t3m*@H8BrQNT!1609.- Npd,=o`Yj$"Xnm?fhDtE:4\7TId3mfFV%$Y`TjN&R0(Ug),!em?6*1I_V'%Mo+E4&ji?1"Z@ gaqq$PF6K!Q5nmg)XVU^2I^,k\(spiZ,2S%5?H[P!(%,R3L'J,]ZI%Z:uV*&0:l+)UXf\a` at@4;rd>&[/52iHbrq*>*=7&Ysdm+bU@2V%n$)'sUmiZA0jVLjs@:'^h2%n*'bsn6i0Z)7# ;QX)8p9YSE1[f0S?tnS9ZFE@_A6Jqtuq:;nd-^_f@p%YS18Z'-K^i@X-5L%;]!'(#$]ko19 .)Y3\GDYG+oQuWJl'G8kLZ-P,Od0H?q#Q`?jo'H_-a"PNlN`$0+;@>8O/Me`U$AuSAEYTaS ()I"c)j%SeiSkq&p`G[eNA/<[ONf#U2`/?pO!@'REjZjERK5`1+l(r6\#!O*7d,TC/_*s(rlOeQojo^`+0639-G_86g nJf0b&7rpCTP;J>`%Zj@q1_W)EULk9M]Gk[2+qc1GPR`seclO@T2GuatPc790:2#la96@^; [(T,t3AhuJ*!*J_PQ`Zi,T@o,'?>-;B6kGHHk"Po:2dePiP;j"cT;j6:Ghl1'_a#=Q@2&D* b!b@n*]b")ZJ^]'@cnTlWtXKi<0WC*WbCC'B^/h0'e'V)$-6=btUD[5_HAm/Wg'-oE.f&:j .f1*t.=,'jS"1_M:[-7[7[ReSRUH'G_j^)$_9"Tq2rS&QgkS=@R6GnH>J8`Z5`G%eCiEVD& \bNZ*"f>',*p[!ld[ar0]L1Y'$,K4d#>8Dg,V*[0G`'2qoq?5\=3=-Tgm[&[L)Y&[u>*OX: $[I%;nnR!UO*iulpeP0E7<;(T&%;aW2o k5dg0/[ZNer=@GoG6DY2M%M;Oh_o%Gjp7r=I,pgG-!/-7M+'D71+f=61[OLL`XD'+(:Tker GP0=rE=G>1KTUp=h@0K-<+a8BD`@1m]CA-6CScBLu;H+ljX9j'EJVE%I>K2Yh=d&TK`EEFR qfc9YGgG3pYnG6`56LO==\l!Xma)PN2RFsD)%6Zb4PFE^!u8'ZN1f!i]XIRB_u-=9pT7PC>M'4!1IU,C`E[u_A='$V[F?'Q$#k,8E*+PqGT2800nVGC0(58)pEOs.5aS1?BD )U$$Vth"Rf#t'FLYIs3*g\E@>1]<@c]@DANCp8E\.=j.fiY)3*oG?j;h$NmQpaiJ]&>UF]0 *"=GsU$iJ&3W%q`;%MIj:9!MC&"5C$A=)"9[d=>u0$5uoCWfJi&R\$:n9!GOj,'S22Z@>&Z 0K5(Eb(r6l5f?93KaCc9o)?I0[M>]k/m1p3_CdI`1W8Dp*<=)KiJ%,/hq&69Ai\ggIDL!Wj f'GFsQlSKZN>TI+J^b`Ldt0P.PZ^O@Tq36TQoe@CPIXh]\QtKg.hX&8C*gs4.3c1bjEMk:JFqRrK\p^.CGku7!bj"jo)XN1:U )SYC(]ec+V^V$XGSMB[Nk"VQ3t#g#"`%6;74[J]9tudX%Bcl.HjJo1>!'%d1_J\q),+P'GR G['IN1YiP;tQ1>2ZVNefJ8MVE/.n\mDS6SfD1*Q!7%m]5>"RE-.fO*6+PO3mkFulJuhU&<9 TK>)l6sUT/[+W`tmk]:6?XSTHFl(iPQYFVh*GPe+;1AhY(SRIpX/I"(bSVpWU3G]S465&d D+>:_ZJ6n(S15/fNE]KgUdjPa$IPZWa<&>)]o*>b6(Aou>IE3g[JX&GJ`n+Z8]El(`dDGd< 5hOqc+"_;S_AcEWJLFTO&"3p\bq;q4/'anMocrtc_9VF!P8IX]Gt@$]+luCZ$R;a_94m]b= F6'iLCLmGK3p=5L1`R3e#nfJW^P5^WV&55nY[F/@rdOM<8!M1%"Z5XcC)aS72+d-cT9u KIdgoKh-6(T&p"4[<=eD<`->>rN_3TWG)ja(kd@F?$!_:ID\B9H[M;J>pKM'iUo)PN$"*KB 7\LZfb>k^J3J+k.I)CCXUD(L3pU)8D\%a4ieSbF6?f!sRgNYlbKjH2^sd]A:1B$f,..N8\o _0mFKX7ub%85>U5!C39.l5oe:Yh]i;4W!HG/Ul#-iLM@TCfAco4-I97 [%0=0T"<'JAfZ8#npX'MFk$bI+7h]So61iCTu7o/C$RrooQ"/D;i`q%G<(>KKjK]$5@*KF? hM0B\fp&R+eK61kT7Rhl)V(iofO'C:[4L[pg0g,!Iu#;iS34%oM3kn^H';=dN8?)qL8L$!D XKjOqQ`"(BIt_r9?KiDAjZmmJZSC0+JeLS.\Eg*!+1uWs@QaiPE:.lqitjrsA2Pn1g37iZ9 B%Sgkil[S*=:i-;mUn&O2^)%D?giXm#l:+6p97H4uIe8@8eO%87D)&/*&-'Lp\/I*4PL>-( YAb,)=c=Jl#c/t4H[,uWqT2)P,(7S=,fkla5?LIOQ@8,EkW:&8q^#o-;^L",\g^X8eKu.9fGapZB&W=\>EZ!#d5 ::Yk[8Y=NE]p)85;O+qh#Xq#d8%4jMEOG0;leMcFrJVk^Lsh*D>)_TY4$ACh/@NWrYGBf_; atZgn%"hO3Qd-\X`Yc8#al$FSbrBa)ABAm.^CK%ekb#j5rO3Y+'X=f\UX$g23Z.a63$iIK& ,rYOD#ZrBILMSnf!/$&gn]L&fU(5u:5k#=5SI)$rUuS0JA-n?atY_f3OS%7@@nS7[n"Ue8_ HbcF_W7<(Fo'ee_>ZrEZ1g$&-!n\fJh7rdU9X.&3#g0YbR%#6%JOu/@J8THq_,tZNqT.*Af UnK;2EkJG(96/Oo/BdVF_'Tt1Oh+5Q`Q9rD(Bs?5?RWn`i&-Mq1*f%)P+"SeMoR3.Iq9q%Io(>j7mIp]\hq12oJ*WTcA#!M4 )@QRg/Jr229mF#"n8A!nUQH<_.r0m6tS"hC@+dF=4[f2M++IQYY7Ioeq^HrHTpVtmsBNZP"M+=Bj,>B(AH9sQDX3 UJfr-$(#](@Vs>:j-R#%4s*,pgJA::Bs54Rl?\>"rNb@_\?rRMbO>[>/p`TcJPS7MYpiAQq !8h25ItM]P%RKkP@#':")T22r%tX(07f_utUEFW;O]p3PHo$LReYki[Bau;n3JW^a+%)uX% q5r3Ldui9N\Q.i(PprgU@mB]p;68fOOt6,'P.O#jP/\D=c89b/]HqbL;moO&Q"2l`cscf,; >ltU<%]mJ_^s6P]MkE>]u/_mOuSYid)40k/ZYW+64,eH,AcYNPs*p>mRqU,<0!W!E>TF_mX `O:.n/]0dS*pP>Yj$B.8(uIam=PJP(TDN:F\EU]d`[EjA"W@3dNrA)W`7Jm1CkD_5P=]6ao ZAVq(k1uD3j>`5"l/u@44UTDY,O?e#N@GLr,"OhmB;JAj.Yr0YH#8ld7iQTuk3+ircS>8_@N>i4ZmpgWa rNl`KbL0P_+/CNM<-j[)8MWP%;RWJqqO]:BI;9([$HB7^h=CKqdF;C\Fgnq Q@+Q^HZ!QZ]:RUDNt)c5/1Mr8,3/NoO)a5?iF'_I")(b5H_EoHPo.*!7dAekX`eU$gUd#VI Li5kCl6m(*2qnGS\DiLGk4U7A7]N>sP9X bet>^^t!Q0SY4bT,_C+Pj(Bl:&9S9Ms8p`t>_N[:/Df>&b#o:XXAY.>X_N8!rtW/7qgQM,f 2uQ4^tD6rsfEZXL,hKu]K$*S>Xb.RoNM>jJ5/c0Pt(E`#gX,M76E4&(qpQ)2WK7%4UY^bN, a9?W`I04k'tQu`rS*FkaR?e^!tDrtfZ!fiq4JkA5Id.8<2\8;`'`%U=;g:Ooe5@)M5T6(9i crq5Nk]:2o7c:VsAO8>9l:"9!93uE_#Yg7$NZG.0?+Q?V\usBB#>hNL#Op1g ,E)Jp)b=8b^7@>cW]@'D1b8Ja;K"N7>hbM,O559`-W:4Cj\g[E:n#[27g;!-n=a.1WXiFk? MkPDO(Iadi8EO?];(9\8grra3rgO$)*/3"fToiUUYX]NFBJDOV"jO5:Z,LWP3D]qg]oYGRd I2^j$Xti1(U9E&H?6#8#c.R\)J,rZ/pN5kB[u9&YhNjuJ3QkS_:6D2TtXTsQ0jjID9pE\:5 2Gu#eFA&*0ph@<&2&EXfgSG`kiTWHm3SC@E1Soaiqg;[gM&KFH"C4dd:`A$^#UJQ\>raXH( O^B%6#AidFYI6L/?9SI:1Z;t8fW8DEe`D%gjG.\,:H$Cfb>$%/9Dq]pc8Z=r/kPLl9VOIICJP+k"7Pqs/GpGOVtt[(i9a i"5gl>JD.l@?8_9#0Yu4q!*oer"jXkB!uJHO6CHd&6h2@GcRTRX1S6cUG^4YUd)s9R>0gdcQ6T EqX&8;:2Dh`4(3DaaNYZ&E>e3YR'#<6-4lBE_p]0@9#586CJ/4#AjAd2X1_L)!Go%Spu1H8 &R`/FDuP!(&N%R8`B7(MHklE#]p!$krbL$Q%V41)VI"[t6P76>'BLh;CR]"j.##Dd[m)'6E =^-p0U7+8o)W+ZD%'1!k][j/lsA&g]aaV+qf#,lOSX38GGB-XE=#DcgniOZktCI//>_>/Na 88j52IN^O\`scrX*-+P!bm3g]"oLeZ>UW!D%>T1OL8_PS0RJSR\NUD[L:C4#<&DY^1e7Im8 -FDd+DqBk8-Wa7K4nkNkVg=d:H8eF"oLoH^jLoim#T<]Y?LY'HpYp@6:h#>aSE.E?u3HNG" 6NdVfMjB*-4\eWOf+,`QX`=`0q>.<ei0qap_6A**!\L>R"k4.r]?sN!g /$$jW/.#.nWlS6\^eCScnk`XJt="!BN!F9[C0#.RkALi/`A(^ELD72?gqHGJ^J"BXLf/DoI$;c*G.;R?VqQT^fRF.IHO!r(#>f*Nln?6bJ]tcX 9[&%2grqrqEJBiWL9P.j&7l$t1efOMbqpGnaOCA,5cE=O7X/p.42M3.9=2p)c-25Ce;uNVA d2p99JhtB'3-iPhFn(51E62*]W4eDWl5iYf5O<-$6K:9aK2G9,ED"LH'$F9hnMR:H]P7LN %4^]i%i^;cPr"6ut04]an#[3h)7:=/V-VX=):eCd"V>L)84827?@u 6"ekI5\0P,sr2$X+pKZ`U5BNRZ[U'K%s$#$r@pchZA-e@r=f(q$(?tG!Cda+\2=#0c;3`;W5;G1eks:_7pW(iE/U:Xncu9(]./?quH4@0=2S9hh`nbgZiA?\ =ThKaN`nG]O'g,G@AFLB)4GGejU"C4tU?K2lkpST.^?]+A,O"'rA=olHeYFGDPZXrX'<)KJ SWr)]_R>XSIDAMmCs!/<>r$*[\>TN9].K3Z*A[RaVW?q78:D$L&Cb%RhT"K>M2dp,c4b5I> Ah*t@_AHoeR9.X@JS/PWYgC%"TeD6JIh3clI!/D,0g+D(9*TCBWj!1&G\lHJu%H]gcgp<15 S4\;:I9NR"4kb%WhTbCnh5LmkJqS[%g>uo"h=94Cd0()?Y![_*Y^ZmkFeh/1%#AEu:d<^2] A'Ib8I/l3=@-=rb"5M47A]&&)C8;i=i@_di(_[r-$r_4I9^kj71bplBOh7*b?W=#cM`ENXb K8prSF2c$ELjBUDVohe6t2%5m.d!8aY1"C"WZP2WObh/H9*))[beTLX:A#A_u8)hdQ&)L,B 34L)],),@Wh^(R^8;`W'*W-WP,+#7+Sj&c417IBGou+_p/BII:Flmc*po9Z=6n4n2l+1Lhu c<\Q@bl.r'XKAs6&&YOFT+E.M#O'?b:"qA+M`]dbD5>C7PgYO99"QJCk,iguj8VRE0?5&L; #"rM!r# [/:>pVDB%LTT:k7U?FXC^3LGiVjn\*aom6E//+FjmH\l?=me_WQ.8E7oh"u*bl:+G6_\3,# dA(R!+4tlNXYJ@d\5Frc-s*l;=r/;:[R2/p:_gG0NF/aCo9YH6@uFDk&'(LQH`bk\c-r;k* IUKE_;6mXaEqn6ag6hHkZB>GgDWB4uRJ`qY$JY]F>e;$J.K$-60P84d@ KP@W1;"[HN"/VRTu8fHo;LPTi)'X\2(Ba52lkdI$q_<-E<@0UIPC%,`S/f6M%rFt2/iM:)L L8G7@:kuJ#AhG3<-E2iURFmULC2U.ghQCGV_'a8JAtH86DR%DVH\\hJVZVjoduHEZOCp2UB -t0%0qHl1@TG?sB7@O,G.qH7Ba,:&#,Kio^j1]CCHY[5g\>5&?+0t#?=VQ,t+Bg].:^6\rR])5O89f ol5j]'>D#l:PEkdnm=(R+hAYr[L&M%G4>u[uPDMX&PaE.WpWG8$HbC?m+"d0^P%b&ff<3el.34sT*'Nk0/+qc\B&C\U$T?G>a^r`[B[;A'iPfR*pVbZdND >@XH587_o6a_3U=E-\ns:h9bDPM?&Ofrji6fm)RYk&(YCB[C.#maP>(Z&-2WKV$id?Bd]K& F"43LN%KmfSaIHS*A60n]oN9K_rp-:PLiCC+^BDd3jYLjOlI%E_NkG^g`&c")c\inr3fnBO KJSI.C&aEmH=1@krdFoCDnP$i"h!3J>F8H>@%D6MC9AT)8+`k2-(+n+Sh\mlFr1AqNouL4D r8rM@)rp>:2NYL%(iTMF7f$#HM,n;.A9[LP>V!(gfToSFUPOCO%%MXi,gD%KbQ=D2)o7Hj` 4M0@JSNtuT)(<&gIL/:>iE,5aR=)H<>mH3;3021m@>7t=Mor6)OG$Xa,%>N5P#0/-0cRE"I Dhhqmp%N$@?Y2H,SiC@:Db"K"?(rtbmt[e7mu2[9G;f0`2Bjb.boZoVT5jJ*]nUc>>6N:j] &gF[3FepJ=o`)f=@%%)HZVa"E*tr@G!aJ=B(u)/#CNoFruLdaJqjV,nK1OI(=fi)?\NH1"K ,/mT2VQ,AD;F>#AA>df,HiU>PLFDq$G2a2#ccIJ8YRu#JVVVIq&4l@Ss?$?6cH:Mlk\8VY&9\StrG;#q>-`UtDo9m+8#F+j?%AH# /gW:j>oJ_/>=0d%\"YXh1#,"\im)7e#B]sZ0H\en\c$4LMOBb:Mo^[eGc+Jf )moj9<@`#ugn^n,8%X.eK5D-*DMPc=fPUc>.R#0PT:Z!1']P-%j WcJ,.MYfG@_O+9qHqp%=5$Ac@Fd#?qO_hWhq_J]2$W+HNnKl(2YK"O`.p7ir@hg?kHfVUZ, mL\"9Nr:auK>1lO*)QFLT;;]_;+r&oCFXKu[!rJ6.J-9)KLtGc=5g8$s8r2P*ZUERk8,nJIutB[h>s-C%6$;eabXKgqn;W`HV%Ceb]N)`FH2T?drO1lFiNB]\(tq'CSfn\H+mTo[$lD$Vb=)?CGf;OL;.<&g2(rE4gsNn]A )du>OCSQKu)bf38?\^(QdWj-^lSBb:.UJl#f%8?H6E\f'[^.]tX5r_;k"[Hd(%)\!WcJ3nr u%Qc?K.HTKpkeUAn=MuI1MB$%,MQc9<^?5Nc4%0Src9Gn#Mcr;.m_D$?`$Gqn;-Odl=e1hE Md-O%.6rA 9UR.tdTiCkaqC5@.`sNZW@UZibdf=KdaZ)cai/guBThKAEAPiq7+F.1#'"rqR`1[i@M#@rL -eZLeFPiLe*R0":fI;t5gY`Y%7JRM>nKP'<,EdKdSt?)=ICF;VJR#ha[T\W"X-QI']fpO;c JH*87.X9iM:Bc0tQH63CAH">T/?(#,ED4Kc,hJ]"K:>r!W%kS)Uhk"Z0*ulBCC"?tV74&VFi9TWpAWX/DYn64U* jr0:Rf9e#le<2hA!nS@&8rLV;0W<^c2(?VRk>&6 ol;q/Tf1jnW:q'%Dmib&Z"(0?Wl+h_i^N4T+bYRRH+D@[+8b;,['50k+]2r"f=bE'97rg%O 6gESC.C!J"r*B*m.6m_0d"iqV8bnr9$VnUkfVf*A!eqEBD*lM?A.J:-?_5Ip4ZhZ(F]r*LP fo)-Y0m!9Z*I\h[Fhf%JQrVr5EpDbOE@>NSY4Ec,oj1NSF6.e.#iLUabZ32rH'['lp$%]<5 #=01M"O1'/)IeA8$t0:bi8ZqPXSNGo(dN@9aN>)ar-]*,h#@_Cq]B=pEXi+hrF)Jl5R7X(# 0+apgDi@m&GdG8pk98__Bp2=9MH_9auDiBq]A2V(.B(:']PkN++s38$ur^9?//_0;173=#B hW;>%Vb,*Arb+6nnkt^)Fl93i@0]kT'59NmZE?7nE:8"PC@!,!]=gG?5pC;PdA;X]?q8`?O =NNJl4G7S*>#m8b.E=RfEc8XVF2K=A'NC/B\m r*CSTopM=`-[Og`l5q_k@8I'#L+-[1uP1ZRT!7'5f(5m"N\k) iQ;\V(e$EX*9;b4/7+()^,,u/XW6A/jJ5/Y1;<_O6MZaLA8-J2?$t8$27h D+atJbaDfa_]b?0go,XT4!K4e<22*m iY[;;,O\\LNQLp'ftehiF4T4SL0=FWPsdXE&>P8EMbS@pYQm%I$CFT&L&?";sJ^*l1g/P,$ 7\Mg5f)G4GO`*:.8Id'mOX$%Dd9L=U_"63QIYV]%C?u>?-3])]k(ZK"'"+pcUO6,?V>C\JS]o/%Q:Qnnk.a3E3T3*`!6S'Ze"&#clPUE"oX oANKcj,e5

    TDqHo9UKCS:.R Kk]/GuOH:O8:NLQIWF>4>g7JPQDN0cP4ul%HUBBM8,X#kC3TdYKf8OHY.*e7b=NZX1gJ$kW Q-stfH+qnj;X-@>e>_j7^_dGZ<,kG^KiSEt]_epS^;J9-AeMtJ>EsB'e?ao7*8(-AAG6#ag dqu&d(QWqGFnKaqr`AVK:'%90*Si_-PLp'ZuumBr)5,mr#YYM,E1Y@/[qXChYp`,DbFB&pb r?65(Cn)(dp2M+F>3%3b#ti@A%uiL;tMqAr)I5a11<=p=BjaN,\8C7_#!fK7n:S*uFG6T#$ d]+N3(*A`IOMgUk.Wk]TatPQg:#*!1Y!$k@t07**(Y,-5:2Y+*l3hrB`KOC3lQ,V=\!;sHT ^pO;L*Wc_\AW8bU'N)%Fmrf@!RC8MoC`n'NtY>9uTcjhQ,p-pEq(iJL(&0Cr",*ZNG(ZF^& .%pYQ1BUH4"->RH02GTtm8h9_H[Xih8U^i8"%pBa[bD$\Tor_2oPN$r \<;;io-@Af0[7=Udmr*s(dMN6GZ9C`,qU7KJMg9bdWso)Hil(*T'XY(jUP&ej5W(84PATa^ kFb7ROkNt.br0B28Xi=[Vh&OBgij[T6iK&K_42)k]*iOm*g,SP+b1E&j ;H6q%&Gg'V)D7<^`9%t));P-iVab!,(<"QD5Q0ac>Mf!pCpLPUTG[9;#n8F65Uk-&MY.JW` o?3eGYLQ&lM@JO5(BX;!TK0('0L6E[;DT@jVG(f$/0c;@Oube;E5Y(u`1GO^BLK@jj'E!eK VY/:f0(P:9Cr.?^,DJ^thbR2qHg(pVf!Uft3)S0J?%bX(#(JVr:QB,Yg2)Uc]Xbc3]9^F`< r/Wmh1JX0o"eeCI+jt:9U-dKr6nLB^($=j,N,!HJ+jY0Qt0OupUTp-)(U)O,!+7gEndiK33 m1%LO15'Pkmo[UVoG)%Eg+"Wm@F"]>AKm:LDrG:G_5dBI9GX*E_+#6W;H8:Y1m:?fdu$dQ8JKW(3KFrD@DO@5UF9'=(1KTKiQa1LRlaQX4- R8EWq7C,`Z,"p06>;dYbW=+iZ%L%,4UsSj"`E#3]$<*5*F.HiOg&%-Jts*/[Et[e,8,)TGX [G0<^W9LW8;j*?e>V4OBstZ/[O&,9G;@7#jYEN^scR*?Z%T6Ua!X6%(n\67WOJ?U7Yq6-:0 5GmUH^d.$E5'9P+n@TL<3(h&%S-P@'.F;,lpkn@JqdQFCI6N(iW2Y1]C'TXO@DA2SAW7"id <+.cYAL8%*!0)1j<3FqgXri4W-e"nQ[(f8X4P?Qi*d"Y\eB^i'd]NtR`b]EV[,4"(NoE@]*MKR8+l`XP,>(sK8gM1f6(9_E0b=@:(L^tj+`n <[@ou?9&_)q6[?"G78.d"Q'!ljTJPA*;KGmdG]dc _F0@Y_]j4Xi?'X,]XgHiIj\f+A"V&L@Fke.(gjgn!JCEg[o_LGLFU+"V;&'OJedAfNQ5>)" )^2-nUD"f*gj$&q$8ppSeL#^\Sf,?\;`6^9#.tbV^C2g:<#/,*o,o"2a[K5">Hlh3@CXPT0 .r8q\k#kr`pY`AY?%ueq\3mK;$%O7*Aq7l(Wb]/(68<2ck)lre.dmVeWFSE,)gU#g*6j).o\DM-sU6If[Ko4&O!0]C gW2X2K#NaE*WR>IJ1Q2bh5jKmg0&S'/sFqIRF,@L)r)52]nL&j)/3,'mVcPH=t_td3(L^k1 `6?YPc_13AQiu_\_ACX%if32+<7NE9G40fFEP3X-LPfRSfd-m&9eoc3L5SepB)UrYa+Y-Wf )AZa+8!]-:G*#UEMeY2KC)"+Fo@sZF0db`^;n*,WfJdW/[QlA8 ql;F/eQ!L$OV@\\+WHqq^OJVA?ee.JBf'L=>f+Vf:n4)%`_e28hcjPU'dZqnX+/+i:iJi;0foA#P,rN&S=OiHLo8co'(['@XGQEmC7PQ.U($fRp @Nrm3*ZW#S*9!2(!ONU7rEn%D5>D*.\M%u+0KXig)BgSYZ-$@Z'&iqr'Y+=!NPZB%eT?%7Q 'Y*2<%UHS?\URRQ<.N:f4U37f0k2!7+h]NZ5Tbe[N,SDN0qQ[6#%:rZ&'aRGl_Rj!Fc\MM0 [U#2Cn,++^u(/YFAY#S!U=I'qL9,#CEqpHo[+Tf>pLlbT-:aI5uA>aJp5Ri#I")Ss\VVJZ9 ^4,G"Z)T:,R*J_1u/S!;V3Qbr\O)>k\_>hs8N*20GJq';F[>T2R_&=!KPg+SXn1-9Xn%(HMkep@K6]Se8J4Q)s0d@?C4lYkQd]VO;.q\RZYQ`YTO)piTISmua9?dVWZg !t"*Z!W3fY[s.YoR*3,V:`Gg2E"SdY'R,cS!DXJ5TrUTUBgEtX\\">UZ)goaMg2img 1M>rWKBW.e>oL9j$=%FNS*3]f]fRWl6h/B*pU#5>5tfG!q2>gWjBgG3tJ.a&hjlhYZClJcQ )KaORd]?APMe0=uE&m1UBo6)=L1a.ejd$%S)*4*^RPM]+qRckr"f+V3tT5`(V$lSe2`0VYb /+gM_5.jrU5@Z)u9('(rX]ItO$SQ9!W!=jabia-dg1BBi/+_$h(;.>c]NRZr;jfs.V?Z`G+ SrUlHhRDH!7=*m5T)?I1HS!*V.eX`1V]na.\@EG]Wj0%`<)I^c,)r&+Ho=mt&+$oH=:1D5t K=)[($<67=)tkIZ'a>;gZ@cs3To'C#0u@-R5Ja?;JJb":*(KdQW#Q,Z(XUCUW"u[hBl'J]&>YM89TVG/:A+*'UU7=]Np6R![0"aVY_4J#YD['S-`/i?r<$&\=uU'Z #K;HG?P.\[u+AC08#]`C^lfQ,idK_0Y!u*,!J!lIS=f*!),7>4]IUdMLm#*l6aX4Q"F(ig+ $4*T=E%h!^oDllZ!cc9`X/J`n+-,8q6YJa6RKS0tX+'8!Y2'8cLZkuLKs\eQue%2/4FUFAu[9[\s'+@\]\\.(>4ia&&"BXSe]'jWnO_Y B/gQuH4_;5(#^C[I?2NVP5Y<;&qNE?.0mM4bLV!nG2(OKh+cW-hAkM4[f"\"rP"L>U)\`Tg HEa8h9LAjC`$GX`uQWoU#0eecm#d*@^7RLl/>(;UsC*3&-#K/V[?C7MF@_-.\lHeNpR=<,$#SjhoJPK\Etg`4` ,d9[jPmA+'`l^k`S`KWgmnm=[ejSdgdAtEID*UD]8?W5l=OeT045S6-km[aKeiM%1j#2?bF cXOAZT$-*@W"_ON(ng'OF=!d[A#=ZEj.@4Zf304]l-^X(PA_A*a`6[u0)4_;f(k0eSsFOcE #Jbbf(OXX6#F]Z/'-M-(Yk:V?%NYEFm'j2k[.t*+VD:/5Sn'/g#l@^6#mkEZ1K)D8\M6s^F As]DB/c=*8[alh7Qs?`#6=RqOahb_RLZ'l5^Ihn38`+Xs]=!%Jo_b@T;o.$/QDQ,SWqSm_/ `#c2\dATG!Mk6#)c,rFnsA=2);ub.iW*Xu0Ha1_*#9+kKgDAied817c9jGC8gpEo0,\U r,B9[CIQ\j7aQ*t*'UDTDO#GcD2uERP0:>MrP?G9LEB0RbkEFTkrddA/;!=-I2'.lOV,HQB fur4>lu9F7/[i6NX]VXTCR)L(C;F2[fBcOB-(`.kZWaIH-_nr,::XWtPR$j"P2(,^RZ8?Kq YPcY?uVJA2@g=P`+&7=geL'OON1mPR67oN0o/^^(o_ZCj#s']k]E6bHJ(uG>:^@EOXb@'[.gP9l,g>,e/5-?Q4jBj`5X:Nd!.Kc009G?!`S!WR4>?PH#qgS%[bKpjA Y*@hEpMbiSe0he0^Unb7FENE6d5d."['J"PWirr>;<'F+\)YVZjn5ql7Rru$RuOC=Vir$)N b:o#`P6SPT#$q$-+3tOdL'Km's0e>g.75723'?.4U>'?L8C`+-\Z*\Eh7krM;*_3L-Iiq9; 'Sdl'Z8@Uf87uAZB!$)ogF+Y:Pb0DI18M*(9/GGo^Ljf PhX^.B6:9L7q+!:D:D44Iem'4D,JJEKjag'I=2Td.C-(Ro[5>7.RjBf[Hl^PlqL0MV;9i]Oo(?p*=#/ZZ(@HX;q+&W/UmBM'.Pfet ^SA6G3uRqNrKq1q!J`i1MS,hCCBD;-u1^Md@8g#@:I1Hj'+>rP`5Ii\i7Y>gb:jl^"-Q3=d ;)b!?nI@doQI!D7'aaEtLGVe<2^6hq7L1(p?*a>';d4eoa=L1YYQ\D[S=;&ms/mONUgN)%Z Xhd&)&L:4_lT7+M>F7JiNaJ2d\Ya79&I!_6:`![nb40-u+aR(R-@r@TiHTg8VJ1?t*k\$+Q 3Dd']!efDCHC%U+IsmBd22.(B#PR&HT''SCn"JO[I"0D`b$PHNk)`=]=.1@D`cPE^2LXWs1 gnC\b^:bjgFKo?G';,`UQ''*jqSPOh\^&]X39?+/df[GoUIBb%)LSa]gr)F1JemP#Ve::=E Km>M)mQO'gR`]r,d>)hd[GP5.[a`%n\/'JjnV)QT.1aKJKnfR[Z@P'q`_u X@[TURU21M['u=ec^F.@tr@&pmQR3]ehtVXLrV1]/V[7M/Im.fF>Q2Uh05b^LV\c&`doo]U JC#U?^nqep"t7K$&4Fp7@o.-_33Ns(KO5!s7``j=^GmdtRDLpP$!G1nKTM_h*OE>%iH%>>i iHUIW#6%P>W73C/GgNAo`/A65DTmU+[e/KK8*$9M%-a:2OKgD@Ur8kc&d,[;:uO*Zr`.tAh ?H]\JJ`I?Uk4^I#fRO.GrV$J!$<[7[KFT77d:tA(!&$39WQHd.8;gZtlQ?GWCM_VAc3D5W^ t3mA)8BOO>ID8@:31#%3@KCB/JeJW`o4C@<*o?rG)a3?'22T9H;V@B@@ia3n0:s:p^]n_.*)Ue8JT=1L(U!1iNdmb;uTl;gm gD",d:2Gi>/2#T-Y@GSResc2>aMdS]&IbfVcF?_5@8uTao=3p=VKgFU"SY#q&6t1aXYco.e "@BPE/]pf3LZ?2R8bMe:q@Lo7p,@';+;n[32&bhPng&.>n4=5QJAEU+/BU*O]"538SL"K*[ A=79M%N)Blu#)#uGXP!HA)g4Z@:SA:9MO3]2Y*NZ!HH3(S@P,-!2QW7<3KNKL(bl!dpMji! f^@H]]V#e?r,^9#d%[9#d6dMa<%<6BO/=OqH.(ua1t$+Xh&X*&9^'&8\1Tti3n[5b?(.(bP VeiF"@>Heif.S5apnRAUD?n;b=cl)dlCh8ZXifmq=$+0o'Y`BRZSE)F+(C/4d_O`Z?GZm,h Bl+M=4(<5X6O&,lL*4%3e-ajG=E]-hh0HIFk1s7=j>2Q&b+hp>iDH)"E,HuB6_grC>J$;ED KX::(ImX_U!>Yf'nNEPB'`F3gcG_*e%>u5<0L"a`?JN;aXIYsctC^s0WjV?a^VcNG%q3kk2o UNOdDeB+\T11%ad].A#t)7g17@ #76O[4:XLW/nYhL/X\`#pCQ+qP:s$,nm[uAPcR^b9[i>K4c%\`#GGR"c=*(Pj*4t*uIYk9" T(MISIA&cOhh%fAaI;rRa:5A?$*+J_J?@b%]L4I5RK.L=5]fW/Q[l%)F9M'60`M5o1LLqd$aUdN4MO -+lKGu"&#)eZ\,iH-nGka<7(kARVfDU*pLkjTO`_/?F\EWe39'B8@VDX1Gjo$;CJ*QW2YH3 ub>W;,\-B?bE^g-#[J$/k_3d!@oEKVCDpocC$]HG$a6g&$=ir^jBHT&#nqX,.AJ#84rO!E^D'SC`-_P=EQjMeA!q Br8_d*MY@AD5B/?Cp_*aXJ#i82kk`'dJG_Z>,J?4'rsX]^L,`_Ufo-&a>;meD^f/*8A&,QE 8VNg3]O@HlLg.Xsrg5tJ#/G87BRV!9pV?tDY*`jW'7r@td(r)t5thrRUP:aM&OD'e_3>hRU +73#EJFNu^T8HiZ!/31b!E'sLT#M(.uc!&D$Hq7#,#R]CR;Sf?@ubK\\$r;E+anB4Mg(S60 p2?e1QXj@KneS52kiY5W]1#CF`oc^I0rs<&U@.G)(Tb648Z$g:jWc/jd_I+7j"nd(D9D$pX YT5e+]nW,=]7]f-"0KYYpGoERd+"iPcmRgQUftaE>K+E!UCo64?<-F)MC^0Z95 AXgcW-a_1WJ[cq8(;FA]1.OTOU%8$#Lg,nHpGb0:IGc2[c;9o9$7?n>D5aAaHT4dUe)&p8V O1p7)IK.87@4ZKLe)<^siiZo6s3*PK?,6#)I:(FB1hXQUuj3&>4+MOE8N;S&rU=ajcP(88Z BEIDX-pWN#V`g?,Hh_M+`g^1^:HW+Q6XBSJK3#%9ee]IB(coE<[9a5j?piib9(4MKi^(9q[ CFE^5cZHGSD6\'!q.d8j"GfoBT^9YU,16De)FGGO29@SWf3*c`P]=Z8gN;Q+u^dNm49Lt\3 9MEF26QlU(`B]k.`7ScsgMB:];+k`LbgEMdR!2,\QcYK=blJFgF(rkRe'1;1bu9+pWp@e1f ?9?DLM1gbN7FuMI##<(0/I92A7nAb.g*Ru"lnXcZ9tVt2p70@c%P0o!,;_&EOF/F"s@H/i+ WD2:WkT]b=q:f0Pgs_3E^!#KZc]H>(87RBR_$.VH"jg >(86?#=`_9?hciYSIOBTGaNPrV3L(IP7RKL08EBr:hcOBA@V$`@?n;$4JLOaB!(iE%fcd;m C3%ULi[0ohh'@B5_VGUGOj$-==fXT[&a09\`;NR5aCVQo@"T5.>I&P=QWg#JV8rXY8,j!H0 Qj,6SK@+<;E&GB97o&.ocJ9qm30/i&GD6guclE-cjT*B/a%V0i/S)uPJBS3OD$Mb=LSReqdtc;h%0mnE<, &q%]9A#+EX#'R"uQt=r=N$$dD^oOe?)?@@%9CbaO1>OF\K+WqgQT0AXZ9 p)KM:;=$MZIUVM'XWbKg.9:jHE?AW+ASuD0K)>[gVGq#.RWe+C$ &!8ltD.e*XfR>9Q+%.7DBR"gDVDN<[lq7+>MCZOMpdXcF'%E//6P>YuS/Erp+LAB*RHoPjkefdqMLYA LN8XaQu.O'W)eo=hF)JjY\o.o%oo1PR_6,CroE3Z/+M.YTkO^jo0ajh9QZ]h#P\fF:+b!)nUX=UX/,6lgqP,miFkkM3,[RqQ:9k[ =_Gp>@q5?qCW/h9=C:$eZ7d@#b]Sjpocq?&%]Ph=];UMDE0-%j-,3``;>rF68/YQ=1gOiFI @l6L.KVR0O"="qB\JQ6'@32d2kh@6lZp1R'n#);u_f#,l8>c0aBSEW\R7(8Wgeo'YKMOGsP<8_9kpgVUi60*bkjHNgQOE^ul).H37S1%T3Sk5EiUPA]Bi^QUQ- ;iX1N@BBn#,"\F87_o.@_V35L)f8Y .S.lskbqeYdrk?Ci62AWBSP)TB&TIs9M>Tl.,2IVk9d1k)A2"K8He6^Kc[+F0Ns3>5dKN84 MI*2W0h5sJCO@4LLUp3+Fg,QG3_Ucl^!+fSq<)R7Kt+K:EHt1k.^0PkYYhRZi5sJ`7VFIMh ad:R^F+!L;rR,`sYO,fk+!9n9g#@6=lqk7HaDY8=a3B-N#,k:2Y++ !C@q("!#'acm;a?+/F2a_%@b.8jiIu#1UupNOj//si$[,J"WbRj"k7C/fSc.sp(POhV"bm# M2L&>)dA#4$l]"YP^3k^ud:Dt<5q]`e-G+1Qd@B]GDT;AW(F9O\h^W1ArH<0AaE7_bFXL+.#E&1LV]#&OFbbtLHR*Uh>_NrrC@GhoLh"q"G6a dfpA)IH7qHiEZj,H26^?%(LjOo-BmFo8q:B8)kEji'MqH@@qA5k%+WXtq&U,SC@5c=*.37A KIX6dFfm\sV)$'uj3/4AKKf=9ukH7$.5P,IPo)=sL(T<6fIs;3L"qO7HT7Z]tm"TIlFLtZ\ E-C6PO9T*2#=jQB3*q?,DY4iT"W1SM:K.0MM[p.1Gir.UAUS]f>'R8M"oq`_%p`h7VOG8gq 7iHql\0KnI#$lpY"SVXF"g'Xm&/Nu3Pij.Z[ N/6Y/\RHLY\%6G(rMjITN\\&9EV/B(1P4IK/7[5\u1Z:\:SQ"n5oP?akLY[YQ&5"rK8t[A( #;))O[@LRY]+!,G+Y^'m85Hh^\I87D`>?MlIpJ(KVYk8G5jJ0@pl-km:!"b]2#:hXAd)[hE h@M(SI<[AN=7H774jC17kMP6q'):=mkIJiVtj,:1mM9jS"!dTMT<$ 3[GQ$8#0$s<4ZX!SPQ1`C/c"5h;Zt+[$Y^icqX3Ig2C>/(Kg_L\4LV_thfW7Oq*KA-M10FIG7k'eJ=W$Pg)sR.o^$'QA4XQLiVp oI(>.nOW?*DmsG$@,,f58"PDKfN[Z9t(kOa(K:RA],]%Br+5$e2dL[F^1rI5p(fD"k9^Q8Qr!5O[9%08a).Dft fkIKr$[Kk4RHCBTA9PKtb*&.mi0\ef$`":uu&&`Gr8JB%i9M6,>&S+lW`Y!T0(IjOGuNKPqbS'!U0?eJGa YV/i9Zo<<"$rAfOV1?O"dTDZ59IQCn^Me"`hC:6ch$f16-rR_"%1G"71DZ4P[,8JQ\Lp@=I DW587**'H3S/l2#dsk1Ns!8XP1#M.2j4/GgB@_+8no Y_EaNj;A;O+WD9$-]@'=:/R;;q/03!AXRumFI^>t'[Sb91"9c(g$E@D7_/MPT]hgKNM5S4+ j>(sR22?kVoRKaHQ8pqH'r8*c=$%/-F#iqOTk9.2GLe7e[%u>51R%-Rma\l(h7Hp:hpQogi aT^K19Gla$gq9E#\f\8+:U\G\L&tWCKW`Pq>GFn_B0EamoTB;FHfRX`)J8h!Jb#F.E8!d+- 5e7nj^F#u4tKALpArSgNUmg%Lu9s)D;&"jM@;Q_/Z7)b3K)gN\Y6EH9esmH`kZSc>2@q;.1 +l.W!`\mV-XiUc(+T'sA]r#ZHgnbf"4be1d4:,5^b^M^IRCO^tpL6]8M\+BVAb34#BK@G1,5'a'e0M_t\]lfL/SlR.h[I!,E''$PV;@;/ du[_l5AR0uYQU'ol/53=*/3iq-Z".\KPJ7mS$K*,(;YVD^oL*$^0)QrhH3@1<7AN<[J](%D n]7!SYPb)l9<6e#q4OfU7Vj4&BN4l/_llon;%J:$>,EQD8n,%P5BP>Wl*8XVXejRf,sK7J+ Sfd/*/7&cGLY#\0J>q=1XllBS"'['T[$DkT6J"m3M9@q*H#MAd(o%I?lH&49<1s),ji,K4r Cd*WqnjeZ&A\m"T2;mQJRaYkd9sdI:L/bmW71LLP_:CXO>O.[j/croB?6WH1DMGLC*)B+J4 _MWICdG>/M=t78#2lY41Q7nQV"k_!KN"R:!\0*FXskRE@#MBeM,@BnWKm@J&s9a_;:sVnW9 #+s6ki&t!?s0$BUri^[!4k4#ts.YPTGuk6qR5l.$nG[)YCjsXg.:PbEXr_'b4&>>&R9<,tF q'Sa-[t4T4O+;6!VkW`<6)"CrBZV`L8<\\fm E0&n\*+>D[sg!H*>3_^K9k&?ebLn8(dYZE%]7?>3BGAE^^]&k^?/Us+ARdk8AL`"CQU+L%) IYTG.\;XoZg/`bgCI?mO;'IBAk_Kr5 $pnR=gRACf56o!T)hOh!CY V^hnM\3t-ra+&_<7hcrjNs/RO;kj0oa+X3QN.8+73/t<9?@2QoD`iNIj])LuCr[KJ%0#=gL%k!>s6S\D@saQXk'`JG)L QLX@>j7Hj[p`QNXcVHc*ZO.3VsZrW@N>[rodDGA5RY7flcYEj4c?-E%qau@?C=_eLabt^gs *CE2]o?qeGLW*gg)`sP]:3"[NW85PI_1I\ufJE3o_Uol!Wc^-SMM=>Z>Q`W)%V^^GHNDb56 Teued=*ePL=FrUYI/Q0Ya/K)CE!@T:E8QLKXF8[)0VouNWEgXKeU:WqnIDp%gh4Y]btlQkJ hG$*PR=XM&##<:5dL5_"3&Do,5&K%7)o#7pte`I;;MUn\6Mu%j^gQS@4Dsc8@a.5C4q;e8\ 5\lM\K!pKm%Y^uS def^sW]h@pF5Ku*@fVBSkjEUVZG<'W-D#7S`mg:521^&'>(kK`:G0\tEciF*AaPA!F335$2 D)04,Qr1$an.,Zl%grFm+Tc4?hMZdP%j(8F0],/?hk;pAN1;p 2<\FY>Y+5E<]mp>f-@2,C,n_p\--We5!A+CN2$5Qm,-N9 _O"CJg8JH/4c,#>WJM_'aefE!?%S@$40R!c+M$O],([kW&%UTGa_B#>a(r2Zqr.)aTt:.uf *sIf*HBk&Dpf^\fc("b`TS9\_6OdFVLS\8-;X1LJE7/+(>!fEHW;KI2EQU-PD=adZGs>is=(C.C,Knnt@NX;QFQE+*#1,!T^>fUq][ 7*7*^rdD7@h^i$,q&BDHm_5/0VgE#k7r*dSbiJB'oR+Y3$(XgE@_ZuBT.8 tp\dt'P9TIYngi_#h$o6#9$5:_^5p1Xo&ck92(54Z&TP@@7V56=%7727^,>siJnL9U`38e6Si0f Ja+<8f0C^r*22:1F.#'fT1NV<*b"Qn$i;k+`#[gQ8Md89FHoKUY2lg3(b=kjO(V"J`CtBq9 Ws:'+hKn%$Mu!dRF5M;aa2Kg^9TQL9iUKG/\Jou66/AG)KYF5PP%`9[N%TY(f\GDW.Go8^J :bmmU86G1`nD/,sg'./"kb;+Xh";(6U3;*eYRR_8[9>1_jGQ7+44d'hq*4H5+12(,JS3F[p!p5dV^J FYCBXh[9Ida>HKYmJVd.of,BdH>KOhI%YViE`EdU'R;g(^FP_E7<(MRA:fRU(o`25Fr#Ysq 4&sZ<[Dp(7PSmm7;Dfn2p'c\LL)C!b)F:YBkVO9QdMXPQ;o-m$_8mF.#r8h>(Xk0>p-D\9; "0#k(DKqO1gOZ:)+GJZ*.`_na]]d[r#^io't3XMea\(K8N)cL*g*gZVuM.*ZX@2JE>B.+;ZAGDkqM]B%@ /9YM8r.1ef5jU(\I`,QT&GV5BF=[EZm7U!C:h9;$2gT7Q4Ck=7pr ]_]&<=IhB(RQJ7:!Z9%^[85D^Omm7rejaK22IKXA9JU\QrlKbsbMC^2qLh2)RjaZt768U&V ZnD9#+\t[1*nC'_JVAO2Q5[S21DhR&pa:.A(`"8JK390p9n`c%* F\,S\>iogFr].cGqMc/+ikPC=_G6f*9!8)+d&#"AVaK$jS4Nb#p3*66^N(DQaqK6d\s5!h3 `%Me+nH?;S.8M\!WAu:Ge`A(Y*qlWJl)HRZQ!L:n(;fKpc)2lmkMSfti\Za\pYD:Z9A8!K< 1?s,[oj'Uc$i2`$%G&V@RUU/jp>2H>n!.qOl!\rF7AOEofZXYk\?s'Cb8tt#Ga$[S)4.0EP?mk@ W[_*i3T$:8b>7*4*2.]c SrmnOZL+Tk8TP+?_:.OErdSM;c01?/"db9TR$qaGZ(M,dN2H8V5/DX!TG*q2m6^'Pl[@MH7 P\X1U!6)Y]4D__QXqI`@%,AZ+D$]q]I=[a\=g)ZDhd_J\]e!Mm=ZtO.(d$Rk:SD^MXh2]ZB l/+^_92GI;Sb@aBsNf)`6V_AQdL&DEJZn,G]se/9F$&NXtbo&>$Mf1>DiWuG01GmBG-J"F6 b\VkJA6$&Y82hP9/TDI.c5uni](`)))c$J<^G[n(5H'R?PYa`ifJ_d%J^0(L7*MM[;@@`+A c`k%G^2?SfTqP'2T=eD(^UsHLote(A"??d!)>jDCp!L306c!uO/@W.(MHCg%!:`Hf>oJ_9:il*Pq&jVFB+Qg)8kj)4buph3$@QT?L9,f);/mrLnNrX.,VObgT'i)kB"9>\L?m\f>-tj,!M.4fQ].6c6Q$dG=.^3QN+]1Y iQOa'g^Pok"sXc]W]XeNm(MTb8-WUIHE6(UTIL?*l J_f63^Mf7M2gFl4A'OC4W4)<&QehG*(EPNF6hYLm]I*^f*SFm!mt4CP#A?*$(hWTSu'$M`B 1rdpN+BsVYS+2P<(!Fsp`e)8CW1#/)DJb&"d5Nj-#)53JG]LC]fZG-?.8)4X25*P[bmBi>IiPF:j+h R.`chCsah0n#+1ss-H;t`S9CS=)K?GlRt()T,W\%d$;O4/Q3R]dn&*?3tq^8LiTJ^`KEiLd f8Tc=hS+32bli`q,d=@*`GNUT5)(a61$R7\I8i#J@m1a1P9s"X+SgLh@,=gj21%i1@oT#5E Ki6[9B-5d2H6D>%DN'8O&MFHNER'^T_)imL"&]k`97j4$ejO0GIY#-a894eh3HUZ$#G.eo7 q:+hX4eGO6'H.\rM++1:knKRd/t#G3;sG)9Ptn;YX&\I#Ral;d?*@>r()n!Ka^qe]m1u0kY 1[[$>O4#@e'5JW<&WIq42pLVHbWp,(X*Wo#D'a#nCX6`0+j/^@r`FaQ9-OXb2i#888"XYlZIOp:=ij^g$X(]hB)-H_;fgS>eD.YRJ?Z+mT99K^=VK>qL/?mT=.Ucbs[nQ!7:d 3:^dR25d3W_"[MQ^'*^blF<_",E++?-NeVh\9g#Z?`=BPBoKqc3#:Y,pW"%_TF<+t5W,7dG r*p=.;$:YQ6fqOQ;A<^,:/Mg]1k-Xh&ep6J8Fdaa,=td$QR>A1KUF8\nslI)9(K?`:7"B]$ s+'P.9];:1E=@h9_1*i1neQ6n(l>OH['A43o_DpHMGQ"StG"-8?-:RKX:TD& 8%d>t7c!Jdu=]"u5t(+0dsb9iH/nU1]ucAKs^B5#qAD-M2F]5K*qOlC:DG9cW u^K3;AFBr^faD_p8oe17?GGXT*?75!WDjIjqqfQ8tAcI9Xk'ZYd[CYm]QNd)U7r,3J4 EOIFaN]&LDuR:)ARX"i!k1r<#9L"sFI[RH4I'7G'LG)b-?qJ]EmnI&/fH*iEWgbuh XA*R<2)D37M`8%iP=o6g:2e9-0=>LdlPB4'=8->CA.fm+&pb4g>IHf'&H#D:u[IOC'6GjQ[ &Eu:-k'n=_$#-PkHJe%k rnjS,Gb1Flg9Ii:W\]CffG'C<"$Tfsq4;iW)8[trZfiJ6=mQbfA0_58KMbSu$?;%a8s6 pCq?qAhr5C(4U_.U_<2KoiG7MU@12>>-hiOO:MSBQ4JidpbsaFYC4+JDDC\P"l>*3]It@qoNR6,pmMWDW9i>n@uO%TFUodcBLf#s*eR^>%8hp?)5L f%1"JBUGfq,&b]o(!L"hWSEu/@$K92636V)J7,%OZ2ObIb'O4![C`InP\Og@'1EX#Xr7qhT8_ mjbLkEPM.PJC*&nRa+W$[-Eii(47+q%?pI")otO6]47#-\_o[(K'IQ3RPo0`tZ7^Mg0E+;; 4Iuh&E+]W+HMOOB[L9ClQiZ3DnH)8nd<9V%g)!8#ea.7mQX/e5i&;H>u\oeN9[np7FqHnC- ;4V3pieUJt>.2q^MHVtDq'Na]qTAh?r[ohqTFYuo*Y9hnVsphgQRCH?)jgT5O`>Rr"@7-\a ^*WpN/:jH"W1=`6NA")KL7;X#U_kQ3-."+L'<">,Tp3";/"qt^L)BfN'lr%I6>/0WI4qF_o g]LCj%W/`ocHQNClXXZ0ZN4e\X)[H>O.o&Bi)tm!uuBC)RjSOe_@^&G4/`6_0Bkem2]\+\5 u;aH.P'e(cR?H/EB^NfhL_FQ_O?qqq4n$H(uEVo#KYb,@iJ?b'jE;?IOR*3JSnY^A$4O@-X U;L&B,t=B<).+bDG1_A^3,%fi0B\iM*YO<&tdCQ3nX.kpBA_tXEQ=\CV`nWkoLQ=2%7M=kO \:l,r3:4P:X:QT66GAr-N=cC`f0F#>'\iDWG%Pc`uDr+DC6bIaUm%&7(e7#-4*3YECoKC4H l5MZ4/_pi_RIaH^c&1^rNZ5*D18]--MuWro6>3J(c%>NO;r&Th/9A -_K],iiLDi^4G2?N7e#+H3ho48C?B-#?Ou1N3U2R[1!"H_mX7QKNg>%g3Aqs0f%#T9$QK[$ =2j5=3]DugI8A-1)Mo;^a&_g('*Y&I)WeXK@^Nd7;gFtL`<*N7FFKocXIdf(Rm3rj(=eEY+ G^cl850Js'l#K:Hl.GL=H('Q0?1N2hqbZ)%O'`.3BhX./sj%d%JuX$LB]3>f.gl2c/&:6H1 )dj_3##)0t8En;]X3)GlJrJI$^&fKj8na&])Q!c^U;;kZZ-t/*%M^iZ$n3c$FTW.]$dNoHf $*N\PP&rKg!-A%['rkn$%;n"01nF.I[Lo)gj^YNQ6?@LS[*2>s.Ef&"&E'Qrn,LP^-mikOU RIq^KSIoYeT?g`?Y4t_O3O;>\q;@ER8fXBsS('?6a$h:LV4=>ncUDhfi620\`&CVVo6i'$; !!uipY/m=BaPM[8Fb\OXL?^e31]Y;g#=+3ZL-T[3,:Ed)`]qr^5hli7ljlAXpP2&r^$H@q! ;R`G&3/_+#ElR41`%t^bc8a15U7&$d.<#Klonr#-ST@kpfKP6/ZW?i*s<4ioHQ[N]K+n14t 6fHuOA^f%;[)r/"X%$(=@^,'^HZ 6&"n6;]Zj9%/OG=*bLAVslYuld?4@#,2\.E.3i1>_NIL!r4LL>#8>R&+T83hPo6kYhF1^g& %5/bZ>7,1O*lq\Y]E28^D6$uOg&kt4t:U`qn,pZAWC826Z?n^#/MSi\QbUu5H>T_/R1cap, 8uT][?q#*EL59JqHmTDfAHS&'KZmZ?Bb<24O>QHG6Hj(2bV$`\WP]u96S*);TNDCH;MK.+K coI]BPW:r;hcN7'APSN`&^8m8]6O-Xcu3Ye6/clC54KVa-;#nE,u87E^2HM6tAeXlq0f*KL ^iN[kp5Pq@Ps9HcV/&8=YQ.XG[H)TSI!M`XF*3&Cr=-c2Wt< :PQq"UI#/f`>@Gs'XO@_j$8F2oV5t$GY-,(N*[>CTG-uBkbR7^.g&Z_eNN2=[:)?k(h7c\D YXJun,1PIqK7j.=*\7UDI3.r\]L0.*dTN]E1K:M.E6tDUZBR--u35g2u92#W+Y[P;N@*:sO 9:W]%<4b5BE'M:LbT+Jn/Ak.D=h1?!8aN",CA(=fn>(G##28msABPLFEn:mE Wt6s8lT$/ODUQcRBJ-19YABiCt9#fBSM%.2/Am.bgFR\dS7s@:"p/pqdhZrX2aM,-[]jQ$u qC(B*Q.IU1cjsE+K0F?A>[ebO"L"49^HJ6jLr^,U@c&[(]<5\k]?rcNNbjN9eDaDTig^cWp 0>D"g_P4gXH=bZt!$H;RC!paY8u#=R+gX$JmH(']@7SZc^LoR(C0=i+`K>ABugt,:)nX)=4,# H9;WScQ+'(Poe?/*u,L]`+42A[3JR4,Z7>_,[6)7Ru5RX-r"s'%+PU2>+Gn+FL_Q'Zj[eOe LLuD(=;G'.jJC*abIYH(=JI"dp4g>&8;?!8?:r^X89W>V%?QG&C\T]0FXpX4[2du+\jS.9& Y^mEc.cP!scbrdKN)r<9qiS0:iGbLH'$H%7\jT+4SP/,7NnR5],#)8C\/Hu^K%*1E#;bC*G\9im$if8Y)< ]LOorI(-M+fA1mWm=/44ZCXm%en'FSHk]Za6GZqafI5KG;b@;lK@iG^T`&V+]!3t%7!![6onaIO8^ skf=rhqC-(S3qGLsG^=m_j8D5UQcW*4:>L>keWrDlMD9f-.STCc.9nCGh-c%jNgg=W(KeQu 8KQ!#uP2@*>2$#'Y9RSW=O>4oH9X;H`")8:6XgJtrAmBho3Bb!C0L+R:J.BuqHZk",=+5-X NLi,IPUY7,Y#2jV.eZospHO%WHFDGJ6n5sdtuQnh@8aSrTdc'! CnhA6Tr=iGpHOP`/^8\"f,i>b^iO&ceSk6`-"K(l":49FG?pihjr,$V=bSjdB5`]#LIg)Fo PhJ!+641LNn!mjkScU;alEA*ULlc3*03n]>:'BM=>lH'slc!ll&2)"]>q&YnPSS,%*k%@2Q scFI$$bT#Ii@@9r3XA>R1B(gcj8Kem;f=Re'so%8JrL@gI4[!>oQ1LQUChq39\jr[s5,[\8 2]5$H,.kk>u+_$H\@\,&/@m5YZ?/[*kWh`YSWJ44)\RO46??PI@n=BjjEs<*j=K6A#rF6)V P))".A"GD.444;"Hj@H2$97X44uM;:5[_l&XF7m<*PpV!1<0)f<#G%3_b\,L\;0!j"u'qL( *hG,\D9&!%1m@]88I;#:h!a.@Sp'5C,aqhHK=b>L=fL8elrO(mtEnSj` ,.1%)q0`87^QaLOKWl*b.fK%H-Hrce_gKY$9qh3Yss8ck*%]aB`@#IF\L@.miVG>dh?41>9e6Z$cDL5q7K1h&)#*P+(Sp9GtJ7oFD,Y_6<,0>K&3Vj3BgO?uZE2@HQEVOSEs+.(7l`eK?2OkoJE2ph^1?]Kr3g:b;e5 hNqj*Qfuj5@>8]i<^gP,kX"E6[Iq^Od*TPG]4\eu99(30@'aKpTk[>MC0aNJi+N@_Hj>t4C 7_G?Y,`T8&Qg*-Bcu!T^h2lBB37uI$b`Va,#utt`p/q=%.7ThL:8ZG'Eq)@:=-9SOElU(E. u<7CYc%$+F[XQX4%QGllNY&-CG@86IY@kP"'E5hEm6'SS@5.N?j8D];Q>6K']CpPe[a/ ]#c\Yu+96p5If$eJ"e87ci-O=[GkZI05BGXsUR4d#(bknoiPA*JmD+JZ%3+?\f_[_6sL5<* C!V#C2jDBb6FE[Z>@fQmb$ (\6^TL8\tn57$aDV^JrQT0-PMrs@_-[ud!3)V;8<@8kGQa@.m; o76!:'r95bK"7=Y=6Kp08[3/p5a*7mr*'G=Cme%FgYgWp q(Nj@lC\XWA2j\a^jRTPJ@n&>%#H)fRVoGo$"t\[F(Li+1BE^qJO_5"B-ul2POfdMSH!G[V VFu1FYkppZSZ4oM&".co\9j5h*`-?m4_?\R\I-?]CEWQM#D!-;JpBn.#>euUVRHdaFbX:rE 2O(fn%2M+E/*jbBVA1G2X#IJb^,&h7D2"0aB40NkEG?fR $M_,Oo=j#:OrFgjRN)?"VZ)GK9PJ;]mEOrRe*V0\?/&\9K*fHo,('pJQdFHj?luLB)4GJ)C 7:\T9tlp/u"k\7'i!bl7p%H4Y$#0P86lT-PA-I>][ihjJgD9)iQ"I?KWr$CN?@id];QJ)/U roL9)gAPCioW8NbN/05N4L-d'1\9p1X'8].e0mKL'/K'RA^7pFh-@H2qu%FpOU6@.,( fB4.a8;Q0CD3&6oqS_(^6S#XQgr.1*l`R0'A(rfFCBc>"=]Q"q3;;?F]Wj$2#O2#2S-IqW_\@l'c=A#pl1Zc(;d@uS\W/[Fi6G(Ck2O[m]]cVh#.Z^%(uqlG@# [XlW_U[C4J>/7e6NeYd567h80"N>G^Z2s[+^fcB/tf2:=IHP:t*r85uLZ^/Q#Hs6dZ[1Q^4EPqA a%>QB7+asPLqi+5en3Ht:+oW-(u!VRRNuTp@1?f,J2Ceh6',Xh(_0]!A_6?WQKB'S*c@GN1 #R6p'!7=ET1>)Ce`3%BM4s.cerc]k3^/h*)O5W_AKOFql\R*hp98*J%_]>iCV'JVYX1j:mW `L$51#h8B)E-G(FG8B=dd5%]s-qZY48c8>JBjEn!9J1A"[@ng9;^t)D4R Suf>_jd^G3t(>i.O^+(s!dD];,GA^]^(5&&Ll=g:YJT-o+Mf_/UCC!.eM_5qMh)K(u"l$`B 'Cm5,QPWn1-5"jq',>"tO'7DfM*QrOL8UQ-E`I!,tLS1m^jboB)#(.4I3%cQJ3LWI9X%O \4IT!Uk@aWPR4iF^XGj?JLK4t&i4N5Z!BjGM9Smu65(-&)-4%M'_H4IF))=[:+?nK&lDR*c i3/#Z-5OY\>isJ+In*(+4S fL!a>9^4'dlBDG`P/12?rr_'gig*8f9ocjS^A@K328QkugXC<@spZ\S7"E$S5kWe"Y@KS5Y SgZNo;C=i1[T%)Ke9C"5YNeK1McP$j]uf\mdD`d$#Ok<,*j@UZ$pV,`tl8H1H1^'p)UpbSF$Ls?,Ch50&[[P]L>>%YE)f'sqVTE$]AI`)Zr 27_$D2t=P3c1G$\(:Q:30k9f8/63K288-"ZT9S]A\kq/52[c-oJK,%WN\8ZZ&GBL,=UoBX] )+dNi7m3lZp_g \@+e*Qsjcm(%@)*3PYUEm]LU7bYcO7Rh/9"'!_"`B.iWLP."spF4=>LY#Q47\>(ulJYJ7>u h",a@\29+;))W'VKHElSPa33j!,shOhn]"#=dS+bCdA)/r@Cpb;%H?4@`K]qX?l7oH52Nr[ O)irGHNWF2\AkC/CXu4p2r?E'SBtHZpuE6Y!-[,NKJIN?+jS@-G)ongOkdbE@:OP%Mkbo:m -Y_;eXW++7]MqM/#ljTi`?0f 4g27fN8^:JPVh_ZA[$HQBGfbT5&otXcDuWkT&tm`VXoqmqBjkYgp*YlXgtpGYg/"$&#a19- KTM.aP2?MrepK8Tf:j*'uM:gFWLkAq\J5M_Ze*j[i@SXYAN[Fc\J5s6\6^nDslH=]K95JcT (rQN?a=@`6Ru4r$!bmK3W;O^5LDi.Xk26f9tti-!I`*dhk YPUPrGjiR+La!:&p`$eQN6c8,,qKh$L%XC(2]^+d!Nhg>7Pp.o2fA6/sP")N)hOn(]Va0tf uZ,:;_'Ca@)7DRW37>VC\XOCnepG6a0;9a[Dj&&S@NKS XBE*f@3-Y`fAAQl?(='sJ*k#D(q6&C+ 90(8EL4iJsf>E)=IYCkiRd1iP>nn2ga?NYS7JhbSXHkqEk!irr9@&>ne2J[kLDP50$c%ac? ':hm6i#h,u^&eQc1&MbaXn/gQBs5F7kn:q]KL:M)h'2_NoU"17Mb7.,6f:d^3T]6C,B+#9R N.Hp)i:RK*7hd5;*?iWDXe:d&#b-nh'sQ.(cB&uR_A7^\*aukO_4DW4R1PL\C_1@s!e`DO8 :@`:)'\Jc+e]$Y!8i>5P@5Rq!IYm6%ioCn&KuZD+jq:FllSZ3)_pcLd3PZ1g,poj*teMq&M hC(G9DqD*5TQ0YQZ.)(>XV=+-;runW%gr>b$Yq(9qQhdP,4jW#@rR+L-2;!^u4h5n1qjX3/ 7&;84D3OA<'H(3,l`%#439*Z_N]*JtubEYp-XHld"p)pVJ!_2o6_8K=]`'s_[*&I`RY\/4, ,*Rss7_k;ZJu6tq/(20$NDS/&HRt=H;?>cbP//_E0HG`$)\Q7+Wlc/. cQ_rG,;SW<:[elM5;.k`o8;t(#Qu5"W4LDY0[`rU#*gL_@3JDR_,?IDl;no;(ljc,2,Kq_6 )#"_LpPLT*A\iq'!ajpR45tP*l7D^ZI^s)<#s3U.ha+Ynbk=dB/Yb%j$uLZP05MabS4q^$r ^q$$[c^jqAUTl(%U9mTq_MeK`4m>3R[@W%jDp#U_:"X3lI^*n,k"0/BKH00_:Dh#CIIV^_T 5k*[/-MYI#=n+Z(u_Ik54Ro.!d=Ill\%&$Z'RXnL+-=Zs+g1de_miMmmVU`P*VIPZUB#;nB 4gDWqg5Nu"0iJ=qL'1.p5`e!7n8;0!%2`H@Cn-G=%aI>NG7]@Qb*W`Yd%%dl>NB-Pe7C6A1 !JhT.nN-;'Wc5i9C37$]DV$]10f4:0;i2=^9H-pZ#&5D$e,;GLrmVN&b\a0"["(,eL)N?41 Q"^k5=+q.8OO4W1^5"Po0Dq>9ZA7t+m^6aO\=f3*,tLCo]&\=[N.Z\)&-j^#H[iAb> *0UR^7aDPE/=%7htQ(7FS#$'b7>HVA^U,:Gcm60n1#k:9-!Dj])OJ1k)XXKh.Gf#q!_7'\c :"[]qP="!R@a:rnP`?W/1U'u>qZEQGK&Ee-):p=nNn/ZZ0/AB(57& qMbR3-#+'/1q$lhRh-8mAb(.*_;3>9So6^>rbNdVVm7:h9O+4J4F/BoeFl!/AK;-%MG2& T9B:M5HW?NG?AX.11rg_uI8?rc2F&g:Se*@o.N*]>$]22Ht#dH9VGj5XD5_W'%!NO)9(+DT6!EWrCW:3`"=#T(ZE,t?R :`gIV!4P/,!K-I!^k(\b&[])`2c,..'X@:OE-Hb"ZjIjq96X!/D0LPV(Qr*9mS]ArH,D+E- ?j`:VIDGj4Gj3^kD0Z#)eTs)H`X"]+efTNT/W!RaO+!&QB-Gq4>q;,FE^AD20L#qhfuA(&u MnmW!"2D7b7/=I<&8%G.JOL'm>-6D;eEB[PkrFa;M.YHC,a$t"?")Y46,&tBSf4:U((k,)pg\['B%TD&(ng(8JOOsDiDNO+aRU>q(YOU 6O%5DGIoQ7_Ko:L@E]m?3eB42$Es[Yr,f5ZXfC`3>pJYsrMfYT-U,p"52(il%& CJGiP$&i!@NPoa&'K'o5k8.d9IMgt'"LK9!>^TPZ>EumKQt_:X"+1-B&ib'F2:S6-@hh;5M Kp7&M76JXV--m]K".54#o+t)B[;R(?FMqX%ZhG##Cs;pNB&aW6(/c:Pm4F-O#^Mo@HnpXl& <-uPo4I,DU'=L]9X=]Qc&Z[)%hmdVbXJ^QhcY3;IF3>B(>[#RFqn.EGL<]E#SLoKIrC#p4C k$.*LK%\GGGaudA4< L+^Jf(0BLH<.@#I.g"h)KM1V6r'R%AdFa*ZDl?)O_%b<8JTfH`+5HVts\qTo=9L$DZPq(dY MF]+F=A"*IehQ27*>09*;6JfDPZTc6/&)TQbSpR$;2o+q@)gJbOIN$$4qZQj[JQsEPBj0tI AY"YW0!MC&$n1rXC;NC3._7-WB@',ATG%9VAFW7-N@[0*sd+>/4U)-VlSl:\(l 9tG+;Z\?H.GhitD65uVL]WboZVSg)\SdVo0aQagVShe+4=RW]J6?(\:"C@)M 'o!Ti)`D'Gr"!(S!g1k-Pu[429E,QXTI5Rmj?GVVI3\a1RIo".1@M=i⁢A_n_r/o,gCpN #;/_QQ-r!U\QZQgAU\9Y6'fs<@CbrjO]`H.-&-eg#:s"r^#\m1"mQKPj$NPt@ZAfNVNilA[ I)1\Ds)Bhbo"ane#>AB\+GR.R&LhG'si&iZP&\SY%(c3;R*)'V,E]EGS4X8EB>TQ2r*2:Rn JYWnp'>YZte@`/_nd9Aq-jd4rV*N1,k5\SE_(-`YMhLf #9ll+fiU%_NVf6(nhV_]Pl2Z.7,LuPFXXO8TYuJXI$VK8Ojpp]s6?oJXAT)d_q7FH&^U,VF uL4)<%;&4]0_bkMB)j)<%(t\&emopCZB@*^RKlaRl]o&_C5c*eE_'r/#/*0HYlNFBJVbT.RM.H93q S)KXc5ug `#o8+r"PtrdEup(\(^[)?'0j_Crb,j;oJZ+?>_Qao&o3r4j+sb$(FY?INX,FdIn`_:rhk^7 #gGQ-Z"gJ`1D`!CsIi8AsAKn2735$"UuGl1@H]jWX=X^MimHkAMNGn%U&$lKd"cLQ!TF#iW W:,"4P$/+L?)qS*d_#eec[A0M1)BEkFcRP#AJ;E,aV^Z"\.ITN1kkP^&cT]bC^_:$[FC%FR Sf7(LKT#;2Sa;CT^(a8t6?*N(!p`pac#DGKQOGJ!2*t=#oi_`g:?7?_L0q56kqm!a0I_O_1 =Yu^I.@!NeP1ark@540Dk*&rThJkQH:?Rhoo_sD-Thss;=u@@`6[h7,N`UjmP2KfhC6<84C 9^jB8&D_+W\2B,^TSf2 :OIGcYLA*KeA&nek,e=#$&dA[@epmVb7^ctN%I>o&o$Q$>BmQp#W-@BnL%p7#?rhW4i&7@RF(,=HC[7/9q&)7jXKa3!gp;g#Kd>ZWf5G+tskdF<6*'k8_.RRFL&A3:W#`FW2\AY3Pf2Kbj /`<1H";-7s`[aLZMl!A`Ya'Et2:+,SAE>HumTls^cFJF'pE4dt9gpa][3LcpL[7"B/4o[q- fEs0J*JW\FQl`09eK7;]'3JfA!1B'U>R&!$"JRDV]!/O+2d C1&b(e//,B">?fUJC"EnoC-Fq2LZtH5;.-AXYN4US7t/ct__^G+Y^J3gQ\DC8onOH5s,.8S qJ=p:IP5Rh!3<<@8*c=WatfXgW)YG2H"9&D=j:()n2B@[R>CWP2P_oqB.h]E\\X=_;B:7;h uS<-4YM0%?&%*0Q>-*etdmb[VXD-uPPd`--6CI2>A@+",b3'1Eg8=/9uM03j,%0cBMMiC@% fEgQ^L2;WP*pG_"(^'BDqQBJ[Hj@cf[Sl#+ZEm<+'B2Q"&oU`Oqm!C2lFEAQo3L4V$rdSAI I"+(Xo?]Q0,,89KrTPl4uH#D!CnIi>SpX9CE\0 oH`=Mnsu`>UtAX%MB2dGVo_6iQ*.X\8;[`6NeB2hA\eWH&j,`!b$'r>lrj?_`*C8guu6hA( 5S:pit(%Hg-=sU*2]u$Hq&*p/Zg%F,V9>2T6puGYppY76#&t@["`?N-ULIQ:.$-5fF;p"Dj !pK+S:ad<]]U*lb_C)cW<^Hc%OVN/5Xt@N9QMdG[>I[[S52oRDr8#!kHVmQVXMZ\6[077`g `s5\0i*eV[Va>k[qA?i9ZKC!oE;8Or]Bq-$X*'HU_2^r/,VNd78`8-,1">bF0a?RO)^D.o%s1B@CUJAAZcmO3.-WrHAPTG[#/E]: X?":sGd/#2`E9Wp43)$cVUSMc;*-4;9]WGpLXO1F]/\=$.-hlU0$>/QMD<$)/YuLFe69Fh# =`CN&JTq;$M!OILK0m[OQ:I_qRV64f\mTU^j1qJ2/Y$$ECRk0NXRE;F)2J>FX,[i%s6u7.^ `BIeV;pd])7k"^n^u@8&hZZ?S^Yi>3;?L:.N.(hF\JG37V"Of'+m:e];Q=_b'V-,gY ,?OSu+26!^AENVI4iMLBd`RWb$2ZDXi4,](QnN%of1B?>!LH8b'fgd:NIC53c1+LR/aqoCQ h@-4M#&RnPf9UE]nI8_,b^-sH[7=a)adGr?mN/.3rEmd,RrTio^_ssEND[nVZSm$R)_%/tC9Ikh./TRVke! /:*g)L18G7P:tO*)5A\Ml0$lTErj0HG8HL>O:fbaiotVSCX6=(#hqE%T(CONURco82[^Qq" 4G;>S%AD).*>1Jm*LRaX96]sY=Q3:e3obA(oXagl2n=DLFA88'$qT_&V)D)fj_D`m\>ADEa 3Wj7bDX@\9Cp6X\5AlT5tKGt-:ee@FmEXi\#5)7\ohMU9HlkBpf7ej/-UVa!/^*C"?!::`[ HZ!Uuc8LGSfJZk^*=ed/2$V^1ige%uF$5<'?.dFA!e)fRI(#A2-=%QNIF_d\W]A(b"l^MGV 0'DP1WL9ajID:1E\==&`h;Il>q`=&^:=:f(s:_tZa"E9aD'PAam6X;prO,dDb^7APN*Wn#M oX?GRo#V#D?[td0uu<_=H.4WCjCgeWfj<(unp-_.S@c53=92lFfulPslI`G):Y/6_BZbmU= @#QT"HlLX9>sE\g+Da^el%AdQH[1rh#k*b3uMpqLO;7u6j["%[Hkmj%:KT>0ql[!7XOiU)( Qa8$OuIh0iY/NXJSmN4s_$99>.r_M.5_TUXiPkIZ0qnbDl%C`=?:cW`JHD>qD= *!;F3e\SIK`HN3[FS#7iTu&l\qqjREri:qbMnjb*n8nn;B0>5#^gkbWCXKGTB84K(3SW%Dn 3Vj(CPB;:4`f77$iRmCq7[\j^!LE-";AKP'L2qU_!DWKF;McE%Yr,PW*4qij68kAl&@`^#M =Ge]GSKdq68e##7,4$N#\Jm8H\SS_IN/RF%Z^FAV;JSZ&-Og#tU0)Fu"A]L;7^2BQaW*CQl 8W_Rmeo(h8L'T"3cG"dio8@'^& nEX$3%#I&Ei/4ZYsGmD-0\gV8[A/3&$9>ORs7!(sfoM!5mG,>K]$0k#W4qanjV&5V+ZCB=Da+G:dne`5DWYeg'375FU)l##OCKk)`rfdG6\7F5 t`Ari1n2GFGFOCL9PP!6p/BJE5r*$_qMB+csjp2j9?k<#/gt,Cdc3H7`Kh$U_nA?PY/rk9Z F/^8)a*Y87tGgJB/FTRFlN`r)h$.;^i(^80!ALZTa=%?H>e(L-T;Pr*D^;N()F7L(IjIY]5 FX@RtJu#Io-dCb:u]CBj!&7SmhF/TRnD1Zb1WGM)dLOMYfd^6Zfp82'ST1J;p/&= 1bi0,*4M%,[OAM>W=2qKXBWcq]ZA;E`NV1R5\C3Rre2%IKffH1"LnoVE/-,T&i>jW:j%P4C ;R?r1&,acS?0lm_5o-(M7L#!e87\5DTW*V8ds.m,h'maB842u"\<,+.qF@%.gFXHaV;llZ* u+]H)rE.b/CI-oZYOtbTi3[Y*/QS]]7:);)^eCbG;MjC.1H;=A57GcChe`da:g3m#P7Z#"V !Pe;_cWNB1bd9Kn*]e?ttGu=bl(u:SeDb,cX*H@?b$qc34)Boa[*^HPtoQ;'cjZb0W3Q m7r'EQJl3U72&OKTWP:>68]NO=NO"!:8"Cf9AK$als,8i8VWG!Ou1$3m21cVEX,-FbljV96 Q-;NERb[5L`Mn`H+Q!/K:K^A;3oGcM^A_q.E.#225 4HKQ2eQ1R;!G:r*S;)>*jU[8WtsHO#3$#.SRTAM@$T!nEQ&5=63T:m95mHQN\dWWk4$I9m>5T^InH3d +r/4Q&""3J5n0LcaAGY[>UaF;:L#3=PQk$lr@0+QqNNX4+1hr16@5]AV:e<=_,5hXM;sbD$ :O0eG97"%@abNSL:h$=."etn6?0Z:9fE$l(EbYj#I5_n2>+iB\aF4 B1Q^pjB>31Rnko!'cEJJLPfWD1.27&rPF3$5!=ZqeHU;nMGZpoH/gLQ/N3)A-89@kK'%ik, c-u.'hY_K3Fg5Ua>Q,Bh/Sm(MC=oG"I=C[#"ACDYj>#hHTXinM&VkR@p4e9Mrn=LST2;6li >[>e6+H$FcOP:=cad(3.Fk<(N9S^9e>HPA3YkJ;M\IdlT63S7D/0iuYi2iS_L0-cFD8"OA+ G8c!K_hiO`>@@lkcEU2*t?[b=C3N`*K]qW3oHrF*D`iZUu;]bKBW!aB4P@On9GK*U=X,nEs'KJ!Vg64R'SFB;G9=i0(?(8ij,r/aS1N\(hI4V-?a_]Lp)ZiZ2$j8F*0*/B2 FE[N5_f1!@ZEq;8k7Ao7-$^(+]r_WSk!7Op"Qu_\1T:<4MKL%_*DHW>inW>1*-Zlmpl0e"k [RDGZJekeMQ`a9AQ9nk]a5pW9j9/.e&8nXG?Y3>MNQ#NYAS>W"BXA 4`_"d:CZeRic5pF&%T_\?=QQ-"j*#a'2E9g <3p4e:QXUo)#'JV;R:ZhgkB;I>.Qf%+@$u<*kQZe*E57H8ChAu'kb2$&i*BIiLTA:G,X.(K nAQOf:bc'1k5Hlk2'B 6baR#"^?'X,Z%]lb>gg/LQVfjGH7a(0$l)C%H.>F!u#*TOA@"p?riml5HE[3J2c>A\<#?Z8 ,PH=uSDdO:K&BUQXk]'2icG&dfG4opc;=,58"*XG^mVu#TEq"sfaY)69T-K?*FpFo!nHb &,n7r3#=9`/,E)todB.B;dn^9,]bp4u%(r&8n>m2K[sM-TCQj7:^$ NnU'H[O#S.,NX#&BEQ:,AQtD(l7.KeYks0(AD_Dr[pkA`1FC<]RX/A"622H3Y#.Rk-QRYL4 /98L"o!Wk!,8"tb0D,VS[6mqOB/0$pW2n?,-bi5o='(h`B0SV@Y96-G]c$rK1f1u&>/;?YIF@ UBE&oR@m$LALkLU7Phs`1pOedl^%< )hS.K'4-ou3`Euka!pa:rWG\@=!B"8^oKns=Df5>dCDg<.D7!=?dDEjH":Nh'6cE^g)3kZ$ SF7r?p"k0O]]t9RC-sY4O?`r%Q#1bs`#;LF5Xi\%I.,3;Lc/rKlC,?LI7]`Hl1:5(<'@2r> .bB2f],IV2u5I.C&46M*LN;X7508*c![GDEDH,KJ,Y"@ISRZ@<\=ru,n]E+F;sbCJ6t-`fHr_O/KfYaj GPlVI+-9$(;E6"g9dc/tAQ$'L[TtPR9P.3`Ut0BAS5*]q\EitKmVB:9.VQd:01Umt.+F\s/ tGV5;ee/cPuakcJMW^m[Gq87?*Dk](-<7s_e68Y/BcTVXd%.#[+e27Q."i<]Nsu-CZX^UHb Ws-(d%^5"bsm&nQ89PNH75'A9(g8VH5@9b[tp!]]OE$T?q7n=uh4,b0FG(fD;%EX')XXCj! ?QLcemcjZ=%_VdZ8Y*%ha4NQ'su3F%#?-^iAeFB\Q-DqikQ]5cUB-,joDd=L"t*HmFuGMX-qja#^LXmLJm #uU>B*X;/?;pJNpSd0lm#4]'"T4cR9I,Z!',g7=-REBH;AS)=&j-\[dKObqf6ALukG oJqY'Ac\F(T%JdA!s,:jAB"3Xb3*Eq9&VQS7T\fTBI1'Kq[^kgJ)Hg7M3"5e9*9i=4VMSTr I<\Y+r&_KHYq\'%t:_JY:Y-n#C3Y:jBV.6cfB=*aDeEIq>JM0*DD"\T8-R rAXeFj8^MP7%r9qnS^'M^cM:024uHhqS8&\K-]PD,)_DDBSu4MIkP?6\Vs+=-c%RJ`1#N5_k9Z$ba4,7YZ@7)1Y_mF/F(gRNk3; FWU]Q"DNBaS9*3JS16'>r641^82bGL#tlN.CUYL<-!90=iJu[`CB4&@Nsj_C@uVXVK8$e/Z @p$&fXc/RIA7(nr2E7T[nRT1!@P9#P+s(:sF7D09(o&?hS5H/'`js2Og;p92_Am6KQ>%@OFRYl#2"J\,:-$?kb9(G]COBhdis!ZD/+8%[j]TMup$Ss9eZ-s3/WSM`("Q!CcY;l(l&AE>kPQGE$UH2hbY_)T$Xc#[4cYlJ9R_="UM2\^ iSA^nJ1p_Wk>"lo)g:jW,QgI?1Z#DJo^;8#+eIf,EgXC[LAiQ`e)0X4qt;.*ESg$Gp+"m=" HBq7fC-,E=LmP3iGSZhP!T%jBpkn(n?sm]kA*#A%RfL'#4O&LWP]Sg5?b_lOYXl/BgcH3W$ \(3*+R@U)W9dQ$V8"))K*!tHnP=H9p.1?E".D2h9r^D](M%cc>.YXYbI]0d]h&$bGWnjZ1u KA_0=J[RUoc#gYp:A8=(iK`u2=>lp&E"$0t49lbuK/kG;AmETKl,ccn`VO]GR$b:1 J]6N\pRSSO+0,%@a2ToM2>d_bb3-;8tX$./G#QcUdA-+d3/F:WbVk/Sj.JYO]-;f?bLJNVp JW#O)./]%^h5h4:n1m'dp:qeBcP2X&sLA(hcpBkGVl\+BUXg8kQtNM04VM"'rCRO_BUh,6N .(*qX]c[%Dg-8r62^)#AA:N,&T^U4ELX4[#fDU%(>20Q2G,NsDk?6+9GaS[+^FENSJMDo'P _rFr/Nbfb"`mEYb)rhKLNo@m]G$bdA>d'H6e`dA6+#2OW<-JhgVou$p1!hVS]:0!Tenna&2+nGpA@.i_YC)Y\]b<9lM-QfD>5MSKet=:>J^XqHb-\@Z YR>EJ;:+2cK-DFF=\9ni+Tsh;\?FNq*\Yhg>YNj+A=i$pI>+p/c>*?8'qql56"@R?hm)lEBV,ei^c$M_b8.uO)0QJ jn,;uga$N_Tp5%haqe3hg"6=_(5Fj13O*C%Un%jEYs7O#8f<8Kl@?(rR2qqfaq>ZNHIUC;l #I*kA'T:=a5=RU:kc]JCSdr?JfK+b2m.=YordV]\+N?)MYL6;M?88-opok>&K?tXtj;ZG0! Uq3WDe^7&>d_D<)WEl>Q).YMB/]7NEYr(sn:gm-`1RQN-HB$KuNW+bG r1ApJsP"H^G#6O6r=F2:hCegLCeGW'(IZt7#pJMWtVX`*c@S`-K(33E8/aA '_+=$#Ab?QYS=s')WGurTlgbtpCB]3*T>usO[U('*t:NU`$&mjTq!&&5cTq/)"?i$M8g8RL _-V[m."bf;#1uZllP-=(Qkq2;(*N)%f;A-)t>!^dD[(-B&_d%&ofE@1"@:afW`3a+!K\n8T tnHknPc/]<(6;V[:O!-eY(?( Vn&X+(EPp;(2(P/(h;CmZEV])hD,#V6?VUuuO%gJ__*0O_M11M;@I2pN\)fFr%Z;W,kGpfR Zg/8"oYcujnbpUIYo<1A,;O&X`7eETc+p0A8_8mF57j3qN`Bgm[d^5b^.#Kd[09Lu&nVnc6 aWn+63D-4]Tq<0b^/r=!(BkfZP.*&SM'ZuP*,\.]P%QFgAM:?&b&6q)61W.'kqKFQ0^(>6! Ql6WR35<%*U[c!"H*3)nGcE+.TX8^3eV=o9Ya4u[l[O51JkIeK16g]aqqC,1i[7`N)U`P_*4bM23Ok#j3ni bMAW[82NquC"+r0\eeAei0!a?i95?`@(c/83Y[P]8;iNeZ.6/(m3Ck-Z1BfIs)agtq6fg*( F"KNGb.qrRr^PX1"%F=ti#Apq7'pAjM-1RU>UT^S,f-AFF:UPC>fEC=Fd,ls-1XbK.g0I/jI-lhOQ)"b@3oi"k4]J]!>TRlMQ<68*>Bi_WX1=8! !iGDA5G[Soal4n1`%m'8;ZVNH<=09@h_3["^#nRek'U9\B,Mbl4T3*tP5[j$`O-<`>UhmE% 8ThjIm_MKdiDZ").(-6RBelD?;,t$[(937ngsqNp,,64Gk ?ig-8FQ!H/0@Yg)-HJcPf>2WUjO.*bSV),@cPV?JZW>23&:U'+"1gie[\25)&`"o>W"*E/8 %m:f_(40(/CqM[F&Kk<0K18?<2&P2K]7=Z@IM%ODS]DQA'!q3%+*k@C?;o15SsFofPX*^_R r*2Nih/dc*ZMA)ZhJD?,V7)4s,$OeY^t':/CPUY'(/\pk`7'oX&dqtgd]mD-`BMi '*$LGW2;rIsof2YkJ>r]b2X>=+$!-$20m9I/#^dZOg?/(W7=i&lND78*-NA_ZJXGKO3DG4,LQUNb[0O8,<)<&RQG 5GorLMr4PD[ETB[s*+AR7u)2nf_:ZGGH?[]0#[Q:8,p-pSW%u\9!5B*!'nuKdgi);0/)K2: fH02k+4!MB7_3I(%DP&jR(2@t(mpI,T!%-HS*<>u9(>I<0oZ_"b;0D)4-8<3"_!=+@Y7X*WbUJpkO`OWBms+KD7!* <8gSO<5g$3)E97*(r\9S^geiY@RZgT(ZC)cfk[:m'e&m8["QN,I%Mum'\H+_OR%OakR?` pQQuBL*GM.tE3MeG&r7muCPdrh(('u'=K5qbSK)*6P/-g4fCgR\1i>HK:Vs"j%pQZVo.sY] lMm8g5=>+TJQ^RB1_ijb&*,PFVC\cj8L?_&bPF8tJOnoX&_4VcVS!k5tU&#o\a_i&CYuqmW B@`J'M+N%NnY3S3:LV0\_.LqoUhAZ-*?gK8R;RGHclI\0U,"!YM"I:m6AIBNNp/3:WTO=!HT\8BF5 'F=qdm)'N:taWTc@GgEj.F7&=>`H5aglY:q$6eKm2gN#!52R`2XH4,fk9N9;@[iK::sg51X YZB/F/jc!;M;mhq%)<"Y`H1e([s0'$5Bk/Q[2M&:J>TTmJTS^"[],A/+(.?:hU1u3gS#*]9 0nOYf[$`q,2q8pO6GM*FZTGF^/HQb&e8dP5QFcOu/$4j,l+2pdWTB'W\DOaLe5sk9'"[hHN l/&qF;)VY(I^EiHOIO5A=tCVOSb6PS!COs(,_@Q66$WG;e/;KT[AA6j_:BKo-L+6I\"i''qcKD_6kt93S3-DY.*=KbAf7:%(]giW--D]#kCL 9Ll8sqGMp0=K)o5dM_1Pb(lg)XiWQMFh+2jA,HnDF9%0=i[ULD3<]XQ+44t8T\Uio"LCUtS AdD['ih:pT'goT3L?5iHa`a%B!HLnUnFDAk/&DVWQj)BScIEl]m<\8@7*1=qHS&u`k6]AMl g`b&#.FPE?R^N7@R5iJDAT1IQX4kBl]KOb\"g$!IJ)!R4I.>J#F2WWpd`g(pr9qrpP` uOus,E!GQ!]Kt0Y?Hq:%*mH6FjYUZd@HEPj=*'om`\sjg&7T6Zre9<8]'nNKMQ6eqle5W\T 3$k[0T!_>%uQYaK2GIID)Ai:%$n%bLW_oNM.rU2sV?T@Ms_R(ZDS6m=L7!?em7+f+MutSWh I8#qs`tnEs02hA,!eV_LP;dp=.h)RnV-T=_X(i]X=*-qCqK?6%qT)84kVK@.)5(q._ilLRU _r^5dY()TL?45t%TA]-3iBDPO5*Y$\/>WAS j#OuAdlR)J3?EXCgU#5E2fs]:8Zob]lfE0G*BWM#Rf[QNjdnoCL:?#'ASlm1k.uE`iGBQhO 6hamqClRG5)8TU#4M#jnFBZKhZ`LdTt8uGlL:hS1T]kg/`GS!itF2&]['':IAFG4*cV,l#])G+,A2"p%a$MT7>JUq=stSDu9D35]@DF!5S(L&EB.T l%3iEL?m!1]PsYs$UX@$1CZ]jj?!l>nH;2k6uaJF'1D@Y;\_`:RIklu7d79Z,jAK2)Fj8(E uN)=`-E@mL?Z!BT1@;j(.e!_FF9].M8jJ"Z0\5-b&R'S.8&$aY:WC&jKOR_`u02P+,@Lm1G 6`4qL':%ku>qa1OD&?:32Zc33m/L8L9ra4Sq?=oE>=_0#sCFEuSp`mlF1["TAh;=p AuAQ<);2?d/ hfN&H:@p$0.M.Kf_>R^lS-L')uT1@l3>2&\hZY`oijh#G8pBAHS>^%L:T:SQ(\Ll"V?/%!f f4Eg'S4<6P""?0=BV(]P@ :$&WS gRe5a4np?uVIlZ,'rIchgj`tc=dWHS>F51tf^-#jC7*^5>BGpi.;mQT)Ne")]2G>@tm4D0oM/jljcN; 5+QAAnA.K:Hrj)1QEqt_rBY*[$E]ON[]j3"49k1c -EHfhd(8aOld]mVKHZ((jrhUCU]2FRn8&Qm>>+<_/qn$#HOk,L@-j,'*mSL;$nE,dlt)WlQ =_9K@AbcU%)4[,igj#jI9!;>bINn*I?1)aOAVQqY;Q%=&U")8&iF*;:,;+jqlb.G'ErOFA^0#YHohRXf QF0CM@$Fj@(4flp=C07E`2fCmMIjPh]SSMk`$Qs:(D;eg1:^R6=JH.6'_KNk\G*b2!WNWG2 n0O>^.(j?Etj\p,uh-IPC9+tc^;2T?o.rJ#Rn6S2oF]Y=2?PJM,8=X%IEK3-#$!%4iU!>D5 p+.QNp;5I/'7_i:c`C^,\XMT[ek"Hk2RP>49b5es`40COJf+7S&GoR=d 5+9GO,ic?7DN[ppUPV%uR'cF)?c@;Pn5[!!C")Io"F%l*Ttp-.6cRs/dfr.s?f"9[&`QV>6 T#6^rA!uurF[HYBN]Q]+!U%Cg2mC5VD7ej1<]&R!3fPW`o#6R'*k3*:PdP<\Os5BIELMu!@ 0nu?j;kg4##e\3GF$@t)G5hr/IL4(jf#`hK0P0W(3QcV;/*!PVC@-GUaLRWnk+(%m:=pIGF LL>gI.8`.PfEX_?$8bDqg!:$HTs%X%q7=ZJa+Dd`&MX7Q<`=J(@h#\ac?beHp=V'rk6s1O] 3)`.pa,H/0`';ckO(sQ?'&d3c2'%mY)7M%bI:.4+DV=]u.U$j]XH1JG+-!f>Di_&`S1:FOC 7YUj2m!Ni2OmO%q*FNa[e*3_u7::'>NqiFR;FUa$ftn$2_92\"\pMse8hH4FrE1<-!A'],U iFq8HX=bt9E_UrOZ6%h.MmsOU"f8mo^=l"G7cQ$6V^ALd#oDY$rn3.B"r1C7fIb3?OMT3$M D`d$-i@/-=fR+3C;$Tu5(V"nuOE-)&ke8R3LHp*>1]KB6G_`MJ5_*K4S.IlS&AXuJ]EmdU4:K&"'gZ(?6" oa?HK^++l+_T=6)]_Yq)tE%8gK4D^MFuXZlb+@$3aOX#FKME@"/C-E!;1&5YD%o9G]N.I?P dq2I"kJX9:k+/OIZ6$L'GP:nrc%>DLRpLPU;4KFu*o1knhG"uG=,M`4!WGeet=5nlCH,Win A.m+2N6\IZkr'3XY5md]163KYATSJ\O)Bg:$.$@?7FDSk0V11U9t lp7k6TYdX?6G-&^4>+T?>Jg:lS5>k=Hp'oTZ6lqTY_[Q0^j*3LBgn7K7I4>Jdq/e_3$+;f` [kUh4CgY!bIl%j`bY<2C&5CaJ4=WP6pp[KpicsVC+L%u6:c&!PZ:3Zb`jND7S:6Q$o!F?D? WFJ7-o*;HX1e'tjZA4Zl`RK?*oR=kLKb-l-`Y/^!,_8 LFM+F.o2EPn;,\fln9d!Y_*954)`+mC&NB-%FKog\Y<#5diGm=1k7rd?*Ui&`'H:&YV#,*p Y9U#,lDC4F.8!HOGpM#;Bi44JWNBEus,).1gf\aEfHYIE5*XaBY`;\6lRGg'9a; b3Z<(r3.n:5R15YaW.W;j.HY;Tc9Fc5>7#*['RjfH,#7\%l?P,nO*PVSOmhWN$KXk$Z0XF@?;ns(rVc^Vj^j/PBX%\smUF9T?XM?,t5Y?p9b`o-Or2`TnY"I0RbfnO14O d(tYWQa49kqASRCL)gZHIpT9lkTs*$WT(@Y]bbLCD*mBg`-+R*AMI9G/$DW,B_q_p2N$:&A -g;umXP`t#UoLGW;]%.#>IE\G)b,HuKLd!DTDCBb]Y9bd1obk$oXO2[p_cYW>OI/"rPn$d] !:T@!eLi+,a7lP8\98rmFWua[1n48@b$ol2NAEOA[h?ObiT>Ai,:i!-l<_uKt:dka#LhaVu KEagE%g:/',g&nL2ih'Lbf'dYY^;/PH_[,C:JDX&'bHi_AWKga;*>jq]c9nklDPWc:UL0Qj ;\e@Ob]uKY"+,G;AAFe-%3)eWr&*g"r.I@?[2q+Ti<%UI:3K^@uDUM f4Vos8%=`DI[AlNUo<3!Z(/?2X(,:I"9e::QTAQE)Kt.kO^F-6uQLqW# F/D(!NML+E)E1icSr9Tfe4AHqMn`P7e?TJ'j8bLYfg5"`=RD!=1u(DSpr *,UHO='I@>m)*0^m%>"jR(#^1t$[us11#L0!s4f)CX^KOb9d3ZR4q-/rO_;(U( >cl0Ui^d8oNu)'R'D3PI2'cGWZ!>s3;KXBlFVBN!EJ;rT=YooTS]d-!\CD%/h/1nN\m5ulp q78BWpQA-Xi8j3&f.8u?&9'J--(`oDMAnahJL7oIH:YJU>1ag?ENO"]r=Bap:(N1%8)Jk-L\3&$&5qN-'Oo.=;E.ZNc%mZjF^`Kh]dQrkjsl:GfpQG1A$-gdX A?N,P>Pp=dtOOVLq+G,,aId]j=S>]0]a6BJK%o\A8XnJI'D1V11M2R[_:+AlB#hm%2nuUHV',r[(e53?N KnUTRka5%J8!>+G)$#3HS0en>?.N(W$u>lG4DhIt0B0I2A%=H3fZC]?Li$`4$&7qm?Nt%Pg$U(CH"F-d85QL>Z+D #jk1X@d$jM8Cd?3e]NXIEeX403stWb`^jT?(M@&Tkj,Llr4a7q@c`tpL'E(I;>*qs7]K@%_ eth*^4%,54jOa_cCTXPrh+!6s'3icl6qGCkeLULDWZD%l8?st>e==VDmH7'8Sp-bAend[a/ LhYBf \ZD.l\BCb9L62Del$N@@W,8SE7%G\^]]P-9nLBeIE;"YAs[.3Gh&RmsnORJ(?#ln+[[\Gjh ?I[mq6&I,A.CW=tCIb6bH%,fsglo!1!#eB$9^?s]CjR,gj*\&hOE,<836Lcu!c,$]K)"&I) m&oMQ,]D:@Z6-f,#3OCF7X/7?3%_`Nm7u/Kr1n13HS-r'mk43M4.BLShJ;V:P&OUbKR;-"C [JS,9r;ct2X01fE2`d![Chs_IcW-#Wbu_6DsETS:g%\%c(a=Z?tSju4$CtdT3@!:XiB\rIg d\44iPl81`#_&rt'/XJ_'8^gB_s-:hL+9`A.F(EA%+#er/ZkiG]k@7u9.A*JcS"=GAHjEN] F`q^UKH;XdjQLB.["]F#mSTl?r@njb'HaSWMqaDi"GEj$uNDJ!L)(Mi_YM:R<7AeO[l0f71 S>aBu8J78!=>DH$uL7Ms:0R;%&*q1gDEWljA'iT%n4Rd4Lnp?VjMKMs(OsdhQoCkUmJE-3b I.G$AFDjZ+0/)Z=p2P>0BPrUK;2JcWCh!uJFIhjXjj383S+E76FXXUg]R&'`f5m8sF0@HDE 6'e'#]G<=i$e;@7Dsr-FLlq77=EbR%$>]m>6R)iqOkbsCFp1#Y`prc9'>@]5p()LhbNc_fAG= u1GO#QNcuA=6:A1S]GTqP(\\mtbf[m$!G1hpJ]IE%QeA)1f75o5]GDh@AF,$Q4.j`71]4]a *C>fMg$hJpq]Kfr0m%?ZC7n*Glk"G`2ABde9NQZ_lo@$:TGDh4sJUHHS;^P3l-TEGm=kMH /H)XD/KS9Deb>'4`rT-ESJ]:`ldbG_R'AjDnp[/r5E'>EPgiC&9`g6Yd:QLdr_f]2j8R^`V c:H7LN]&8'HA,bps'AH^D6ff?a>=OC7!l#E?QFIlVlar'_lf7mNk?Qb7`JEQ=;A7<8c]TPo Q4at6g\LS0$6oRTOY>dO1\r[ibWBQ2%3FNB6^rbptKH?^G#!bjrJBA -d5".oLrW3MrqH"G"NrL,i@f>eAb*$dpJ,E'cL;kiP"B34GsnN0/!`h>dHA-tf\C9l>A\L&h K(ZI:M5meh$/9oTMXk%>"''h8#=XJPkoMlRo?7c.TKZk?FXBL-Hc`Vc1.)eo%L/HMke#26kkOp=h1=f5nFWDg.]LhZnSHi,J219S0\NZ0YAhC6IkBb'4nG*D$m^Ps%c><7OR?EuJ$V@3M5?dHYP=-F&; CeNGeeO;;R:cP\F.Oa2@qaRsSZ-AXf"J>)gK*.@DVNb@_/RE7n]Ghf En%^Ch%s>0G265Bflu:SNTk[ob2Lci(pjnLEF7>rXM#KnSM*UnQp(r93G)RuL89%PfQWeH_ 7WfW(bRP$j&f&4Nam>%5t@BMH-15s'3X^XAOnn_l^R=mP@N7UNbOp5DtF'qk=F"d"4l#AFd ZoGY(rK[\ittHkh9$7AXkYqT:P7NSuJaTg:jhnlWW/UY3Xg<6T(I4q6j:0\"2uom9GU$-bA4.bR#mQTO5mX&:/_=.:j*Qh[S?D#X-1T#(Dp@DX6)j6UR9k31TV eP(+@YJaZrr)XAMcJbtjd%XWr"XF;=dop6mQ;V&7QmELp7F77$Z 2(MdrkA&G@M+eMo_sYhTs)%P0kIZt(:=q15e>)S]qSreC%BMfE>17[VRAj#h04n/_^k=M2p h!e4@jQ5.H-,L3hp-S56o![*FinpNRSmh,Le9,dPaWeaWu.$5i3E2N->aK@j#=C SWhKN:eDTo.-2_N+D^L$$Q+pSi`*"9'#%F?)-W9F!8SCMi-PsE9eOtQSJfh\2+Hd6kG@-]I `&[?NR=sh`I,IhdgBb^)5T.=E8)(ZLi\M'k:ojK&V>$m8'*b049r+ZRt]@>],;&%,ZN]mdu &BF)S*rL_RNWHFE`J#G'FF'"uS8n# iul_gjBUt%#rXoaJtPTW1fpA4fm2'+QM[7&#tpS7PN[92M.s`)e!RM$VD9,>--8c057QM]s lSli*74TE6)eT*%RVi>aj\nX-Lo>e\UgjH\ljcnq%rU*7n=D[:E7Leu(@mc.IT`@YL)-]9e uY?+U.s`ur%$$'sj#oMdjO\dA+lfAAN>p>lmnoGlA"7"/;>`OHT]6u$KNdBJ Fc16O4hTCN?4ULVM32g+))rEX<>"&$.io*@F69OaS.C0+VGkXYC.+"#(P?`T?-CoN0P2/+0T*G)>FVR7 SJjC;fgf<2Gt]@YAHMQb9AQj6M[d98GC;gJbCoIbpOq`dPe%?R+"ki3H]d!H7^L4Da4iYbp t;e9Cm4`lY`e/:SGD@P-qpL`At[5JTAOn#mSVY/g#hgB@2_($*.]\hHCJ*YqoXeM7:+F$bSk8"Mb>dJ_!)fUN*UE$VoJM`*ARFmCQDFt_@7iVdbD6ReL`U5o^'6?%ZV>6? ;o)D7lB,FRs7"b@D)C`4m1W#TQD6.qD4BBTj.huE"8/Ko2t&n,2relmY?Kd=RI*?H]CSS_E !>ZV;e7pEXTUdf_1A;lR$8+@mS/bbncl3I++S8+kf(*e=hIKhFdAlD;759HgeiM#&b;fgH6 j;nD58*Ga5QrCJROdSj18@(WV?+GDa6J'Ri9\ak>G`f$Y1MHB3'rfK0m]o7!=\A'AgB.6uh ^`e\dK1"G0.N#3GEH;8[,T*q'B[I=+Di,7$]cc<9dANmliI%Q\prb'J/(E2@[%[Z7jQdpGn _`;@*SV+sbmi(&Xc8hT7AYJRd*HkChrX[QEIh%IXim638:UXQKGiBU5#N%jVeic4H3.`[CS *th,:\+Mp:fg$t)PQTocfY=j)Ze;-!Y?OtAS>t_1A]=p!t[*f7H2rN\H4:53j1;tYL`ZL#k R7l*m6=9m/7'K>5aOf2UC7Z+o]s;4t^]l*KUX/AVTp;P_P7u7;Fsi:^IAGMZAhK5saiZ-PZ j4RgIH6$4rrgN6KNX1A[*9$ICQ2L@?//Uq2:))\?ET&&oF+dN7B<*Um*ud)?1XgB=Vq]SV^ hYN6//lG#$.%g0o6a3s%q!sk"g%l"(Qj;8f/c5K"4*tG+WYnn"7)\LI=\,k)!iK"?X2[_>l "&>@&&18&e+LfDXV.lD.d+C;F.X@!RN\FTMEE>3cbeN,\"p_W2`2l5d,3&1AlNmS*s`N >E1T(^]:8OUOM&3u2gs)%i&M;3mFupm"]0'!\2M%ji4sf#2NA)2is&ECf\;J9B79JPfD^d9 .ENaGnSTIkbLR,35\RSJUf!=(0Gs/k0br3ppG-mI>fLnb4+n3fh+M*b"KL&_A.g$R!k.+U= 7qWY2"FV\9Z=+m6lB%-JcaH@Eu&'N)mq8)W,2Ztk?i*eulu;9L2(bp979R:0?0+g-:B.P?W K*RX[(">iO*Nbf0E*O52_EVh,(HHK+aB+eJu;MQZ`M^ZQY*PpH(dN'MERjis1*q#"s*T>usP"=mK/f,k<,SENTE_S'IaXkC^Ir\Tn19N7'U`?Yq-^&"&l?m@;E77VO/i*#Gd e&6/nskQ]/X$8j;[5"?$B-.N\FQ171D_c4R%Y[#$^2"+_>LQ2)(b@$'Q"'rL&c3?(/Ij`1_ VMOc5%.+$M+oV/nd'_1?C0A\7rd>JgOJMcgZ):Lf,;klEqTJfL81r9)3PF=+ds#1S_Noe2#+m^6 _h(B@Z27)7*;YhAaRi_1C583WQ;tiL1WAr@h5S"k*Oju[R_(pSW]X,496[g(Bl<4@r3jZ"O ,i:]5(IG8_cR_m2/FPiujrQhY207e):1H1.Yr,G7)=u0qacV^f(;XC;&"FHI ;hj;sQ&9aIXa8i]_4WCfpi;`#aVd]H=IjWG`+6'TgQ%e>focOg3@!>RId'h:1/HVMnm;RKG '_DV FCeuJn.ASV8Qk_hP&-)kFdZI!]3Eh"enWS]FS/n(Ao5B(*!'q!61Uh:^o6o/*$K#unh_C=c ::>!=@Eg!p%MS=pbG8n@<8JT_Wkd-k]YL]*Y)Z/%*Mgb'j@tG@MTOKLaP>D#@c7;@hpi2Dk UFe4'$r`/OA#06(K=11oU*4**).?Dr4XW"().0cSed1en3rQoQ/#LAA[aQiQ`@-,lhAo%4# XqVLN"HX_?91<0eqI2KNSuRq^HFUD&DB[Qe$*W(F@G82Q*:$GT/5AJMW<*$b`.TrrCt/S:< ^D$;D1LHKYo[P"?b@)tiP(?Rh2Y0"Te!D#J!QA]XHO(Zf0GX7Vp>AKJrXEp LeVgGEa`,PTI;FG-9c'lF8I&5B\sHG*`#R9F?r^/sA.SH^EcA=6G$eeoWOO[13(BK @g7L=_Jp:4J=BC314]V/bIohHNQ:#2+980AP/(bi1OQ7[S&tpdXLKGLO7jilqE2QfU0+Wp] f>2lW>AheM,OJ[BGXI.O7>\'SWp=_DplUK%]8P=U7\l&TG[l\n+%P\ZCKSBF@HccSK$h(9J Dqie=::,@l[c)bZHabU6UD_XdMhn^^8l9!bP@$0gPWNPMX1\YiJ=s%acC]hOr5L-6KDC&`# "ePP6LDq!W-n?-D1i$j#DeZ'!`I.0"b+5Nn:J!8VN3+INJqRPJ]ZKGc?f^>0ACY,-1LRbQ3 eC&XT9\_(<$q\RV"pMjW1X,*o#D:b@ki)JusB*T=Do$3p,GeWhQ1'KBnPChC\\\AoJjQ$H> t9chB$ViQDW)]=+5!PkB1+.#U,auOmA=_c_CZ^=n?T,I6m=j5+6D2c#o9#8FbiGDkCgRi3X a;Me*O^]ICR9-s7U(jGoNQ\!jA057KQC67&/@*g#%*?a^T)(=9RRB@lU:O:">$$Xp- $WSmV?iM,[RF_`pSE`Ga?eFP.V+$Am+I]:S2tk0c9W\dDE8rODgCL,+hT.=cBBhMUmdRK6p .lNK%6+cW7nSY>.8r60H;7K(4$"Y,).'<\/!ZDX,7,jRY6[PWLR/FXm0D\&P]AP8D[N+Wbe K1\`9K3o<69sWOf9s]'HSi$aA3P+!L+ol'3F&S[$,7*9"sU2^>Ql!7DKMW&lf<4#a;E2XN& 2ZD7PmHD@[U9=0e8k97.oHUG31>IE#d*Wat5g;U>5\f3q3*]^"'l3@2+40r.>Z\osQ_/AXE G!IW`Wk2'1qj"P4Wq^.C*r7P"gS_WPX%n6D*5TW2gM%;3"e_4\]#ju;iSCgZK=ori]aA6R8 lLa3_CiGj\U3AI]B;*aO;bWo^"`.n>PC?/rYtsI'q;`9,1IWAd,g^5^PVmS@=u6TcaWfo't `(?ctgHB8AC)s\XYIi>Vj+G]u%EH`#M,u@I#0_e\Fs&XLc[uf[Ic1q[DH@]Y#3'>TjfCigD m_`M2e.Ho8X.2oj&'_kh(f4GV"JM]hk%`9Q6c+bGT!N1^_``gig?gntjKd@+'4ai"A"q0C$ YH-=p>(i^$-0oa@=bKSbf$9Gl%*0R#MD7:I,bo=U!>[to]B?Hb0:401a*9&d^ZC_!+cl@DZ 8uX3O"j`_Md2`l$gCpi#Z*CsoH[EDVRLRY9\AdE`cJ:;&&l0f7)8_po5YR`K*4El![X,rqS-d!a[FNBVNdU*:rHH^rG]9t:@U3j%jBB#U9A&&r@M8U/]nb:3S( Z(!],S0+"KZEj>=^M4g$/F=@?&mP]@1H@1kc;hIBlia@?\)3tCrG*p;fH+]R=#b9#L.?MEoF8fo5FdCgX]icWtgYOB2Y:VM\Prt igXOr;f:nDn[2OONX4/*]MI>=;Q`5<&2+3g6-p)Ydn#km?t'qCb22m6=P:)`M.,R:'Ap?K8 -]T.TK'/ruV\1Oij-?[)7"l.S5.N4Tu"+*sQVs%4A7nXko32JcpDs7h7p*5tA?T;U$oPsPG Bq]E0A7uhNMahTg5*-qf2303rNp`.-$)5!,k8p6(q-=PZfokq##LsRu2riBh(ste1+I%V-^'&X&c89](L6_>d 7AsFrMa!c"XK;m2!lF[c)/8>HX;3Xj6[Ad "LWS#N>O5EA_8dUHA\+F=[pQDnm<8AthY2N9iUM0jSmOFKdHU=MrLVnj^Z"_YI/]aCXDO4; M15J3fXq(\+NF5c.W;H1%]:8=?bM9RGKZ>Ek qehr.o=4XdED-C!5drQt\ZFmK)<>H=)@T^&rO(;BO\;)YTH:Ea6(0*d!s-KeH/+QZY*.h7&+$H![t>/P]6a&b(1>2a.1k?nX=3AfN-dF+dU3< Hj/U3+a7f@Q84@A"1IXXDjeel1om?\Fr.KA2tDqP%;*]:R#EN;KZpsp>kn5^LnFu>9>fl=. En`eA[Ch-E4RUhY3n$HY@^`Mkk$T*niV+ @:)kW1IXE4BG7Di=ZZZ[dlh_Jgd<)u2:"".\$&ibh7et\Sm6(,Ug310=DqoP"f6?(qY2YUk ^h%-TD5#eul?XG`pQt#ZL["Y`)TM#Aa`8AnYNpO!YIEjKB)0MS*lkhEk5;tMcubjL7oAu&> u0AOrZ?@D@[j5*?>cBJma^q/^[qJU&-`/#3!fUn1%feoP`37BoUf(X8q?D##qTN74%>^pHV \eo6'sY:+Rsi+mtL;J3(XEK!6lK..JUchk6kX]085M'hnN7\lj(o8+&JCH6b%CP@Iud?&I' C4"7ZI!1>ZTI%OFNMB_09sf,LHe&&HmW']QK"M[S$PN\PK9#I4VlObOqfZ0"*@N+[jlU)?G 1e:NNtLM;8%A@:A+Y6sjEQ-O7-r,'E9%uIeXOVd)'_nll5dc?/&b(/ ,il=8P3$:-`RqpMV"<_0A,'[H-rh0s1i/EH[T(DW@f8argDrXlI#kZ;-fq_EQP/Fd9=]=$< f5C1b@(9-ni7hhoZ*@&dO,KT]IP8Oc]]#39$J]>-HDeP*:kLo3Pj?2,;cKe;PJ/+)9CATFK c]/i`]'effNhgn"(34Gu$2M\-Bb]*!:"X5agk$B$fiaj'$+j3XJ(81t4-uCj;",a$6MD;Nr CgE=Bt439LG]U=R8#ZL^+%+bYMil,$3) .RK*O0TNja\1:j:2>!=XgViNTu")q"d&-n,Bfj84%Q'cE:k6ZqS:gc=^V^#KJ#0!D=\hiUVL^!M`5W.1t&_=IaHe1IreOBd2[d"f%R`AF`*ngWhWO7N?RLL;3f G>(P_Hd43;bd2O^+8V7`NrX[$spbWE(8C%]f5$Xg3Zb@Y+>U-e6m!N;4p%l_P=k J-O!nj)1umO&&K%/cjdVKHuQL_P*aVo?]64b:O(;-[n?_WHi]'M4p/Tqh5K""8n[4t3q0PD=d` %Sp)KO08,bpD4mud3bCrG$qfOk6A4e1Addi)jnBtZO)FS4W6j2c.P*=8\dX3q_cNj"sFnWS:KDN+CD$R<[eu3Qj7?'[*J[7p]o>O^2=m7MP)W_g Y*CJ%mm-V?mG4shK)i&Dng?5`M2T7>,.1$FGTNMBbA\ 8M8\8LO&(j6F\nQ\\H`]3-&0.X'r50;K)2eVLr.YWmHS(h1fJ1sG(I?1tIg34"2l[8#5N3U :Pq[[l>*XBN+57-:e:J)E$];Nn+i*abXL[a&KHB4ccepH#8a^Z`<$tGlN8GA8=*f&-h5=t* R8FmmtQc49Vpkk2C/k-Y,dr"sh2*9-n@:qCA*>A-)Mt(ZcZ8r3!f)>l]Z@/VSqZ"&!r u^G&J$mDgL"#WQ8A)]'IPG(+2KGl(Z\cE/"dj;8)_n]Ag]Kg+$,E>D^pFK4nh15A!'X8WKd "VCpj8O\$o[lt#>f5$N!;M/.R8:45pR8_KG_Oi)8W!4#4QX:g^Yq\&A\p$_5hIO:j]$\'X9 +<*HB^RdJcH0-,O1>_K70BJ6+\s)L7(e(H,ZYd:;eAq,EQb/ ,$$'P=J_Hi`,&)b`(\,!9t(fJ6qM\OZ>;qhDa^Zg_,A(eRWPH4;8m'H`H52#K0-p96\Qd]O Xc&5A6?;@DBkZBR!Pd16qYGJ@E'R%`\_20?uUlT?q%<3.LMlL/7^[:3etir7I_V&WfMnA"@ eVn`q42i"E:GUH\][d`M@+'_RQY9%S%1EL@B?jjD0c"fISiCa)$+C`-fVTIA`K]7C72,MRp jgDP=Rg68Wrs1jUa:g.330Qc%(+2W[EE*hP=+NHEjmdmG D<^bbB%V-&9e?Tl*H"&1ShY,"Mi4q_9=%s#9\,C3e=Xn8@1e%[eYmfiEiI`8i3oq9XN!e`6 ?HPa:'bK4+\oh6UQY!N_J2HR)1^iQNF^#H8FA0mL0)$+Fa12gB=tG]=YVHoTT8:3>gI`9be!Rg1Wi##Rt&@ttKs Q('%mXfiU5OI(7t#cReh:K_WlXDnDB`3FN9@#mn+hq7#D0Ouo8Gr;KM-!RN+o`Fs;t=CqqV W4@8B\X`g]K_'rn@h$Vb3s2`aKac>Y%FF/`cuf/BK]G7;qU"PY#;CC]d*bas^X4VKd<-8QK F&GcBMRc&;'d'gpusL5B0#I&;8jX*"X)5.+jqY\dP;u%#Q~> Q Q Q showpage %%Trailer end restore %%EOF interval-3.2.0/doc/image/inverse-power.svg.pdf0000644000000000000000000003005313316017127016155 0ustar %PDF-1.4 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xX]d}Bv*} !`ɼ-~05אǽ==kaF(U:u_7gw?8ْ61ۇEW}ɕCϟmDUɔl%~60ߍm~o/F|17.VbBG9cl*։GG{m]mzv?t6KCl 2 8`O-6}h?2Eߧ#SE |wxvXXߊ+|[0@gGh6"٫b!^y/6goN^ћ ߜ7'?9yb}_ty$5+8{t|aV y.)5zҶ= fH~Jl679axIT %|ĹH'8]OEOyK"h`rd @RAl.lmZ*R7#l%L-aM1W rۛ=Hon&[ܑ(gϋNh c=s|zyn8we7q{ٔkoщhNnUssO&*. 8ǁ\*`4eNa`pޓg \|qhQ"$o F_LZS~O&H$~QR-^15 )X…52h]$8;qI.v#cSuVڛ8K@^ Z2i8BX/*2 .H)\40HH\Xvx9h Vm0Պ\m\r> kb^ LWF-%RME3d LDNH)81ͩ⽡Y,.4Tj}q#6j8n]Q:TKBŲlҦvq(wVFXw {wLGɥXɯ}[%F.$ruZB.`LPB7rAT~`M(PJPy4UOrx6-ւ+F_p,MG͘Aܜ] (#P2P[EM/9&brK.=+< #uإ̈́|̋tQYsQ|RWT"qQt*ܫleQeʘȂ^LDkB#H0g@-5to^r74XXad hZts4T]n %TlPޔVf=ъrԶƎ.wGqV/oJUa!zE ׵#t;zJ)YBOLx)ְZ|LbQ@zJiI =,=,L?&L?ޘTtZDK1W6ݙW`^)7&3vjxsw*blX9N.N=|t:9BEN\rS)u7 ?uzM>EsãQ ឣSwV^S՟HD7G_^$u*QBLY@!r#ڔ$p*~`6_ _FcЁF<7Ll _MkgZ;Zg}_Ņtg9͹0'ڥ_k }8kQ660,:4ţcax/NOiN>vmttf\z.oSҭ$2s{v,ƚtPP۠NeuqjºAXCNbV|ÜU endstream endobj 4 0 obj 2435 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /Pattern << /p6 6 0 R /p7 7 0 R /p8 8 0 R /p9 9 0 R /p10 10 0 R /p11 11 0 R >> /Font << /f-0-0 5 0 R >> >> endobj 12 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 339.375 168.75 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 2 0 R >> endobj 6 0 obj << /Length 14 0 R /PatternType 1 /BBox [ 0 0 100 100 ] /XStep 500 /YStep 100 /TilingType 1 /PaintType 1 /Matrix [ 0.0046875 0.0046875 0.009375 -0.009375 -0.9375 0.9375 ] /Resources << /XObject << /x13 13 0 R >> >> >> stream /x13 Do endstream endobj 14 0 obj 11 endobj 7 0 obj << /Length 16 0 R /PatternType 1 /BBox [ 0 0 100 100 ] /XStep 500 /YStep 100 /TilingType 1 /PaintType 1 /Matrix [ -0.0046875 0.0046875 0.009375 0.009375 -0.9375 -0.9375 ] /Resources << /XObject << /x15 15 0 R >> >> >> stream /x15 Do endstream endobj 16 0 obj 11 endobj 8 0 obj << /Length 18 0 R /PatternType 1 /BBox [ 0 0 100 100 ] /XStep 500 /YStep 100 /TilingType 1 /PaintType 1 /Matrix [ -0.0046875 0.0046875 0.009375 0.009375 -0.9375 -0.9375 ] /Resources << /XObject << /x17 17 0 R >> >> >> stream /x17 Do endstream endobj 18 0 obj 11 endobj 9 0 obj << /Length 20 0 R /PatternType 1 /BBox [ 0 0 100 100 ] /XStep 500 /YStep 100 /TilingType 1 /PaintType 1 /Matrix [ -0.0046875 0.0046875 0.009375 0.009375 -0.9375 -0.9375 ] /Resources << /XObject << /x19 19 0 R >> >> >> stream /x19 Do endstream endobj 20 0 obj 11 endobj 10 0 obj << /Length 22 0 R /PatternType 1 /BBox [ 0 0 100 100 ] /XStep 500 /YStep 100 /TilingType 1 /PaintType 1 /Matrix [ 0.0046875 0.0046875 0.009375 -0.009375 -0.9375 0.9375 ] /Resources << /XObject << /x21 21 0 R >> >> >> stream /x21 Do endstream endobj 22 0 obj 11 endobj 11 0 obj << /Length 24 0 R /PatternType 1 /BBox [ 0 0 100 100 ] /XStep 500 /YStep 100 /TilingType 1 /PaintType 1 /Matrix [ -0.0046875 0.0046875 0.009375 0.009375 -0.9375 -0.9375 ] /Resources << /XObject << /x23 23 0 R >> >> >> stream /x23 Do endstream endobj 24 0 obj 11 endobj 13 0 obj << /Length 26 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 100 100 ] /Resources 25 0 R >> stream x+2PtDb  tDQBW  endstream endobj 26 0 obj 41 endobj 25 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 15 0 obj << /Length 28 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 100 100 ] /Resources 27 0 R >> stream x+2PtDb  tDQBW  endstream endobj 28 0 obj 41 endobj 27 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 17 0 obj << /Length 30 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 100 100 ] /Resources 29 0 R >> stream x+2PtDb  tDQBW  endstream endobj 30 0 obj 41 endobj 29 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 19 0 obj << /Length 32 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 100 100 ] /Resources 31 0 R >> stream x+2PtDb  tDQBW  endstream endobj 32 0 obj 41 endobj 31 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 21 0 obj << /Length 34 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 100 100 ] /Resources 33 0 R >> stream x+2PtDb  tDQBW  endstream endobj 34 0 obj 41 endobj 33 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 23 0 obj << /Length 36 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 100 100 ] /Resources 35 0 R >> stream x+2PtDb  tDQBW  endstream endobj 36 0 obj 41 endobj 35 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 37 0 obj << /Length 38 0 R /Filter /FlateDecode /Length1 4932 >> stream x7[tǕVMtOt# =bx  $a"@ [A ,a!20``b QH vp@]#|,K k{#;$KLv-H'9מg٪㾫h s̮N72sN<-&T0Y^EC #O_Vt{U̝1<.Ƌj5U`Ì9Dg%ZV͖jus60{ .MO8JaotP5ەgyF)RgbGZ,vB4^`;#do\3:`KIs1z2]GwYyR~"_aX?^vڽX+r'WѲ$xXթ,jz,/x my Mܖk2Au3~n@pzW7lg]T}7B۬+5^|u~p%fdyڷLLmVg2v> ]uM`qMu;ɓX/%+{=kd,%gZnxr0##ϓ [E0MQc!/$L'pЦݥRoUʕ )S2kS\uFF.}{g~}sdo]:dKaXVf([̶gcgv̟T*GeV_w">}'ΧȤ4i1`1+h4RQS)6e .]CKhz~hmH)y4flV8˼W:PP [2@gJ1+Q O U+bTqֱ *neFy,e4L4B 76{|eṗr5Ɏ6 `l8-vi]lT$I)\f{[d-g[6󋜌ޞ$RCYC{eL jwilwp4sRW'UzY޺{S{ۼeR.ZxQ3??pa("욲RYK[aTՋi3Kj\jDIwSY{Ȏ$LMp8. Vrp `u^;Șpmlq(h721/z2kX% YjU'.7}^ $&%cr]&ho@)LKI0l/hs3~m;sqMҚ5)+yHʆa1<=jC,3m9mTjTŶf~TShظmܱ>};/Wv팣y=ɯC8|Օ)q]snw a2XO2}!e*}B`~+OwK޹{Wa.Q([Ej-ܙl(lUr*[Ɩi \L}wn6f5Yr5;x-gG}WCʈ^ޅ9}atUc6LiXY0F+u8 zکS^0%ǯl%8 5ЯeCtf̋4Η+0`&(l2;: K(6& :x0,(, 4?nZ mЄ?f$5T6Fl2H M>wq0h LQ )CD$ujQju掣 )"mKЙV.,PAcsxy*qWb̏?N%ޖA[Aݦ1wQloc?'-7oL7x&ޘf8%k!?:W%ʇS? r-NK$K?Hߗ[xBwqQ'ux7߉sJ|[[H|S%Li$ADg*~Aq|VOxLOxT%6I#Cv$(^F8FJLW$@a/ă/yG4DEݸD//5 =|K/s1ܾ.q[,n[>̿ĭl$H<7 :.IS냸¿v%J\cj$xV<+8"%.XniKbX1\J %]\1o>%$\\s$>!q,cn%Q3%h4%ΈO3BX,q:<=p3Ŵ8ՏS) uɏbGL$(L"ĉNpGqıJS8%>G>5^i91ma~EY:펙"$qua` ]80ŀχ}E1'Š$IT3Շaw{BLä\L$ Qb&$ӢDE&$Z$f-z#h!MKLtIt4DՏr"r8$,JʾPґY3_(7n@}z endstream endobj 38 0 obj 3358 endobj 39 0 obj << /Length 40 0 R /Filter /FlateDecode >> stream x]n <ݡ I&HUwal@dH By:iσ5* &eux.YEq_#.ՎuTT\cpQn[PuѸy =(t݋bA8(=B|I:3:{Vc[=H9s3cqS!nTf kMhڤiya߿~FvoQn!PwyԐxw>%c endstream endobj 40 0 obj 262 endobj 41 0 obj << /Type /FontDescriptor /FontName /OVBKLP+DejaVuSans /FontFamily (DejaVu Sans) /Flags 32 /FontBBox [ -1020 -462 1793 1232 ] /ItalicAngle 0 /Ascent 928 /Descent -235 /CapHeight 1232 /StemV 80 /StemH 80 /FontFile2 37 0 R >> endobj 5 0 obj << /Type /Font /Subtype /TrueType /BaseFont /OVBKLP+DejaVuSans /FirstChar 32 /LastChar 121 /FontDescriptor 41 0 R /Encoding /WinAnsiEncoding /Widths [ 0 0 0 0 0 0 0 0 0 0 0 0 0 360 0 0 636 636 636 0 0 0 0 0 0 0 0 0 0 0 0 0 0 684 686 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 591 591 ] /ToUnicode 39 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 12 0 R ] /Count 1 >> endobj 42 0 obj << /Creator (cairo 1.14.8 (http://cairographics.org)) /Producer (cairo 1.14.8 (http://cairographics.org)) >> endobj 43 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 44 0000000000 65535 f 0000011117 00000 n 0000002550 00000 n 0000000015 00000 n 0000002527 00000 n 0000010707 00000 n 0000002963 00000 n 0000003270 00000 n 0000003578 00000 n 0000003886 00000 n 0000004194 00000 n 0000004502 00000 n 0000002741 00000 n 0000004811 00000 n 0000003248 00000 n 0000005108 00000 n 0000003556 00000 n 0000005405 00000 n 0000003864 00000 n 0000005702 00000 n 0000004172 00000 n 0000005999 00000 n 0000004480 00000 n 0000006296 00000 n 0000004789 00000 n 0000005035 00000 n 0000005013 00000 n 0000005332 00000 n 0000005310 00000 n 0000005629 00000 n 0000005607 00000 n 0000005926 00000 n 0000005904 00000 n 0000006223 00000 n 0000006201 00000 n 0000006520 00000 n 0000006498 00000 n 0000006593 00000 n 0000010047 00000 n 0000010071 00000 n 0000010412 00000 n 0000010435 00000 n 0000011183 00000 n 0000011311 00000 n trailer << /Size 44 /Root 43 0 R /Info 42 0 R >> startxref 11364 %%EOF interval-3.2.0/doc/image/cameleon-start-end.svg.pdf0000644000000000000000000002247713316017127017045 0ustar %PDF-1.4 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream x}Qj0+,kZ ҦGRĆJ)Zfٙ20B 6Jabx{B4صT?TF1qA(MGr1Sw"AG?(_*ENF29ǨGny0.uiݾ9TM*SAD 6 > /s6 6 0 R /s8 8 0 R >> /XObject << /x7 7 0 R /x9 9 0 R >> /Font << /f-0-0 5 0 R >> >> endobj 10 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 249.75 138.065186 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 2 0 R >> endobj 11 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 16.065186 135 138.065186 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.C3=3SC 3CcSC##T4. endstream endobj 7 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 16.065186 135 138.065186 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x12 12 0 R >> >> >> stream x+2T0Bkgilbah˥h^_ah endstream endobj 13 0 obj << /Type /Mask /S /Alpha /G 11 0 R >> endobj 6 0 obj << /Type /ExtGState /SMask 13 0 R /ca 1 /CA 1 /AIS false >> endobj 14 0 obj << /Type /XObject /Length 49 /Filter /FlateDecode /Subtype /Form /BBox [ 114 16.065186 250 138.065186 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.CCC3=3SC 3Cc 62R(JUHp ) endstream endobj 9 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 114 16.065186 250 138.065186 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x15 15 0 R >> >> >> stream x+2T0Bkgilbah˥h^_ah endstream endobj 16 0 obj << /Type /Mask /S /Alpha /G 14 0 R >> endobj 8 0 obj << /Type /ExtGState /SMask 16 0 R /ca 1 /CA 1 /AIS false >> endobj 12 0 obj << /Length 18 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 17 135 139 ] /Resources 17 0 R >> stream xU11 ޯ%9 4E(K!H[ʹ0V5᭲tQl/J> >> >> endobj 15 0 obj << /Length 20 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 114 17 250 139 ] /Resources 19 0 R >> stream xm10 ݧx'Hc;cp% C#'?("jQ{xmU5c}hMb` BXђ %Dp>de䘛Yw~π] :1 endstream endobj 20 0 obj 121 endobj 19 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 21 0 obj << /Length 22 0 R /Filter /FlateDecode /Length1 5776 >> stream xX{\Uu_a9<<"B *hq25_9hFm,#C +LS2S9zP愨!S7Jq=5B1kpfn}>w P ?Hz8Qf}17< `~.0a/)sjzM'(Q7t>uwhH#-禾Hp1ɍ$OZXX.,Hv?:x z& A .V |&&hn2/dHk pX=2t`L5Q|壚d`PsU!4$Qr:5H.st7GUY*}κ6i0bmIF㓔M`ՖMnh *74[#'NU,cmfdfq%%,g3`q#\v? 123f !33"q%ړ{~}ŇKX[,w6\)\8=1cW>RWT`Ka/ua2XY`$e)6X52T҂#C:Huf8cuY6 gv6T\Ӥc"\i}1{ʀ JW8VE5Xo{Θhu1I.3 9e@"oa!kdddaaa2KI$4{c`D3ɕNO0T+Lfj$i #Ќ C`OLKM~ ,|%t2%{tާtᙡXO8"߬?!O hZb  LdcƆBZ mMAj&ѾdKFfiW/;]I49%# 94UTuU+Z٤yI%`(pXY'Ζ_ckֆpRse@boີۂVqL\(c2TЂiJӍ#rgCG]n ً;K[ze{7nܷoƽxD>tTGG-HSNA9521ڡ9}P*f2ѭ^=+&^ /_V2aJ,NJOqMI8֏Űq}b!cC#vF^or l(FoQF{1jFTv FU[9KAOϹ҃9 RZ$ThRm,#m;N1 ⊕¼ҠrE$qE? c)]m*5TĔlQoI s AHx}Ky57{vTwUrjJJmdXNB۾ϽEb:++]!\}fxżkzMc.x+&;@?8B;^fĎG51ID6&6MD&)>W:n1_rn\q\M;qq<rYȍჴi4"(bER(FOE0xB|BP4Z됩s+Atui[,N2Al83%>lrv!~@&Iن`2aX[̞bf{;ݝ߫Pæ|_7Nl+ƶSTϰ34r>3hFXd}JNz&xeAZZTH݋F:+qyUR*v8O3+ke` z.q :t8L{dJV#,Ou%r/LPSO.᧘ha+5:E[`=RΊL*Ri [x+Ey{.(K`;Hv N7fJiګo #9kNYV a(F@aofy%. 9A'`>k4l ٮRuwI9§rv}J<,M% ړlV*TV9ed5@fz*pRN!{5״r ټV P( Ve r+w7eLO݊]y%@OO 9ϬބO~lAfnjuLh6UИzh=zꄜʼ^6|>_K nݿyke2`/UPX7uN'^Qr;TbEu( pLZCr`ER668-p.L a:&)ozh:t$)Fq7]yIV!>OH4F]ѺO<'Z%;G?_ӎy W;ŋ_Zjl QUcS9Qx]2Z4~hb4z%_+i~alex8/=2xn~q^Ͽ |7M;x lq[xV` +oS$MxRU lx\1+6Txy< qw^<,j<$z {ۆv6wZ7~)5ոCL|Lh͏/nUѸU -fE`hQU5ndᛓp7vsnX?o8zٸ'?u׮ \3WU+|Wkc!UVډ:X`G>_ \`LÇ_P(p@,N߄'p3 |f'0/"/2肋8)|ZN |<#L{>Y= N8F& 0^q|Wp8ThwINu>#69Gzpsf >·wⰡ fǡYF>T,#qb3n3 1=͘fz>XT=^ǁ6>Ћ6LJ;1ыF> F/0A`|zN ~tuLp1Ό`N7 IHB*R`-F@p6`h%[PYa~4"Yf"(Р^jL2E¥Td @`X d+Wp endstream endobj 22 0 obj 4037 endobj 23 0 obj << /Length 24 0 R /Filter /FlateDecode >> stream x]Qn0 !𣎂"]<G\,/%);Tq;V({\:o".5j ΋zSOCmYq꼝RP|PrY'3_A@ FG}{~pBB) Z{0!Y ݺIW:+%=\ 1~Dʲem+ЛȒCHeI Աɜ@(YeN@5̜K6ճ1yO#s$2'8o>MW=euCMNsߧH̏w<9! k endstream endobj 24 0 obj 306 endobj 25 0 obj << /Type /FontDescriptor /FontName /GRPESW+DejaVuSans /FontFamily (DejaVu Sans) /Flags 32 /FontBBox [ -1020 -462 1793 1232 ] /ItalicAngle 0 /Ascent 928 /Descent -235 /CapHeight 1232 /StemV 80 /StemH 80 /FontFile2 21 0 R >> endobj 5 0 obj << /Type /Font /Subtype /TrueType /BaseFont /GRPESW+DejaVuSans /FirstChar 32 /LastChar 116 /FontDescriptor 25 0 R /Encoding /WinAnsiEncoding /Widths [ 317 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 631 0 0 0 0 0 0 0 0 0 787 603 0 0 634 0 0 0 0 0 0 0 0 0 0 0 0 0 612 634 549 634 615 0 0 0 277 0 0 277 0 633 611 0 0 411 520 392 ] /ToUnicode 23 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 10 0 R ] /Count 1 >> endobj 26 0 obj << /Creator (cairo 1.14.8 (http://cairographics.org)) /Producer (cairo 1.14.8 (http://cairographics.org)) >> endobj 27 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 28 0000000000 65535 f 0000008642 00000 n 0000000408 00000 n 0000000015 00000 n 0000000386 00000 n 0000008224 00000 n 0000001634 00000 n 0000001181 00000 n 0000002548 00000 n 0000002093 00000 n 0000000587 00000 n 0000000812 00000 n 0000002635 00000 n 0000001574 00000 n 0000001721 00000 n 0000003006 00000 n 0000002488 00000 n 0000002933 00000 n 0000002910 00000 n 0000003314 00000 n 0000003291 00000 n 0000003387 00000 n 0000007520 00000 n 0000007544 00000 n 0000007929 00000 n 0000007952 00000 n 0000008708 00000 n 0000008836 00000 n trailer << /Size 28 /Root 27 0 R /Info 26 0 R >> startxref 8889 %%EOF interval-3.2.0/doc/image/octave-interval.svg.pdf0000644000000000000000000001131513316017127016453 0ustar %PDF-1.4 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xZˎ,qW7@/d/ -4$A^X?0RI#ïzW#ï:@A^c4wA~~&d|+<?*u¥Y (jB߯~׃C;t]R_ =\(C՚_N? W)?W-#&jPcQkh8_X&)\sJD K(Ns!t}W-feX^o,Ď^7!A{Ia yP{ 8Exb-aҀe_' ͅ<[#sFbVpw̒6jRlkn156ZmڮFsHd1HEo+ EX }qU(c搲thjx:SO|-eksX"X>Y_7fZWm+)-IXmk1>fchbOl=qխ~&s_^˙@U~ Ǚ&ķт+WsߐK 7Uz@K%%l23?p\"x7њD $Ate96z :d8 \Brv0F;%رߓ{NP",V3^Z99j,PTjaS*> B=ebP%לiB>oz}C/{{D_6jp$\R Fm[{e9)e0M&Ea6 |F09`8)F!B69z/Ӽ jY@|wG_z:,!QyJg6V}T-Pt 1FMg4-dkgJ HWɽ)h$U;̶!=̔>G6&.a )7ţ.Xs BB 1! y3}LgcLxK5E|[CbA9irTHGŒh\V<)ⳑ(я|6mk92Aq(rgAJ<96Dptuʶ%y_6~3߭3m`dRTNƶ&͢K=pnragiD1#'p)o b Q $G)@#1㼕8j"/~Exi ]bM}[(C$0|Pʞ?#*6u<n)R\axLae+p$ۨzߘFYQ ]>ВMyW|d<M 5x@cY:W?4GeLKϑŚlH 2 ۜhaoJ";R_YJe8"6PbM~0֗z[ $!/H1sƱ 2}40:viZ۶|7:fRjrE(p ȻO+'_oC炗r/SwA\ rUar2]4"`K!`81T<) ;nBMR&d+Q)d ,ON /`jEzPƜk9o:BbYy&PPM B YvkV#Pv.@$3MI6ߵbBљ/zg 'G{v)Q.Ku70tRT/ RS hLDS7#NmTXwn9rcZMжi~IRP dj?(TJc67-bzް!ߑVy]LD},3 T*+ 9P |@8-,rdspL6<; \Te@skk 6d(*h8ƢKđVh0x/n˺_$&5vճgAe- ~O({\6wX%)5XPQ* Ugd-,CۀQ&baK&Eur`.,]A IٶN]#]R/=7Kk2(z]!П7d2T͆AwP5WڢqlǶӁF7CRJ7pRx8HaN5#9}8m@q#gS"bıq`zAw&q32 w\ &I,sC7ើs19b(yC:6{9T>o^`MUD;b\ =&q]Cac9Bav]5;"FȎB m]a"@[ehe٤A[&~91w!G45os? f}(M+ ÅŦg*ǨfWD5H^oNUe\kT n UPNY @GHf5%0󁶿odFe$TOO-ܟ:_m5KJ0c [s~ꌙPt'wq2j"[iTЕD:)j1EIŊꩮ2pRX HוN\GkވQUxE-cE-")l,, s`f9gSW F-n'rN`nl{?6>G8,b|8grNXO 93SZ9i!5k2Zv9 s6U]މU6=Fj7[I2+qɦe ЮI0o*?ĕoNuS9g`<]V<>zXs?# endstream endobj 4 0 obj 3919 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 5 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 72.1875 46.875 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 2 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 5 0 R ] /Count 1 >> endobj 6 0 obj << /Creator (cairo 1.14.8 (http://cairographics.org)) /Producer (cairo 1.14.8 (http://cairographics.org)) >> endobj 7 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 8 0000000000 65535 f 0000004327 00000 n 0000004034 00000 n 0000000015 00000 n 0000004011 00000 n 0000004106 00000 n 0000004392 00000 n 0000004519 00000 n trailer << /Size 8 /Root 7 0 R /Info 6 0 R >> startxref 4571 %%EOF interval-3.2.0/doc/image/cameleon-transition.svg.pdf0000644000000000000000000010502313316017127017323 0ustar %PDF-1.4 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream x}αj1~b^ ICK"$1Ƹ pƕďn;Bk6S-x`xW|) e)>e N x;25ιV|j ǤpsSk<8awù_px>zneHoZ6 ]` ܰ` sÂanX0̍"Wg endstream endobj 4 0 obj 193 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> /s5 5 0 R /s7 7 0 R /s9 9 0 R /s11 11 0 R /s13 13 0 R /s15 15 0 R /s17 17 0 R /s19 19 0 R /s21 21 0 R /s23 23 0 R /s25 25 0 R /s27 27 0 R /s29 29 0 R >> /XObject << /x6 6 0 R /x8 8 0 R /x10 10 0 R /x12 12 0 R /x14 14 0 R /x16 16 0 R /x18 18 0 R /x20 20 0 R /x22 22 0 R /x24 24 0 R /x26 26 0 R /x28 28 0 R /x30 30 0 R >> >> endobj 31 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 396.991882 301.819366 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 2 0 R >> endobj 32 0 obj << /Type /XObject /Length 49 /Filter /FlateDecode /Subtype /Form /BBox [ 62 119.819366 198 241.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.3#CCK= CKc33Cc 62R(JUHʂ 6 endstream endobj 6 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 62 119.819366 198 241.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x33 33 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_al( endstream endobj 34 0 obj << /Type /Mask /S /Alpha /G 32 0 R >> endobj 5 0 obj << /Type /ExtGState /SMask 34 0 R /ca 1 /CA 1 /AIS false >> endobj 35 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 8 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x36 36 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_al= endstream endobj 37 0 obj << /Type /Mask /S /Alpha /G 35 0 R >> endobj 7 0 obj << /Type /ExtGState /SMask 37 0 R /ca 1 /CA 1 /AIS false >> endobj 38 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 10 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x39 39 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_alR endstream endobj 40 0 obj << /Type /Mask /S /Alpha /G 38 0 R >> endobj 9 0 obj << /Type /ExtGState /SMask 40 0 R /ca 1 /CA 1 /AIS false >> endobj 41 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 12 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x42 42 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_ab) endstream endobj 43 0 obj << /Type /Mask /S /Alpha /G 41 0 R >> endobj 11 0 obj << /Type /ExtGState /SMask 43 0 R /ca 1 /CA 1 /AIS false >> endobj 44 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 14 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x45 45 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_ab> endstream endobj 46 0 obj << /Type /Mask /S /Alpha /G 44 0 R >> endobj 13 0 obj << /Type /ExtGState /SMask 46 0 R /ca 1 /CA 1 /AIS false >> endobj 47 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 16 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x48 48 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_abS endstream endobj 49 0 obj << /Type /Mask /S /Alpha /G 47 0 R >> endobj 15 0 obj << /Type /ExtGState /SMask 49 0 R /ca 1 /CA 1 /AIS false >> endobj 50 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 18 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x51 51 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_aj* endstream endobj 52 0 obj << /Type /Mask /S /Alpha /G 50 0 R >> endobj 17 0 obj << /Type /ExtGState /SMask 52 0 R /ca 1 /CA 1 /AIS false >> endobj 53 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 20 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x54 54 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_aj? endstream endobj 55 0 obj << /Type /Mask /S /Alpha /G 53 0 R >> endobj 19 0 obj << /Type /ExtGState /SMask 55 0 R /ca 1 /CA 1 /AIS false >> endobj 56 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 22 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x57 57 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_ajT endstream endobj 58 0 obj << /Type /Mask /S /Alpha /G 56 0 R >> endobj 21 0 obj << /Type /ExtGState /SMask 58 0 R /ca 1 /CA 1 /AIS false >> endobj 59 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 24 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x60 60 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_af+ endstream endobj 61 0 obj << /Type /Mask /S /Alpha /G 59 0 R >> endobj 23 0 obj << /Type /ExtGState /SMask 61 0 R /ca 1 /CA 1 /AIS false >> endobj 62 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 26 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x63 63 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_af@ endstream endobj 64 0 obj << /Type /Mask /S /Alpha /G 62 0 R >> endobj 25 0 obj << /Type /ExtGState /SMask 64 0 R /ca 1 /CA 1 /AIS false >> endobj 65 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.]=C 3ccKsc#T4. endstream endobj 28 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 0 -0.180634 397 301.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x66 66 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_afU endstream endobj 67 0 obj << /Type /Mask /S /Alpha /G 65 0 R >> endobj 27 0 obj << /Type /ExtGState /SMask 67 0 R /ca 1 /CA 1 /AIS false >> endobj 68 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 176 119.819366 312 241.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.Cs3CCK= CKc3 RҸ l endstream endobj 30 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 176 119.819366 312 241.819366 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x69 69 0 R >> >> >> stream x+2T0Bkgha`fl˥h^_afj endstream endobj 70 0 obj << /Type /Mask /S /Alpha /G 68 0 R >> endobj 29 0 obj << /Type /ExtGState /SMask 70 0 R /ca 1 /CA 1 /AIS false >> endobj 33 0 obj << /Length 72 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 62 120 198 242 ] /Resources 71 0 R >> stream xmϱ 0 DўSpGQ4FFpp$ 0 wW|ޤRÊgVA -u?+KIB!xRq` $PŇXwf =ȱ ?$'r:8> endstream endobj 72 0 obj 131 endobj 71 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 36 0 obj << /Length 74 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 73 0 R >> stream x+*T/67UH/VЯ07SpW O endstream endobj 74 0 obj 32 endobj 73 0 obj << /ExtGState << /s75 75 0 R >> /XObject << /x76 76 0 R >> >> endobj 39 0 obj << /Length 78 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 77 0 R >> stream x+*T/6TH/VЯ0PpW O endstream endobj 78 0 obj 32 endobj 77 0 obj << /ExtGState << /s79 79 0 R >> /XObject << /x80 80 0 R >> >> endobj 42 0 obj << /Length 82 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 81 0 R >> stream x+*T/0VH/VЯ0QpW N endstream endobj 82 0 obj 32 endobj 81 0 obj << /ExtGState << /s83 83 0 R >> /XObject << /x84 84 0 R >> >> endobj 45 0 obj << /Length 86 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 85 0 R >> stream x+*T/0WH/VЯPpW OS endstream endobj 86 0 obj 32 endobj 85 0 obj << /ExtGState << /s87 87 0 R >> /XObject << /x88 88 0 R >> >> endobj 48 0 obj << /Length 90 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 89 0 R >> stream x+*T/4TH/VЯ4RpW N endstream endobj 90 0 obj 32 endobj 89 0 obj << /ExtGState << /s91 91 0 R >> /XObject << /x92 92 0 R >> >> endobj 51 0 obj << /Length 94 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 93 0 R >> stream x+*T/4UH/VЯ4SpW O; endstream endobj 94 0 obj 32 endobj 93 0 obj << /ExtGState << /s95 95 0 R >> /XObject << /x96 96 0 R >> >> endobj 54 0 obj << /Length 98 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 97 0 R >> stream x+*T/TH/VЯ040PpW T endstream endobj 98 0 obj 33 endobj 97 0 obj << /ExtGState << /s99 99 0 R >> /XObject << /x100 100 0 R >> >> endobj 57 0 obj << /Length 102 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 101 0 R >> stream x+*T/640VH/VЯ040QpW Y|B endstream endobj 102 0 obj 34 endobj 101 0 obj << /ExtGState << /s103 103 0 R >> /XObject << /x104 104 0 R >> >> endobj 60 0 obj << /Length 106 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 105 0 R >> stream x+*T/640WH/VЯ04PpW YJ endstream endobj 106 0 obj 34 endobj 105 0 obj << /ExtGState << /s107 107 0 R >> /XObject << /x108 108 0 R >> >> endobj 63 0 obj << /Length 110 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 109 0 R >> stream x+*T/644TH/VЯ044RpW Yc@ endstream endobj 110 0 obj 34 endobj 109 0 obj << /ExtGState << /s111 111 0 R >> /XObject << /x112 112 0 R >> >> endobj 66 0 obj << /Length 114 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 0 397 302 ] /Resources 113 0 R >> stream x+*T/644UH/VЯ044SpW YH endstream endobj 114 0 obj 34 endobj 113 0 obj << /ExtGState << /s115 115 0 R >> /XObject << /x116 116 0 R >> >> endobj 69 0 obj << /Length 118 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 176 120 312 242 ] /Resources 117 0 R >> stream xu=0 = R?ۍcp. %QVd=<GP-L^ O9siaZ_AJKIt.PF(G#d4n]ZY8ڰ@oc7x5\! ? endstream endobj 118 0 obj 135 endobj 117 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 119 0 obj << /Type /XObject /Length 42 /Filter /FlateDecode /Subtype /Form /BBox [ 85 120 221 242 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb. SC#Cc3 mP endstream endobj 76 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 85 120 221 242 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x120 120 0 R >> >> >> stream x+O4PH/VЯ042Pp 5& endstream endobj 121 0 obj << /Type /Mask /S /Alpha /G 119 0 R >> endobj 75 0 obj << /Type /ExtGState /SMask 121 0 R /ca 1 /CA 1 /AIS false >> endobj 122 0 obj << /Type /XObject /Length 43 /Filter /FlateDecode /Subtype /Form /BBox [ 39 120 200 302 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.cKC#C3CC #T4. endstream endobj 80 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 39 120 200 302 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x123 123 0 R >> >> >> stream x+O4PH/VЯ042Vp 5; endstream endobj 124 0 obj << /Type /Mask /S /Alpha /G 122 0 R >> endobj 79 0 obj << /Type /ExtGState /SMask 124 0 R /ca 1 /CA 1 /AIS false >> endobj 125 0 obj << /Type /XObject /Length 41 /Filter /FlateDecode /Subtype /Form /BBox [ 1 120 163 285 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.CC#C3# 6U(JUH endstream endobj 84 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 1 120 163 285 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x126 126 0 R >> >> >> stream x+O4PH/VЯ042Sp 5P endstream endobj 127 0 obj << /Type /Mask /S /Alpha /G 125 0 R >> endobj 83 0 obj << /Type /ExtGState /SMask 127 0 R /ca 1 /CA 1 /AIS false >> endobj 128 0 obj << /Type /XObject /Length 40 /Filter /FlateDecode /Subtype /Form /BBox [ 0 83 163 212 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb. cC3 6T(JUHf endstream endobj 88 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 0 83 163 212 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x129 129 0 R >> >> >> stream x+O4PH/VЯ04Tp 5e endstream endobj 130 0 obj << /Type /Mask /S /Alpha /G 128 0 R >> endobj 87 0 obj << /Type /ExtGState /SMask 130 0 R /ca 1 /CA 1 /AIS false >> endobj 131 0 obj << /Type /XObject /Length 42 /Filter /FlateDecode /Subtype /Form /BBox [ 45 10 223 176 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.SCCs C33T4. endstream endobj 92 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 45 10 223 176 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x132 132 0 R >> >> >> stream x+O4PH/VЯ046Rp 5< endstream endobj 133 0 obj << /Type /Mask /S /Alpha /G 131 0 R >> endobj 91 0 obj << /Type /ExtGState /SMask 133 0 R /ca 1 /CA 1 /AIS false >> endobj 134 0 obj << /Type /XObject /Length 39 /Filter /FlateDecode /Subtype /Form /BBox [ 138 0 308 164 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.Cc LRҸl endstream endobj 96 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 138 0 308 164 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x135 135 0 R >> >> >> stream x+O4PH/VЯ046Up 5Q endstream endobj 136 0 obj << /Type /Mask /S /Alpha /G 134 0 R >> endobj 95 0 obj << /Type /ExtGState /SMask 136 0 R /ca 1 /CA 1 /AIS false >> endobj 137 0 obj << /Type /XObject /Length 39 /Filter /FlateDecode /Subtype /Form /BBox [ 227 0 397 164 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.##s LRҸ\ endstream endobj 100 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 227 0 397 164 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x138 138 0 R >> >> >> stream x+O4PH/VЯ04Pp 5f endstream endobj 139 0 obj << /Type /Mask /S /Alpha /G 137 0 R >> endobj 99 0 obj << /Type /ExtGState /SMask 139 0 R /ca 1 /CA 1 /AIS false >> endobj 140 0 obj << /Type /XObject /Length 42 /Filter /FlateDecode /Subtype /Form /BBox [ 213 94 368 251 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.#CcKCSS 6W(JUHb endstream endobj 104 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 213 94 368 251 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x141 141 0 R >> >> >> stream x+O4PH/VЯ041Tp 5= endstream endobj 142 0 obj << /Type /Mask /S /Alpha /G 140 0 R >> endobj 103 0 obj << /Type /ExtGState /SMask 142 0 R /ca 1 /CA 1 /AIS false >> endobj 143 0 obj << /Type /XObject /Length 42 /Filter /FlateDecode /Subtype /Form /BBox [ 145 67 322 233 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.CS3sCs 63S(JUH endstream endobj 108 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 145 67 322 233 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x144 144 0 R >> >> >> stream x+O4PH/VЯ041Qp 5R endstream endobj 145 0 obj << /Type /Mask /S /Alpha /G 143 0 R >> endobj 107 0 obj << /Type /ExtGState /SMask 145 0 R /ca 1 /CA 1 /AIS false >> endobj 146 0 obj << /Type /XObject /Length 43 /Filter /FlateDecode /Subtype /Form /BBox [ 147 120 270 257 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.CsC# 6V046W(JUH endstream endobj 112 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 147 120 270 257 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x147 147 0 R >> >> >> stream x+O4PH/VЯ041Wp 5g endstream endobj 148 0 obj << /Type /Mask /S /Alpha /G 146 0 R >> endobj 111 0 obj << /Type /ExtGState /SMask 148 0 R /ca 1 /CA 1 /AIS false >> endobj 149 0 obj << /Type /XObject /Length 44 /Filter /FlateDecode /Subtype /Form /BBox [ 181 120 333 267 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.6 /ca 0.6 >> >> >> >> stream x3P0¢tDb.C CC#CS#CsT4. endstream endobj 116 0 obj << /Type /XObject /Length 29 /Filter /FlateDecode /Subtype /Form /BBox [ 181 120 333 267 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x150 150 0 R >> >> >> stream x+O4PH/VЯ045Pp 5> endstream endobj 151 0 obj << /Type /Mask /S /Alpha /G 149 0 R >> endobj 115 0 obj << /Type /ExtGState /SMask 151 0 R /ca 1 /CA 1 /AIS false >> endobj 120 0 obj << /Length 153 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 85 120 221 242 ] /Resources 152 0 R >> stream xmϽ 1 Sx@QDtR0 C&Th /7ABf|1c,$g X %|Jg̣,+)ֶ8yW!?" endstream endobj 153 0 obj 132 endobj 152 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 123 0 obj << /Length 155 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 39 120 200 302 ] /Resources 154 0 R >> stream xeM@ D 2(# %Y7/F,bh9<:!-^"HUaI"Mb% m> Ej諌#I%yS|v)oEvJטAw`Fl% eF`> >> >> endobj 126 0 obj << /Length 157 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 1 120 163 285 ] /Resources 156 0 R >> stream xeq1 {M C##]8E m:N1 da11{Cn&Mכֿ-?H`zB R1әIaAs!Gٮ { Mki't:+{X*#tcVSah:7+\ќUir$Jt= endstream endobj 157 0 obj 187 endobj 156 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 129 0 obj << /Length 159 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 0 83 163 212 ] /Resources 158 0 R >> stream xmq@E w)%8Hg Bgq_u؉5b.BiFd%aҕ$ټpf5GCR}AD" HhT z35hN4ј$*R_MN[>ckVn矺s`: endstream endobj 159 0 obj 174 endobj 158 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 132 0 obj << /Length 161 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 45 10 223 176 ] /Resources 160 0 R >> stream xeU@Db*?a &> qWC#36S";y6xzx|/gFihkÐ;ҹc RD#Թ$ [XjYR3ɭ֦cnQEi:;ӌ_>TS񸦧asyh]hyz^?:Z endstream endobj 161 0 obj 174 endobj 160 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 135 0 obj << /Length 163 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 138 0 308 164 ] /Resources 162 0 R >> stream xeQ0 sWq.Hx 3dѝVKY‚끧{([t |$M;&ƨj0%2F&;${a'%sjڸECMn 搘߆52XJIop9=ϕє5a[0GA{F1q=ϯy:S endstream endobj 163 0 obj 176 endobj 162 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 138 0 obj << /Length 165 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 227 0 397 164 ] /Resources 164 0 R >> stream xeQEQ CW+ޗ2('|g}CF摭#bO#%sf~˃s0:`I:E0K @ꐈ#(Ɓ ٍzQ(OhۓPjGH7U.|-Qv Av-xm[e^*},f]t}z= endstream endobj 165 0 obj 183 endobj 164 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 141 0 obj << /Length 167 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 213 94 368 251 ] /Resources 166 0 R >> stream xmQ0 CL -'v<#)/pRtғ=35DnǪc뒗8[!OAb,j{!,`s2 5e@(혙W Q̺d-D49'hu@P> >> >> endobj 144 0 obj << /Length 169 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 145 67 322 233 ] /Resources 168 0 R >> stream xmQ0 L Q@Z*羓e)_"aȭFOzy0==ޛ>Iݠ`v !#QJ P/DqTY$z95d_҈I"F?bMK*q4cwܵ{lP>T5+H<1IT!4[,>@ endstream endobj 169 0 obj 184 endobj 168 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 147 0 obj << /Length 171 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 147 120 270 257 ] /Resources 170 0 R >> stream xmϻ! )2A̓$c8Zh>ȅlEnNHQ NgF))J endstream endobj 171 0 obj 177 endobj 170 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 150 0 obj << /Length 173 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 181 120 333 267 ] /Resources 172 0 R >> stream xmq0 sV x r (8{p M'-R΢+}}3]c& CНLB Xct"HYt[劆ظ\}א4xsPC(7(RTh)AtOAgԋzYNsb\>ѿz? endstream endobj 173 0 obj 188 endobj 172 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 1 0 obj << /Type /Pages /Kids [ 31 0 R ] /Count 1 >> endobj 174 0 obj << /Creator (cairo 1.14.8 (http://cairographics.org)) /Producer (cairo 1.14.8 (http://cairographics.org)) >> endobj 175 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 176 0000000000 65535 f 0000031487 00000 n 0000000307 00000 n 0000000015 00000 n 0000000285 00000 n 0000001833 00000 n 0000001378 00000 n 0000002742 00000 n 0000002289 00000 n 0000003652 00000 n 0000003198 00000 n 0000004562 00000 n 0000004108 00000 n 0000005473 00000 n 0000005019 00000 n 0000006384 00000 n 0000005930 00000 n 0000007295 00000 n 0000006841 00000 n 0000008206 00000 n 0000007752 00000 n 0000009117 00000 n 0000008663 00000 n 0000010028 00000 n 0000009574 00000 n 0000010939 00000 n 0000010485 00000 n 0000011850 00000 n 0000011396 00000 n 0000012767 00000 n 0000012310 00000 n 0000000777 00000 n 0000001006 00000 n 0000012855 00000 n 0000001773 00000 n 0000001920 00000 n 0000013246 00000 n 0000002682 00000 n 0000002829 00000 n 0000013554 00000 n 0000003592 00000 n 0000003739 00000 n 0000013862 00000 n 0000004502 00000 n 0000004650 00000 n 0000014170 00000 n 0000005413 00000 n 0000005561 00000 n 0000014478 00000 n 0000006324 00000 n 0000006472 00000 n 0000014786 00000 n 0000007235 00000 n 0000007383 00000 n 0000015094 00000 n 0000008146 00000 n 0000008294 00000 n 0000015405 00000 n 0000009057 00000 n 0000009205 00000 n 0000015723 00000 n 0000009968 00000 n 0000010116 00000 n 0000016041 00000 n 0000010879 00000 n 0000011027 00000 n 0000016359 00000 n 0000011790 00000 n 0000011938 00000 n 0000016677 00000 n 0000012707 00000 n 0000013173 00000 n 0000013150 00000 n 0000013461 00000 n 0000013439 00000 n 0000017857 00000 n 0000017429 00000 n 0000013769 00000 n 0000013747 00000 n 0000018727 00000 n 0000018299 00000 n 0000014077 00000 n 0000014055 00000 n 0000019593 00000 n 0000019166 00000 n 0000014385 00000 n 0000014363 00000 n 0000020456 00000 n 0000020030 00000 n 0000014693 00000 n 0000014671 00000 n 0000021323 00000 n 0000020896 00000 n 0000015001 00000 n 0000014979 00000 n 0000022187 00000 n 0000021760 00000 n 0000015310 00000 n 0000015288 00000 n 0000023052 00000 n 0000022624 00000 n 0000015625 00000 n 0000015602 00000 n 0000023922 00000 n 0000023493 00000 n 0000015943 00000 n 0000015920 00000 n 0000024793 00000 n 0000024364 00000 n 0000016261 00000 n 0000016238 00000 n 0000025667 00000 n 0000025237 00000 n 0000016579 00000 n 0000016556 00000 n 0000026542 00000 n 0000026112 00000 n 0000017003 00000 n 0000016979 00000 n 0000017077 00000 n 0000026632 00000 n 0000017795 00000 n 0000017946 00000 n 0000027029 00000 n 0000018665 00000 n 0000018816 00000 n 0000027476 00000 n 0000019531 00000 n 0000019682 00000 n 0000027927 00000 n 0000020394 00000 n 0000020545 00000 n 0000028364 00000 n 0000021261 00000 n 0000021412 00000 n 0000028802 00000 n 0000022125 00000 n 0000022276 00000 n 0000029242 00000 n 0000022990 00000 n 0000023141 00000 n 0000029689 00000 n 0000023860 00000 n 0000024012 00000 n 0000030141 00000 n 0000024731 00000 n 0000024883 00000 n 0000030590 00000 n 0000025605 00000 n 0000025757 00000 n 0000031033 00000 n 0000026480 00000 n 0000026955 00000 n 0000026931 00000 n 0000027402 00000 n 0000027378 00000 n 0000027853 00000 n 0000027829 00000 n 0000028290 00000 n 0000028266 00000 n 0000028728 00000 n 0000028704 00000 n 0000029168 00000 n 0000029144 00000 n 0000029615 00000 n 0000029591 00000 n 0000030067 00000 n 0000030043 00000 n 0000030516 00000 n 0000030492 00000 n 0000030959 00000 n 0000030935 00000 n 0000031413 00000 n 0000031389 00000 n 0000031553 00000 n 0000031682 00000 n trailer << /Size 176 /Root 175 0 R /Info 174 0 R >> startxref 31736 %%EOF interval-3.2.0/doc/image/inverse-power.svg.png0000644000000000000000000006315113316017127016175 0ustar PNG  IHDR60sRGB, pHYsttfx IDATxwx[ǿJW,9d9u{mcZSFH0ʞ_)M!Je]V{h$tH^qHImGq{uޯ=`NP^^%``84)5559]QUm,?Gav&fVS5"Q^^Ku#iD/agE~f\.KӴKh@SsWcD4:s|MӞ(wN N?1lܸ1 EUX 8^v|/Ս=~KX=Selƾ^gRʉ1~qy~ߏ9$ '~{3 ߽ \ؼ`Gj`g|(25`"u1fg84Cףq;<`,94 ;,u\[OsS@ PӴ/ӏہ_qx;G'buP߳9z ;5^[PZ ,XWkvB/Ӎ>~7%Fg`#po76^mTXU^ؙCLi?4 ৰF(Q`Xט=u-+cMℵkç"HG8LcLpM`].W=` 0Qi5^D41΀|eWyqB8]kEDNDnejPxL=??"jbsD|<8|ۃiCFJ}&05Ȉ@DR9|={V?~Gz]QJt EAD t34s9z=nl ~^m?7wEdYڥX{miio8 vFe=iYO{n;AdѽD PƷn p8\cj^=XSxպx:8}N(Vg ;쪏&05 Z[[,@"ڭird;NJay5XiM`">g1ۜ_vm# 0n$.a[[[Y ;MDCGmy7n3sptͲ%%Z @[{{,zpF2f_BO`Wt wXu;3^Nvtz:d$053 5Mò)an$.a322KKKg,\n@ vI5!ķbp|,--.<6@]]2~i_ԍd%66>xo|vcjV8o=;w#`YMba޼ynr?N`jWى#&Ν;nY~__ ֥s\RSp@$Z 1Mr$ð% ~lrzoA_*36›Pͅ;?Pz˲~S[[ŭ:NJaGQ_IKK3㘚a]Siii?p9n$.ax~z"ή vjȋX} nݺ#98V }hՃLmWW?%y @;S^13?{n$.a9sl,k|B)ߘm7|eY׹\N'tuuu BG(S0*'&05 enoӇt#itəV!tH`ujaaxf ) *S׋%EEEkߝq&G!`=K=mY֑tl]M=a 1V7#߮t)x]SYYymĞٿs`$>0[]ų16}SXzT*M"@:؃%FgggWJ\YY9/0@$ $K)bLMin {D,X #wnݺ2 ,fHJؙ SB{ƠAymmʰg]HD_ТLMRLM= R"rqT{Tu .yhjjz˲_8 {~LyjaOo]zxǎqTS\\QHyXϒM஬4 e-v?flrrr\ڛuuS` ued1c`͈ej^s:m 8jz+GZCD[`gj:~9";;; ^UU5F2R*dl* ovK>q֍k` 35X{ h$yGvO,˚QHYXRMӞ 8_lf7u\p;NP(ɓQ7X:ᰧF<O~(++k bG`W|#v O,,zi]s'^LͷF]fAii)D4ͻ{[5ϨX1k~FJ')凰g0E25;05L*YÆ 0ZwF2az`0GM 2-K)Ds<{8x*kjp0㺮e*++PW$]iZ jpJbjժi˗/:14tu[6}0%8c`&CLo /Q ~A)6)|5933s:Si(ؽi7SkL())I7Mv"j$``3Dt͍yiYe[Z^MRYX#7ѲCzWV³;05LNc1YbO3:05oL6 q#g'OR^.**ja]%zozB1#j!čQϿz\B5BH$]^/Bl|W]B^JPЧg !\!D_~B!NǓs!vϗTTTTV_.V\\_! M*!&N7MC?]jBNv0|_G]zX%XX׺G˳ d̘1րLŚpVigvvv8k!!HhQ^^^(kB텅4m}~~~[D|>䂂֊ 7n^wҥ}5yke3vADg);a~aÆ5؋t?͂E55NEs4^e76Ss?09^,))i>@D"z( !555"Z\QQ쵟:~ڂOSOqe7==R4uX@+7l=M gpyyyM˒ܦnZ3?pI= &N♣{02W͑jR1tԨQI)[e4d_1kL4 X9zH!hS&?^!y;999Ԥm=z[D^&"ɺ͓ǼGz0{fLD_ >|LM' {`/&Γ;c1cjkyj6xMDw ˦i@z4V 2榈K)*L m{15ot~kgTvnLFvv륔DrkKߏ8K J"UYb^?R$vd#$Uež 2e:Jwbq6"..--ޟbI]~4ѫY`| {S< NMfž]<{8qҿ (R^CDkh.u ԏ82c؋E|^]4C Ű]p6T8~_8viiib17 fpL=5~ʹ@7^Huƍ()0|2ݭillR\)[~c^25[i:8L밫kxm/#VNiii4߿TJ [}hr:+{E3h=+ȃ<>fS,'_~{dJJJҥϖ5>̍  IDATG̊[jjY]"RGFS YXp2<9998/( OD?/++X1}Cؤ>@G?뺞k?.YґBhUS&b陙` %+n@ zvodffzP@ T:884 `LNN+''= ~{F -..p:nws [TTNOOߔ#B͙[BǓv7YYYk@CNN777wsff7`pq 2337U@#Wv7@`)++@ )33si0\VXXXv#2337fee- _!F s 36++k]ff`pU~~un{V nwWBvddd; ~zqݯ5SZw^Ν; !jng7xò|/X `sVFF촴C%PhBvvܹWfeeݓwCKK/,zgeeonncYVf^^999477?bYzy`pu-v677?nYɌZ/!Vdff ?znnn> ϧںزBSu]_8>?===}ǎG^KC`0x?r\W^ޯ_k0/|" zeee=vfkHMZ 6P=gg.Q}|`ؚZ~k>_XXKoX~a85鯲0cM ~;N vmeFRGaDejHejW? ?'7 P nt͚5i6l˖-[>XnݡEEEZiCIJ?H 4hPx׮] O;Mo~lv o`7]1Z7M4˲?<6k֬vυ=>}դɆݟ:N(*Kj24*9&MD0)((|G~-˪,^ٚiV`|e.MED'8C{NTvRjYupثUWWWyOb35`p#[be+`y+F^=Qˢ %ڞݽqd{vn{Ѻ+xn- s5M[z]gt-oGՇɰxLܰaÿx;vjY4M~W{Jd㙚[U=¹:EqDسbZUnw*\`JY /Zh9q L jZ/׵~~{`w)1Ɏ+VL4nx?޻4aѰ`~RXS:8 x'V㱫WyKe|.gjwkD4j˖-B<j]KPϟ<ܫ0'OvZ's8C nN(aL͎L͝Uy0Y}!+G {!ҥi?ܶmùyyy;UkղM *a]cRL4m*1v9%^5j`>;JN]L𫘆j3<@sLpeJ^cj-xnSq>v^KӴqeY(9XӴipzK0IE$ è1M Uk0NuLB {ACUW*i{3S*xVbD͊uJ)˥g7q)I|屮1iUa`ܐ,L2gl"zRkƌ#kDdj^+g.O:הtTLMtefu]hD40Ǥ;S4:ܨ}N-v#Z[18aw8=ALZXqy/MQClXNSSSi$)3Ra\GD2FLGGfv3q͈15u4 @x&R>M GtMJy=YvuEEE[zrî9l'|r{ԬLF$~vB&i|?HYYY9\JyJn&9C Y^TT4&3Afva25u?ĪPRA/嫌uaMЀ`Rgh5I)2MsrxFHJeJu`j^Iَ=+p1=ejvulfQ$M,VӴ*^˲t]qq0<,xuj]3Q]<ޚ0lL\~15錮\Beb+mB7o.nmm}k?ohhبLk>HY5M͟>g{=DUsTm&((((߰aÒTTVV,k|8`MƄt]mYV-Zh+WLmsTQڠZ1cJ)O0 VX؎>޲Z˲u8C|m۶>כ6m ~Wdj`mOU$☚?aWu}JrNs+`)5D&"0p@cyy ":b`y t{hF !BB='5!B !>ozBX@}TǫQ !Bpd=L}h}' !BBjc/h/,,,V?Ixϛ,hB!Z|>_t!DsaaO"QBO}ޅBÇBDnj3敱cǶїJǎ6nܸ;^YBmW!8̇|>4!FrrrBNFi !zWqƆI |>߄7~555fCuCeV 36XuA`pr744z{is-zn=&^+$Sa׳aXAUPPТiaYVU86Ufg iɆ r֯_TKK˭ 25W a$ܚ åh6VaUׯ?$_PPpY>k֬赫3w?Y ǿ9k ͍qPh쮩іejg} g+VijjQ((9 ~Ga5߸q"4m1eIMFi6@o-ZֶHȀs:+̙ۜ԰1%%%鹹p8<HM4mVX|);wvLSs ǰa\666q$:|5\Ӵ[5 |k6755KOO,''?rgWúưꚦiC(˲8_D,ZP(ͷ~{z{{֢.]&)(((8hÆ HtMJKKnP(4 P]ׇZ5CUwuuu7pDY֍TbM+ ãW5llR[[}֬Y 5MOujz9 +uIMH&]t3ɀip8V än$.ap8|0Gc0LjR)[aXo&)x<50ɤKllu}6Gc0LjF2&)4b&5uuhaXo&)|8 +aRS7I0IeYr8V än$.9LF2Rv'vbP/ 0qFx/79O=T9QWRRΗv_(pkE<=--?r Fusff"n1ɢɮKsU+teB#Do-˲P(dtI;T;ꥺ?Y &={wdɧIHv]:[x/%wɀ5dwVDZ++%\bX =AEϾ:bŊtmԩVY&NK"Ȼ5N6Ngv 7,[ /ZFƧ<9|Gq8VH2ھw\oƖe˖W^ܹs[8uIH&]bgXnܥ~_NN]S@ pv}}N^-<c ]u:wӝN`0x… _$n$.M= ӵgY^^nqtjпnurX:AYY%pR˗uctN,d4ԫM(=jut:Gq8ViooG[[5&t#tW6Xi4]_R坜[n5GctNלN\5&t#tW@ ݴiS9R#O>s8V 4Ge=FMúoH&]Ʀ-jll|fգ=MD?pzÈh#͘x~34MSQQq |aX`ۺW[u_?~|pNJw\.9e ^bߢ^ ~^ࠦ9jQzhy!XYY9< -Zn5k0bj@1c|B-Zh5 $b15uuu8@}d,eYiG-2 ,X 'bM Bеcƌ!:DTƗL_'977XSK, 5n޼9^!uu)Z6{GJymi;Dt%m4Mv˹ r8VL)Ә MmRȑe`]%i$999xp[8]ONNbN׈",j,{<ؓ&"w!m% ] ֥^"'Ov+cƌY6 #GAD0L2]հy$fE~Rʝ?3N*p`gR|q~:q%05_w3Ǫ4[ᶶ4X_EN^vp8in.u `VGvC@DChizxb?WJ91OSBkZZEE@)q6gx28cs֍ѥd,p5t[uuu_eY7358 ߲}/4M{71(p=ixo5Mr~EDĘ8^: b`]^nG7gl"H)ORnIOO]iڊ4>E,?Oh QȈU/J)jjj241!ؓG-zy̘1'O~+.L,yeYq{f~|αbz=;KiHp6RC/^<-BO$ _p8+WN4 XVWWp\iv#ohvg~LX1 ùÆ K1,z5;;J4CJkkl*~i#ߕ!7oP(37q}g9VL73k֬fMӎj8=\>gΜp]SYYyGu#Uti4S'&Ӆ0\fY7 ,fWE.X~}eYOfmضm*IzM嚦]dYֽLȾ -˚ŋfn.ݧ xtΧuuiy{YG?&uꋎPSS!@O<222PeNӸw^IrMƊM]#<"4)pNUUU^)f)|*YcY]-`~ @b"Zͳ:uؤt5)OhmVV֑K4FlϷR2ɪK}Mtkhz >zԼTjݕ222~ϷUDŽa7±b?iY҂{{Ձzqa"( `D\\Wh&&jI\O%mݨٸKb-EY bTAK0 s:G`6~j~O;USo:?P䲳7nU`q"J /B1y{PYk/HӇӁk/"͛ !Dk\]\9|H$.dF(a%< hiiy86`%PܲeKyWK=3p ǢE׫9+y/^jy7BK 61MN/ 5 tݺu9sJCC8)1? J.TZ=H|_2Ɯd\)'/)|B.]a 2kEB4m߾krũ J.o7\a&H\ mii`;J9|Sb_g u2iҤ.E=\׭q]wGd"C(gE ھnf2=b&1o`!z ̙3'g_]jnnn鹶9 \} CqNşڳNJ+QxD⒡CvN2"iZZ{|)>-\}6o+]WYYyj&)ʪ&L;ΏTJ"mmms9[1&SE;(u-Z:0l֕ƘoHH?'$Tn&8r1#]4mڴ>*-R@ZM0aO=X\N'U#"GSK${1\ם8   ߴiv,ujkkՍ)Dinn8?_',vKR-rf;/);~|`FPۆ ;3sʔ),V J+rĝtMA!Hg9rܸq)݊BDi`JH$ 5lv8LR"H l&ezybuݵ j,f]CCCIG\[CZ&? ihh8ȹC\]tUH;L=6YUlT`E "kg}Y(8!^$Mqk<ܠvi5۷oy^I=hfGwU0OZ`z8jplpJ$|c#~[Q~Гx9(VTTT\/E.9wѣ;u+ ybg=$?uww?s/B KU%"Û`q.|_±h\]dVQd2y]tzHzMMJ~]_4isÆ {$3󮮮뺝#T-a0NNZ1~_%>^dO.x%H4}wGZŐg5k{j֯_oƗ(|x>CCـ?_2l ={녡09XF|QqTUU-L4i~OSݓg/YkղBDQF-Xr c̀[*ܨ!Dt3gNZ<0-/ Ÿq4VF|I0M@m:w3niilJRcV،?5%Gf7ODPE-[yx#qcggqFH+}ϟ,SZz"P- 5_Re10`@uSW'y^샍hi%bk/]<trE7 E͗lz 7-,6ľef0aAeee'Pݰaq8:ߨ37CW)">,f1BDT*5u­?5_R ڥT_uxUZc=fӪ JĊE@:57osKk;w o?,\l|I&c0}_uvvi"b \.7`e&_ 616c{ATٸό8pݪ JĊE!n؍;wŒR0Mx[__?466vK)|b𝲲)a%`],0\ L6RJ^cL~9^WWw] 6q5?~|O|P׿>i%b`k)߳{ٹsJ 0TJE7K 6!V~hll<cZ D| ,޾ v oɗlBBGGq644T jl(i%E2|NR௬H%oJ7K 6!aҥہU BS;cI)!DT?~ykkkko-<ޞ0(M|YH$ 5s'x ܯV"_2nsSoݺ5/)؄crkAxߕ517J9i7ǹVb_R -p%p^߾}XF|I&\,fkԲBD׀Ui/Ɵ5˅Հ 6q%LH$;Pk O<*{MM̓JďWꊊA1oqT}#L`",X [QQQ/Trkm{.kJďKnEF|B_ 6ivڵkrc(² ؜p-0F҈楗^dWXq3lXkWk<+UaS[u5556VwAo.>@kk+8L&tuuI%Zo1h ,\cI$ 25k֨pGtwwO__iӦS2e{b1`4,%BQ'Bb4V(xشBDih%8N2!ba` B!B!B!B!B!(JWOmuGX Jsh$!|M!N n9Z !kB(0 K/b>+5!B!B!J HVIENDB`interval-3.2.0/doc/image/cameleon-start-end.svg.png0000644000000000000000000001522613316017127017052 0ustar PNG  IHDRsRGB, pHYsttfx;IDATxy\ewJHf@fEvdd>PtEE>ODA n,!$@KdtJ;?޷&'EUVNYN=zλS%Hӛ'^Jix_+sƔJ-s^Qqy!$$$$I2 Id$$I2 ILB$$I&!ILB$$I&!IIH:6KgoyX]~$ =+}ۂ8&pLI}(fuf $`oBF/:I2 ɾ g[˫$4&6l"&.1Ϻ} \0z t~ ,MhBqQK :_% oS pkLZ暘.\qvj [:gu"+5qq*X.(ʲv`0,~' ߮n&4%]x&Ƥ5%&{%qis \ k2CbR4ֈNͲP%pUvh|=)z|uׇw{&>w8?důMcG=x^TVmq 7tqYDeXKّMįngiG O"̫=;K'o|WY?3>bm6IJ̈́~ܚ+=6McEU&I|9m~J[y HO7/Mi8=H#Y\%P{|55u%Qkx>yM/|? aôX96& MT~ ha_2ϛ)ݿT;X:WÚ o%K#c"LB +):֟" ]خ3/ϲ|aT… Fhpn\/UeI@+ӻq:1]}=7p+ݥ|rȝVM:O',R80uY8[7܋p* 7eY>CװщUY6馾y#Ԙ"}1f6KWwVJ&k& 8,:cC.(2sO5ioeäk"\M MͱMzYɄ;=dg!^}T^ GB98۶m0@N[-Rl"\'Bs/Rk(s~G|?)jaڐXʼc) p'F%/D}8pg ٦c4p>m" AF願7s=)&ܵ`ax _*%  L|8\Gl=nюJA^J&mmFcԌƦXn" Ѿ̞Ms  sRƲ$G%j2+c7.)A5w+i1axm&uUFz6>},5ʛc.X9&s-!T?z萹TjCƚ>UX+~Iti5 >oi1bnK7r3եK|fYAMp'ٿw\!uEx[s$e ƓТfUK/]U;;k~\u͜kSϺl`D#WNg(v?z85ʓ6 XVYٽ^NNsFU&֬G-XŰ5!J C2]vu_YB>=$,T;|K&!5* U_cSn}vM=čy5;Ky5cRuK*5HI"PyΩ+N~٘mTZnmH2 >_~gI#tQusVmX{S?ާʑ IHiv*b'CQ yԋ*zwk`QV#}`4g[Ǐ59ozzыNԍLBN7M6ne7T12 IjV:}G3w_Q'`aHOzp}'դ$oM8cɠ+ѐ5(aqm*N߫Xyn-ٵrfs;OI'}RC^r|92iƻF8R%%DNB/m[_޶m伖eMBЭzk!O-3fp~99ܱ}3weFV0OcbڭAB&!F' EkSoʁkH&!++ EQ3j84N N|$ '$7Țf~ 02 Xze |$gG]7$:xh(TO;IDfdPu$/`P= dMc+ LB[ ;p1pr$%$뎒> &\01j_N_R1d* LB8[`P3 |5c~$&D&'p#D*3< \bxd8LCjipw~G&!IŶJ_,!4I&v`F)F\۪ xzne:=b 'Ō3.f[ 3Tj1m9`.ppU3pom;X(e:%YP.G{V'x"?|4(~P^~ <5gu/څU ?5Bt`4w1ee'ֿ >oC❹mRC;8qqiJlĄp0X <YȲlyV]6o=<۟X CcU\~a:N4y:O"E5'ff\( XV$TlyVܜq&X>02Neˏ~WG5f3Âv6ZIW >863˿ʲYW7Ńw (Ⴙ)Sǽ⇺Kl L_qv'{_KN~)-xߙn'{{z1 'ϣObI,u,[UpfGcH&CFqv(aŲlz3ab|$$y1sΊBB ͞f5t3c/,fB 4],}VX-*jJ_c2z]nvw#Pgxf]Q:g)ub <%1nf!}}>"o%LWǚM ߙ6L֪۲t@C5$6VyVZ-j$iOg=qlL@9|`LB4쳐F%}/>yI/K& M9>\봦93.w,zYw+.˖gT},7}iqz_EӘ3e]56fU2OתҲlyVu" 0>%t<xXZ.ΨB?@[Vx!vcJЖ|.iVM8@Q+Q\Mh?0g aaM 6f;+c|C~f' Ќ5pd˲YE1n5{)]J8&֠2/>ahvm9y])aFf^qc~ƞW{}}]7߶ giS)USbsa\Xߔr(fY<2gb{F [)Cr$1K}1U|􆌭qUܖ}ӗiѠ(g~QhIENDB`interval-3.2.0/doc/image/octave-interval.svg.png0000644000000000000000000000552613316017127016475 0ustar PNG  IHDRyOjsRGB, pHYsttfx IDATx{U?8<ƀ[@aM+^-$EaeZZ.t $[MbS\TA~ᚹNBu+£ ԫd?ɯN~!-oxӆVl#L'Ma&rk{z4ymoN}L2C\W[[@O|hqǚėXƆJ[\ד(L*0.?5V}L/Dm1? 4,hn:Q3c=A=`|&sm ]FG v]+]s H4.Kl96#ȍ'pU4 7lUK)"cǟbQsJr$J{ă %Lt 3;c^J<ɵ*&Wuu1MzĄ'{kE.?^grm&o$엪SC1Nj ֊ Z߅q7 < w-v_RhL"JuF>{B _gҖ8}Էpnσ7IO$!$Q-y*n˼c+1+*Ux_d39GdK c\>"wZVc*mLTy| jN+"V]wѵU;Znwʖe؇?Rj '~U 1\m Iȹ| &f-4T2]b=, H( ߵt mMFcLd/Y]`Χi0t;^{NVZ<1]LcxkK멻AT!C'qI|{ELf9&I@^>ӇFUjOc6j'=+iq O 0m0GAHnn-O1XQYJbR&6_$['YoWx$LU+w6c|l#Ж;}6J#~݅+DsV]FÀU30Z%DӺ*觖tV޲ 3/uԿ;'^[h{5^{5OsuWL<[4sҕ:xնPMR:Il3MS4?qp%n#j?wpG/;n.!VZ{"a|01e/9b~vJ)6S*M=Ìz8٭zݘ7;1QYOn-.l+fU7gVzUl8ޛbٮ}bǫn3R1gh(m#USʍxIENDB`interval-3.2.0/doc/image/cameleon-transition.svg.png0000644000000000000000000027020713316017127017345 0ustar PNG  IHDR䭽sRGB, pHYsttfx IDATxypWv;Y fll "v6ݹprT8R7*'ޭ~y*⤓z7}F F O HHG>:7k-A(R޼AĩȮǬv/J BaQRB1cg7}IJEADX ”`u~VX`ku[cU+tAph)'kﲈ׈Md<iɮ`))AA]P@(&l,_]oyToy4+%& ",a )R28o  +tnjhQbؿvw_  8snk3@a*CȻWH) Kf x zf ,1^AD&ZaNsf5+lǵ4Y]aOJVADX 7|V~ -y# G…9ɑ`X2pQ6I) B~0xﱺX֥vf -2ݺS)qAAbk8iI77S  P93`ꇙՂ]]38 Kappcu+ZYQ>땞Ԅ  ڥB>g|W/{zFAaKanp7~!7TDjDA3 ;UsyduFABSMgd]Er Ԍ  M }HE:ũGADX E+.L$ Rqt3fAAPp[~ZQ-i8nWiAAa)d΍5w–B?F`QwũGADX EJg{RF\;z4ɖĩGADX EʑAϩ@TΎH K9&L \6gө}^AAa)#k87SϞ۵ |)5# "$N=l0;顙4i}1 }73Ԍ pyCMZ<44٨]ߐGa`k͵bAX E e酗UVkO cg`-gZ{<6&$5& 9Fk$~X+,C4+f̗zHAA v?WYKrBv' ;#x;F& n'2bYTCldž.\A#rR(vliq6!&*(E}0c`A=?)W.ADX BٺhM}cGdkRq 2;T"5* Ysl:ca{w4N)ܽɧ%. >DB 0i)x&΀Un>VY4S 'feeG;AzAyXKCyq;\ F9.6M=hEԬ  RfuϴP#c%^l#POV5I ",a%tױH>C2;揎'5GEku[cU+A0eǁ'pUϑe'w!~lU΍uĩGA(FyG(Zm ?D3X5!uA]pgbW,ReѬԴ P,UD(Z|^ C_Q99-17 %WJM ",!`6 M9uBa`(k뤶A0Vj T>A 2z? 7.N_AӅ~_ ivԾ 0W3¼pf$, ZG}͵wv8Ӱ֟qAAX e 8MA^b7ݭ]y5ki KANB?BK.= Uw'&?{Ť% ",aly4kzQW!iu N=TvhoUW+AAa)3wB>a&`z뮳#C+(!7Vi C0l1b ~痝zU.d}S ׳%q̞tȽ RmE݀K역ώ0Yz@77tt2dӝNUc TUA.ee-[))A mos4{|;?NwiCBuғ!ެ RnVinKZ#&n[jj RduK/I-~}H|e0?pf5n  b\ _jU~qJJXa)P5BWT=wO;cyf޶6ٱ"LL R&uP?zЀ"yd6!recŢG=ݶ8,-E& R&P7~ӛQ2 ^,x VF6|D&A(:K`$L;v0Ә9 YAsT~!յ \HUX-Za>lJ. "4N+vaoKs©hϺxfkc5"|_* 2oGvYFY :fkWK 32H7oqu 6>ҕh,icҜShъN$NA>?*lo[0GM:BwLo==#gXP$ RXUu NbDX BY"W/;|s N Zyc2/+Z^q֬qtU^Aooz켐ȚDgTJYa) R%_rP|,_iy4 d? ]2^WpB_ziDVZU7rLZP4 s1KBe_Bu%vUys1ă/i6{,s2nݳk{wmþYy?n,vP#,3~`<,BBamXTߒ=Ë癡/w)"rDMLeĨEf%y;ũG(a; b圥 R(^ln>=A΍u_ҲZY9Ժ'yзVTUezyvWz,,Yu֠3x ep?)RMe>rbuniQ}/b`Yd@f,[_=E/{:*tVq2<@8_ ?|#rJz"5q0=N/ l'#7 %WN2 }91{}_]<- Å_D:#E 3☂ˀU^sm{fO~x?ѷ*$  _ 7iY6P0vl٢GL?-B.Q{c '(sIW#fl{Twx{YEf:+/N*]--_;^XZ@ULˣ5/]'Ρ̍/Rf{<}Y3=GX}ǧRo<80k}PqeCǒM#/ :τZ#+X˄!5af ޖHz?DMܤ83zp7JVU|VYPk;7UUۈS˦AZP궒G?tn6ʗ@ Hi>^vq3} B{M1қ|PXF+=A($~ ,d"?U 0e*iX|exfg\O5\IۏUޢ fG6m\fJK7܇}ay$elYk>)tǽ Io ^Xv$6b׶Bm8%>+?6SVq+Xh`ϑ"IKA(@T<>r#5e GdsfELq \]#a4G9(/S0j_H-kۀyb&2vH Lț/!?F?\[otg>C,z̠Y =dGL,{zsnR}f}PVɉOrJEX زE{`(t.[w> Tp9sYqƳX^Wƾ[XO/^H->%Gua0/aiU6qG[FJ/̈́[PY%'}/a)Ral䖎?pPX=φI77"蔉 n '|WR?.˓+*զ&xwBkQla a>z꼲<~|* /k|7W &Τ c0 PhKaٱg%+?W{a1#kT2aOַMԳ}@x&2ai&ߗ%g:BN=Ŋa֠jέ6WᬛOF/v*I:݈@;Ma$sh.9ˋ 7$L72#|,_363'tnXwΉ9zJOFDǬA=f?\e} Cp(sScژ醙6| ,F&X1،yVewQiW}`#o6n`Ѿ76TQZ|n}&Ƶ"q쵔Uc3=}hV8FsX,Gۯ@UվkK<'[Aƫ5cB}M⽜7a)?87}[2iۀo4|}`le ry፿Vݾow<}{߳ы21`ڦs~A뮳#ʁ5qE=2ne<{csfkk~餻"cyHX?.1c9ufQWؓc|5v1dV*0qwP bm `p9o%\~akrxm龭8 #بFxOfbj0ç/4sNƳK(̡I>@晒f7dѺ7xdsªB?F`Qw' x~x/-?\㣶e1Ҽap3C+6.3W.x/@J_SyVBhů2. *~XTG|A( b)˫J[Maˬ|+\}?F k¥Ԯ85d J N\Zi2;OYR9ˀ5%{Zc_1E<<&D"ytl8%uÅX!b N\Bb:M{!R(zvlP^䁺 *h]ȀzV*==]yj 퇽g08GeW2qώ'A;75v:;"=&Da@ݤxoٱC9_DSP W~F `u9a0T!1ZKx㏫K;Q-C31`,Dj&4Gn KbX]W9x~k+( :ZGbܳ薚_f ,TL<}~yڛ V>"? UA<ׄ % 9~IyAKP:FX2Q#3c ", 'j߉Sy6p#uf}V{P-41 Ʋ5&i<2[M].Žz>0MT3tri7ܹf7N=HTey/t&&iny_cr:MsI {WKt>I⇋m+Yc)XY}MVv8 Ș|NNJTHgp%29ElIwNKdm8^Sޥ}& IDAT]Wϖ P0**N.wr:7s!_\ z`_-?9 "":2C|=ol~% XGPX5RADlB2KfƻG5>CSޭsBaV*|*=B0KJ V`i,VNF?w`!ŕKqʪ)*}]][uYL?h!lVm1"2xi/\'d.-XM,t2Jz`R:q¯J¿gt"ـEdoZtN h̃ KҺޕ^1ׁœ?.յo@ T P`2F{lo `9e@,H"&`'Gu2:) |k|Kqy"QrC}T2<)6Hz/&IC  H;ߟp'*V k}hX2sJƯ" ,ߪh ;$}Bp?mx.Nm&brFp5*zW>{zᢺZ:SHQ 3xXˣo)6qLK=9J+xP^(2D"ڿiͿuX H;;6`G*b^ɨxcDWW Yd*:wV jUm9 Yͣ×# fSOO\Pׂ*ܑ4B@rՄ丙HSϬTpb[߽Ԕ # Π21tJ&d'Ӌ7 P!b  yB;b|Py;߹rȌzIguu! MF/Cg<CJC量Yj~kL4ZFaf7?kFV-S^f;pJVcr]BB\ʏ^R|p4,-YR>tgy-He%\Kh*.=Z2\y(.=QsEp: DBE,pOuǴ<'M!pJ6ƃ.\Ut>^=LzSz4 xmpN[éG ϾT+m ^g!H&:r;:de4 ϗo @!2VxsjBO:D*9.Q 뙊`qE&|Bld"x0pfV"#}(K\9p  ;4w?Ieߟ<j s3jt='B|1yKt~ eViw#(5i\Hp9ZeWpB/A//EzX4_R_RӺo}^9b9X%XױH֩ݦҤ$ZDHti/yq"t|}>dC5CWʫqLj=;Ya`FC@ ",oR^VRmu^DszBCRjL<'|4[使eod3K:mzp0z^:='3k}`F8䝧ϗo $Hv>煓b@L&pݩ"UP3bqFKKέ49VU)åx4)c¢vMY1fՃ9Y}8YΡL8:y]-bT:7=mE㚨I-g8ۥFw9ԍ =F廋>jjËJZD׊HgjUN/8քbՎj`b |F]Y*߲eǤ󙱡w rŚ]?Cs9cgv=-9\l@gT1PTX>CFVPuӍp YXXG8b?) )k)'&W󭟴:ɑՃ@A`v ,ˬb' w,;;͎}uY>w/|9KW~*x ކÎ!CNX3aPav }'.E !g4wΉYV9ݷ2cTI_ЍpRzy 9~3{Z"hX|dVnFmܫuO~GΣyu量olNFج9F3:[&ֱ5);^_>sϨSֺmDvQ6, SOn Cfݟn^5ٶD\= 9Gdbe76su2epm?~2'`؍@!tNj)t\sh(;X8t$^/Rboͨf@.g_Cn\"xxɵu@nf9aa pũNVs7~tcZ… 'ڗ9+M/0P2j pVK-1ρTyYDKkJJK9CQNtaT!3mF&͙$S[6]KayDXUF8z;2Nѿ+cRx0_WP t..*dWpe{jx!F{J 6fS\$bD*v>pzt| ':B> !h/i ߽3n-cd&T^Q}'0d2x'Jf`|gR9 @hJ!97t[Z1Cl^V3u &pwT3L܍=9ŎMR5A=#,*{{Βgɥn& g|Ǎw:gȫ5#ns:Bdmd Qjikk~؛  bm}0S#րOΆĩ6)7?_!Z !:De>Zl iA aaY2*iϠ|A_<2@ jO @m#a@'Q@",EXcR-=yԷrL R]˳Tp"3 nKAounj<&I:=~.Dqf@[0jcԤN=s| } vu|bC \3~YdW|.5㦿2KjBa}XRZ18e>S=aJr2oMGF#uΣq_ώdaԺdԙo9sv&[Ȝa{OɔU@ߤCcΰ &hwDx4C|l10 ;iP C9snT\;~Q"a7ANH6/p  px69od&}6Sʋu҄0$bmi<׭beC.ڐ1_ɡH7Wvܷg~sW[)Hi@#k L2TjklF/L"Q) W ;)CjωC8Xxq Ķ2aS.uX?_ rοN3 )i=¤sLݐV$Kg/Qҽ xoCx{^?W)\0pnq'BI~D} @M,x6V?Hv }_]<߹eFz 7KQ}eϼO!w(v|RnQǀu)SjcV6ƐpQnP/ĝn*9T0yLsn,+ vȳ#pBT90_w4Q;O i}d:SvS&ln9f"FGguf:O|Y{4[>[w M4ݶ@кF33n뎲+V0- *R˷Ur^%A@%2k̸p9*\VֵsV;u>`xlӝ:jXYnC", 7&@/| ZjԼԓ1KNe%_"Hڃ?xJ<8M^tR gȝoóxA|LΚSkUK5c"1N= ^L}S'R!f3cv"2b +]fѫa1V4zVQyPX 2S˫W+ CB+XUv2g]pGf碚ZvtDX.Z׃ 84j>=I27txKUBES)8Oay.ļߜpUχV  Һ\ь&5cFl n2ˆ<bwgȿCXQRYN/&{x֠ Q$guwүtlHs]\ #*qGCS7l4a9+I8퓈`AۯTF|#F|wS}KhL3EYX\sdv>m~ YOlFn/<Äs*(vSËҧnsSJ"ZyTdGGM$:W28@;k*Mlf^ın-ƃ_y&ߍ_kNm}U㹻%-YP!MGD։ f{n*T 7LiN c~pc1vdsuu2 !rX"{x5ċBod= L䣇lxA;R+oln$_: E9c}"Mhml)jƎjˬW BPsIeEsJkr.8i\SS;n- 08I $, H `,c /j>-{:Y"tv}f~N B @tI圀0Qڛ7N.{{訬]}ꇨwTbާK7ly΁Rh֖n&܅<.zy-/c=4~{*i%:dK#YPw Ae /jr>Z+Q%[GݝId.$˹թJ5\޹>W~?\)^dC\ &5{Oe^>]72fհ"5Drxj]vaoy-,w/ m$w6zn&5[#"My,YsVg@k/d\\Rl֛KVI9]:d|[EG3@6+f,U@iwnj[~`l DX6OqK;)>R-^TYu2?{'3w;l#{&}<ǵ"X_QfAӅ.oŠt+Sih(:rU,H1kRۃU F( b]om"UEXi`x{{_`ONa9> -$wDweK1f8j&P궒G?tn.T?8 ?9t/E 7k)8O`/c8G) N:^$oV-EP?[D#vPNx5TȉyEc+- Vegf)DPY$=RLҡرSD8K3AP<󿂔n dꔰC",s^ƞt@/o@R0_S-2ϬdVOcRXw#C`ixR|e|(?c_o͕iusSPdVK^8+ (_"LʚT{N~kt3JR!H)pd2SfZ+gu#a76:ʘ|R^ih@10<-qddf֬D܃d@b)R;*sv9u۰aY0Zf.Z5''=*"u`rVzO:{p;il:;rpS'& $@Y⏮iI·?/}@{Z=.X7>9 D$h,evFNF8UË'+#q'-qI$5$@{КQZچFΫ$3hϭu6Ge9@մCI=:/eeh,ͮ7Pc^#"K<5U_Ir0bͪc- ++lVɉa [!Cqx%tz鲖ߏݺm[X^FZ!Pӊt<|~4d77n}b-$k 4.g9tpL|utT}CLPx|1wg^s̕P8GȒ"{ X hXK"" BUx(ݬquG IDAT4ER"pȠ"3_od`B1""\xKNYX^R\q)d kì]oDKl5&-R@\3h'[S9>w 9,,W钞LW64qnNay}}9b@h:%رev;pvӥWeg" R_.{פE/lnIK+'SphP>u[GkNͅS. 3SVpCV\_JLޗ%Mu"ee\ u2#ErP0:q^p] N҃@G4(RP{J {I_ðgaҊH",Mq:0m@Lܺն{)!+f7UE0&ns| TȠ* Ah}7ƛol$̜"S-&rB㒤Z d5ެn(@g],3o9޼ʪTУ TV=Ѐai#Mt7/Dό=?p`̏ c"Zi`dJ` $$dUI%UIUY|9gzd͛qN>D sgﵿ֣S & 9vj%i)\0N }HDp ~ etXWq)$2G Pawҡ,rRNI< 4[#Si))m`JARp(.Kù&w[&𥽽=(!(+2P'E.l]($RpYJuK5;^$MO7 g ,FIz#uj%l2Db6(j{7%t Aۺ+żnPWapmI1+lR=j[}TY+c'V ^Cy{+-J $ " vWxku-"n"н>hEaڴ\G=r9 }~/`啭Kȯb=Ofٙ96fCgj1 =bBG-A5bZ 6ɧDq jVR8|1-5 |Pթ/R=ڨmcy4: ҞM4t$U: YmդZ*_,=IdS W q2c[ \,-JwOX8R߉Z Ku`ۏ /H"XJc+T NO5Ũv9o|kEu<%JnE @bRA%HtBNKC ' gB`?S6B"ÛjQBuU!uc(AIֺi+yb{"Vl %c8:V妋8hnHZKb!T|6d^jCEIVZZ*Jg7Υ(y>:A@$Y2wf:s:Snͳ3.%މBiUJZ0{} fxNB:"tIl B-de[P盤9|er=SJqMA$.&Rž,Գm̃LS<%N^AqY*''qFq){O/ s,ȾRK g}ў 0ԛEEYw%HH z0YC| !iO p 䂮|9 +BZjG䔈\o ,ù4DyÕfK!fVoU &KK\)([FrG"UT R%uXV8Ŭ4nV^A+;̔8r!({*ƃa RAs!k=O6q( 9-١MO|֑Meo b~J,Q)׿q~S)0*&35B::A58Z蝔m=-ܤ|1- ,pA}-96hU|2>HY mRۍPqQ_,nax(ÿ &?J$,KQI8,O)qbW PrCZ$ X6}Nx:Hc);>Gv C<>Ѿ:rRznX{mku^H. / 7>9(NSO8Y'߻vfli<¸x(J6\JDER)UtXSe%}0d?11!7O*G[ ` V3PJCy i_<A# Cs`2TņzxثDpFg (ӚL ;(TC-+%{ W $% lVb~&'}Dwm .%A֓)T,ۆ4`4C\q挘ʎ u4D3l޸SXpX6i@0-y)@gĄX`O_媨g:YAFktFW%)pkE8MOtwnɀfA5 R/"e ٹ0&ʵRMЊ5B\ +(-c{zC5O?Z p9bmDOU * ?Z<d\۵$)9phO/ls?d(Ϩa|"xC) Ĺxs`7'kӸ3%sǰ(LTp>вj5 %#=%L{&(+FQm_8~$_ oov {>T%\n{^ߏ!cU>JsU  :kyKA;++27nc+Npvb3wɻ6]I%"5u[47AU+1KJަi@֝wH"YSVsb}EPIlW0iTZ ӭ"P !){`9hlqhRCȓÕNަD)ٞ6SAkKm(f8$0  =|Z $2~6q\=_<^ә5dX])%P pSxEq+G {W<ІN6 gsZ⨚k̈́5Ojp]*/D&ޤru?# fƪCP\#&C+BqP{Dt>)zj(mz RUUR+*)+ɼB+$P/QgIQ ƋcHX͊R6A{ފ6B 䋹$`e,-UM3rM=`|0!Xg+NP#ʜmK !8j_8Nde;~SZ8#xk`E‰}sLJ ǐImEE {$Rv7$sScHi*җDi_a0Թjݒ|vzækT!"Z= u䕥,hmYnyT Iٷ*`b d&viRLRLa妍|ih=M5P&ncv.HO'I48'9HdyJއa}uئ$qֽIԸ2yж x2飯#:4dkrc-aUh{HHx1/nĜ*%*TIBy;x4q.iT÷.!\-bd$` l]Ɗ%c>+eIAH~Y+·#@ztjRa6Iة܄ȥMZtH O0PD]M̢vJm-)e_*7J&Y+r \+v6X(,7>,޸Weq"q۬pҚ=YDi,INKyhY`SԬb,(/[B0be +~BIHR5TVU--S"<dwKx]i@,q=0 `j{G$ $d{@GZDNzڳ#;L||lWnAr\ ~U EzN+4 pٛ7*a $LKaREUj;:|i#*^d-VMIe}r#o;f6r% }5*7#ƯQ K* ynJд `bYŔ”Q ;Lbjo"I]5ojQ^VĄ4҂P=\h>3o4m/~V ӱ$Hoj[ "tg]űqh[@~.*ibH"U-N'>ynEΔ[wPدկp4^ eG]-+ZPHuJ,Vcr99G΀eiM֦vd6XeG>,+܍ QTG>aG:-L[)X*e.MsO[_f^J޾&Q:Џ]׾Sbrqd᩷3#~ޱ ͷ baw{G/E\Ӗ^Zu+̺F>Rie /-p:CZx@8t,HGaS4&"-r%st-_3qWx0Pӻt~n(\Gm k`tԾg._~pS:Bn~V7ij.WXDy_.fVzQ`na^N gΤ6-B Թj)uPd.?l:PK^5 9U:}|&zW3QK8vO5khX,z_LF`͏qVDQqJ9xw_khK )EZٺi>7>W?޼[zKP,n)$ܨ;R)26`iR#;hc3U:J0Yc[! #VLT]_1K \d=4xd꾹CI~fʆ!s믧1߶elDpC}T3•0[Bߓ`z0^K Rui2sa#C2Dv=O]Xfk[~wBA/-~١?E⎪.3P;xqVqUa|u{bP>̮M淵|_~j;cseӼ?.'> ^r1gƌ\d_ٿk]+0ĬD, UA'ƫk+k n+\v>DZ]xcf̓7R.p货dC5XVRt~pzLyC2}Txv^1'R1AW(|R61UO?qpUӟ],+j1{j`q8ʠ$G~t+6x-=Lu6χ$_Xĸ*l Ii:LCxxw}#"tH-ï2H衯&;>;^` :$tUJpåm618jI5pgG Pl,2t`uv[X>wbHURR8#DJ`gs0t TtOnx?oYBR&8g "7 : Q܈P>ѝ9/rg^įzwLb:PB$n iP A%ڹjttG:{zXmA/ M؀CO>{ao^º@Ms&+& IDATi]TmWċ)+ׯYLr֔LQQ4%{eMZM"ӧBD1?Z#W]}11xKĻ?@͸_Z#RR$ҎmRngF8Amؓyi)#RgXsܾ=|ώЦK|zڅ<> `Fڍ/Co$@}Am5q+_1݌+\ML"-f]LP-I z!60j2bLpr %AT]ˁTBQ]\|h&K&F.]/eu]H@>B4*ܐ~PFMaoO}* Jq 8K-w4^GTW.[EYRd`J0Ϗ89GK/[ {G}%eg{*<ך;p{xvnn} MHkP ^v]7o/<[zm4qR"n"e4+Ks 1T<:[+Jjμ-n\e+ g#W_yn`1ܔ9T,}%JRH 'h\/ (+$GqCͽJHYhb04Q6:kې9`llZ:/! ޖ/ףKxXڈܖį8ڛ㩒9؀ߢsN-$V#CtxIJl5~)RXؑ3 vsfk|@%S20AP?%ErCw};SҎ+-dz8I\Λ42#g\_=@BW0j` ١|N(Jv+T.8;xQoafusIA?´ &қ|эn'}4;6 pW*mIh O`L6Yc.ٓd5Kfu8]mJy< _-N fOg*#97 qeH!$I9/MS~ C~񁃷 S EQsH[ogXG]9 7: M2t=y3gnb9R/Usnd͌dj P]&3C˞&$QxC߽E}hXPCl)R^~-תE_z_HlHr=/̌.N`9j+~KvVUJ}g{MG']$J~o`<[%'o1 N?M "3ֳ{k2éfib+cU|9;V<sy|RZ7³ ŗU[cp^GwC^WJN4I^d~7+QڕbtZ C Oa&Q)Ri aAg} 2Q~{XM{KlL"j,CvM'2梎]^ֿν-Xema(55P+4ܨ3;/dbxĚб5{+"xFӇ^zX,r97;֨'X,dFܢ(`fo v&&,ug \U!O@ G#xhRbGvm:ϟ;ڬs(ҡ%(bg9j^H}X|<"cu7o%xO#irmy]"FuT8MKPCJ៿IϿvh=8mXJ)(I-نR, =.)͒91ð i21gp7N9g۰R B\ ѱ2ݙ\Wկ3Z#%9)8xn"b9';Jj8,WN p9G١;C ,vEYwZzQ`~}r4WF3`-khYOȊ'xn-_,\w&G\v2+(}p<+=ղ">:0\T}G؏+\x }sDДMqJoj$F%CIk66O3t^9]w<։nk?YX4XzDB[glfgp]tOv2BHB BDTLHic X&>~K|e/E2APvJ& *@X7EVd}1Ab[M[)&inp%pNX;|tEYcƝ흭.Ki.(Tأ*fk暍,)TofNw<@Hs.F3)5 {"T#o~:Ц< Iɧ/}rUu_W5UBOF֮'#" 糑b9Ae0M]Wbmqg"_׊R k)+iOKpR%e2.HG zNB?FG6h2]w%I8ct|agd8vϤ 1H.vf,1``3'χ=_Ż-([Eѹhttር)yZIy؆je.lĽDފU3O݇>Jڙ+`%! RvM܈}Y R"RցzDr0^Kr(=AAGIZ+ ͥAA ,Eo_xPUVt7udl5js%'. vSnC^ӝtVj#шu8лU]TLUIMJ.O^tp.:nS3'TJ F- Z0_2޼DL+M,'·`Tuu1iuayi}d iw™+;&!e1&%nWt!;nVIJ-'ǨKϢ%&;q/MM?_˴ Z{Py;`A6v3ʨ{\8̅RH-adKs#&eT3,L7EfIx\8_~㓘F)c;-x?l$x͝>D tAﮏ\v$YbVäW!iሢEz@B#< kD?u{[yPXao4[[5T/or/<& 7|ncgV,Z@L &eQG+;5TUuY̖JR^Vyn>PK! GHRoXn` Ƙ#iW~hJ$ݻ8d= ᶬX3uSN)ot(RK$,fFusk$)vۮ ,,!T˥h&aT 87o?B@Ń-D "Ll]+ }i@k:BRD{WH: c.8"~jxbMuE4}܈h"JTp6^5=S"I5HHJ DG`Z倯a:I)MR6]/gEB3Jh Q>&&'&>{J,;u[X׎" EøT1S4]w ~#4b0`(6|KF}q1 M>'buS{fE93GD8@o|sP NqfO7T6<>2:}/;( %{iRPzP\w+l7[>8JwhA@X6h#UGl\aʴ$?ErSO7߹n'c'RJI)~~\xTj:19KZd!žmZ('[ Xq%Åló:j?> Bw,>c^XQ _:bgl.oQvˣ(s`7E鸒o5dX_]WMVl\εhapagR\t}i%4tX,jp "()4 M3 C?”SLցM@piiq]68kEG:HiTN]o_0msֈRzR !DF)7mh~ό8)JJ#qKIJ@(@5wbؕTY/%\N[k~EaEMu.Hk's1Ts)x3rc7(jy0%G# f,^,[A }3 ȓF jP }K/KJ*von29\t<<͒RU׼f3q)m2B^?]q~%QN]Y `LOk+1o??sd3>T^i~bAˎ}&ؐR[qV!9>v&R|O@&nd02BchO dȍm` rQtjtԎK HkBO&ZV ]/+mˌ}yDp3#V!Ӣ|9³oM0i0_8.j!3D)W>%ؠw~?@,r%KA4U:P:S‰C:ѻMQWiMQZ +h9k($kf I)a\{}k…x ̹_U%١;>yiOBڱx,=;ѻXS$0jD|Ç_)9/.edx(?"ST@lT˹ŒqG#7`fʦ!bԦ}$JG7K|i׾>鰻ɺ54A,g^Ek7`(Vv /vbo>?:kndvV`Dڪ7 w9 :֛co7 ) ک6a5Ζg<Ӄ 9#otwl?` h^&Rc2ش~ w|LGߗG o}!*"ʕQyZ}c]ؔi7i9TUQ:K*y=zpjΣd'-rK tFveTt]X[> qfb]o}OOn3>-,'Ͼ3WCKBMg.7-RևmGsyyJ_~|[AnVņUsޜ0 s t۟!Xmt5G KkPIY1cFgߴm{5#EE7_*zo[?|S` `?_ ߎi8y _B( y>fNL3{Gn9.>!pu~?N)'ӫ&θ&z͚' ay%nRgbe 2ӀɟϭuM>#pob/K>p/>%f}@1:*T4PawRtm7ȦM)ԚоV w} '_=|ڏV' ;ж_H'A(w֢ї`pXQN' gGI=wVY=E '"dR)qJFH|1*̧g_䩟mA}ؼ,)˚TRJp.p =p-"%ӹFv,{{=dztSCyL)/0a]CW5)Ow(j3x?|XY?8տڴgYkzON]OU(R6@6C\' % 7H*=Kb8DE`LJQfQ&u 7{{h/2)˩B0b/q9"L5[-gcHEE2Dsb<{f`Mbܖ@~,c|ݏN<OrJzL~¼G?! t7%+\ rQ<~iO߾{zѢ?An@eɷ3POcUjyJ<%GDJj,v:pa.ƥ0"ty:29=EO9zC s")C0ztVynYIx&o W^/_(w}@SrTWMr$lCGv=ұ-]Y9wՃI)sSdLWI{Ԩ1u!}ӃW\}ׁǮ51Gm4$,#{g],VzPC\?x0vFc8sJ,%@jx`Yib/Y'15@ KM.S'&"?VC,2vdSI@3\d!Lrg̛XN ^WE-WT }SGFz\$frn7ّ7#5Lm࿻p;{xgݭ$}#}&6"Lj5Dw`o+cY;Q֫.c|\V)M0և˻W}_+)=*[*u #V+.βw%#Cl,j!^ zŭI)LD%YpE6(} v9Sd^MCoS^O?`u]י{1$&jeE*;R$Kr,WuWZ,~]Ǒ\3%Ĵ5َX%K(S$$xӽ@ 78^As9'+4 .g4Ps{Q@$>!<,/ R֣@#q}_9=q:>NKdߪao)urP71v*C%?`&{~k>DlD,T1۶rrT}r|kK`m?@d DM!J" A$U͚Q"37EaÊS+@Ɖ-!_OY߈0TelbIp T xSw^lN"}+hődeSNqCTB5ѶN5 ;^Y.}1io9 l)ʚ|e5LA`- mP? 5Df""Np Ӂ_V<_ZV*3/ M8}l7uأ϶' 'Yr " 7ZF 2s9( $*{0()Dk10 ٨w~Ա I"{Bz1u~)-9:xw .s<>qG%ٸ>)Fxg( sCl 1!蠏>Z&2'#&Ot6}!s0r/ЎN}w~F(ݝ@̜Êf6s5jg޽١5tEH}PG7&X&#ɚ#L̲EFK@MLQsKQK/ ; uo (Lgma@€h@ (gA l`q7.kRX$zHO2YDI(7l#j 2ĔBQyӸ۝ )`aC y0Ih#sL0TGP66x4.q_KtRQ©JR]2uJU C ɔgB" h8(.΂(dm4."AVT|44);kd2Nġpgu7ל(͚ЏDwGa!BܥbD\IA:ZqpyGdǀ @uh4g!?`su\377G]hwOߧvHjOT37Ri/9{!RBⶡ.7+,X@'{#OEs08XiShE)k<2K9AXqr&*JWVbd@>G%tʥJ33E6Mg7m cɯ$]NE{4Ų7ێeuHjb?^Zq)hC]B/q<eVĕ ؘ]r)#l`+D:캬޿{, !QeJCK}F㛋  1R`?F/++]#AITz!7i[~% -Ё9O홂4Sk6` z4o I4.έ_,#̯,\5.RjʩiNyMJd,#byB1\wH\Y5_8?:JݒsMwW0P|y9p"B,WXNd6dpP%ūe@sM7V^@9Ԧ핗nwj# 863b:*ԟtIdbفu&Djq@-(4 ,ϲ+ g1ngg{Akkű)z; н&;mLEܪ(g ) 'P92 dkډ#"\T|n "!F[ xD+u0pVRk9rh/OH-rDl(4jЊU#`(_ճQvӅ﭅gva<úz0=-.i UsSÓA6B* ,d&)p[#3$('_Ru.)P`$O#;4jg)ϳ[$6ET%Nb\Bc)١3co>o['aԁi5ći4H,y1YB/|!k5FJ''[5.K/[qp >|~l%T 1A&bœϕeN=HmRs){V βRgEյP6X)`µLG_xc~W1/oYcs1˨4sٯ]Y*-A˹Lm8[vf޷VvCa!`I'/牜d1uk2OcadzAfh3Ž aAp^sݞU ^_wE(7}Ξ* SaRX%9+}m -HW~M+9L]% U_O w/wґ A*Sΰ}ozhyƘBK-jtRKl˴L*R PTt`e4S7^mUH|ݜřn7͋/n"bRօ%jzn VvhyS[(A]r5ޫm hH{V[4I[S>." Ԯ*rf {,ڂؕGT! {“tXXr(N,mM+uU+Tx$.je)vw6.G; c7Ms WvHsM_C [gͬ=)ukȶQ IDATUvHdMv!hX8<e aA@o˅8WI'x6¢疓B4ԯK5k\Sarh 2ɇ`O.nhSHu-pJ o+Th^|db(ܩM- KT7W+Kiq0;Ńshj:Ø8gs/dRsTO?09@ t95 c92\,?Y+ X&;` ƒ]VǛ62G1_waNO~"(Lоii2@9&)$aj^ZN9e9)䈮8E` & - # u F[ Y#F?[8M@k/RAf딳sgmzu3NDRve!$2k{@H\t%c{L7"TC "Wpxyh<HOCGsF`*AaC -N9u\:yE!I&቟;qYءMi[X1_T%c52rJ8JI#^,҆ҥ3u{&c 99c"tݗEj}wf.愵5#ڇ|l]e:=9>OlϞ[1 ѡvo T +Kn2dz--cwk]uj 뼄XbD$/Tyitƫ8Պ9 6?('MU (JḳU2f)ҁ&P'?-[phmzϞjPq\K1&Lu%Bơ577VYUR(<7ggP~l2J?ZVi66_ I@Geܑ] *;1 V]9c`h';6Q(o.L_;ص!$8]NW *0d(8[a]')+ CK.}Y~0pcۅyO=KD~d*:¸3|sYʢe(vIg]*d-í'66Mi"Wv5z'!ofÎ}]W(ř #9Axac+Ӛ:c њPR DSgP5Y$ ~B<*'}5?M靥kL:Vq q3*Ll2;snh'0YK/:;Ԧ'flM d׌Y8[:.y#)^zs{3;~,%2n-:@yvo͖RoPKT\w>U#m>;hԦe!qZ/q!?(?z?4i37GW{c쐈w"?Rl hv&18ĉxA|/, "$WGQ/i]%Ȕ֗M]U(^n] sMس)Ԝ(f®Pk"d uYO @%HfvdxȤxaoze@=R.W?j[WLX"::m?q}IsHȤ'+'tgrÄ].,!qyW{UP6)u8bݦmq:V 9}qUHLQMؑv oQՓ;׊L-#;䆴X>B"N(bHkxOlQEVjqt[0T8iAJڶRS`!apѰhT_AϛINM93Tgm{ ݗ3q>ω/Dzj'/AUe)Zp8IOuVNmPYUMC .~/-I Pˊzر)Ml\!(9ހז~&c<*du"SS,4 !eY)F0V׵>c߳ U5١ XZ(`GU>#Oy^ZPmWNzXHۄis n0y @ětBv1#0d!l?M:AAƜxH!JI~'Զtzzw?vo !VZpP}WzxYyЊ',ѤEv[,zs#3nAVegs-~"$$̞f[(/+ /~4:GF};rJw:ީ+NAnE^ 2L>{+è x8e\)ã"(SQW0V,:Զܢ2wVU'vmDɄЕ;L@ 0Lxv44b[xk(ZYDD D0![|vpy?>ca[tV^B YGiS/oXh $S7>ѧWV9 \i񯎠pPyE,j2x'9{taL6c۳?`k<g_V&[vޑJ0LEҗ7xwwkTNi=:#,&q=f/m% Yn{.0G.;Z8>{ K4dQ_ O 1>˘%ߛ7i1|>p}q[@roH۝gAe` ma p;0fbuqT̸zfDQb2t۟3rQx(7;\ m%$"ˑr{ŦAUUO[)ręcYR9s,BCmi{`taR{n<|>+wA?/_t:#D!Zl '8IPw*reNtwI+Ke`{XjJ`JȍU#W ݰ6c,I?d,$81"L}$3( U])W] '޳(DE&%@ r䬞{CK!0UTq::6R.2#yyVq(Sp|try0wyN(N˜PsO@ѫ06Q6QSш*LڬL[)S nzE(g4y4 .1)bqI%Eu Yzĺ7 agk}W~g{cpq̩zr >%gJC 2lAƑl8v'w|ymK豞JlJp,;IZv VZag& jӱ,|G/00}# sQpb Fxg*tJN=Nt MN,ms(9kR/& ;PΚdW9TI@,DIm\y}Lea-/ *gI/SBYr{Lpg[`VmJHkE/K_3,%UVO[ Tu$db}s3#'Q$iIBI7޾u#>7&DUU:z C 7YwL[/B5GHC98YK蒈 R|]xxMϲ)`9>% Xy$Lh *[tKd|`fͦ#mr"PS#&iA[Tzv#̄Jw9cpT cbtDz0F9O*Oeݏ6޽W-'SG!n; (tjW]`پD%Pvi:+ ( X HFs|k򿽚c%mW=ݓd" 7k~9!4&¸|C}yd͋VZ&wסMDboUYn& 2RU!q$g'P͗ރNp Oa~GF"Ǖ#w}wJ wz}]WVM뭒3_'m "d1DhU0 cZʌ +"(P=32/5RMp1HۧdH!+0aE86Bx,=qeQבo^6\hbPY )'JK]ο(KG Gg kg?у74H~pCꕲJhB28-xtt'a( ' 6̰fF@Un.muHH,XȈ%oJxbeN[Ǝ085`y_Nblp;΁?+N1{ut%ROB=5۔E/X.$m"pϵdD-h,0T"2$ Q1IC"P>!Ph;dSV὏<]yNP)=#bi:Nf蚆b ݣB@r>G ǟ#6Ή>cpT0}5`Y<@*y!MF.-!7TT  *;E\Y*8K ZΚ*J28|Ҥx,87_ Lw*LJ4]\~%"HE>˜,J\w! AFKt|pD9O)DkGsnW,#@dU*W~ Ȼu05Syj?rڀM,eNGòCX6zd1 s"jU; )Zj2-ꀈb$ %3@  Z (Xӡ^De^c~ ƪ1L6L8ZHŶoo^`ȃNa!uyٌ4 @}mDQd_*^H z&aҕ\ sRo%cP>0Tū$P[jgiVRU8(EK0J 5"h6ݻzDĚD2,5X9gIJeAO ,L|?t0<nU;C:@nlƴ$l݀vUF;\qii Xe)Ɂ+Ex={f&$MXUij2;,w;:Igka T3I I\zlj3+ tJlzS+Bܢ8u;GJ|c`"Kj k?#u!,B%u?XRTo#Ž bP0LbR Iصƕ!vF\))ܪ"HsbNXCGZN0YG+<Ǜo7+$ 4)e+:p1py0bZ/7TCoY?蹲W HRLX\0 WPww #oySӄeSUHԖqRۗ+sEYۜ;NJ-翇cڤ*! IDAT=ep -sE@Od ?36lLJM q!RGcKT>6ePYz@ 9h-\#^50Sədn֑ϗ kȨu+{QBS8:|QN#fw zx ♞$ؙ d*5H!P!`lT4{"+ʹ2$"w C-cU~05<~:eTv_6^fv;F+k@0Jre׵#Asó4ƬML|}(bz|p& VUXW%O$`!c0>2̟y-b֯xg X2_1WZe bj xSw'6TVd@虄MWڂD i[pȺP(%̔A[*e'q\.e!%&`P&-xכޗox]Rv= #n}Jm0^(G :]ϥJ\@=.<<Dod9bҲ>S3r[?Һ[ZYs+66`/?ӣ+0/N0V ܽ22}fV!`ʨ 1B|愩i";&N?kN5ۮP{޸Y uDHwDaG8a;W^\HɅ_ M=3XbhUn+KoO^y>[ TUГe)SsXJIw6m!@m]6/ )ᵬU @,ƀ+Scq=3Uӡ޺2ɴ"$.; J(5гBjF)2\uīdsKT>.VQ} GSc{?<b.XéuE-o*a7U8҉Xv;p*ȲL* !ZB:(/5$gJ RAoOr?{|oJhCTsyFhtr,J M_D .BDN]H(BhzAKf|AʌҘ;0/ށ"!&XJA̔3oQ pm&Dy!FVP.mgEoDZCɜR뎥f YIH_y[d  D8"t׾[P YSJ](X+"SQ 1hCg@̩-JسDŽb %r &@팗v<$(Ph5`vCH|m}r#XD"ܱ8;se\<-.ֺN "eEAE ꪵf^,CJ =Ld`IOX~w7{5KP}뾾^߇*<:2 u맻ZdžpVHxU+5*Aƭ$_ؙXwlCHᅐG#G4X>(&ʹXPɍX7X+y8ky>"߀ T˃j;DPNk*u7Hi GEiaL(K`HK]! ",#rm7'KU w( D{,5å5`YQ>O`|Pc?.^8D" N@pEZ'D\7*D};\CVfI$d&C?m@%6e؈ֳ ~V6^ 0 O-ـ^HIY5dUfUp3t;2+{osVUZZ(δ/"Fo/ _&r-S%AE47c+^ҥHYiok-}*2蛶DF @{d<|lWtH,)2-BL=NѬƣ]P*٩d L ZM-2j=!%hnƟޟߛ VT728ZI$A>^ 1]"ܰ);:#O@,<,5PN(VCD$PIHr\I3%%UR(Y"MH%Ęh;k e K^~vltt,U١:d.6k(6(G=ti wjdսk圌GoE%ֱN,'Drz))k r\Ұƥ1k]x9CƇ?~誫|*ea+j{1*$E_K_XKKcY'lԶV+W3}q->M%y'۵kiǃ"{m6$[Dr%]2 6弃LY#m  Q1LPR?"H)P ՄQ=9xCIbtp8{_~q}Wal%6ېBOZd@;쇘z>x'7?5> ~ ro\RRHV0fXꭂk4xRWm}\ z=?-ʽ=clR-w׎MzT/T6'85Z9 "YXUsPoۅ!qc̡[,oOR-'=ux> E}@CE00r :QGJУ!oZP.Bp@=?&zBJ$P&KJQ%%EM:u^ҔtL_Z-';T8XpqxMlg21RO{ݧug"g.&i֮֟83WaIHdf@&ͅ)( ՞fT%3SoN@X'`CW \*UgT ՜{JK,3DŽTrD|K\u9; F+pNUi谵x1,9/QAOf8C WZjՄV;ӡYǤ瘁jw\?*@YIx\b~^~A(3<JRCtJ ģIl9$?+bJ 蛶kOua JjU|)z(  N-`qlJl&@e8h\)0'k+2UQwwS.w¶dNNd&)噬l(7_bw^9VyKgW[M瞽HѺύ&HMe)@iT ؠ#8hȈ\ĔL. dPduFu2p )I I=n\P2T!oc{g?+7M!Aִ7nӒxLsGEao%NMg; _zDI i-`d%F@IYZ!g0GSIx`>w Gْ7c i"8[mO8+TD9F=dn6fv+2/oš_3 27?J/ꎵ|u~"$kRFn+j(ä́2<:|[>I}kn;pKǘHc7PڝY[ۻTh8Ǝ1'גjU%1~Mu}; Zyȟ*- I9׬*KD< MGy&p :uΐ$fk `y^ۋ͵`)E/Dγzs$<0zBf'H{:g`|D=ʍW TTh컢iBy4IN{~>^S3f6~ kjߜZ{t ?7K;`zF##zDU~~b[ 39Cmab.$nj'tX{ ,P3GϺr{o><<[. *l](ҽ$!kwgwD|kb+ P.Dy?1HAժ1ٲU⋺%c>=N\Pz DZH@v1AK";xcyXJkcfԊkAv J-H.N=yži:@gmL32 +q݁fVp34)xo:>WLugbf<qHKxY{//]E^<`R%pv)zYP"ꞞMn+nڿ<~TtŖ c`]ApRs54aϘ3ttXKU4.7($S8HG"!glP)`J%%)EW=f<#^MnBxMQ;zTv}] 2sɏmw$ &"Vb% 04bǗG 6<Tn"g}}jfdlq^R)"сjSUm0v}S}EmP5),Smg'ۏy6ٹ/K,Z.fǦTYPEhU/"5/'Ce_ |u{!qe55% &TRb..o>{3gftq}W`|u 05ͯ(O<R7*zplY95JreG7ڷ@ZA/zL]Jg%^uաqu-=ׂTBE/oE[##\ R\^hZG*EH@rf™\nL=2u{O|@y[+Ēz6"U:{P&HI]].ԥ] F%*])O z*a`;S84TIXq^'G+Qa#mkMLjXKM8[H(ɀkGes0ׁJĶHJ8@jʶˤb}=77R;[j?J%-d7gbl'f*.QY8If8{^q`R_B@y)q^<~g '_o5f-`-|@ yתD`?V؅Z"OwL W H3|9:a4=_tzw\1Vk>` ̦g:} ć?їsEƅ'daEK[l%l{o~:ӖN L:bqp% 3;RP3MM8tL{,sq0zN?-@ٶP6y`Y!qR*YKbR rBJJ~]5JzoO [;Olj=m8?5# 08|7|ŚA7_a=SQ=+Op 3Bߨ Tv^L/wtp4OXXa&*-Z3IM ˹8L9ZZ(Y (O%+b'zC`-Jt@ lmkF3q\Ē/nK3$$kJI|yicI^˻ƕ#sS9m+RC1=8HTqFM{OȹQV) 6pcOVYIT=$o3hK)1y6r^ܜ~%Mƌ#J2DsUro +~JrdsemuXHzk % '๐1H& a?XKB8!ҿV!UN RtٟmPLA2ԯ.h8KN?)Ş GnS׷v`AjLZ7MwY}[on L3 kJK[cigX>t)lJw UqoD1Ga3#?7ڝɾdRʋq ʝ/dfwN3`fHP?&f-Sb:/ecȖ-Q؉wfmT#yKR,S -u4bg髼 hmֈߨ{C@%T!(QeEC@s@\ "?vu:(0P,9̺SBWҖI| )m[%4vDq9o;O-$2HDUm8 H'XbH۹sm l+%v8cƁVVS5A]vRp5_^H)*uFlzwOf;m aۓ:!g_ͬ-φU׌ލքcOLQ0^=O9;Z*tC8Y*5@Y4Ie9kIPԁqFqVM`l{UkPV *xf1C9s(6l%nӨm 5N49Л~ȶ.\hWxۖ/T5/S)m301ys @ۉo i ,az"cl&,.~P}kai^⃇ /jfOBZl®&STu{:Y5 &*äwoo6uI_$ydmy?'RH(#|Tg} b@[tZ(1$2&_+ky2#:9 _eaQzE{!\ PBj3$TG~^HķLg(qt!Ɨf+ڮṶTZ|i,dR963`ྏzq Q@xG$˖ܶFwprz,I+K0" X?kY\MBSC-_! *k9Ki%)č3 [7F* X>@yc<|˯\>SY}IRVff ҥ81<vtVrqyoXP jҤ%%pQiFBq%LkYlP󬧆mQ.Jr:CrL=)T'a^rqwΐg)֒HEUX9@ r1Tv!CthNYc]_` Wu S<O#$N]$`*'X5KT ,ĞM {>?q0y^{3<=K|ODNmzNqOx΋׏VA_U܊T/DZ),GZ%z|1 ܀cJ! 9(Qrq&SmU<'|SCDB=-?' WsJrjtWF.bġ"{Jt93G9%\M3$+mSsE;ՙo۾|7V /JζSR)2V:f"XU0|6STr`j7Im/|O;UqJge{0k t$W!K8!4y0UVnB:/$]X:\7(0/$Y?2m(G7{[|Ͳ<'ƪM!qPB-@ A- aM/f-u"Nf-TI ;RLR@ -;gW47*u3w9N?TUzٗ>*OVrM̝vxᤳZ\C׏r?5<#}8ߎբXs˦s ohշhex:FTy.Hz 'QKTuk;.ĩhnr$ ;\%a%VxYVhv:SJ[*s|س\ݢ%==K=q0e?1ު3K3$N (%Dir1]D\74^y1@ 8Ἰ`~7#A!qkx}KMg W)9$Q}!qe|  ̠;J>]wNwŠ }Ÿd Ϛ^\di cnBJuКl>HsӉj~jӗpWl1u9%!IΉ!ڏ@$4MLyO@A(]NU}ĥnA~Zy@3EUz"- %J$&`KTnMۚ-&mQP5IliO)19*]b P!UOa)/;._Ʋz9@9mZORWaaeBbM t%FrT+l*k.ݯM"ID9Ċ!q%QV2FqcC:x/5 f`}[*( 3A`Is:ΒOTaϮT'1[qT96f:1QqI5 $dM *ͩ\zMՏ6r30$$PsHUNd]3s}eԚ[N@ο OPZ$փ4Ǫ⥁HT/ykh;YˣRՙL acO,|R.svӘgfN˅ėe%Im!-Bܽz=9-lgN|@W#5yFatJTOPpy|~1/܊[Qj^u`O_3 pck #:laBǠ Ό_P$|mʔJՖ .AɔI4]xӣNK5S.Ut+fi^I9h Gˇ%_Ws`49k}zrj )5̐Bȧf*;.rX[5~ le;8r\zjJf9)mM廊eDC:-I0$g"`Y L1bxPEKo&s&Oe=/5ǘ0]L(i\Gďw&ڶζ SNa&q*Z$l.3oq]6;H[ZƺL8ufbl-8-6*DEI|;{|&׻k)и$Q@dBt(CFՕ8b4_ Y㞧w~q;> 4 oѣג-{k:`C0/K82lmH``ySW^a9}Қ]$;>Pح+b}zSΜX#34ZȠtVL=%kIiS`KN_=ƠOz4sS *bJ ʚbku /x*ҧZ S'U@F zZ)3'`Zz^)U<8~?}ԙ@& tvHC?^uX5u3|Ɲw|j874}X}%mRR?f|sPQhqZVu>-y엞;8>22r< w+B1j0=m1PpyոJH@(&)&Z ㇿ[xacT׎N^21ౄbRtT#we K6ҒSٛc?wuL q\EH,r0U76iKSoPT>u_}kƫ@R)=+xqaKrǑr\ f/LyV׊Dr>+D_-'۝B![60,mzBXŵѨ8ƤUŠ8dBl|lX؝]w .⥊QXW < 9<6fBcv'|'$O7ϯ:(/y4C \Jr0G_iV%"pl;Hiyq2y1%Η>1SiAgsQOSLn M5}FVg3~&=XTMN d ltx c$~Pt)5,{6αC"-&h/?C85 EA9 fc64gH\A%5}gq"-` $ɸ#_[7p靟*hռ55`mo?:ȿyd cӯj%KVVdc)gsL 24)w~@ь9`-7X6E@(0$t%:`KꓙPc<~P\)U5}I|%d`s^ FCyg5=~7j3~[ϐ/MgPfM'dѻ}X'ť_8Gԍ﫛o%KyO{~R.kLi]U-glRmEx) IDATϨfb>/m`MӲ1ZQ5lQF@o!k0(Pޘc Up.+?@Pw."A$ .3ר⁍\U_1C⢮-Wq/} &jϘåel` ^~79y~bQKXzR_9ȫf{J`e.R.k.#]2Rj=ɢĖXFd=#:#ȔC yNMAU֨Z- M0:o7+a mo|mi]778؆bf%L39m6ă@ߙ slL e)=h0|*U`G;c Iq(QY<q2RIgEwKy CHD0Ip5_01; ox zi͎ov? ݏ܄6iy,?|W?tz4l>+)*iO}a)wȣxqq7Z.b%oq#תv;qGRVsE@Jv FAOIc@q I#`b%=fnoB1[Ic(-6qp s؆K21@wDz}4>&xw]6fH}͏*^{L+S [x9 C){&[2Sp*uk922"1B::K~zRg%O`^R6[#5MMT,MV[WqȘ^ģo=J4.' u(AεH)Pg%[>ɍf7"+rxH:c_!P匤+}b }+,[`_A`' vJɲb[<ŠhM A$o`3W8| W T%c~?g8gCHDDu%fYKèQ׆Qvv6` ³r̆'Y_S6>ǯ0[DmId@Wp ¥Ioůb;pjczTfh9^7bXr1r>)|oh=Jlq>#csOW. ogljAI`(^"PvHǨ旐 J}o"_}{ӽ?YIG`=pS%B " *$w1%F{pC1@t',.vGCDJ=r Btrs}.ӯgdb);R."[ҝK*G3!*ӡNMe]ܬt7mx `N m4oOFX`TƦd*z]3ݤ\Yw6kۘN?#m |Q-F O fHMt!.}Nё`HA46n˧`n8@(դ[ύ?]Lϔ.S)YkBM[~H'f`ힰPZ1Oy A2OMڂfٙq &W΃|ۭp_t\>0W#A-\jW㷓,:)t>XOLXh-~mOZPAu-PޱFP-j Nxe;䩔g!BDQ1QTs N[yM6'KXX&&fnnݤФ9)uK lԛH^nQ奟Tέ {3Hs/l&{sX\+\5t5d~r\sr 25T*8 ŪtQ2%yOax-xUB sS,s-PPbWIJO}U dJ[;#.U%?>3+r\0kهZx.:u65#DVŰL\ "[#lbXvZ%70hH0fC_,2p0 ډt+ DGܶ%08H:9BC`Y%U SyiΊڈ>;@a19+qwP$(<bQZB ˉTJfZcUU%CX ~mZ&p#o,x~ZB5 FKn]fVzX9*x(*P}o,PDr ux˳ ZO7Sq$>׾ r11;>29M'adLNh ,uUp)_&ȡnA=7{p94Fh i!_jKK "!b4Gv+XƻދǓL*1t4{DcƓKrT@D"15J'xڵa]_OL M]Zچ`lvr.;JlYjZ˖޹ɛ=1zHN$4eAvɨ@窮5O~o>_ᢶ,| QP3.ς#(uhm.IXBs^eHrpt)s{Z?#[x%43{%  ⷇.ϝhLbяl̜6Ϝ٥3-RZ07/Ω|ߛ9s8w p8 2J \OʁlZT)O/>FSdGJOH B|~#=D}U\C3"Scx[NQǑ#qpk: ZHoo:׈y+*hGk%vU$ 7H:7giPkVZZh6UZ(!K` @$ KfJp^[DQM d27 /$AP~kH?aԉ4UA{wLxS4W/` БqҒkkT-=jl*噈TF&Rf*nXPzgeZܺopyBB8Tr1qֈm{XgF(eVb+瑁F*W-[DX"bOT@0|]cԂy佁 q"α*6v̆aSIY0Q9kf-M~)qJgI}xndH%3 72>.۾+I%h9VL/f%/EO2e}4ө! _0zAS,cD& /Y oWmw 2PtOկQSSuX1!hS#qwZ̀ &.tD<́Et=Ju 02E{|ɗ2Fg/Y7kNaQTgZ%-6hؚpIȒ^zSS amۏ Z (οo&30 e/|ٳ J[S nŊFmd1} :3S0ھi0.|'s)[&,q7姹Ar%o#r%E%7nZ !SSz=^[1B^`;ފUMUGrY"R&f!yDmԸ>N&M(`dHIDDf)A Kᑸz!C #" 'YEQs?G;2WAcj{:q+`";R[`oz޾ޱv-wI*V-]m?Q}7jOx8.NK~ùxVKnܞ &?}b ֟k)|ah,jP=a$P7?fO9IuM[csm|nS>C't͎RS r MMZ5b~|\6Oʾ̻{|*tt a-ț5 $ Z8_g|MʇsS `5'(AN;6-R.#%?ßRuM>+0rLQNavvj+ l53gzga#{{ዜεB޳!PFOTɥl E F_z=\9ZS&Cxah;OLWO`uRSX 9Gc䟡iYS@~Eqm(Ԩ'a8jI@L}>He-%A~M:FYCU?8M`ЀDfUm{MaCq漨V[#/yћ4ZĠK=gWb!`WS5H̗p HyDm-lj~.lT\[e9FpeĕJU%KjRH8GJ2Zx׫w|i }Qa>߾B6gjY}xƲ;Dәf#+/wPؗp+HBXdBg Pk=B8n|f⎥@txY+E#=e !nŠ[nxϟqF W3l@L` ˳9 ĦLE'1X[?$œ &pVk 4GR ꕯ3+WSiyx0!gKDEm%vbg~?4sq999-Z֚iY?.kF|2Tm:y%N~oyqX(B0i V Hُz2 >3P41 PHLCh\8=$4Y,K@6-051BZv8uAO>nʚ[II3w",}cɵܷ)Y(*CwE4.SVb1@Mviĭx*eS+-\f5/^mX8T<JAh s~ N_CsЏm $`Pƫ10CA=k \,\V-s,mIص8>87|A4 %xo/>mcoa[[LLH1YWms=2X2GRşqX8,~S1`^.qxP3 $3IT@nďQJ%V"$8Fh.0w#F\}1cҭo@ÕpW4Gql=e{s:`{pt̓|]JĵfpD&6K~tؗ6Ǒv tŀp:sH\+sX}!VE{d_L`Ue0(NadAGJn^3_q8JW}$R)ΫKGaѤ!6E86oSi  gB_{#a-,u1X>N+Y?D5iHK'LTu_ |/Lދ¹x |( 5$ȈQ1#B$0bbd'COq{ x<;eEN1>d.ci/hJNnh*l)ociLM,$r|(KBR0ǒTUg$Qrn[1t  ד8F6Qb(tsCOn#ʭ5㍎ǣEl_0Jodo1(=8L)Y7{*ejQSݸ&Z%4ݲxZ&xXdX$r`5P5:\LN hQ u:+:\ȹȨPK#źvMe.g>(j=Nxʞܨʯ x "_@ɢ;~NHѳYQ5_kTPRt9n_M/^.eS:ku*x)<d.~:g A|Y.眂4fމ{{v9jc0 \' qT%>S-_#EObGTK{&>>+}aoPLyq ؈ w43+w4j_: -*en]<E-ht_$Ttڦn=ۢƧE; Af#D`b̙gRNU3[k7Ij \aZ$bCY#16-ZTs[B 1 Nl5ޘcrb#Y2W6D$};.fIZ-}jUaI @ M5jq,ݧхa[=Bt4lU+e+{ ;] gMs+9/-:,QPOϼ OHdؖqzN“.zRe:"6bkG>ElFOkUl.|_qf)F.Oxa `ʟ} PHMnc@cxAFxf.eQ)"g6`ŬYVv I 7v1_f/4WT Ŕ6&&(xIl׺i;c[$R!H3MG 4%y|$P_0Yk̂-}@3,/ۜEA 9T{Hcr)Z3 L!B+{wB}kH8k3(+y~T3ci&>KlI IVZ윬:\q Q(M5P>Պjy@GdH%fQ->b@NpDATa9X{< 1t_ʤ7D|<0T;X_G*3Xjy節ј9J*-ekrb5&.ذ1p4JXXou Qr ~1WRժlY!>= 8).PځT >c@^ k:ǗC!nf8_Y@ ݈6D\yqZȖ\ʟ}{W9u$3#SyeFWX-x{e̾J@UD`s286L+EF{%6`s 5#$:?r)IS 4౞j9 A73< "GcpܾF^c "Q2~0..?8b\;P՝ޕE\-p)3 '~))jDS9ÐK%EZI׼8ōI=P޼l^ۖ/ܾLo_= .qJIW/mZx몝ؖ A7- #TJ&D-BuD`s .&ˤ5 T}O7IX.7W8A*@1B&,57nX9}$.EaXuA7Ud*|ZEUoh^zO"Wfݸp%mL##YҰ[+d}|7/- 7RE*@16 y|#=ee"DO=sc,)ߡN@lr96'~7?r'(|)d|w'? t@1 Lyj~f0$ ]ˑLHܠY`nZh#ĚssLD%$G8QVL ̴ GԵ1ʐ meL~O_ 7P~rQζEs8/%/S7 :E2vD`s]8r)'D펌+P9XAؓ7X ds)@Q"0bS:>o5d1O˩{쑸A3Ulҡbg$$hZ@:T,$aٽSeɼ~y S2yS+z3CJkPJ(hW8Н]H %3 Հ/9YNW:;TAv8姒JPmՒ5 p qɐJ"PL8*c?Z \p!r[:x$ng~2D?9Rٲ*&*Z7X }'%J7-6.?(cLkGɴT-ozS'*vu:$6~$0$ա9a#5iG6eDsѼ?-8bf0W3̐7,r~!9a%QŗxsݾgIތ|I4F -2kG:cmzRmA&.wUB:[ B\AؓԢà5ܼ^=s-FD J1XYMe`5c  cH#_M|EZc3!'#!Ñ,ߖCS,ŭhiu*nXFbf;QZ)j8 a{ʟ:3{.NvN 5֧?O`gsV Hq[:D$toR)5d,1YP|³Rp~u]2'*_Own,j8L#B3ubǔ)< "b)tQg t%8ZZ̠d t DҪe,.)N}&ZTKW-A Qj \"]BږcsT$ZR2{U)lal9;3m!4Q1ӆ䭵4TGHe'煠³ r6]iA$ ayd0z:) |pvC^.K6Еx $&Nlp6CkM6V>S[A,1y}k㗎t0F8Cյ5!ȮpA CZIAʳeoE3}) v7ג:m+ԑT1)_V L!,;1$6(^z8Y9. m?»nʓ66}CdiŹYnJ%e;[#'ƠjyR|SƗ;SXs8`>`bneqojQ(xM " XQw~wghRJY>$oKo|fڄbdB2 moAK)sVsKu/ackΛuMf[|r;sCz*I V *5aL(\cjHx*jĆJEdEc p0 R ~YĚݎH#FST'I%3)4P0(ZTf;{LwcjdWOF[O->B2SI%:#VJXzp gA c[Dn$ЀH#Qo1JQqX ZN1'>S(ǀo.qH$>*dS$YBYo؈{u'0$*-/[nck /IIMK 7sO%~Y+V4{^t+twS,yM~LNmt]_Mܰ 2fb]},Dm.ONA =y|9A+BW96^ؕhNV` ݿߘ5>g[#Pׁ"&Rj¢h?fͼ+'KfHVnl; KK6,rG&=b!XR1`!fٝmf*gȝzn}6k ^ 7Q\# t/ n|pD^uۊ]􈥇= "GcY S tf|?h'p\pךCg#a4:>O}3:;Y AC45 X?.#z\nDZhv3qB$oVS_Bܬe>W|G(=b!MPBxq yvwX!$H, x Daq t2FZvuN;o|'xOtw/BvNò[6)T7CsYUuEj9j%;=Pay{'.e*^c-L΅{:Ǝ3ęYrsPipe5 @D6tP-_˻Xn!oPy 핛=RKP:/KFJ>ڸBQq=g:f΄xl$t-I݆#Z\agy:|:25I( 'g BO 9o-M:pa r¹ϒo@D,s M*54~'xh{6.Mɢ-*~Ѷ%'b}((>\Cn-:_b* iLQ`!ƪAcMo\texתLk[W1gfaaT"Jrkd5(޽.Әɽw(BN&6KN0-c—5#Y`yDA+tToyYukAQ󷾼W78 az/ mؠ/0{ZTvBgi x'G1 .TE{ޅ^3_Q'Sj245Q%CRK 'Z2u Xwp̍_ Z#V>3 UY f~ɦ7A rk}x3 IDAT]݉UF{f~!&"#W ڎ._:zXzp7'r- 錾y kHw]`kx'wrfnɹ(as\6pivw!¾f/̕#&0 8D+g3jDW;9CZѰٲ]a[&Jx6[,=bY6 S1OcS$<_fd䚌QgA45A]K$S-ߓ[+&Ȟζth0kLBO"g`&8u#, 0x4)}mBڊaRu7,r5H7kRȎJ E 66>v'b&tCul_t!P'lh#@Zyu}ӂPV Ә`0!ˇ,,||pW܃٠YD/ܶ]Tv-n~7UL_iR Z{O#D컱Ë|㑅ȵmϾm@'1%Z :Wn1ϊz[cӉLN/pwI׼0{]ulE'g8o@qT\k'p*գ1cь>xd6BU-iEqLK 'ς(#o p9)8,m$LmlwzM $ޛC{0(sLc/bG:ʓ|Yg_'5m,;{7  k\f+\65r`-tr<7=Wڛc|!VrpI8L_b|)LߏPd~ 'He}4%o#7, Ry"lLߎW{؞ ]cIM&hSuO? 01k0)R x)" +8tmn&]cql eHe7VLf5Rٲw{@Ȃx< L-e1m23 ɲS7N@9 4 'lToIIF!9I WۆҲ9Q^sa@צ4^yĐ`!pmw"]F-Kqk(xܟqA*[ IxDE2naz|$uT.bE~ilԄ/9Ax]/x+}3SpLP(yH~7ԧ`A>O:'ILs.eczxl\!A<~q8c9xDNE4qex0URq,G%:vUNB 6`rPFmOF` '"Ue_ZHjD(7#0FkSϭś#߶NSRa%ץ:1cɌ|LÄ]NIK" ޭTP Zid\o^ ̠gX!0ViPf?2'W Qh3vTK(;8J p96*+?! w7Byo޲g,c|A9$05٬AU3":KXo6xCR׻!ABҒZ!$.S6<8TY8Vl"XVM S@cKXպj)7炙 z% vPֽ̟ ;g3̐9v XoaΪ 837z[(>M.^[:sBgD/e=C`t%}M&k*ɱ)ZrƗf pkŤ@TxMڐRP)\Eisj, xO$ O09qPj 1gNGP9|"_U64vD*C{ P($Z3 L9n#SOJ1>ݒETfŰ4kke,[lC0bR;=:ʳ!W#\ǂy24b,C Y t-`D$&¥m8+Bwpr `$-M+d[U_U <[ Unٻbyo>6{zBُs/G-3$Y >|h_9)=9 0)4P{^O Zq!D cUw<źs: MN2DΩ̰pm7t\hʹ>%HPrs^ C$ˡ4鯷jz;1(H'RK)G0ʙ# ||< `#w@'QXF tT(a$`.p9x/ezJ1ЙK(AD7zyC_a΂(`;J8QqFV8;{zn~K¹A0HP,RjGZ @1aW&tB6 b-GӉPzC"D&|vvX#S5fDq mw(IlTfNL,{K<83O :-33 oD&%hOZ6y0EB':B jέ^2цQ PFwey b1A0}"@s7)AtV*WL Oe}=\(#aX!0j}#• 5%WVh<|~sl_RH9.ALT$thZt*q-;sq@ ms >ՌAoݹQK?V eOFC")6Jн dGcOeXq塾=v"B X eqL.AGs$' _E@ԣŨe % wnQ E}s^.GjjZ" *AauAjUW9K"B`Hf "h|)%A-cT%\l./X Jt뗻k+>y҃X)rs]`w N$D-έ_qR2HBI +Gs8rAqqXF2lut\U<5?M}G/hlhX ǥuOz\q/Qː e910FzGwN)پ%Y0 ;@^T2_es>j$'Glhs҃'%AI.A{v<pg˶a?;fS+1-|Ͷ׿W?Sb$`hѽz61>/^ڪd@ Jc1zO: rp2Ջ%$`%Uz3F` K %Vcv>Ƶ9fDC/ %cۢ4ʬk%:B FdokkJR^(_R̠Kp n fNC3b.u,.*x{ߐAK?#(Uh^ݏӐq^?k D-\B]eVSݥpǐPX  ꜐?#1K( ǯS02:C@hrN_?V]=>2s̞Lk!3] PӉ 6MR>!pn0,=0!4%"Y^N{;Jqߺ]EΎ`ᴶۡсN56TJ(Ko#Y|Zh҉rhKR<.Au偀 jhކrLYݽ CGe+LGjU#\/Na6C$RQy k)b)e@.$XaڳJ[NGY\);)O[RcM-5tF-?J({ V,t't6egܶI8K12&*kݨ~Q-ee{LlMAlTn(!2BX:̉xs7ȔBKRK)vDkauq#X :D>POA_Nv?$ 'B AZ9u|a󋢪;LMr\}(!Jٵ9aݗD,В.%$A2_0j ȓĖ_3}Es,4|jqg VYvZLUZR(mF+/Xח!{(QFv^=Bxn^;i0 &]WhR>[ h'th=T([!¨X9c! Ee]y[pi0ԷCZE> Ww BXQ!}Aٙz 3uQ w! RGX\ρ1f=:oSvv 0$ f`…h;W19~G-reoNfJ,v_=K㴥^\=Ғ Rh/AT^ln͆GܓCt:OVw?P~QX)dYAaP+}ך/Hx*r+fPOU)he8| BC#C ^6 d g:Wh2 6'qS0tp.`9c(f3gѫGcj2a~nqumwQK{ZCNdT?^So^iU1 c}Hs~!MX4EYHt|Zʑ︘gԒ^X+Qc-cpР3/Y6퓊hus.2 j,@rxVJAR V3[8VGK-}9A/X0׏G!P&P[Ne_ɧs"z.67}L__=uH1A PN/?{$)?$$OZ*8Xvm~X,˕SopGzΰ_(~ys ehց$ t6 PKc7q?]O$F+Z7gZaJuAjwsh |$&XZM8F5A^ПE8;b_"71:zV(CMHPcӂM]}.cMd6tBI 6Byش`C\V. d̚%dk3^WDbrOMdkyo+GvV;FPG(@^T>u3t}8NcAXh1zO:ҮUR.d 阠@׊GbюZ.YF[!UJ)ƑT+0cm7Akf%F'gضʅ(b)$ JZ֢6t:ʓ#ƾ㵠 Pl*"%..VRXJo<ߓi*.և<<v焲ŵU%U-b)>lEX(51Nū霠@^稥XS/> " @!,8 \کW1u||mA{8cCP Pv閻rVe+9X B@y_p]$I%QtIkk[>8X1~kਫ0"BI Vv45>)6? 2*ĭK^lLu>X>#bѬ*WAQg  }{gQ*oU/7j9sn:'Ql*B$RQy ' X B*Y𽄈/ƙ8^mKc8|lK(50\3sLNƿ|wM]_<f&hY9(b)Az11L6O "Iй|,AVK3.^tbPkûeZcgcg0wO >1,s 7uͯULsQD0'lc߾!K!3\UkQ Ŗs,X2bү0 tНC#xrLS#ܰ{gR+{ʡў # %6F#֋P ˪3A=s :%idGl>.-3hj tb)]P(β/W|cX/u.j`vc)od#M]񂈥 \ +0߶Vm =:L[ŽLsb1U?ht0Us_p)Kd̍Ntk*6 b)[$ 쁩Pxm4t %|U]H\?襄Wa`b<,PbgY LYq0F_XS?rեSLω`QbM[G b)Iߖ5*! :x%\ @iɊZQ ᩓz!scrڵWj>7dO:n[;4tUNARO2JINxrF3q $ f`…h73ݹzUO 1i[`JKAL)naJINjYzq|%mP=v5  RUc7OF82rgٴ)du}w{hgYVWf]x'C  )[$A'#3PaPf)l[8eiR(ĕpg@@:F3]KN8q)wNj$Տ=wdϝMVG RMY+pQ$b) l>x_s :EHN<}j% ٢G\epHmd<7=rD(#KA .EAy%3o㘌Nx=" 7@^T2/0%=6l "#1&IIAKqj˧亨=#2_9frNZ{km\D,!Yf)&hO-5pkhP+A2k۴"-*v!{,rL3 x `-6E(C [W,B?pumYK"B׬2 gyb& ܋Z*.I w j@oe]~z$X 2RLaܿ ^Nޗئ~2)ݐkz b)?O,` .pҳ| ?VOz`RNԬ]Iy " dq"mp0/a{G(kJVCkhD,AR1V1%U(\" BY\acB [lLfϲTe.mUW<[$X j\qy^ H4bw,+Z517D+R G~,_ e6*g(g eYopWF-I&6/K;O!HRBr #uPǮY"_ձkB(]ʢSAX>#W(u3!N -v̓+#*tGE٫;$mغ7I%!HR"<}9;#},vP 5So&m"B Exl6@#KS xof!!'|ks#QK*S✍ B %R3tA}@RwOIy4Bٵ" BZcұӖ"( 徊yLqݐ=i{HRAHG\ŗȂ0w@5E"B'kWn$ή|4׭}j b)<UxUFDUM=uަAAA8 +DIENDB`interval-3.2.0/COPYING0000644000000000000000000011322513316017127011266 0ustar The interval package is free software and can be used under the terms of the GNU General Public License Version 3 (or at your option any later version). The wording of the license can be found below. The interval package contains derivative work, which is based on other free software released under various licenses. Original authors are properly attributed in the manual and copyright statements have been retained in the particular source files or in separate .license files. For simplicity, most derivative work has been relicensed in this package. Thus, the GPLv3+ is the main license for the software and documentation in this package. This package bundles the library crlibm in ‘src/crlibm/’, which is licensed under the GNU Lesser General Public License Version 2.1 (or at your option any later version). The license can be found in ‘src/crlibm/COPYING.LIB’. The GNU General Public License. Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble ======== The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program—to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers’ and authors’ protection, the GPL clearly explains that there is no warranty for this free software. For both users’ and authors’ sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users’ freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS ==================== 0. Definitions. “This License” refers to version 3 of the GNU General Public License. “Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. “The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work. A “covered work” means either the unmodified Program or a work based on the Program. To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work’s System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users’ Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work’s users, your or third parties’ legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a. The work must carry prominent notices stating that you modified it, and giving a relevant date. b. The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. c. You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d. If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation’s users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a. Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b. Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c. Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d. Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e. Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. “Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a. Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b. Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c. Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d. Limiting the use for publicity purposes of names of licensors or authors of the material; or e. Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f. Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party’s predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor’s “contributor version”. A contributor’s “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor’s essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient’s use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others’ Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS =========================== How to Apply These Terms to Your New Programs ============================================= If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. Copyright (C) YEAR NAME OF AUTHOR This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: PROGRAM Copyright (C) YEAR NAME OF AUTHOR This program comes with ABSOLUTELY NO WARRANTY; for details type ‘show w’. This is free software, and you are welcome to redistribute it under certain conditions; type ‘show c’ for details. The hypothetical commands ‘show w’ and ‘show c’ should show the appropriate parts of the General Public License. Of course, your program’s commands might be different; for a GUI interface, you would use an “about box”. You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . interval-3.2.0/CITATION0000644000000000000000000000101113316017127011355 0ustar The interval package is a collection of functions for interval arithmetic. It is developed at Octave Forge, a sibling of the GNU Octave project. To cite this particular version of the interval package in publications use: @software{octave-interval, author = {Oliver Heimlich}, title = {GNU Octave Interval Package}, url = {https://octave.sourceforge.io/interval/}, version = {3.2.0}, date = {2018-07-01}, } See also ‘citation’ for citing Octave as a whole. interval-3.2.0/NEWS0000644000000000000000000006350513316017127010737 0ustar GNU Octave Interval Package Summary of important user-visible changes Version 3.2.0 2018-07-01 ======================== • Fixed a regression where decorated intervals could no longer be used in Octave 4.4 (bug #53331). • intervaltotext: A change in Octave 4.4 has removed the possibility to increase Octave’s output precision beyond 16 decimal digits (bug #53456), which has made it impossible to output intervals with a higher accuracy. The function ‘intervaltotext’ has been reimplemented with several new format options to customize the format and accuracy of the interval literal. All recommended conversion specifiers from IEEE Std 1788-2015 are now supported, e. g., intervals can be printed in uncertain form. • printf, fprintf, sprintf: New functions to produce formatted output with interval literals. • numel: Added support for additional arguments to compute the number of elements after indexing an interval array. This allows combined indexing expressions of the form ‘x(1:2).inf’. • Fixed several warnings during package installation. Version 3.1.0 2017-12-21 ======================== This minor release introduces two new functions and fixes severe bugs. • mod, rem: Two new interval arithmetic functions to compute the remainder of a floored division or truncated division respectively. • plot: Fixed a regression with plotting 2D rectangles in the upcoming Octave 4.4. • The internal function ‘__print_mesa__’ for off-screen mesa rendering has been removed, because the upstream mesa project no longer supports off-screen and on-screen rendering in a single executable (Debian bug #877149). It is recommended to use Octave’s ‘print’ function instead, which has greatly been improved in Octave 4.2 regarding the output of rectangles and boxes. • A package installation error on 32-bit systems could be fixed (bug #51857). • During package installation, FPU control has not be activated on x86-32 platforms. Thus, the crlibm library could not disable 80-bit floating-point arithmetic and produced wrong results. This has been detected by the interval package, which fell back on the slower mpfr library instead (Debian bug #874135). After fixing compiler options, x86-32 platforms can now use crlibm correctly—even without 64-bit SSE registers. • Source code for interval arithmetic tests from the ITF1788 project have been removed from this package, since the loadable test data ‘itl.mat’ can be edited and processed with Octave easily. If unit test code for other interval arithmetic libraries shall be generated, find the project at . • Thanks to Olaf Till, this package obtains a configure script (patch #9518). It checks for available libraries during package installation and can help to identify missing dependencies. Version 3.0.0 2017-08-19 ======================== This major release introduces support for N-dimensional arrays of intervals. With previous versions, interval objects have been limited to two dimensions. Only scalar values, vectors, and matrices could be created. Now, interval objects can be used with three or more dimensions as well. Binary and ternary operations support broadcasting of singleton dimensions, which can be expanded to produce higher dimensional results. Most work for this version has been accomplished by Joel Dahne during his Google Summer of Code project. The project involved thorough maintenance of all interval functions, which led to improvements and bugfixes beyond the original goal. • Support for N-dimensional arrays of intervals. • Removed interval implementation of ‘meshgrid’, it now falls back on the standard implementation which can output a 3-d grid properly. This no longer automatically converts all input to intervals. For example, it is possible to create a grid for interval X values and non-interval Y values. • dot, prod, sum: Altered how empty input is handled. They are more consistent with the standard sum and prod functions (return zero/one for 0×0 input along the first dimension). For the dot function it is slightly different from how the Octave core function handles it at the moment (bug #51333). • Output of interval matrices may be customized with ‘format compact’ to display more data per page. • nthroot, pownrev: Now supports vectorization of N (for nthroot) and P (for pownrev), broadcasting is fully supported. • Indexing expressions on intervals can now use the ‘end’ keyword and the special operator ‘:’ to select all entries. This affects selection of entries and assignment of entries (bug #49592, bug #50626). • Adjustments to ITF1788 test suite: • Several further unit tests have been derived from libieeep1788 together with the latest version of the interval testing framework. That is, tests with NaN values, NaI values, IEEE 1788 exceptions, and tests for the following functions: numsToInterval, textToInterval, intervalPart, newDev, setDec, decorationPart, and reduction operations. • Unit tests have been reorganized: The source code of test cases has been moved to /src/test/. • The test suite is no longer compiled as separate Octave test files (*.tst). Instead, any interval test library files (*.itl) are stored as loadable test data (itl.mat). The test data is then used by built-in self-tests of the functions. This simplifies testing of functions and saves storage space after package installation. For example, ‘test @infsup/plus’ will run any arithmetic tests on the interval plus function. • Adjustments to the package documentation: • Information about how to create N-dimensional arrays of intervals. • To improve privacy and page loading times, the package manual no longer uses external references for CSS and web fonts. • The package URL has been updated (after Octave Forge has switched to HTTPS). • HTML fonts have been changed and fallback fonts for Windows have been introduced. • Adjustments to code examples to support the latest versions of the doctest package and symbolic package. Bugfixes • Processor support for SSE2 is automatically detected during package installation. This fixes installation problems on devices without SSE2, for example the usual Android phones and tablets (bug #51758). • wid, mig, mag: Fixed wrong return value for NaI (not an interval) values. The functions failed to return NaN (not a number). • diag: With more than one argument the function no longer fails with an error. • dot: Fixed error in identification of dimensions when broadcasting: When the optional dimension argument is missing, the first non-singleton dimension of both arguments is used (before broadcasting applies). • infsupdec: Now creates a warning if the ‘[NaI]’ literal is combined with decoration, e. g. ‘[NaI]_ill’. • infsupdec: No longer produces warnings for mixed parameters with strings and numerics. • verlinineqnn: No longer produces warnings for unverified solutions. • pow: Fixed error when called with vector arguments. The result was only guaranteed to be sharp in the first entry, e. g. ‘pow ([0 0], infsup (0, 1))’ produced the interval [0, 1] for the second entry. • pow2rev: Fixed errors when called with non-scalar arguments in two cases, which could produce wrong results. • ctc_intersect, ctc_union: Fixed runtime errors when the combined contractor function is called with less than two output arguments. • sin: Fixed possible interval representation error, where the upper boundary of the result could become a signed zero (bug #51283). • factorial: Improved result decoration for integer input, since the function is continuous (bug #51783). Version 2.1.0 2016-12-28 ======================== • The speed of some arithmetic operations has been greatly improved. They have previously been computed by multi-precision arithmetic which simulates binary64 floating-point arithmetic (MPFR library). Now, a specialized correctly rounded mathematical library (crlibm) computes identical results 30–100 times faster. There is no accuracy drawback, arithmetic operations will compute tight interval enclosures as before. The following functions benefit from this: acos, asin, atan, cos, cosh, exp, expm1, log, log10, log1p, log2, sin, sinh, tan. Bugfixes • Fixed indexing expression in interval constructor for illegal intervals of the form ‘[-inf, -inf]’ or ‘[inf, inf]’ • polyval: Fixed unnecessary warnings when evaluated on empty intervals • Fixed compilation errors on FreeBSD 9.3 Version 2.0.0 2016-11-20 ======================== This major release contains fundamental changes to the interval constructors. After a discussion on the P1788 mailing list, it has been revealed that this interval package didn’t implement exceptions from the standard for interval arithmetic correctly: Operations from IEEE Std 1788-2015 which trigger an “exception” shall return a value nonetheless. Conformance has been improved in this new version, but may break compatibility with previous versions. A second big news is that the interval package comprises functions from VERSOFT, a verification software package by Jiří Rohn, who has generously published his work as free software this year. Unfortunately, some of VERSOFT’s functions are encrypted and could not be included yet. • nai: With additional arguments, matrices of NaI (not an interval) values can be constructed. Previously, NaI has been restricted to be of scalar value. • infsup: The bare interval constructor merely triggers a warning instead of an error on illegal input, which creates empty intervals. If input contains legitimate as well as illegal input, only entries with illegal input will carry empty intervals. • infsupdec: The decorated interval constructor may create interval matrices which have NaI (not an interval) as entries. If input contains legitimate as well as illegal input, only entries with illegal input will carry NaI values. • Warning and error identifiers of the constructors have been revised. The warning identifier ‘interval:NaI’ has been removed. Illegal input signals an ‘interval:UndefinedOperation’ warning. If the input is of an illegal data type or of illegal size, the constructors signal an ‘interval:InvalidOperand’ warning. The warning identifier ‘interval:PossiblyUndefinedOperation’ has been renamed to ‘interval:PossiblyUndefined’ to better match the wording in the standard document. Also, previous versions failed to trigger this warning in cases where there is a floating point number between boundaries U < L, which has been fixed. • It is no longer valid to call ‘infsup (+inf, -inf)’ to create an empty interval and the constructor will signal a warning in these cases. This change has been made to better conform to the ‘numsToInterval’ function from the interval standard. You may create empty intervals with either ‘infsup ()’ or ‘infsupdec ()’ or ‘empty ()’. • inf, sup: If the input is NaI (not an interval), these functions return NaN (not a number) values instead of an error. • Output of intervals in hexadecimal form discriminates between subnormal boundaries and normal boundaries. Subnormal numbers start with “0x0.” whereas normal numbers start with “0x1.”. Also, hexadecimal form has been changed to lower case. • resize: New interval elements are initialized with zero instead of empty intervals to better match the corresponding Octave function. • Interval constructors may broadcast column and row vectors. • Performance improvements: factorial on large arguments; plot and plot3 on input that is plotted as a line. • New interval functions: tril, triu, qr • New functions which have been ported from Jiří Rohn’s VERSOFT: chol, vereigback, vereigvec, verintlinineqs, verinvnonneg, verlinineqnn, verlinprog • recip, sqr: The functions have been removed, after they have been deprecated in version 1.4.0. • plot3: Fixed plotting with gnuplot and fixed an issue where the figure did not switch from 2D to 3D after plotting. • expm1: Fixed documentation, the function computes exp (X) - 1 instead of exp (X - 1). • norm: Fixed an error where the Hamming norm of empty intervals was non-empty. Version 1.5.0 2016-05-31 ======================== • norm: Added subordinate matrix norms and the max norm • strictsubset: New interval comparison function • Package documentation: Added new example (Cameleon problem), and the growing list of examples has been split into several web pages. • Package documentation: Updated recommendations to install and load the package. The autoload feature will be removed in Octave 4.2.0. (patch #8981, thanks to juanpi) • Support package installation in Octave 4.1.0+ (bug #47288) Version 1.4.1 2016-02-13 ======================== • Fixed a compile error for 32-bit systems during package installation (bug #47100) Version 1.4.0 2016-02-09 ======================== • mpower: Improved accuracy and speed. The interval matrix square can now be computed without dependency errors and with tightest accuracy. • factorial: New interval arithmetic operation • expm, norm: New interval matrix operations • The functions recip and sqr have been deprecated and will be removed in a future release. Please use ‘1 ./ X’ and ‘X .^ 2’ instead. Bugfixes • bitunpack, interval_bitpack: The order of inf/sup/dec parts has been fixed. The function documentation describes how the functions behave on little-endian and big-endian systems. Version 1.3.0 2015-12-22 ======================== • postpad, prepad, subsasgn: Implicit new elements during subscript assignment and padding have been initialized with empty intervals before this release. This behavior has changed. Now, the implicit new element are initialized with zero to make a correct interval extension of the corresponding built-in function. • fsolve: New function to solve (systems of) equations and compute the inverse of a set under a function • ctc_intersect, ctc_union: Utility functions for contractors and the fsolve function • det, prod, recip: New interval arithmetic functions • diag: New utility function to create diagonal matrices or extract vectors from diagonals of matrices • decorationpart: Choose between different return types with a second parameter • For several functions it is now possible to broadcast row vectors against column vectors or vectors against matrices. • The user manual has been restructured for better accessibility by new users. A bunch of usage examples demonstrates the package’s capabilities. Bugfixes • sum, sumabs, sumsq: Fixed result for matrices of size zero • powrev1, powrev2: Fixed indexing for vectors Version 1.2.0 2015-10-01 ======================== • The output format for intervals has been changed. The number of decimal places now respects what has been set by the user with the ‘format short’ or ‘format long’ command, and is much shorter by default. Also it is possible to use ‘format hex’. The old format can be accessed with the ‘intervaltotext’ function. • fminsearch: New optimizer function for finding the minimum value of a function over interval constraints using the Skelboe-Moore algorithm • fzero: Changed function parameters to support optimset options • power: Improved speed of the general interval power function and monomials with the notation x .^ n • plot, plot3: Added support for colormaps Bugfixes • mldivide: Fixed algorithm to handle more matrices without error • bisect: Fixed an error during bisection of singleton intervals (thanks to Helmut for finding this during OctConf 2015) Version 1.1.0 2015-08-03 ======================== • meshgrid, mince: New utility functions to help plotting of interval functions • linspace: New interval arithmetic function • intersect, max, min, union: Allow evaluation as aggregate functions within an interval matrix along a common dimension • Improvements to the documentation • Added cross-references between package documentation and function reference • Extended information about interval arithmetic in general • Extended information about implemented IEEE Std 1788-2015 functions and fixed references to the standard document • Added information about plotting intervals • Simplified package description • Graphics with higher resolutions, demo of interval sombrero function plot on first page, and minor style fixes Bugfixes • plot3: Fixed plotting of interval edges when plotting several intervals at once using matrices Version 1.0.0 2015-06-13 ======================== • IEEE Std 1788-2015, IEEE standard for interval arithmetic, was approved on June 11. To mark the occasion, the major version number has been raised. • All interval constructors have been extended to create interval matrices from a single string. Commas or spaces may be used as a column separator (consecutive separators are trimmed). Semicolon and new line characters can be used as a row separator. • hdist, idist, sdist, smig: New interval numeric functions • User manual: Relicensed under GPL, added examples from the former Octave SIMP package, and various minor improvements. Bugfixes • mtimes: Fixed matrix-vector multiplication of decorated intervals • Fixed a linking error in mkoctfile that could prevent package installation (bug #45280) Version 0.2.1 2015-05-30 ======================== • plot, plot3: New interval plotting functions. Pay attention to the included examples, which can be executed with ‘demo @infsup/plot’ and ‘demo @infsup/plot3’ respectively. • polyval: New interval arithmetic algorithm • bisect: New set operation for bisecting algorithms • sinrev, cosrev, tanrev, atan2rev1, atan2rev2: Now allow non-scalar arguments • Simplified licensing: Relicensed parts of the software that were not under GPL • Updated information for citation of the package Bugfixes • Fixed generation of the manual in PDF format • subsasgn: Fixed cases where decoration could be lost (bug #42735) Version 0.2.0 2015-05-03 ======================== • User manual included in the package, see doc/manual.texinfo • New utility functions: cat, postpad, prepad, reshape, resize • and, or: Removed deprecated functions • Improved display output for cell arrays and new function: disp • Minor performance improvements (all decorated interval functions, horzcat, vertcat) Bugfixes • issquare, isrow, iscolumn: Fixed compatibility issues with GNU Octave 4.0 • cbrt: Allow negative values as parameter • cot: Fixed accuracy for x = 0 • cos, csc, sec, sin: Fixed correctness in certain cases • Prevent multibyte characters in Microsoft Windows console Version 0.1.5 2015-04-06 ======================== • Implicit decoration of bare intervals triggers a warning now and can be allowed or forbidden by the user. Implicit decoration of bare interval literals is not affected. • newdec: New operation for explicit promotion of bare intervals into decorated intervals (without warning). • Decorated interval literals with illegal decoration are no longer allowed and produce NaIs. • hull: In contrast to the union function, the interval constructor is no longer considered a set operation and can create intervals with a non-trivial decoration. • setdiff, setxor: New set operations • intersect, union: Renamed set operations; the old function names (and, or) are hereby deprecated and are going to be removed in the next release. • intervaltotext, intervaltoexact: Decimal fractions no longer omit zero before the point, and unnecessary trailing decimal places can be omitted more consistently and in more cases than before (also affects console output). Improved accuracy and performance with support for interval matrices. Bugfixes • mtimes, mldivide: Support for broadcasting of scalar parameters • nextout: Support for decorated intervals • An error in GNU Octave core, which could lead to lost or wrong interval decorations, no longer affects decorated intervals (bug #42735) • Some errors in the function documentation have been fixed (thanks to doctest-for-matlab and Colin’s texinfo compatibility patches) • Fixed interval field access on Windows Version 0.1.4 2015-03-15 ======================== • New interval constructors: hull, midrad • New interval arithmetic functions: cbrt, cot, coth, csc, csch, dilog, ei, erf, erfc, gamma, gammaln, psi, rsqrt, sec, sech • mtimes: Support for fast, less accurate evaluation using BLAS routines • mldivide, mrdivide, inv: Improved performance by using faster mtimes • infsup, infsupdec: Enabled broadcasting of scalar boundaries • rad: May compute mid and rad simultaneously • subsref: Access to interval properties using field syntax: x.inf and x.sup Version 0.1.3 2015-02-24 ======================== • Fixed a compile error that could possibly occur during package installation Version 0.1.2 2015-02-22 ======================== • New interval arithmetic functions: nthroot, hypot, log1p, expm1 • lu: New operation for LU(P) decomposition of interval matrices • nai: New decorated interval constant • mldivide, mrdivide, inv: Greatly improved accuracy and performance of the linear solver • Improved accuracy of vector sums, dot products, pownrev, and powrev2 • powrev1, powrev2, pownrev, mulrev: Now allow non-scalar arguments • overlap: Renamed one overlapping state from equal to equals • mulrevtopair: No longer available, use mulrev with two output parameters for two-output division • setdec: No longer available, use infsupdec instead • Small performance improvements Bugfixes • Compatibility with GNU Octave 4.0 (bug #43925) • Build problems during package installation with environment variables • iscommoninterval: The decorated variant must return true for common intervals without com decoration • eq: The decorated variant must not consider the decoration value • Several decorated functions: When evaluated on a subset of the function’s domain, the result’s decoration must be dac if the function’s restriction to that subset is continuous • Decorated boolean functions: Must return false when evaluated on NaI input • Interval constructors: A PossibleUndefined warning must be issued if an interval is created from two very close decimal numbers (which can not be separated in the floating-point context) where the lower boundary is greater than the upper boundary when compared with infinite precision • Interval constructors: NaNs must produce empty intervals • Decorated interval constructor: Illegal decorations for empty intervals must be adjusted to trv, and illegal decoration com for unbounded intervals must be adjusted to dac. • cancelminus/cancelplus: The functions returned wrong results if the interval widths could not be compared in double-precision • cos: Accuracy for x = [0] improved • pow, powrev1, powrev2: The function must be defined for x = 0 and y > 0 • All reverse operations: Must return a trivial decoration information at best (the only exception is mulrev) Version 0.1.1 2015-02-01 ======================== • Increased speed of computation for large matrices • Improved performance for fma and dot • mpfr_vector_dot_d: Changed syntax for faster computation on intervals • Decorated versions of mtimes, mldivide, mpower, inv and reduction operations sum, dot, subabs, subsquare • Renamed function sumsquare to sumsq in accordance with GNU Octave function names • New function: fzero for finding all roots of an interval arithmetic function Bugfixes • nextout: Function returned wrong results • exacttointerval: Now produces bare intervals instead of decorated intervals in conformance with IEEE P1788 • atanh: Function returned wrong results for ±1 • dot: Function returned wrong results for some inputs • fma: Function returned wrong results for some inputs • infsup: Function returned wrong interval boundaries for decimal numbers, function failed on mixed numerical and string boundaries in single cell array parameter • mulrevtopair: Fixed order of operands in conformance with IEEE P1788 and wrong results when evaluated on intervals that contain zero Version 0.1.0 2015-01-21 ======================== • Initial release version, which already contains all required operations of the preliminary standard document IEEE P1788.

pd;>m5InK^_D(8,@Eoq\jEgKSJg\f654C`eXZgA:T4s+E1FN*Yem 66=@k[3r&u:?ps"Z8@2t`)iMaGa:p]=mY55B:TOZ'j`r;?b,(9sFN.N@Qq\o+=iB0>2P*ZV Zao`5JO?'W:?XSjjVlOC;^lhBKg)>.W`3`@3jiS)>H?@kC3@,$EN'MifkiWo?,k+@MI`4hCpT9ZQ?PhTG`;&T,ot(go!t:iG=S.Ok]J o+P_1t7R:pd@^!?A-_;%O-=t.E0>u%D;HMtS(GK8\6p\fPJDl;Lcq>Ph-ceJHu^^qIh!l-K P#mjXIM*47Jad$G:>R0+1,YgbfNP,b(hG\ks-C'#]np7hinh<)FC@A.^;*OT`e, )4I>b+DE@rg:40o`.=XP''?!D,"Q`*OX%tG0rRR*#,-?VSW\r0.8#c9XXqW#gp&J);XD4Qb Yn)T0[-hbUi.;Er7O!QdsU+6c;U7t3mQ3enN>,rh"a.[e+oqX*RJU;6I:rZ(IZWGd6_Y@11 _Oua`Ndk8^bVP/lA)O2*!D?ZTUTMe5Z*4:`*f9poSGelADO(8gW2<[W?4VeL=EYR;i`M3iL_T"Q IRbAELK;saD)E7c?GglRJqW-kIM^cU 1d^_Oe_/E2OUB*\mCr+l5H7dWp3crWLb*,YtT<\"l\NbRYT#OG"n:9fnGL$Cc1LrV?dJHE?J2VAM-ah]qY=L5l26"f ch[P>cftKpfDml586[$AKHuP=^_*5=%"W@U#XJ/2"/)G%K!7uX6'sA2i4L(_:jNU;pdGHs, Tqce=De9o 2[HEek:p42oRNMNM'l`H\d+@cUXLd;CVVfYJEb'P34XSh`ckbn\8aV%R9o8I((1*2AI6NmZ E?7nE:nj4np@Oo@R9)#GH:"GDg\<(Mf'40Co)0CrG`9p5>l6h%uIL)@iGUDRL"JY"ZPC3*.U4%cJ]*2U$E%AEjA/-Wn#\5-:-u^8*sVfj/@;8n[F`C'f-K-t5<8LpEmTb.12`#-b"gZK<^]Y9#+237jPX8&ccC*QMkEuN37$NRlP"J@1%0[t%]U=thCIDi]3^a7gY^2obpW;n@$Ep=A%[@H9r*qHP if.H`iOR^1L-dCT'QmG0k=G#A?5.Rr'P'4XY%Djk%IpDkrb>C15V*Wa(Mi[,1f88+c,"so# $XJiu18(=Qr>?$#GY2!?rnVZeTa11uL\"Ab&'jFd!O!WW;Qu6gs[p1q+']mFk9W>`^bkU'6 k1/O7%f=GjQ"&;[_gH?(q]4&MDaikq)kqG'Pcn)ClK=^&W-'/XeG?(ClH=R)&$baf7UW:*4 au%,)eI\!#A!1,QaCpYoJso^VAeI<2quX>DlrJN[t@dcL>fQp":3s(_J8@AMlkob-\LpF$c I9s'B/AHeJ*Y7D[U"73eiQ'CsB;eXtf?(`ng*%=1cf9#5`nRhkft:T)\Y*;sHMGp`(I$0Fj 3J+7O.Tp:)p5H_5)_:iYOUoIYC'ic"-2epZo^_Un)hF(uj<(d kroQQEhf%u^gkZdK4u*M<;s?DQ]GcCBbP;+PjaRfsr*O-g%:L"fI\6<0+;SD1:]AUtf)SVJ !,qu[Tje^e`"HJMcOB0d:`BHI*s,7YO$T_,/I'QQrrYhDP78.gm1f`_'[_b2dOcN)5n4OQ& u\)A)Jq7ZD*la6@g3KW"n67TND.kt*="9AeSoPs8XPpfT[n(:ekh5ABrWhc^=UKFfI_j2/W C)KT*e;Z$>Icp9q7gBVV37s%:K;T!8]K(jIQg6,Ye^):s@jTE81o@6:!"5Tr+R,0]_`ch@S o4&FU+Uo+%Pn60'6INV),4rt%Jhhsf#)d*E:8dbk79)JX^>Y]Qi%r^SSEiaeG9c=lA.CD.: <*J)c_/p?h@6F2\D%oDd,D9rmr1`Faj'olTtmUHnb@hXu8j'fG;b9[ijlkptl*3PUl&UtVE K'>"F(^grmiPliLEu@iA)3LC+d@V<[l5h+])(sA(dB=J9ZL(Mo)f`8)L)M%?L8YUGmV_D3O j4DEYSP5h(nhXU_*[Zhipi/nnT!k9;=,EemiP#b]1]XRTo?Vl`#jR#)C4_m+kdpuj;!_cL=X$XC,*F/pZ6o7<^^_Ku*?bIpDf6m3FX/Vc,YrOVc`7"]=GB@[L f`Lrb\XP#3Rs;^Y*+)o0Z)TsP3r_^JAa_TFG!NW,nVqo4HmfJ`)mNN*iI/2%nW$BU:V %5,o*H9'(IhCd:kfK8fPUn*mtE\`Qo6^Va+1^XFVi7Ts$Y%''8Xl(3CKZoGk$MS/\0^5N2S ]!TY:6Kc%0U6W?,aPWZ3:kT<+`6F9BRe5&LI;aj+F+(=FTn\%C(]1,Z47PngKFD>-5^)*IR *41&5$Z``XZkn8f*!)9:J]JaFP92WJ*u(1dFIc!fT1W(WCG-[u!Gif#cl'[f*b!9/nX^hRl 5i7F(dVXTPg8nS5/&d,9p./(dOe3.gERit$\?S6_!NCho-CV5:R(KoZ;2ig`dgaOamuQ1d] lX^Y9n(kbB3tceH8\^_Kb%R%03UO+MnETM^]B";cPn.16*@,;6AU(4td)IVh9+g);?OrIfa$>`BD[7O6YJLn+Y/JX*oQU_@0')`Ess`@jNCT0a=6CdgT+78Qu_r#X hl+*9ece3@gb3Gpb3)aV1Z+lR1Eo5@\(DjL74_:fg$G=N?cE0P3Yf*?9h$FF6I(;T<-dEQ\ 9:)^r^%KX-X5meStTG+]18f'R1QTn*/4`iVKF/uY_6/3GgKH>^")aX6@;/kf/qB&#o*PmaO o[+i3dil*M:%[Okf6_`Vj*2pS*2)p62#V\6pN\Ul_,UM<&+og=gJsM?HBhKVaGBiiT6jRjH \e,@L^X\_'3"QaI!%T"Qd-PCapL):-VPutk\:BiYBm[UISsbri8t=\A-^`ZJ!FYr6)Y9DL` 7Jr$,O1^J?Jo2f`.nH=V[!KeW#.d[M@cF'>Y>c'rQ[$08!(J)F5T$ErCY+[a:*t>Or#'!X1 9caO/rR&`JjX.YEHYAfB4W??P4]fP?6Wl6`q-B_+0 496gBR)`kWo8a5t%rNV!,,o92>ck?uC)4pQV+dpJrK0M*5WISZPGG;feWZ>+-\5kiPZ]Ol',63Pa:Eqb6JrZbE7'OQ'kjAfj7I*mVCDdQBr>Pf+XJgC:/W<)$*,DbC O[/Jn0G:(Ei&`_2JtW`YrjUFEs?t=eBf(URBf3RL]lK+gr.cZV,DOD6#X5U#^)-EL^*PDRX n9=jM:!7uLAj*=ejH&NPbf=NCcUFLKPT9n`5fBRZ[[=MKNTTp_9[$`VO+mpF44-gY_Oh2R;C<:'R\4PE]P']MeG/KMJ9t*tTk:o7FTrK-,f9CPVPe2^\d>/R @J025K[Ha@iZ'RPYE1t2e+X*4S,%HZ&%AC-F_"o#oRM,Fq]pYe3 frMh+gV,c+C?Dr=iS#8;Is#s=+$o+r@H\X2S"+\D^lfe14:e!Q&Y3(M*%V8b=mNp%,>WURT \M"9T\!0>2oAfV_ieY/ROQ/nB7$>^$u`JGg)6U^:OHu9IULZ^4@R,bP?6Hu_gH19VoBW?g' ==7%Y.Ru!9sg#8'"k.aEgT"*" =tP66dRWOPRJBgXT6/.d@J(h!nFHEDoZe4+u`&)i"n3kq`.n'=]mX?+IYig6b#d:f3T&qQr dJZ'.FJ>_A)i8LB9.M&[cl`Y^adTnB+qWk>s1"/a7N55K,JYfB"BG%T^[J`b+h+t:=:d>t0 B"K5:d0:-Q`R4Q9esOR]Tq.!*S$UKi[\YXaHZuj/E_E+V'DnOn)dCiUPmjRt6>_H\7USkC>V.E"0X_UmbdhI"::@XE6GjaM!b%$`3GIjdEVkF>Pk/9:Z]eQ;` gk_G2o[0t"RPNEpNH9n26+Dr&>lif\F%_ur&^9>VLZ_\R7aP_Psi/en(?A;Wos'2>A]VhYb MB-,7'Q=cfS@@o)L[I:7O+Er:26k@ho?;GRn!1Yem2cgi'GrN$e/[Sq57U/urX^(:cT`Ap+ !8ghYh `%,>ugV@Dtc[,N]?:/?[OrkA$WjVpml2]5i*'gR$iMr4n0d9>AQm>RG+3cg4?gTpL2kIU"L N)qh+)F_*(()TDBLHqL?]BUs'^m\O)MZ>/>(r!P@,-]sti?r_\+_@Fj]#Zi=D,s.B-m_>sO _4l%Zs;k]APKL2@d\9'VP%#I@2E>YKX/K'Gcit9A^G!R448#2:c/<3FRPX\WsKqZ>_Yr0a; F"*pAD)jJ^(FNhl*?=-T.&]a!/KLf[Us^\kg19iipu mbc;urucfoM^SK=t1Xi,6"N@klIK>$43pjAYt2iH)Fo_JGlhe/LgCF?MaA1sk8lhC@,J"Me npA_n3":"rmYRD$D5nGjd#!m3M'aR+/oAV/]cWi+26SEgA%Du$'57^.9lphUSB(4"p)aamk ClAEP>8P9+KP)/lZ&ET>7hN+L*_15BFWa2[%"B<+i\A/($S`>g-:r6"88aDr]Ho$nnuO&d9 /=Gp/'G6J]HJ/&QsO<`_,6LZKr0[m+&-fmff)Y^K]b;>Z]si<:@iJ&3f$8@i[1.IE3AX;nF =XdNot\0=Aa0W)+RR]KdTC=[$<48;Y8Kq:/_l"*-RXE6,lNXV\(1:<:rs_;jI0CYQ;J\j6n hnHMCK(F@=HguL1=X*7kdIH,W[GHn/5Ob]A1+44&&>(I-=>4XX%SFZhBZe9.<`>M+)sQX/&BCHl?T>,\9GGXMLI^cBEBqp4jAe!fUQogFbL.RU,T-4,()C/`DC41SMg%Tq[ LZeE#KPl0DRO;b>rVp6bs*rB!rkLJo!?`'[JIik+5\M#:?u-2h"*f).-n,=-Zkn?+Adq&93 >UWYY0j.Ylg]l$]"48+[d0(&0 `quJ3s?[(4f>o2+M=#+/>'No8W7f(<4F(#mgs(,YD1#l#eMQoX:,4+hEO[%6('3i:IIte.J XM&#^17T[Wak;,EA(%:K8mJuY/8`cuV2.HrtF2"=R\PuaoA\7l1UIPlbH/.M\GD[+RqGZ7" e;lX\1esb8qlZHsF$:%i'iQ*>K'#.Muj^-QMnR!fsIBXIc]ds`sZIX/QYmWF!XTbN0(B'.[dMD,%4AQGV6,p,'f-1ZW*uX d69d@a*N+M6n''cJ0a_+@N0WE)/@X]m$Gs>+8N0%F41n2W]'6Q.%^Uk5*uIn0pdsg_'[)BY9[oJR1MF^mH;(]Xs GRn9)sl(R#/5qnsJm:s9BC'P3%3&2RZN\&8A:5Vgu1M.+U$Ih<_G`/IiVnTHD%"0c3n6/4\ [oSU[+k8d(F8I;T>r4cA6+Z]Wj.7W/@LD_HbA;GF?EK2]k\N_NS*2sK>W;%I%mR7Tdi]JH- EfM#e0kMEIQnpX1bk[S^7\T$0VLD^o)94aM4R&DX[Wg%8k<2>OoK:0!S!,UO5\N:aTl^d"d $c1H&OF2cKM8,)6XX,R0tK(B8E1U4JmdiRJZ!)qSC@=]:hi-^WHA]Ke=*&+QOuns$aFpu,M 7/MiUf<(GfLTkCL'Z*GrIVIhORjTFR2$>Z$$o&fUEl,N_oKjVr[[-)aA%4h4qA9I/g*KAt5 H4Zl4O%7,/LfEE$eq\8!GI%:N1P;D$S5pNG\,;DGD';#)I1&-TB8ooO3Q>!tHjE)U5o\3b-AQQN't)&jf%sEM H"*9Yj-WStRfd$.[l*=a$_-ajEi_`LOUtP?_q;,JZdt+tZ@+*rFGhWZf/SHrj!NaX4$L;P& AAYUjBYt2\SV-8ZKrTUYkA"7D-6jd&`Z8G$"9lQqPEKEpC3_#p4J$;Vg!'];6*ul]6=)7J+ )5!^A'nmeuo$rnJG!9\2OcRfsbt-pTjO(4FuUAVjGIgB?PS(1$7;2T+n&5"St4ikqH-CAY% l#HG[D$<<5Cs9_,F?"A/)jr'u=u/_1WPXkZ\/qDhX9>#:Ng[Z2KAD?+';I_?41(9Hpo5,I UPr6;/X6E,l'%2E%%>_NZIcUME3&BK!bQ3"h=9M(,r=KXbhO_\=f7?u,pI,Jr4f6W8S(>Vq Q;E";Y\!uNDpj>sco4#cLgOiVDB+=;jL2FD"?_f6+eq"b%30LS;``(Vp"!+uCq)EScK>_`L*-"IoF2ot!`uK4*]QQeeFiRTHKtopnP^5iiHH3g+"7SECe:'pCI`MYAKC!CVjF 0WJ>Y$u1a5B+5^g+mlLIT4;aHUKCkX#J%59EE]KTKmNJ56B^Nl_-Z"F*[rZcPcop;o:0S7$ +8?qnaRQUu"[a^N2B-qf;^4G7rl*#+r8ballJS@sGDFBFbZ"U,Pd/C7a.[0;K[c;Or4gITqEGD*9[po&j MIQlD$MJ89Ni!^!-*c%r]eWVbs^*seCMlC158>@LFgitUtX)#gWd[lc-nZX\93Pm$c'.-^o ZM?"QE/j$3rP$"W2$/TJqVX?j$aSL2]jQPS_WPlH[bjE^JmY^LO"jfMh^f:JQo$9 Gi#/F5kE,Gi(4U2g-KP5H2cqb'Hb1L;jJ4,'XAV;a)"lM^ J@6*\RS\QAm1]PM:CXb*`UOh@3gfMto'AB.epL"L_J^;BrT*EgQ[M b@4897;?6NK)T\VG#.FYgX(9o+7N>NBQpW^?PL<%*d#gcIm7UL>[+XXPMR9*)(4*=k/81J4 iH*b?8,D9[/r.-(!=A(ku^A#E>4GY\OJWFj4IKg6JVjUt8eM3/+F.L[,m_AZjb[YM05bgCl [Snn*YRAqb?dgJm4fAE-m:[E]V4#+/VME,NoKBf+?->L`,rh!eP8^Y@kcg\&B/n8AL278H@ jcW.s19ubLECkZCuKoeS*+BnuAFbT%i[Ho&qeGrDdceS3?ck:;Q#W[MKFT`OH:iurtA_#UZ #EE'qd2a,:\I)3a+&V.Sh9cJ>?1sIm:dl*I?^3"rV(#cM<.g!F"^ jNgTLd%<=,#(4;[*8eW-/>h:mF"&dmaMi?3X>'#F1ZgKTJLKIL;BX3Rb?H@*r]l(dnQ&6\M ed9!s:()lnVl4GC10],?H)4\t$Z:LSrPiKb;=Sf$F`(Y&slT:f!a-uDTW:/4n]"P&C^^*;* n,?Ve@KNLg#:dft%?=J(+@X]`bVCCN5.:U:Him'(6eh5tE0B1hBip^7Vpd3T_IcEkG)\%;L qn("6o[EdORE^CfjuV.T45&IQA$aCm"4:RQ,\-m=KT2"&-8sp@ecU^r]pfI6&MuYh^)6O-= ooYrD5,^D94Ym<#&nJ6?*WJ]-s=hYjV-p4fMNfOQ"6BQg)ZsLc:d8-rWW@:U1R1+@!`-dX6 %=$A_!dAhHYf^FGHuejSiTM-=Z*qA*,arLCe-'L1]1XB3Tgtk'1G@5^3LS@0aku#<74\86DVKpKupB/c^"e\9h0O+b1qkhmB>nt^ l*eNT$reCJ5K(.Y"kj&IU7tbi)KSW.^QAT@IMWi'-?0IH06dqp_dm8ha(B%1[@ea7h:m=s<]QJ1__5_D$DBm;FM`m/DOhX1U *mM=\rfPQ8..I4^YmT-r;?KCNdkO*N!#-^%<0P^bu+muf*DSGK*k3_U1m;E3smgegT(@po@ o7@fm",Ip$:ce\ap@!J)Dhe)VE+ag-)hsG9Jc>T9hYhBTs6o[^n*^;H#6Ji\!q8\^n.9=;0 IMV-KNL?jQT=Z@3chbmo>a#c^HV8 @5BH!PoG9db-U;b:7g)q'"H)pF=DNU's+Pu+LBgBBT1O.&9D#\eoVc^4?s&0Y9a)q\"Gfj. QVmE/;KXotog`$T5?@GY=*8.Wop8eRVc\(\9a4upKNMN&f3WUW?M4V2p(q(Z-XcX$@J2Wjp .&]f5A'Uc>m(-q/KdCb#Wm4-CNcmsp=F-SkA5>9D>+!IpBP^4(NP/ET_CEZG>EAU7s=W.GB [\DpQp,Wa@V,:6)=iV"TW@l=AO[lIeWklGR&fp(P;DmKD6gHKX2nFa%c>IL\02SG^"u=Vht 2XM0R'ups4lnf8fXhO8.Uoq"Knr#Eeg@P5.V2Gh>dq3,E`0>Bt^corh9s!)!NWGkoC)H.R1 L*^f!?Nj+u\0ZHS.+D&aI94qsAp M]VD$=duEQD>eOEC`b;WnmKBHQ(/fA9kR89[/C"4\e:9@Nt("t&+" #U!:Y?3=K)^Tp(JKHb2V)q\_f58$%mT/YM`p7]X?>gW%NV/RMScfBr?[ra,& ka681B09A]#Z/G1YNl/ta!5NOf#m7ui9FD$?&7c234N#!K6c)Zq-ORa&]JU'``;og6Q/iN; &B&Q&8JB%i9M6,>&S+lW`Y!T0(I_o?;IPohM:il>L7,i&V+D%SJ"3EVk$XXu)160=10g:q8 ^`Qk.EV.^V(50$]X9<6P/P"=R-'fM<#*k%b;)c?9[P`Ao5)r99p9td36m_@m5^HMa[B1r_WbrA Z@B_hU`c\h1>IOLLE86c`c#MP5/^\^s=)HE1h3WiN3g#/9g-V3O^%6VY6\u@dO!J_>4H[,p $:'bDOVg`[QsL_d@G$S`M;dTj)GD'3ju"/hES`^:j4Oo(OlRB,7?ZaM5#meXR7ZamT9^g8R HBp?D4);sZ.r9C7cnugB=\"qT]hgKNM5S4/s3!p>&KP%l'd?tW0F,M\VlodQ7K(QR&7KtiI na2Ch:.`;mPd051QuVRnh_&SB#@6S*lR[Q?4+cOh,CJ>NY[on/MB2^Mo\R$c2>f:D(S8r,3 =jEL_M)aRYjV/]/B[$,*qASF8VeoGnH2dI`t_:"/bU:K3Drk/i:KW*P0hT_L208<#E\M!E=F%O6(TgOGe+Y&-7-U/R1nS%;2MPQ-q-\''k1S:(4qWgMNJ`7K^a.(_K7h.36N 0a1hhp]Xu")MeJk8oDiR]73_'JC*94\B*(%;+]BK1^A,F-),H,75!WMYa,`.XOG^g7?pcQQ h`\dsfMTIk1,tP!.)rjsf`'O;_#)KUI16+Ul=+jEX0j-!f;H?E#>q2\%9+&QrZ--%a/^#]S )M/MIQ_Nq%jn-ABErod9de[>.Ure'pN,q5#=tk`)mMeO[I#g#A1WBiiP*9d#&7\[T%Jdl2; hf<4)9Y#&0u+YN6p_mRUH>B)coFTilCIOc4m03J(.&-hMh)-X"qg#]-d;Ha=p[L@WTubRkl (gknh*aU&OBAf#>nG1KFm,\UF:#>+d>*F&XkFDP_tW%)GNce3]9J:J7B%.hQBAYqB(>PE"8 /)ZVp0LVc;fM;i5si',#F`'b6p:<:<\a,tC_I@6LR>'iXC?;,Pk1WMn>i[Aq*8X%Q\cMkR^ 0L.LK.8!)*lS?B$o8^MO^F%)3f'K"_&+lR&0aPs2=!BW/HZf!/ZlKc>=iP`IAsTtKQI^oo3?-dY uj]]S[COqe?-Vc[oVAAgREJ,g+\X&9kM_Zqi,StULJ&*U=J&RR<.aqct(4u:Wh0\UEn\/)Mq2^Zr3TVNo+grs)e-pmfY8(O !'oVTm"WHBV15t_l%e6bb)?JV7%7'1j7_j'O_f.PgG\7F?7RtQsdj4"uQ]lHC*?9Xk2FH\R %^O)U&5`KP?Um["U-r),;-PeEN5lV9Gj,tFCiP>0"WfIQFj;`)3bLSBS?p4WO)amni%4i!8 \k'@K7bgjZOSP0fLq:P9*Uk6_ljRbt"Gg)S,kJkR7JA-%)h\3epUJ16=AGi( fV"Y$4Pg1_?Mu`7A,4>"hiG1%>/dIKOh$#XPsNK@&WoU+gZsOZ5VF>#2tfjXOfYj^SokL64un_A_YgT%BPc`H]@Jj#$n6n_0,Gl;o%f.Ft@( C8Foj7jmCuT[*f\!qn`*:?T;hKiYL\$W?0cStll&4B:4$80mBl>mpC>b@$N]HO#+;'#CBSd>nT1j^7NqR glfJ'%Q1Oufd.uQhl=!pi2[.9Q`Rr6!IDN0rYD15&E/5rXj0'=fV&l]h.dWg/`%$]oG6i Zh[pk@Xn5L#r84XUUM^.knM&m`1>r]SiC6]cJ`O5u5c-#CVQPgkmP>RfN3=inj:4TnnQcn_ 7STR-'L?EoDGoSYEu/SeWpZ2ijZ9HB^8rr0(p7osmVo8dOrR,q#;Mbejbd1%P$)d')PjAGJ Ujr/JE@"`l)pcGOhi",`9OVK>N"KQ0!aeY,jT%>?j6c#CHChN$u8VdnS]EhdI?\'5T.DJnk l)&j`KqYocS/L+HHIEZ4Lao2AAH_n?M'uk.^?to,dGp,-iUeJUeY)g)<*GGj,J]9KXA9gK5dm6V7Dl"m 9X!pr/.<:t.ZCr_1Ur.bt(Z?#(n%/E0[4=#BJ+(>Rb]*Ln_(9D?)?B9IT^2qmXq"j,)dqS2 YO_\@jXr=Ps$4"4!9O\UdL\\F!,r"_.!EdsA;I1F!Ab/cJ_h1d?6*Hb'F`\,keI\42ZqMV1 9`hqdjU6\5pnHK-]@sG@I!M!#/.kH*[05XiJJCiaYdNE*Rdn.U$s,P7O959)kiujs5H_J8HG.b<@T6?&MXq1(Em$(!F-8r ^_B'41DS_$p#.\aj^%*)1Nbi:[6PGbiZ#^t>Unbl!UU)BGrol."ef1W'[:"%5;WDs?SZa_F +6-QLLMF2%q)4nOIK`/E\--n)Sljj':35f5aV)5tDfB(eVTF;3=??CN29M?%.b=$]Ee6L'9g?I#rN Nj]D9n?ZPu:9kr_[.e`#ohRm=*tWF4Dc]Xih]RJD'd:""!DXRW2AC_EGBDY8MgB-3[VH[bH )AGpG@sT.UNT,bDGd&IU$`uP&Q%!kH^DEmGIAM8m-](;I(.@JpX&*>j;\2g@Famrp$[>[o( V+?Ate'$ToW6@oi?;4ACpR*fDC'jBH/1]'*5BRT]&u)'j%m_=6sX'\04sV,?WSH)NrQ$@$l OrWEQ^/K=.QaJ^=qcnQXHAKX1a\[M<%d'[2-^(;Wfe_,_0s^^ic;W Qe"f[9L]pD5TBGPudeqFVML(Ic!f=%)]GnE6Ho 4f-Z$8E,WMAi2^Z'&tmCR2_#feI;$acgngPH%&<+a?LC=;\lq'4Gu%G;#4>j-<$H9K)9V^7P!B:sj'GI12GG2Kjg(Bp2Se==I)V:OMmgj^^fm9)9SRL.i2^'K@DB&\fHl'Dif>"*W 7.\6j*J)b43`2_7M\oqL,;%"/pNsW/&e@6 (Sb1npbm'JTAB%\/SNe.=ulFJm,:.JY`6eQ!'BB)o1E93'DnZV@.'RLD']ipe@k*_-bhobg R@_Tu[qA%NF@i10A[S3q7tDordZELRMq\qJ74HbSp=[FKH,%=QUcXll6rNR4SO\qJ+KHX,@ `GTP+Tr?BF(nj8OS55[4-:)_VVUY!hKH;B4.nj)XciR[UVoB5\N.8>4@MkA(BL$H 5s?*Y]FnXf)`u+[+`nV\kEUDI]mJP3p?S#+jd$kL:B;jX=`'L.EH!i;Q\?h"+a4cI&TN1)Q s:#d@Gc)#O0H86,uf8pb430@ST?Nn8?mZ5QUeqRYJXMClM82:r'2--lQ$!7&ols*q9u'a/] D>RRG8UpX0%t6&/5.=)Z_W,JZ9=@4rPRXTUGiu]RS!`"3:.d)`eXWr/bV'!ZN%"Fk#m!ROc ?SneklC*YMXok4>Bp6-FY`bIU"Z7l#.5@Ea,@bdp[miNO-q,Hr0>VT4)29aFiEoH)uKW*5, )r9_fl:!XgQqJ8\:7edK4S^;\VWU*]d>-"ZLYL,KMr.+>C@AFCkJq>Bt%QH?V)TSpM9H8TP %Cf!YqUL9f"]#Te%0,6k?m'Y<)L0rE[u1-a2=]c'(2Q!G+S#lV]E^MYg8Sor+J"I\8$l*uR2kuV6+Rk@#?Sa[(4dL7)! O-:CQCX1[_$UA[X[-flJ&q"3oL2Q+`Fm$'9N#)Oe)H])jW^N'bQq-P*$^p$8FgcWo+i"]07 7IINT@K8f/^&(?)[6r\;'ZA/SgjQ(C.U>MHkRlb7XU^0r?&'MlJm+._k)k*IZWiKrPS0U`$"CY6(/=X)k]JK93NJ[PeG4E U[)\r)6s)%94Pt2J"FKb'>/+pq=kW>S]G&eaF;t4^>\IAC)WV'm^a)GJO^lj\]M=P\UM*T> bJKF1F$p%#9h$t4LrZ8'CgI_oE"(r3/-]@-1ZO7+7b!94`/cb1r)V;(M/7@@FuL2p"TL:oX t(ns%2kc%/Sq%&,cg]hd*g]Hl]%9Pu& kMOkWmrTLR`00J?*.2/Q2;;Na^DGWcO;Xf)*EsR>Aa*"L!Je&\D>Mf"bHaNZG'\L\+C"*C4 nsY:l'iA-PqZ[A+A3I3a&879XSooN4rpbS'P]R);P?+"MR/CQJ-a^T^I)3*OXW2I`H0/gMF >-q+@hV-TTumIn-KelZB`Z?I)udh>rVXG!j8f3F0I-l*5YsiV"Mj-PNbOf56!Xa_:lHb06EnBW %79R>1CceAoKs,,E<0<9'IC!c:7#s"=V\o\KO5TcdA17j`c8A,*(OT!&m_!&nWIsZ-E5lH8 CB&M,tTk&OXE_@I%)NVEg3UQb47Q]Eh93,].ZhK"N)rfF!Spb9_1[$2,/.&gG_juK]>'fEs _PhT>iUmEkt]7r(%XDkmgsfPSFKjd'Q4P78V"_#$)ZF\K#6[1n>pb;Y7@Q9%.n$3DEG["[> j_eKmR\e9'p:72_k7$>%bqI9frUF`?_JO+_595`u=s(ebjD@4l:s2B@K\=S<=F9H&WLU39\ JI@Y%TG*T+Ag@hAJCKi^Y[r5JP"hSa.pCVpiS[50AF^93&gNQBSRB1TH"Ym5T'S`S.:RWP# 3bK$-iL>@*=:PRg@(8Z4Kja%W*)E",3E0m*31_FR@edAfMW8s$3K7OZ#!\4hKaCFi=V`VgP \#"r>Er;Y\OLC?=f'60>^=>)SEBXuH_+B\M<]NFqBh)HT82*3D]<8M\nu/mI\!EPHBtV1lM @B_X(scY\$'RO#.q,*q\IA\D#5:&XII7]hkKN8L?#g^H`$,@DYqHF]l/8[qnGf0n^_@hB0h \Zn@Usp`,U0+)oV:EB-G<94JsRMEa6X8bjt\`43hpFha>_0kL&O9:.JI&?)=*$?.UC9LKiF (rKh,`sA[V@s Cb(88Sh[]K(b/mN4fpJIc2u5DW/P,"-[2&n3[iM%M?f7+e1H,*:e!i[*!kGG!:a> h3eK$\RhEmACW43)5o:td'[.$<-rJdbH]d0;$f=G%=.T_0B65^UMlTbkU`5+oJa8a0+XV0& T#;XqVV:jOcM$N;C]M4"Y&Fq"/7mIa;0hc9;Kkr#DKUH&V:C3 X#t'@@">_hRo20o%lIPej_pf*4KDO?Mi]/DjBq.Qe)$\!U)O5["# iQqYs"Mqg^@!!Pj^TGn&_qS0;#3*5blW9.=A(??R"!(fL`L>VUs%eeZ/jB+En54buZ8i#'< t>K`AKpMim<`L*hF@]Wu4T-O)ZYNHg6Hu4m`XujZ@e7]);GVoT%72l9O-OmlJ(#X`RJO>)N "nBq^KCgA1OG>>Q4KAc32>:CopjJ3]nhl2)cPA-&)8fRO'B5gSJN0+Y>K1km/I*MWa=O0Rj%Zn:_f")q^^h(bLs%"j^HG"Cln.B #)sToe:o5D.'BWau[@PT$o]OH>ST23b)kEjet?r'^+r&BtkUA60!U>5&6rZ4N3=@n]%H0hP -\RQEE@D#'p6[Y\Q469qtRXg'bWbhFd>s)/.iAg##?^7@__FREkoALE0&h4(TjcWTd$bs6X e,3F>mH2kT,$,*#H)M2o!P]J74&#+F^K2FGCGn2bO'\kL!;<-KNBaC(B")>0k%PLJbf,@mP>ge$:U KR,k3JVf!*$RLPR?QR&qn[JZuR'>hFT'Y!cBX)L!K:=W =-kDP)!]?.Ep)@G3n+5C6-mq(@]tmQJSBmiB:SEXjF\di,H^5.8AL>/O`g%o2ng`jkFWQ_sD%HdD,.\%;;Tn)$!2C=:/ `/+u1Dj*Z?=npXZFbJWOcN58SmF67fF?WZN@I.fTj=K3IKlJ" 3W72X"1uk&YU^@^0*.\.!CB%DMC27UY4!M4$'^,'JlO!_)rGuC_f<_)md0B5+ENWRF-eOE/ &0=6.n!un9TiIBa85#el0o*hq#>?(#_C[V!;DfFC2&%N,Lb"4q4bB/'202ebgb/ pUB*8J\[B),@Ubam7>X*MfL58Y1cr^CFrgpoGKtp>>9KP.#4=3%d[Zis6KKci75RR9p"GfG mbABX06RLi3KoeTR+C6uWF2X#.-Y%?JPY/E"H4;BLNEBBen2uE:I74NkVt`B,aBc:A<&am: -rYc.,ZdEN"[lTau\tMX*gj ;*KHog>:8%DM"J4$pU^q11\"1_XJ4G+Br?5LgDTLe)oM(9hVgI!%J"d4HQk/O4 C]\8R,^h7R-14H,FcKTe!]'8D^p4QF[X>aH;S98*(V4U]\/@@',5ejtaiaIJe=^h!_sGY#F 3#IE=$jJ,sJ5i9H4,X,Ql7A`%gfR#,"55: ht_<.Yd.RK*ZH"-oZoP6A+V59\V)5e)d9*H\Y^A#A@iU_Z7M0(!TDg9iMs(>h;\c2*mJ19+ 9L[cub"Ucf7:5Vi%TL&]j1:= LU[B)4.OH>57Bn[+8KqLS%fUFTTFTp]%6b?o*D"\3`4i?pf6k&n/qIkT`81(BSceLnrF@?T $5m.Hu`.\7O70<`.8jp&j7)]?hK6]lC5_I-^71t,IU4*3k4K'3K:u#$[$AHHGK$b#=.!('& -rNLI'LfdF;aTg7>54>XjpDdN'JkMj_,VS%5kq7 b&d)'Q?P_-rPIB#(Ua:K]#b?jJrQ5X!4l>$`>LRWQ1NS\u^;"jYKge1e64rK8RQ;'S)HjJh 0TJX?sl/U;ke(gP:iol,)D24*%.bh]CqnP<-_E9Wm)I0),]TGc9a[nWd(`5[Xo&2 1=QIO-E<8h;:]Q@+$>R(7He88A]?!>B^>ZJ>9L6-Q `N5U9/!-D.TL=49jVN=WNY:'Q56JctJY4eB'kO%WIAL>Z+G HsjSVCsr^8S2Mp_t:]`Q-;"2p[O:g?ZJ/52tK:.3acd&^+!@Xpm!%8cH&-qf+g'NeSDn3rM !.+K%lD8+Ck>U]MUd:i4W87Ku3)pu(4;6@htnHVqa*o)_r>aZ')M%ii&bXS%p7]9W_]PZI& -;n)d;K^DcNRH7;,DM;$a$#UACAJmIsT1:73Ppe&>1cI%4Mk;r>jt/pMVrY^T-QAd:SBh]5tP[KBni"BDsZD?jQu#X0 Y[L8\D2=YL@ARR\g3-(lCLthOW`k[fjNXZY!(_c;X]inaN?DA_0Z70*<* KJrcqO^K2HJQp9uPb6"kSq:2!g; >U`S=4%7P2[9Q,m4-CH3EY7XZIceKVPfRSm-3>m8Vg,];ErFBq@XdWO)$-9#R_^PCc0PK7e o4k`g<0jVU^djX\7*[n+)knGcl_=<+Z6ZU=5ZDt0QI:E3JTjcKDm:&IQ1I9G(uAg@l> pur[r#9a)$biU&He3SuU'aI#!N"C2V3 O-$>lqHP-I>'C/bAL!WTUXS685VrYilmN,)?.'A9n87`!&:[#EE!(d=O6\JBYAPKArW6&6b =74:*cul_BGWiO=>2+4)d*9,Jj+(_/?fgm1gXKD=7DEbiA++g]An50M]8GaBBlD:1gf5?V^ AhfjC_7LT"U8jLc>KWpV$5uRk9gI>%Wbo?#\RKN'"DZ3?I&&N\5Lj0&5Yh"mFuUY1#:E2kP a<.-PH]'2Zt[^?6"NLBibjA]F<00(``[?tL(+AhNgrO,IUE_,5AeL"'IJ`r5](VJko'DuTh5+@h+p+QiE`&\)- MOAY0W#C2>Mq3H*b=.=/iS#WE%LJ??C(S;@hfNjUB"CPPK`dM.4IW7"QqHp()jF;/Y_!!t8 nVuS@87oJ<[['].ER1e.dcZA20&US5e38kH3-0it=n=:$Rg12&+!l8RL+Tf,BihldKh[61: BnQ`8Z@s=T.G?hY1)3)lS6qTQ>m=Ck`Tfr7T#2T3HdE>^m8gZ_(NNkOWGS/-k2 hI(/egn99W.@/f6IU_dY:?IGX%;ZZ?$J)=uuBP@_R%$9%,Pi.X:/05N4L-d'1\9p0@Rl*2E ME%tP0,]d>j2s;"5sF"(SD+CGCn=QRPtP\Oq-:p=i)q2YMre4#F#]^dB9W/I#(8h2;!;f)d [e=>4AtFNb&p1I;lA/\NlkmQLdVmO"F=9ao=<*9"S/u_*`ne95+>EMeSB :grB]Z<\jN&)RpEb_EP(%FG<>Huq+@hV-TIW60-?J$k&NK;[,R2PTLPU(W3dJ4Z.eR(&L:qS^q_iXdZ&Atam5Z\QZ$#i.nV;,&d7<*-P(WKgOf$1aBgXaokDVR/K`GCrSdG[4D='aK:T-rUmEh6p3 U33"QftqYC7d7=/hm__GJD_7bs+9022@5#p=AB`e@&3DZ6kb;m-&Q/VXtbjp=LL5Kj1*r/N tXr*XAbBRk"V(Nq+b(Xjk3[CQKC2VAX_bLGrefl,[iO6(G3b+gj 4F;W+jtGWN#1)\Y=8nBD(#^ldK:HG9*&W*O9M6DU5WU)d_('m5odM\8Bu/C2Y&(iV\/jqqh ._n([jC_!kSN$,Z2e57tj(>S6g\*p6+Z<1O4b:W`1?V_--a*8`Epo3D#Mch(KR8^MS8+&C> X*FDgtof[e,;k57L=FVEJgr=]4B.>s%GMV_H3`HX?0Wn+Xj?Skbb$E8m328VbjirL\Skq#0*:iVEK1W_dJq6ReTh#B0;8^ZY[ui "Q?F0HL9\L^aDnA.*t8.L8;l,6*CMrYg@k,nUD>6X\RZK@"cQ&5gA%"P_ZLU6'L,iG^o7=O \E;fQJSg\=Elgq]A2TF:FAb1e!n=LX*IQ]*B`D78SUU_K7h,G`raa<)&434se/bSJ7fO;i8 t'/4E+;(#n"OMiiHA7Mr`S`t5Ed0a9I&#h9K]A8.%+E-[HeT]5"-FcOl+4@atn49m]\O3t) Z%KSU3LB^5QcS++6:qAPB(hC8bke&V'Mb!ZAqjU Oe*Zrllh#NE`bs)*(7lKi?KS+Bo4(@/Ao[*IZj[&%RFtY$8Fu:`=c]T=d(S_5tWZ(JnRjRU fZ]Kd@,c6?AT<9>Dlp(S&M$sM6U$A9'G'9Zp3LiB5>`M_bQNcqfii5/ Xq6228tt:_R.V_oTGKLAlhPPC.6X$,\d$6ASJ0RO\LXSJ&dJ;4^B:G\GdjUQg.)*b3QDW?L Z)a08O%6g0*J<@t&3]`lk'>th5Kpd(iA&L(D$:2/]5VmPla+u(&c"hHEXW6V/;OZG,uOJ13n3,DM"r,;Cj1ouN]G-&Zl@98gc$a*ghl(g@KTJhZ3u?+mNo]Z[gYfb!M [i,S^"^34e(6mU_^ FQIpWU@I-@;0bu(RR%FuMS5"mG7OuHrChX4gZ7JAM^;eLY?t5.6NcF2CIo#V?_(:;%E[2=> faf=g=9(1qpd^V&5$6nQA4.R\-,lZbEt*\$4,4Zi*i$AcO4!_d;_r\@K>;A`ERHV]SDnA'VXB3bOuMT!QF`ce8"<7Tduj1a[1g\[ioDTpdL<2@%X`5=f0:r&Wg!LsYS$5t FQpVW=&6P+$GfaRQ8P!aM\Rd[sK2SPQ8n9W/l(&16KjAX#_:[)931D@;R-NqM?b)^;@B%\\ +rAlcm\@kC((9;q0?'Pjl[>;,p-.Bfqk&B,INQ1Y `=Uf?iV-[=gi`Jn=7,r>cQD5/jc[BU8cIVn,7P4Z&@J*.erTb0!Y3AV`-:E?Kct7R+j_+Cn fEA1*MKDJ&!m$mhTegqc]Bd*n1b!k1BW^t"3?SN:aH6?R07.`*l6>FYD!-VVWnRio/AXRa@6PCA:)@cY0$V,c9u,P'jIN%Wh'qRumEhHB1>Sr (&"rb06#the#2Xu+hWbg4E>&ok)W1''32'Fc5roYD0]=KE'%&3C"2^j/*>=<&'*3%k6$aGe 1uf')'[]Pg$=`%u6KE,j'p2h`KJ_c.;WUN87EV!sb+Rm7@2G&LWfCoY/pS:2K,BVp8g1G30 Nf8jQ>n7[:Vk6e6$=3MUDf/c;=:=IDQt-5[2VuT)hgZlTpuS8*:+t`%fmHOdF.C/dL[QG)< #i4DbV9MiuWoW*.ci-03#?[?FD@r[]=<>O)H-r#&T9InLkb&ne1J).h+eKo+*DD1*Ii7QkE ge)Xf[2$adOCPoaj:*jRjQ"hknk`#`oc9d,lE!R2aM"SU8F-.5u+Y5KWoB-rdW-IQf["k4Q S+U0Vl-dX4gZ@I)=?lQR_2]3bK)"gc"&f.$ZN11""#,oCc EKY`o(b!r()66Z(D:dE'-_EeC*,ai)1bjD9H+1TD[*Fc1XKeG@'1B_rWc8J#Z-(/do+^?#R W?=/PqUrVm79CNY3pm%FV?V+i5"G'aitq$gF`/:ro,Xg_8Wl'7igk_/U 91h[XVc3mGbVd.'1oofJ/ah:'(R_#+]dD\.d,4N[U7mJ/nB'K4>Ui%=ph6`<&n1D9*l5)ME 8DBV5>*ZH8A)?IYgnOYuF"$hl$'ld^ue.EH1&uYgL'EN7jb)GGb?Ph"%(UPb1nV\6(NC.eL (bq-p1F5Fg7SLtW*s!'PEN62SXQiFR)pu,a'OO=,^9>?1<#*'*199&i 0(,1hb3$,P9kao\h$gO;e5X1',B9@H0un@7p1f:NZGA_;l\(nO/WM:t6(R'bYL[//rXd;:? C[nq;(XbSe5m/_)L(2)-Pf1K0Pt;q3`*J\W+R+#ah=<3iu4ePZj^].A)///;GA80f)Rns,m T27$XA201XjVZ:j#H=92[_.X;ZWYQ`.)SoqnJ[-'LmMk,2&E1PE5qX/9OqcFjc7"T)dfirS $X7b[>E&M8'd[&6+OHhU*b]%\-(2CbDB&g82&Tfs(i1_cWQ(: 5RGe#R%VkV1Jl4-9&G&GD_-rB(0M1m&/.p2N5Ofk6E_hp^HpnKSZ]1HsBJ5.6M9j0Ls+q%K c%($"IBZj.=(UM>H!6.?c-,6.o) "f5?_<'1%WuZrM$AY=6rT7W`-Yf)ls<>#k+77l5E1G7s97J.f\9)aSE\U")^Kj`6UF>2b]O $iM/_@(&^A[abCSpHq`r)bX/BFOCnGju6fOT1l^u9UB(rVK-6OI7LL\TnE ubL^eSHJ^o[0JZKVpgt*\G0#8MIiK5d;[9Dq[>P5[_'t]-$5;3hiHT/Ef#@bpYNI#hR7"P% Q_;]J9;2"*a?;iq@($a9lW"4E>?dhl.(&Ne1S.G[D)Slka=9g_hL*Rp),_Aa>PuQAni#Q6R 'ilVi\?OX%04S$=A!jir_/L#=XZ:qT'-Tm\!F]h';e;7r3q2F*p0Tn)@b'uD4:q?Fancfpb E%bo%j?!+)$<$Cgu),ji3nh`(6+FYa_>pfBq\??J\,[*V375nj)bfI(:e3`18ku%63LpfA9 X#Y7mdc#(`(kk(>kBSJf@#-6o\J<%3QDeW#`\o(W!k)FB:o?"`O3`Q^N;%WtM[]$s"M?%(--i8&r-$[m6FUY$*Q)EX`U5GUV%HiZ3SkL5;In"k6oI^eou\+`oAAq;?[#@XVD+ I@VIGDSX,JD*DO5roplOb*9HJf9]Kg67)=Xqm\m)o6b1[@e/q-X*ho0A&js(dk>`8#o1kK\ @lL=t4\hfH7s(DL*>*%tkt>X;AIcLA5no($q%`Se&VbL\QS,)X`jkW">D?Vm#u*VoG&Lq@= KM.j;P@+TmX'.C!`T$[BFl(qm4W_@e"/S"W4`JQJ)'fo>kj3j$ScHUEfqlXkD349K+1=Sl_ \#ESZaB%t%llSO,H*R9bTsp[W(SGmMS9`A%4/G G+a;BVn=L]UciPld%6);(`akB8-*1P)5T#@^>)batMg0)U(ZMcgmVOD#=)J7*MSZht7M*0* 9N3168TbJXHW4_#e*9!l%O+LfK(BF.JiI2AibS\/]_4%R.]"-0k\'UDRX8IUk(eu-'ar6dk dEN^S!SeYuglQc%Y$0hI!O<5-/sA?hLcmo).6&4(!XIG(KA-GINGo[6s3$S2*+8u-t( ap63Z8f\Op,Ei(+gSu/'L=De];@3EWK"TLZb&N1Gj*scm:MoX1XQ47)mE)7Q*J?fddqjf@dbr$B2tb.*@m\U6'$IWE"T.N7)(9j-`A>Y"!ZEZ1Xh,dMG2_=5/9 @Hj@jl-]VR!UE=K$0n+_lIVmS!OJo/*4PAt?@R94n(bf\iM7!WLXb2hbh@R6-[dTJ.F)9>c9EDrIj8)]l`&hM*+ =V+6')ej44$+ud!n.L&2DQ2\a/`1*C684$W:nLYP!dsdUA^_3)?[T0D:Sje6n]o+*5p2G*E p?ei_0AgB3U)&(RtmfKi*[GdGtj*1>P/f0>i&!hIqb*"mfg%<1(Yl,hSI4kS5gN]iZ76S1C USNHoO%mb3C;p3mcXgS2_&Ar;r_#>'S_:u`jgZh)[=WK_8EZ-b8\3^20C,fTt8/rBW#DGI; OI0i:*>+)qiJY-+9k^J,7UpG:jF068Nl^8o8JIIf-^@9"OnD>[T!;D!Q)h;RV0P"ic6lQDj Sj?hT2;I#3].\7]i_[JoX\lpSPc=bl1J5F>,bT*;`#"Bsh.3QJ6PriG lD5m[%.chXPm)?LO2hoD/Df=1$e^jn!m1\SbkrGcYLA'SBFE%d<%u="fl`B(K0\c@7jIcY. Eh4Z83qV:=c&>,-ZmQu,0qp.Vg8/XUoTZZfWuhY2T9iGZ2]`aVYWg#R1a.FmI(HI6nXH@7E D?`i#HpA5lUf6>'gnTVX;+"r]!f5\JVY?0KC]^U-Mh!RV3H+("r[_H1qg\Ut8n.Ya%5VO_o "$nV/(B_LX<#l0/n<>.)64gLF:EW%k3+g'Ilo>SE0a'uW`3C"N&k)7h84=2hED0?$AN<_-7 WGMD)b2X$G8nT-e9rB.ne?]p'*S-67M=jZP9n=KA=k5A123[[P\.hX/3OWpcRqjGm'eWA1B b-rRcf"o1efLT!.U=>q7?sMn>tY2:33f(4AN6,ml`qUM:Qdn<##X):p`(j6r>d@(Ih9/FWX .P1mKDoT*KqkF;ZAf1JQ=tjZcO?2!me0<0\1k<)iNj9ib7OD-'e>22,[Ef!Qs4>7SZP@Pub I=g2.ka!%BYfQJj'@p(]YQXe^WJ:NDAS(;3//f9ijb:+M IQA3(2K.%.@rX,Gm6^!jEWXVP[p1_:R1$%Am^m:3Gqf0O(&-m6OJRQ$7Y.`mWkF<3X1A3kd hOhU1jC(PGW%4.E#g3GNJLHgI@T!C_l'-IBHY?mTq0kcf7+o FW&8(Gn3c=i?n\&kQk5W-a48/ooE-sSP`,M5J&&n'$B-5074DuQd($&)#>?7972pHEVcTf] SB1\IjT1>U08p*9u=4VN-Emf9(`ihb`F4B0a:6.lkoIKZams3f84pQl#pq@Q(iciD(r#qK' pi5JC*e0sMH@E?"m!?ClYO-\NkJ-D>#)NC)BmP!Jo,C*Me8Q8CJ[/:8f\S@ZIX#k@OEH r^2rlhl7Z"opnIrrHLA#(VdV"[JFL3lTID*(!1Y5o:sPTVNBUct3X$\1n42e/a2RIM"m08I .]![M"0_;[QrP;9C.;-t4/bMua2."r&qLnCejL\9/'33jStjlTK*:?RVbcu[l5ZCi1*CU6V]J2PQIpqN^UgPkd;/#$''qkUSo r&aRCc+noKhblodh*llAFZE/irTT.+f-VA-J+de[NLBqbDk,>f2MMKqt]ngULOob%T$9K!M %5cGJ>V'JZs;\?7*'Ot]&,s%r(;Nb$PoQ%'2]"(:Fm9?X3FC,J#g-3R:Cn.LfAr`"u9rX\% XjtF\f*^Z17F`oj2W(ID'cZuG37O`V=6GK(lj'hB& PsYLN%,Wa10_JiN^rtbaF)>\bASV>s"_'RA`:f_@S-0L77qdN_9*R,T.g(4B\JH!<%M<@u?sEu\).+s\bd3WXoF?HaNY?"e`L1-eB $?[7%LFi]01A^ARI`3p6RZXZU(2Cmg#aDEBSR1/HrAgX.%77H0O*Q,g4NE SY,Bb:(_,Kt>[)I,X"0_uhZ\9ST/k>2PS"X,/(Q'3,]8q>h?HBice[hN2m!,;qr`<&!9bWHFTsaG,)4II#t#1#&(\>99+,aH /d?"SX>PWehRV6apL !8-LTr9ol8f-p/&Jup[:)8Pg/Xg*(a;F:FpNh`Q+.nbqpt/Q'A?"JFCr3CD&&/>MBUhk'Fu(?SmQX6G$[Vn/3WBEsWD2+/9VaVU! ,q]BP=g25sB4n*HN+[S'*TPqPo#5NX.l"1-USdL*08qaC4&r(Xs$"HM!Z_9,k+&H_lid1je S/M&bpY5TfGOW*N*SUC7kPWVYFGuni43#(N*ojVHQE))6dE^ `hP=^cd:%+@&jK^fqqsF9[JU5lrjrY8Zd4QpcO9cbRufLG2s9dk.ll&A\J]ZLS3mHSiQ+1d P%t5ti%:OE#r@4GR$>K]lcsEYc+,CPCe01W)AloH(j75-t\a66m_k)acGm,d^/q"40/adn% ?.8Y]cfKu6R#Z8n]D>6E;=2&n6V$W=B:=$mZU_]r4"-rW!TLcA%2,m[;#k\[a1?T$n)_j!4 "Md\M2@RJUS_q:6NqI$0>B>bHr2Mu%]e3h'r7(1Q_2ZuUgA4O*7WeU@g^W]hdp'N:pF3s9>KNLGKZ_h#MU.*P+P2KW#G]a1?A VVs9L+$tnOC*aX7KqFZ"]/rgbH&X8W^_oI7[.YLZ]r"JCq4(n3HLI=BMXA0S2mpG`uK-"3( F+eC:WtZWjsWKjEJSeGX^ADLBr#-]M"/jHjASY"do3WS:APcJ4?;r37)k>`.Q-!KZI,HaC) `;n9tVqd=l*15=;m#Ul3=!9a96U"8h#1O>[=Wj1WXX]TeT$)UJ^cD[!C6/Pp`uE,>i!EJ>, 9KfkR@[$""lgkQGR"P@MoBK3f^cq5"Fas59Gj3bP6UqJU]4[GKjJWPVZ5_<5J8u(-(PcMKU ge#GdQ=t.?!'rd^ik?\BYFFRd9BEm([*(kFJl$-6\0hKZ9EN"G"OJn.kYA>an%TRMbLF8@* 5A!_o#T%4bTr&N87mQ`G_Z!)#LIfH"GY-RaK,)a#FK[*_9]n"!R0$o9]>#dTK[rq#0dhd9d Btg.HlM25_7j/">m1uBPX$oBS4YRL581u7&%gAKndZL"+gE)<"_J2'$^pETK=hnCu`?:j?[ nLLHnc@X(R.UP@[1"]G'`,]C6,Ph`__hA1*0mmYKWnZBUcLl&"OKR@_lPsfm0CPj#`1WS$'StT N'Xn+%(:C_6o7>-V%:L:BuGs#;&i,(,&Oe-E(lN3d9s?ed^-CaFf/tu`;EHN,ZI2i)q!1U` A$,#E'k(mJAlke`J#MG6oID0paDYX;Ik$5(g@2`F9P3G#7sT6&8d)>?:Rt+`_e&1jCO#NAq msL;^?nB1kF+,CQR%`;e0aoFDd30;2%8P7hn)*,s*SA8VH#;7q81?o:]'(H.3QUe/9imQuE :q'o!9?#7WN>FYhNpJVGk"#:1/8[7f#g9[qJA#EWl:<5Hel:t5_HSB@R[TK#RMDMAuqaj!l /j]<8>Gm@/Z'SsMZi-W*jG_\YF8QAkmoiK6XEJB9G#1-J)XP?iEUJ9!Ec,?DM?"_;sBZa.c "8F+`XOgLlCY$/#8MslZ(i]b):'Re\b9X@E1pJ^0ZV+6Z94`7tF61,_k_-dDKZGeNfM)HHm *#UI9BCTRomY+!_UTr0'k5&aUU#WrEX1]#fO]f%E-?u/>hC2tbfnAVg]G^XB7o[qboG27oo @]+n-5OOb+,LN%+^/h4ou=Yc)f[Nc\1mm>nYqH '@A\ZMPtKLH`bqCbeLZ8d=b$ncsm;,)Rl7XdDaPi-.C9"bQEA_dKjE:cpbp=,$g;i`ML+4@ thF.LX[X+P2'D6"CXbF@n&m>hBai'p#FmWC'<1")bik0FYmEQ8B.09;ggRQL$L2o9a)q\;o S1R^$h*I9SEU[\cqZRnKq3=6Jkf"?X-j".5T20CkltQhNd<^[HL-u=pFJ57*'i4ec4P3!8n Sb#M=A.MtMcmM:`jQfG4[UiGf"NEe@J0Kr?ts(f=<3DW'(SQ[jI=WBd?iQH=NAL(`/C7LiJ m'G`Z*#2i\fjd9J1Qf43A@@PX]ok@H[VI@l?L6+TN*Gnq;+P+g]0-R:Q;5o;k?%^]7@V'VL rH21Z.+`&[f7#2B?t]\I-Hh@YK[;H.kY;56IcD/l@jQW>+j47o#=u2p5B'tb_/QJ#qVWDTj .No;\93Q"1nD24fZ$,-\`*h/4T_9g"9jk25""Bh7'Zq$JclE%=]^u]]r,FqVP4Leg7DL%Osr^dX3W"[>4hMlqbX &L>(cB1>=GmE^14Pj0O%jpgNI15A[p/`BXO40#"hfuena$cCtmTng[2dgotQ?#$8u9t:qa` m`cKoe`+_Gi\0Z4B@Gpg#Lh*oe+-A08MJZ()L KOrg"FX(1pBgZE8hdo,PKdfor.oO>$iU)Un:(\aH3[/Mh[2'Zq*92aBdooog3=t"5#`j/n4<>A8k:TAo@n.IV1Na:$@oMN_ !(Q(iEsBD.^fsV*8e["i":L?sFcGnKr<^-s"^_ph+Jf-AHa-QP\hG(lJB6#DLB=h]&+oHfs 71;3H,NL4O"s+QtI%kWmV+mY-Y/L=.[,`LdKCZAC!,TW7Kf#(Uj9#]g.d@gQ_^FL<*X&`l[OB<#5KnN,gdi'iLA!WS?f1hfi8=Tb/216$Dr^Km[YHhQ"WGR-Y1j*">Pp_aIic!/fdLLu%VA]ha/I[])Ik^YB" /QIY1#mQ!tiD>nP+rq&H_dX1#MKl)F8s5q]W6B-B*KWc:;>D2d8LK]o8PK>m4fk&([Spe(l ?)1F:7WaGWQadY4ePS!;u.L=M+===BXB-"]b9O>WTk3JND?TUXApcNHJN2D?a!L9/@AEm\A Wd-*:Nc9[bYl3>]*V)V:P$X]O#MX]B/bbJ&#H2=?IoH%=Wai?I"j7VSQQZA*]-Xl05R$/*6 @_N7N25T?ZS@g*>9VS:;Qc:ZIF8ZWF9]C\Cs!VT3JYgMV3S]tX5`X?[8!aAS?5VUe'J=pL2 M4RbGqF?0:8MAVH-nlH6,Wn=g,R4Ce&3L[06'+bZ"i8QE+UO27)(%J:ARRQBQUQQf%n!T!5$\oM!E*5OUt3TZ94;90$FL'qE1)hYju*odmVM=Nap1W2NK0RfK>M\Pg2D8PJM<':Qs$$4jW`I#X=TM=U% f$e3sm9d?IoW78ah:,=g0]XXQokFFbK.(W;_VCt$o<5>]jp*DKBM,dD6((WN/dEKUeDqh`) ]l98@BiQ!=d>cUth%sqYG?pP`e6\FfWS`$YpU0O>hcK4:J)?UsrIEgn*Y![/(b+<^*XBk!L Z0/2-&LWKXt>O&VpYBqA!c^lBq;&>HuG*X@B_hU`cb4EAN=(&QKB&sAXDP)NbP!Fg!4B(k8 EE)T'.%_n4/o,E=?E>,[$Ku&Z0H6VeN_kV5W[JL7C^NPq>k8CR$n@?5plJU3:?W-HEFZ)a; bp(P[Ll=;ba+7UmD@TmgeiL"WH7F1US%nY7Bh+p\ooc7[E:K=2V3+hkiVe=`X*PZaOGFd',h=ob:J`3#m WC1Hbj\`SLq0lD5kPS2P68d5e8L]c54B#AIY?,O;oJF84E_=c1UA/4I(^(Lk2X+%+Hi_=@:aa11ga,Cjuu;33f X^oWIaE]Q]Mm2.$tiYeJ(C^SPKGpEFQO@PU'8/VdXj>;^U&hZPmfbGa-@+Q)YPj$4fV^9WQ R?H!59M)cX-Vep53TEq$KX6Xe`$r`l187c@fi]ie>d9RBb#h:sD(T>;[$F(8AdQ!9*Fm%&Q fF$0,SXYconeKcA%9*E)0-3CF''4H]cL@UF(k<.uX;l Xq7Z>rl9HoR]ohKhNie2,'oo,L+_I[I(W5Ni7OTMuDQ(]iPQ`Z."47:aOY@mF_kKb'nILs- (YR7X`a'JEapY5#K>bbh^"nLl 4u;'=f#LnU*^-TKO.KaI'Fj$kA66s:T0):e=Y9X6a8M4-L/#fn5:O$O^jk"N_YL=ko7\SF*8gteIkL2kLAcSlB^p-)+dWhFLbH0;j=T6(9bcp^WG$_[SWAm @S>_TXou0r-3E'Z&3r"%m8J/#;gE>9+r-=m&7,5E&G**^d#D%`,q6+],#a3b)2Z$&Bu6d'4 (fc:D_VBs$W[\^oL#>\gRu,c%6/V6mRuP2UcaEqE^!/QKEs[Y61?%6G rJChmkKo6BN>?-eh9H\53Go>Sl>W::+?]DW7[e,Q*sgAULtj!/Z5'U*eR:ib@;69&E80s,*S-!"*%HIt8 ptng9'!;*:Y])(.nfBJo+(=HX0Uibr8JJ01J)P5XBNjE\-KB)M(#Z55+T;WV72E%!(=#Vj" )Ji?oEE("%fgGTkq_B4aV^u_)kgRKc?AC=HPpgn5H]V%mY;]uN>dHu*2,>'Y;5]eT'@t#)r tPpWkRdR`uLe+lY=f4n^ALeWpD@ZXqBNm^uA&UfWVI4*msKElO<3$q&aA`n$2r^Op(5/#4M #Q+R]G3iCXqQ\FD3i+n?Wt0,dm;*qE2[ng1*?$Y6](D&[LXo1kYf5u\Z(7jP9,,j!tVcYW8 m;^HHh@,]2_*n l2P;on*3:0lk!U)+V?8/)H+$o$1@G2Xe9G`9()So-.!Ce$%FqAW/%!06Ho>MQq`fQ;,%]2Q"2,uRrH10IRsG$lK >-<*Q:127jrn@OrV\Y2]j+UEH.P?+uK>k6o-o(t'tfe8NZ&g9LY; Zg?I$!rR4&`f'/\R)$M2]N8`2&JQkQ"=%1^lU1(,6J=T1%D+9jPF+KVfTP6oH;08-q)8P_H0ngI1R1#_:( I:D[OdgN9QZe#;8^sS/&Z"VV`Y*gs*J%`8[4GR6C))lE;oRKaoYl)t_FSdj9_Y5S`2QHciu R(KY$gKgpTbT-oG.AQUQuih3;AimS(BLFWLA+7D6:r!+YF)C^'cb ?-F>-5mJ89\B6#.t*[/6862$:@4e9.=bT!l3+k;4 $IG([A@Dmipkj(P,[(!Q+F&!MhcgX6%H%3_P#?ORtCrJ_1pD3&2NL+XVKlXlrG"!V(d\csZ NU*<_lNdX`fK7>*WlYIaf`i;O>ISV8hl&#Pe0+dNV3'H&%d=kIYJ>9gFuF0^@[%j>$mZGaU ;^U(G,Ze14U@5&PB4c`_8M>L#T/4#.QX,:+e[ARUMiCk1-].gj3a!!8R/;]=l(QA.>NOsbN qh8E$L`2uC3ME(+]2,taJ#iQs%*eD`Y+iY;V*#jH6%iJlCS-?\j#n0sTC-3&k!N6PpR@ (O?CRcQar$48TO1j<')khutqob-:$(Dg5_qD62r']>kiYk*:38lV#_6t"BeSdd@DtGe'+_V pjcl4SO+.MN84EQ3Ap`ADV*'5)?m>KEs&1uNYO\cKoXPSo#L#2t^U!*,]$9;'m/%_tn P5]kZQ=hpfN4TQ"d[r'?8.2i3jaa)BD-.Xk\-P-6O?(0@iS^Y2lK]@B$HdM6K.$KOFop)[ fb;ReZ^j&Qic[+d0Q*NXaqU(r4u>iJk/!\[&o^Z<2,Y+_2Jf6eo:>h!?@#6%QDT;;JjPh:k r;R&Aef?f$Q]GfPr)qet@j#lnnS!>rqff\*c]KA_1eb&ArD1K5?FjrRgciVT,(-Sc_dn/iZ nir1[m2DQ=j*P:(m;PNBF5NfYNI%t*1\dN=U"(YR6jQ5%O^e!d-05G7Q &5pH01X'3&a?!7&S[.A'J(*-]Y5@&hDf@Sp'r8HKQI;eT3fIm9^*nol0?%B$o4+mKkrqcZp 4cU*4-lO$9+:Q`A/XCNJ16+n[6,=&O2kcVcpl%NbDaUdiMKV[*2]@]Hj3ee2N^4qM*E=Yt6 K+f#?*u!-$%0a,1Rh(9'3WQ9FZl];o(f5?:,?b=$[p%ZF1Y\\(L,/@omOP]mqgK_H(Lp62_`mC4sq5+a'u =kgl=TFQ,fj=%CBSN@@YU*F;a_^NNg*0]/86$5,VPaf4q`4h2]6][G#KkH_%V2EP(+HGT-l t`Us2jEVUTG="fudkB$J?*g[oL=Xn,rgc+,@u)FI>Qhct&C1<#GkUY_4))6-uDP$Gpbh1CQWi]K6Qid,[D'6 >#J*5oQSUf+^YN9NN$!Z%Q6t7IcmGCDMPBaCu>9+fJ8YZ2B"m89,E&+NX+!OX!FQA="Z8;M :Mfamt[ZF;neM"YEAfiVn?5m[CKsq`eU(QQp#Ua3=>gK(AeT3dWF\\FAWp`Jk1P,H7[Bi[Ce8MP%=AH;j-6f+fIS]7VMc@Ai ZGoRV)B(F.29;`d++f\d!YXBA+\YAWL8>O?8.7o"D=&]=-$B,AU .>_a9>(.DYT;jAZl0?j#-f/q9!r80h.O_+V"6l92g;:G2$B33]-?&)Y:&EL*l6k^oNDqt(- f6c@urSN7bGU+.0?OnC/E&nLuf9bXqSp-snH@C-]2if9KfK>N"f=C;G^?F]A(LtPW>l;?$c 1HF6=53BGj<4G&O^o>(qL7>*n,7`#kOJR:\,QD8"9X0N('),.*[_-\P89p*#!hAk"5oCUJr i;,5k-fdL='fW0QI[5837)"r#p`TNY=`-;$gZ)-\YC*((7C-1rZ,d(!t5EMNM4$"aI3kK&t (`pE^A["@It7(*Q(ZLuLpD\eZoDd)>.@kTYs]MG[D(7TJ7nSTtuaLrF#"CmA[Q8(j BaVj,a21NZ$7t7``[l ,\2RlOn)OE8SKV"jOBT]P%%3Y\N_HP\98IZ1cYiXQle_Papo[FMNLJ<7-0Z:+s^EVbAp$(# rK7>U#]5__&-$@nNnW;%V&18OYJ1^_\E8IUn0$.G\3*!RWCr59mNj!8tg#PV?"@J)8A.Co] )GTOAUmdZt52dl^^t]b"hcb@DmDX)Q%t1)EQkm/s!q&qNkXE]8b=p5^ aq@Lc8U2C>O>U/Y01;/.L\.!XaF[!%L-qE[Yd'dKN=QBN<9i&:ib)l8@FQSHWe9IYBEVNe` 0$W,oll-e.\Me*`bnVe\.F[K;S&SKU>NDaL@7NMZ%A^YmtHq3]**b//[[cZ+@>A@aj@dm;+ 6#7hP!4!/'A6&pN\QVt=?EJ@M[T<7\>ZA;&C?gtnWbUn"#)IX4,?R;a.fcgi*J:RS'#@[S& Rj6?a/N&_V:b)VO9Z'9'(kUa=aM^.f'<';lfudKq`/>+oqJf/Nmh03_DF[]Z*9ls:%P`W"#B8B=KB\+j)hDsG'uRP:p8O(gU+Igp*FnH0Q85M3FBMGe&"s#sZrVs)ma^ "&QX]D>d?G]gK2H@7QL\@*Q8:n<2QlFYXk)7c>K5m2&%,lKhg=a>C=W/sNPW.b*!"nN'7[f b"EFfg!'>n=XGHX0,iJ3#/4F&gMU>3-3JU)g?$ilpQu2mtpU!kLf\&%RYWi`VI;_#m'Tl9?A&1-"Q3Q!oU-nK)&1m6 ");rL<46O:pVfA]YOu^%U[F_Q4_"?AISh$X;1nk>==G/KQ'kmN] _jFd/TA5h-UtcC1c+9Bd!bFM\((cA 47dmhdrmR&q!uj'cts9OgUB.Cg#7:%LE6Q%2M]^gi4N-LEIKX^Gh3lu,NO+[S!V31T-L4&b>kCmSJ`\t;jhMqTJ8=&fOacTR6*Nko#NnB_\2phP[^V.-MbCU$%/[j s&]u0'f9;lY4NK.1X1A5;Oq!NF'o$CN]D$L9qd4@1rR3Ne+O9UcAu4u\&BYL@](WP7Zdk9o j;+ISUu.2toKJVf^Xs>'i#f)p>G1!hJadi@5u!oVTAsoN8]tc&!9c,^*Q0&/p3t4SM/c&Wr ^%SuNF;Z0`f,ofU&89&Ri&E+!?S1"K@!o/b8ro7nHIAc1(tcqH2&JF-8KrU5b&3;F:3dY.' fWY1;"+&W,.0dB*S5g5q=\+4#9/j'-SK)#"WJPdN0S'nNiX*6*'QBZ6"^PoX"Ge60oXYj$> Lp9>VAe1peID)bMr.dDB-8&&Uj]llj5%9YZ_KKDYU)6W:kF;aT7j6J><`1/n@#7>=Vs"AiX :W+3_52)V`t"3=";0K=_X=gdTW6^h27_d^O,@RJjT#saa^@qW5\5su,J2Md`R\75`LL;[;N 6u.RrF,%.#El=Ge7&+f^0M$m'BfCB^Vh@f5i(X@\Cq$3<%-)]Dr)>WIt)tD-I?f=TR"MP@7D5G7P&%9BQaTI>J3+]7UqZPHtO;KDh[sT]CO0+Hu 'CVE/%Ie]>L40r,5(3-\j*c"Yh\t<+D;gI"tO=#A@HJA*:mjkaP[s.e%J4^e60p6O(n<".S AlqlRpAjVm0^]+_Bh0HGmu4FuF*KGZ+!PIF)@\B'nj8=R+NUiAm,]W?X%L-S6u[#bkm^cX0 24@G@F9U!Rk_hND0!cVlWn1Fp\;ZgEE"[G$On6H/JN04?D).=Z*!5:TQD!Zo-1A>D.62"/n[Hj?#6t!4E;"6doOA 0Td[P?mZRT:i&GEF@(i"8;7797"l";h$_3h$kDo$7'-tf]Lu*-^k>7fKd]oTgeYl]'h%F)" SblLe5EcUI17H';63gG]Nf9WN+UM^BN!A3(uT7ba?@WRCXX.>#1-\/m%)5R1s"0banT2jR4X3PH&$WfL'etp[(4 Z0]"2CL5%njL58O885OpQRY-;seZ>63`19l]`k86OR)ieC\9S;s08JXK <\7fE!-neDAP/-Jb-bkSW%3Ui5(YVneuZ&U[',mjAV9Ik#"UiW<3nb'E3CBr"2GdI>5-)WX iK?[P:0F0e@X=bl5PZK9C0@+Y]PRY9?p7\*-bP=>P$.!+&$2=9SCGNCrno;b!3616G$)ggs KZm<9.3lTETjg"i;V3IABs[V(fRHcFiXMIA]iMGDES8<^!K9+uonYW&-p 4=B#%&k\QulD:]1;u]3n"F!o)N5gYe&L6Y0)J _,,Qs:l&2173b]),[='`2Xn.P"V8uqaBX6kKfEmG9bq!OFc=,\-dq1>Z= Q2q4B89<*>]%GcIFfm/>mC@IdKQ]-^"coq/"2Goko(QLr8;@IRKIufQ<\R1:][sSI= /^0D&4]n&2&nc/g0K9#-%k6;K/!\d_P7dgZWp]dLeR5#=IJFq],Xqj*Pbs@j=0gY23D#NP% 78=TN.607S!a):'KTiflg"kL.e4Ni!1r[LS0#)6jIs`g9)@U\iPUCH?8.Y=LF^/>E-.)Cc-r41l,g%">F> <3'oLL7*l+M:^t(lmVkuk^BR@r$!3@;2:>b?KkO59%6/6\3o@q:EX.tWB81]q^5E@aGi'9AB^Upprf@Z$K EcSY?9XP:3gYU5@0E_=Bkj6tD-Z!oR:/8_&b(2R^j'Q!l&tgjLO`t?mP!i7o]#Xf"jg(,GX p6X5=aWjimgER`C)5Q7E@`."7]CL*ira-XPbG.<5QXhY*nSZl3-LM1H,jrRQ?BOU_ %#/EBRSg)b2,OESB)Fc)`L-N@/BQ3D6thDi)O=BN8.ET7/($!UGDCj(CpP`45!l-uc1$1es5EKc=>je3Lm]K$)1&C=`8FFt<_%uQZ0(J#>&nKio jS7tXDYSH0SK]1tn#(m8rqfl2rV@T8>1e)]YA3o)onQ$>qB@]Vr:.$O63O^#mNPM(@T(rJ= 9_Ipk(aCXNbO53C?E6HK0L%Q(DD-['mj:%qerl^DJr>l]lAh=EI9oS#'Fq#]mIhfKZ$:M#; Q,]_$a8`ne]2a-c:ju;$ApqkRY^S@)Kql;;CbiEgDIN^FK/rbmeo+#,$.^:go,%EI8kDo+f 3BG]ER]eU:fU4TK\\aC+V+flO8JL:CE>T36;uDh^5AF`6/Q!-\YrA9q(!#5Ds-cfB;jj\*+ *L#>g`(g@-)DhX!4C1hhaffo'%WKcGK!Usk-,II,><.>ugs!_;t?f1Nca+jY+"K1%s&T2a3 >AJ0R(QJp^fI[l2=)0\ijat0SZ<6JCdn0oZX'Di@G5HsKr9J!s>muu]hXc!*?CV>NdqJAT_-o $B>XfeML+BWl`"m(bEKSB(ZC-*KB.KIqB/<]H#(K(2AfjKYK=I[RWmp>,g>.LiAZseRG+,j Zi,6q0&fV1QDZ>@)iGj+4INKqjhH-/nKqq0jDg_0a"bMT*ljE@G9Dp@q0k@87F [;B8FfHB--=S7TdH*n@.I[IP-h8?NaonI4HCf4]eE+N%*:6JdhL.q&*7L@6'Ti7h`":DSE2 fW1VDs7:=IG_4jVU,mRNIpnKqG/1bB5*;&!:N7aX&@)+Tsh6+gPCLCGh/;Y83o:".VB5u,o drC'DHk,H:8*2dNGI\4f?p3%H19G(IDot>'EPDl9G-/"QQ\AZ^DHh;O_$CirZmcBLV2;3rh%s)?FktYdiHAO/IHPk3QbDd6hRD>1G Fh=@qRECm):3JdKTRsoXB8dDL91/n)2I3RN[]cnfUa^mOi7W#HCj<6"d#SD3TPTq\NTV.Pf =Tg(E0i-@2J&dIV"t:U\Qf"^ko*TdVp-`]2 71CBP601D!#F]rp[j%`u!BgD82Bm5j1^6Q"Qqhm[JBT&mQO41]rP%YZp,^$iSqrP7nB*rj+ H>W2u,nQXr:<1.8_E+tGgfr<*a]Vd@*o,QX@cLY<83R@>'%nY+dKRnMcQ:C,Heb-Ug?.eik T3p=G?+4P&pKc*jgiqT3J)9rA+,/_L5!OnbFbKE=6kb;nS`k@uO/_C?hNtM4q`_d&me`UU\ +'5>d7A$ej\`S[rBEg&pALV5fD,=%Qf7c>ha'G()an*fb5\[8rs_7H.)s'9)C)Ni5_opP?t 9Xrcmf;dfHULVPSJe3?4"H8/I%ld)hZL\&4+.b4ibYAA5Jj36C("tLNr330YQL6#F,_VPVn 1LhASb:Ot>F"-%sXF+@I'#&E4s(Ls[7h7$s5Piabc?d68sI(o7q%aRC1goY*bWpD2c,>`2I &0LbcU(S`6aN3SC!7UaFoK^dM-+g*ao#i?V3UiVRDaui0ro,Zl@I?*>u>_ccL80f1/,Oua> 89kpoA7U<6_oQgd3@,roM"r&YN-:-L=Ei(/iKKFR:J)Kd.-1T-PZ!fB%\\1u#;EY$6\nnOT suV*_8\K*,$R^.EA$@_D&VDi15t_l%d"JDQua$PN<&M[#,m.]"'@mD3MA:,N746E'`t6H.E[#a!\`4oIPk?3[9Ml7MDB0toH_8dZBSkZG1PD ]!TTg@Hd!?EnBOqICe1QO'g*&lJPng#M?A_U;/O@C4QjNpp:^-s+.Dp-1Ur419&;j7UWD+n >A131.C$/1SPr5.d?ttQbe2N)cnf:(cI#h^g99jmhMF,*bN"?1$6,3I(@+qMY$D1:4V,ODE 8uu#rZW6;@?)s6>Xk"E(=K;U8XOWWD<_CnFlWn5,Q+j_/)VPXQfT?g>(n(t$au(D;=tf"@` L)i,@#QMe%ma<1#QSmY9_FCMQ9W+2+iI'3DIq#%aIs+gZ(r Nbk]md,nK9XBZZab06qUO/-f,!#PJ_?b(Wg"U,uEfl'.R\/\%OSp'\&TcqL)0VgAG;^omQ; _Jl%=b8DkHgJCK1*'S?O*W`;WBeK,19=?0$5@C/%MGkE-iV-'cUI;eW2_8DXi%q6M?M"(Zp \#Qfb&#&fVEF(-6R(RbVU&$olQ8HU+f,P=Or]`ntp)ePR+62^=O9]Il+(M6pO0"J,Z;+'7A #+C2Z-#1!c;Vlr;_)Efa?0^Q/n@WeFFd85&aP-lbdj=UArP!'F(T44frI)EguFmh\2k"+OF <22IhKdX-"RJSPcgUep]BlCISbB,\/b*RAS\?CMBnI1l, S%)?_J0%.0Ie2KmWNoiA23HGK94*^sJ]&VBLe\i3? h[UZ/e].[eX;-GkIbVk5;Q/dZ6@Gj'Sl(p?']fqp-dE4=8./k<`l^%460K_j=m2.%]fQJ3B=7G>g6C%rU#eH#]D'`)OUAAK 35uO%*Q)Q>O0S*'Mhj8!!J`]6*9HhaVq(WN>O$Wd[J"Bt#R3Q`HZ;eNe]5Ji).KY8=8N;3I pn9SiUA5J0BH_oV3Co00P-$tCbeAn.^P38ZS2BcYQcsnU(EuXmd!R8"-OZJF;)sA!Y3NX.p TMUCBD[s[_VAQ5u\LK7)Z;n_nf:e--!IA8mJSq6;*KPX.]]Y<^e/96brO2$aBno[0E\A7mr )&X2>1#`s9f+%H-dnX3sWDMS4r.#n,Pq/*'E?o"U9Y$.,E]E242kr4ku6$P9KKiA_Wi'#BM K$kU.hKhbVor__=4_9MGtX5n1'M%FF*90:8pI%MKA]q[i?0&GH!_oae;&&('k`+c7-C R`]59cn,819a8u,BbA`27NniE,ZkRC-5l2'djCa:L6C$*Pgg.1e:t1=D.(o=@hd<`'bO"P9 lAOE>8;n`fM-u69n=(B@b7:R(*T@(nTNV2t&Z0mU&p`m6)f=fq:$ils]&(7E7IBl#/cO^+b2G)#iK;M-dF0+r'H-$R!k.+VGG3;ALS;l5\cekHZ;pOs]@4.j@k@)e![rO#H4 M4!TnPNT%5\_#3rqHLe@;,f)qj@D3OU)'Io7*s(^K_29"i-RR1d-P"TQ12eO-Z5mA"'e*=O l!bT_?4T?-'k#hu0Gb<#;Tr4:k3j,W>nMT0/oE&-37X5jT%jJe#eO#1MT;'BU1ZFM(Q@#HPcQ!:gqFLe?Ui 5E"J,&@"Y=;,9i);bN@i9?,6ciJZPo`\?\=&m:G(K'Ot[7s\eCKAu(kQQ,("$<$9./[l*._o=NoKJ8=:R-GQcXe-cMSSGq?XC1?kTkT1:^dn$Xf#%/( M+;;[fP>\/55M>#'u-;V`r`.q4et/`EE;+Jbe5_PCSs0D7adejhDP8MG<*AJMUa2A[Oq<;: Bhpu1ui;<$\Flk,p=7[A*beosTlHY6B*#QVXL%T4BWjrKX`YS1/R;cXdOrWfcH2Kkj1&+C* ;>rU5bCDO)R6'`')BH$tR!ER(ETtV:.#@1?_D%=ZK:bt.bef:AC&HhY?oMJ#@6ko`&"HZJC aM%KR=_@,)>;PRX;r)0Ek91r2hoqgXt49JKO@FN[Ambn\KBf2UXY<8E+fB%W*%fbEn ,<:,:"HkQO<)V%i?L)PWujnFRA/j:>$4,DNLM&8@"mO#gGKo+HSMAW+G=JkC-iZ$jA=Lb\>oo4liH ME%C@Psj<=Mg+b]GQ23AQ[DiBa,YFms@$mP&=SI6)GLmc]6Q1Nu$3*3:?_V*#r`m.'em_,D @SLq_d;b)Slkjp'6_G%?\1;Oic3`2HQ'/e<,=#)Lf9XMq*?hj,;].==+Yle8*s(pS+PICC(]j\V#^;o/=/D=/Tpa- e!?bnXTV)b0l5\d6W,>WVTr8bUbl(IES/G385c,F*EGBQ/SJJ"X@?qFS@;AemSbBBL!Kmuo @N'eg$rufu2<#79muLWNPEsg;UZ*8e1(Zb,(?&JB3YoYe*H*aODbs45D8T6H_AGZp<1)OG\ni%?04'qo(>+H-XFS#Y/0Wu7P1/BRsC>R)B^$D=sIJXdVaTH% dYH_pQS"k"+U!"r^`*!#RCf@CF5gO8%IIQ-G=T\'h7PRVs9YPS4%)[ET5P\\NBJ(OjR)\]K @\U\o6Z41SD<84^G(UCOiSq1Gh==\uFn[$K3FVlok30/o#8[QNPKG>5T\4I3c ]4\Q<5SU-ihm(4V\9GELEOWH'\.0"%P:*?HB#[.5LRUrDH^D9IRWdms*P76@>Go'%X1I&_q *F!\+d<]Y[>VQ(]@DcX_0?O%4,eKSiE3%JY)._p)kj1%g\6bUqk +o,>iF6MJP7&WE"^""'`dnu+F"eIoEX?V&:gU>r$RXf+i<"`@/21a*&d@rZkm-C]\,N6>Xt #:0H&h'$,NVTi4Ucn94XH#Q2G"/=^>S93PIUo`lSc3Vp$04^__Ra*MKZK60Z,=Mo`u4*l6> F\\0k'__kl&%tL":q:3WOA2Krk)*-[!=lmhmYF^8R)?Dl+H1[GdO:B%U(P,5oS,^a%"Zg/A *.]S'_.j]'RAik=DYbTP$]h$$>.NSr&E/3OJIEAs @UV.7Z>!Jfg)fc($E`u87h'P\Ng B^W4V/umi=$q(uB@GI2VMk:IH?"*+85TCY(]h0jZo&8YE=D'-W:t_ch.P;ECNo];f,\p6!Q D/Q&m\pOLZ(K9U!=:%O;oDL(ZD_3+`&'op)7#rBU]=44f@">X0B:9)*lU]]+)#N]lE%W2(jZJF!9*S,4c*-)91Z^p-_rT)Wt>T6n<\XQCP*VZs'=l7t8i"ZY75u=A%?/XI Oi9/T(Thl\QAq4*0\)&@>4sd];.YL6&-+o6TJ]\s\p#Fm"j9T?7@E=TpFl_CTjW7@^8;8/$ X;ALd]H1RpramfLYSO56]fXL%3mbJM!<_Ybq%?A%X5.>m(1`$tr/R7H[`9k-bj'H kH9*r!['q8OTlQ@@TP*-(I?C`MEADIL[*!U_!p`p1eBkeA@o%]g[:S/(8"S+`2=+efL?L!" m0SKg2$\`<=P\+HG,bMes(i0#"P:(82a3B73,*hA?Sh#eh;&jZ".JRB0tC!Q$mcZ]-1QMo. Yck+naUHK9cSJCsMS'dcKqA11#4Xnf\.0qV_F+#id4Z>WS44G98e3C`F4\)D59DkUt'4H"k g4$lLJfNL"M5lQd5C`FbldjkYnmD"g:*:N"hg9qTeT\*&8qr8+/BDiTQd*FZc)Phd[119UR B9<6N&6NNk(0WEb)f/i1-%1W;'_Duj`2"q%?bWDq#G2PEpG;lYTE3uI1ZACbO=Wo\]C@BS8L(/#C.d:]jhcRQqL0mM5<0%uXRXjZT^]O( %#gXZ/rJ&,N2MIr>hADM*3EHnQs595m+jRO0^Q<,f-c"45LSF1;YU!RKEqHXkV4MGPS'9(a Z]3DJlCj)9W[a/m"ghujjh9Q%FbtTW*b&pX(NQC/NH(;Tm/"t5OoD2a!3^GUR7O@K9`4Cr4 ]kG#??;DZ0dHC1J]q1j7YMJaDI/X(PQeUd!rI06gO(#P>Su;Jk!^NtH%g50P<#5a)Y]Lrj) b52-e&&44/CQrTe2%S%&G.mi(2Qk=INOZ):D?5P<*'i(Z#j=i7PU-?)Fh!=D]D8%e9;s(Z1 NM^*sZf(F;ZAeM^-6E_9?C'#,u&hbOZ.Y0heo!cS<[#1t= EWF*-.r9nQTS?&p?VW):k3bjdhlZfM-Lcnk=u5YuP[$UdgU<=Vlta,.VT;DaV9I@^[Pg0bZ 9@=2)(FR;(a<&FhL:Xlce9i=s`064d0D NFJF]+T-6kURAh_N5isH//lGTVe]KP]sDT\G4i7^>IP'VEEot!cZ.c"2:ZeSGBMY^*(F?q7 UEGrm7#n+ean5s'=gMHQG]6M3DF+B4=V5eW0N'FQsL_f@JH-/MIJQJ-];Io=e87mL7pXZRf tLqD&!/-99\Gi7TYjd\P?LtAf5c%RV$iRAXmACH+[Do\+TKfhms#ITkM"IO.p>&;9EX`qR/ b]?^GjE#\NR_J[A$r#6Lu^f4hSiC=j-n_AmIa`>%T0?S>U[klI_>*5*3GMH8*f5KKoLKS^tS4&J/iHUq9MKG+Oakg;=*bV&+q>Q_Ul?XM\V sF2na1(G_^9QMVPiYJ^nU-rNbOg2^=3^GdUcB2u&;3?'q0ns(#"+b&i='-)U_poXJd>aL(^ C&6,R8kH#Wi=.Q6!n_c@O>/#Jh6+"Q6X"K+M&l#>kCQ_k;;l:jrtm#Xo&.,U\7aV@u:Xi#Y >>C_%`h(^oiu*X0o9%jL-U6`>&9iUf9h&FptM5lN9%=G%=8*[J[[PnRV;:Pj'\-UfGW']QK "M\/i8M"*GXKUB.d0n(gr#fRZk,\N'UVDC]?^a0/gg)"6iE13`f2']2H(ZSJ7%=uY`8(d_] Xa'sYZ.M*Dj4TP-*^r6V(F!C#O-.j[7`dY6,p\]!OA][b8\$i/AF_uRKCEF^6/3aj5iI3FB KV2mW^c)i)3s8t=:p]W8'+=RQP/.\'%qM'L-\-S`=cQP3JB2"%*'dU#\4Y_W`8+kcRIs\[$ GF*2!2&YRe'Qr'qkUYL4Ot2'8CI$1C6%=.=W#K/8LsO3f#/*m@FusGu"1u4:Ol_2oc,N:RU us-g^`&`r&@7!MX^sSHkh;,jJ4;%OFO,f/mVeC)uo_Io"bsU@`&U;7\JP.+K?6'O58[dGlV 8f^U%.id0%`kt>ZK/u=fHGRdU74R"^^V\J9a;n@6MC%X]h#f(p"Z(_7*A3(%48>:AI::`+T3C7ih4d%qE;ltmhheDhH)XW>oi7CB\+9)!CC+$c1+Kd(2/.1PEhB)WI\R3u;1X E8]pr6?9b@ge!=Xj1fgl*u,$3cm]*VQGsP=)+f)tp]Z<7IBTgoA%1%dhi%)TU&[Oh&FL\a" :9Uh-3Rk\OTOHW(P>j\-tP@o"5r5]Kb1F>AXp:C$T."UEtKTQ=c 2`b39NE_STC*?Mii+"`h @Cp6>m+qQK`_Um]]k@?=TKCnUS)Fuq74>,SF=Mr?c3;$ZGafBlAr+hQ.7a/U*o[lhM"(Bi` H\&m)M>PL&+)WA\D[B'@t\c=%S==D2Y#lC`kmab43Mnn0BO7pR<(AL4\%3VWEeS_o;\G.q= RK%@c0H)$FS82haZi:J8L5G"*LcsfX1g[D[VS>+H\)A)+*d*=73VUHLG)(h1r4X2)m`gnC/ P4XEE0efj[$cMs]gMFGN3_3CG9;=ok"-#[juPHhF'$(6?9*rrfoM02D$X6cBBe`\^*aeeWh KUkZKmDEP>"L4aL_Pl$"+cb_j^IN?n-`?UnVW;"n'@Zo(XnEehfWX#Re:ke<)M@*t %`AUmqQI[/&pSV[Tne#".rN)qe[5iOq@W3#rkMl*l!P[!*eA2>q\Vg/ID<,_0U&5QJKsZ^J A$_&1TMH=X>g]pHn)`U@dF'4R7!#"u;Al^pFHaX"1L100nS-_!jL@dMN/Z1*Nt^1K-+r66W'R3]"Da_.4@gZkr s&4L=?=6*)$3qCr.U@g;3Z,K`0El9D'OS2>Re68SVX49*/c-,NST^'lC+KIDsrIP2gc#G?A K3-;\=Oc:KE#0U/e"'CAXMm_#=[G"fm$X^=V28`7%$%$/?@q7rjA](!LKG^M^F?I!j4Z8dG [_$BE"@'g9ZAWD*Mi2Vb)fnD@7>nB?L%&if/!RS,8Aq;qVgE_K_gOr&9Z5t>NVH9Q0Pi^)J ]/m3W%_$O-uCqGmgfMX7<==)K8W0W=2g>a#I+n.OV_`;s^%>RL6t F;:A]A7mO`L#J^iY<5:=s6ak'-@YZp0KA^_P-oZnE6A#W g/Ao,iD'g?b&l[h6CbFs;Dg702,f_Bk\*< [=MkD[K90.=Ubb@p1dbe1cLgO]$=?0%n\_0n_ha_53174>5#5R`-Bpd5o_?acq50fM"e'AJ <('O3r5;E4L;[If[/a#;@8Ifc`5GG>h#p.5"Ll`MKb.t;1P/Gf;UCn_L>YOS^pumCMT)Z#; "Ro<"V/oeMhaQAb$="_17HQ9(!mC*:ajG@G^N6PjO'eBdBsq@_6!ruDMC8i;=nYP"Dnd]EX !fua"8OV,p^MdXTn9(KN+VdqWnI9h9j=Z#H2MN*4sCqIaZb!dcE-e(jH6e?3g!5O@:(oB'f!OG.Cr1mb_ q*lMKeQJ[kXbpp?A#IL9T=,;SB3O&$;A-Vbft@IeBZ[1ce"m'"*cq^jO-ab'\CuBbtQ^5>h <'mJ>/Rd9q?pQ`Ijq)D$=T_#:(HC>i3gQM:T@tr`U+"Q3 rNI-Oj2CP/jI:=M%qUL)7L2U;8i#n(30K^qo%S_;G!2K\Z=>A2?16-lA&=s]r$pf%GrD[)a 1`+8jNGeSk[BadEGg9haEFf`qDePKf\g@YVR!8rN4:Bl4Qd&")'0^MWaM8a.qYLLi!B9G1bongbm")6tZbOH&#rQdM9gXFDM0V?A(HfdT%PtZ _I`?>D&>neD3iS1"AGS`/l[#LH'6RD(nl\eD4]d]'+>gLjk,pHOr=s;dJ/,D)P\Mgdl7:aG =a;0JTZ8cdU.ue&C@gofc@Jcd_H#L!VqC1mCR:Ps!]5K[;4R\5Blg92q`Z?KLY4o@2:/k#C I5h^.ls`DHg3dU-IS#I&<)h,QX=q1?+kK@hKmoig7sXrKD>ZTXui:6LDpeq@[6Nm0j":.bVh/_+9F^\QsbcQ(_ `YcqK/6As!bjlL$MAIG'3s3FM=6:U@;`E>LJ79iKi\Df^22'sgf`]B$L>Z0g899LSBd<7"= GfH'c&?,W/_IX-?Z%O>@![U\I0T1c#CBC)+BjNhD;4HAcC7s>=?Qi'CKZ!iLtqE$[QN6E1l 6NccS_hk;]k&&0P\86l'4'^%SB!ohE^i0KS8`)u.'?$XM-85\OGR%AF'\1fCNX08uFC9iE #M=:V+U$W/gtfs*kGEUTA%B0a63F0*"<]OUfL#`-4_Q/%/I[^&p4UkEE!AQu?B%7m8Vr1P9 7h+t"Rn#r&2mk_NSar#?Oi,LH(O0dOksE-kYgZ#TQZ(0A8,JRY989!&5RrW<_B<)"7RJkhO NKN_]1t^JPH5R%\V_aTq'C0;:0]6f%E'.c>FN_1@LB)."jt0]FFToihm>OrO)T;uR!mu+88?_ulH[T4l0i>(c+.e4#EX0shI$cE9nn*UcDt-'`]BrV 4Cd38m:ot)<^9gM5sqeA6c;.T_eEX^7q?2,D;_hJ[/=*f9(!P1"LE4;(11r[jGc?!jVI%@% d:CK9SF0E@>o3-pG_&2r4_s">D@i/`^S"CZn7lnZbIc&8VNS3@_`,/]C)/Pskc a7]n(unhuR"5*0+Tn`_tOks$QdE./&5H#Kl9Og&q]84r-?[[ViY!T'AI[')/."#*3ctTPasqIjn.:CpYMo86fp'&"bHcgnk_M7muZ,'Ob%Ni FbY9:)E5_8^,.uiNGo?U(G-B)2#OW=78qZ%_q?G^i_#%ln*m,3(sLkD2!LNLGFdC#^"msT\ ,SqFgfNcrJYd+?)cb$LQHcL8Bu'!dofmXK6UD6-9G@_?7!$CD0KX1D4GI0C$hRfD7-&1_Im `Bhfe/=p@,EBq5L$37TLi.-DFnQ=+mWRi4L/I]$g8GpAm`t0C_gqss;MO&rd,nL +#4VBtn\p<1#ItLC8sCc*p%NBZG]:c[+F3OU??iB*ppH)7,,,6qrT8lq`kZQu%YnZ2")oWM PE,^!#\U7u-rf`6.l_t)S\k^%I?^[@L"AD3`sd7>4-aTf#-Eot-)lXr`dKEq.8\G`-0oX@Nm`Hd)T49b1 KZTc+_"#TZd_=]J@=:\?i?GpY\`b][U,I3e]VC[,pl1NBL:,fe6_6/#BI>+7Mph4LIf$_jF l@YVnD,ltsDV+niBF,_Dp86OCJm`c97!?fK2Q(H[s87Ar647s-pE4uD&W=.5&dJSn6/bXRA 0G./Coj,.W0C1-'oYTA;/#$&3ua5OA.gm"Q:3-`8``j3?[D't[p6pbm_24Mjg'=lWdF$ H6m-e'%\%ZNfN;/$<(ZB\>B;lZ=P)P'L"=0#A:[CX=t[9]e2Ru#S3Fq2EoNE7 ^K2&,f1Ykfb`j]6WfPG_84f6hJ\(kkF>J91nID=]ZG[*E[(Nf7gZs=**5;/MMkB)"j5(?Y1 f'7DT?(U4hWn^l%g8bloO3?VUH@6jL5I]22p3ZdG+/d$DoCfWF#WEu*7fL0koDo!.:b2\N^ lUqn"Mp1)*)W7rnSI5POK0@N*_)9JFr/,&3=eK]r'_18OT\Aj`:5BU'ua$d;]!E8KO#G7Od p8+7hMhD)okfAjCt"%q>>^u#N=6VSO=V),ft(+R4$,)N129=&u;?Rb7_Iq.nc&L].KR!+T- 6kURAb]N2FE"/"4C)V`)fkFQ#7*;lo"@cBH363#kCr2[7)t%08c2oHaZ-d1e_Y!$"Ib4DL0 LA+42s,0?i\MoNk42]G1NiD.koog)I)<@pR:e>uao?D.?Yueoa!c>nFA# I72]Z?%HG:<\8r6fTnscAARG[c=K>nNMU@CQE@7.Sn6;iD\&T\ZoncirPNRm6g0PBO5\(*F ^6q3h0.WkA`\-mGE(0c%tT:n4,"L,qgMo)%KV.hh6h,>DW3_ iL03k6);Dms]Ph$Bq7lBG%fO2'U\T@"%n5(^`Gn"I*QIXiB-kUhI#-]D(SeM2>n81%F3aCT pHd4!>q\RoOG!@47?D(>=k@f0Iq@:+SVM(8pAM17h=k4DF5%;fiI"4_VU(+ZGeQD-jS5OeE ,CmF8^,#T`]:2G>4%IGFr`V%Q)&ca&&If5s"D@_I%NXRo_k3`ZhOG@O6-2k-3;,*[-]A?Oq U<9ZlfPIf74D>!5L;T/;Bg5'a%&35fa`D?ta?i_a$)8EKp]8]G?,2D@Jna1C)k!+G8$q&jb I"+GN!+KeT596J,EKiES*kd)m1m3,K+5J7oL(*&i[^N=TIq5)9d\+[fFb&]8jK(r=QtN0p" HU23V_;+<$(#d"g#]N'k%DCn<0ZPVW^G7Yo]H1!T[3W9kTM ]QK8GjI$ZJN`)YUIum)G6-'oM+j((]'Z41[(&8hNUkF_j1-A*aTr_D?8VMJRDG<^O%4I4s^c_3e.2@N7,t5"DjA)+ (.dS`uV"cKroGdmWU2@B_Z==L ;//NiWDsk6.HP`VBm!:M'hXlo3iuCs`Df+?fQdrej]CaO@7%#*>`N4o*ENti>Q[)Q"81n_f >Fm_)]Q+())1J$;TeM(qIW@G&h])<,H\%ImmM-lnGC<_XPDiJK2,i: e:i4diWXgA9\qTsPSpT8mNP.>:=+&jhO`L_2c#>8(>O9nq?02Tje/Q+=@>mC9U5khVa2K=F tei]&:SiESI,EgJE?>h:KI_iT0\NbQd"B1V:T^"IJPV:E3@Gjk)!iOd^%n6SV:nD7Zr]h^1 qMBRF."jkU:Efe"niM8P*d/+ok&ad9d5C`&9!48*u!an,"J=4)[_,r>p9G+?f7pNC;6u5PU nZr5b`!(Z7ls(!5+Tq6;%N8/9$:6jL#dHcD`AjJ)6%IB,7SGaqR*QX[=E0"$bunaL"p842[.h$)tP;k6A/\>/sf^1YOdB0T<% i?EFPhni[4QTK$H>Et/!m5O>8ffioh9ClP!k`EecFKCjO%@qA!j]b]@%=)MlG]=.G(?6'?/ 1']PJ+[[s;&>5*<8EPl8+#gO)S-D(P>Ro8NHs57,eJoD2/^r(k%hRkLfE 8>fWph(*W_cThJiVGb3(E)72qQ^U21,hSY?!Ka)4U"-=+=j:/XrO@*%']R:ljkhT*6uCl:1 _[P/VR\X,G!JL`%2$Td-+[k(lm!o.u2dI*MuHSi-Yoa3dq2N,1'IMHXUc;`O+r3g>,ui^"7 T7^USJ,Z?AFPE\:qLm6.W833_Q)DPc(!(L+I3LK/T&07!",mdbS<9mQ2=m!6oCl"F!&4,94 "^Q3H6Gi#.S\rVsD:Uc>Z?S1A0B_NS%:G7QUS2N(F"S>"T?B'=sLqPtt`ON8*@_Z46nN^^u @j;q&O)=94`](q_qqbj*H]Xt.9$+gUiagAnnFB\,'n\>4$c/m019]+%),Ns7;6B"F`g"mnD sWZ#B:FATD#@GJnAoSb-\d(nrE7bGB6'pt`=U_KRM5O25OIFE^\.U;:ga_rQLa4G+//NHJ\ :l@[/7'>!9ml1+l*+e!6fWi:*;gHqV`"4i3:YfnC7uPfN0[?$uk;:YiuRX m1*RW*!T[QYk\g)@cO8K*+8bEKtnV"p^)s^&M@&qA`O_Zr!(.6"YO^+DJ^#hE>":Nk>$:9C D%Tf<3d'b#]PA_U"U=A=<@Rj*$ZrtY9+L_,3f3_B&T6YkR&;(r(CoOFDX)s%dWk*5^'j$%@gX1Vdb; ft^TT""n_"q&h%e5+&(0J[AZcg-^`/@J1ljc9lnn?164Lb1)K/CD-mnX#%/$n9p$>HJ05ef c*?hLrpMYI(Cjq3LLA:.* )`=XEk*^+]dr?!*J("%coEY]2_=>m)^0#-n4s1Mh#u0`/Yh#>!L=A&mgap&*'o3."!/PXmN -r5(h$ng;[F-o%2pK*#uIHRE2,1mTec3g$&$/,!QktHkhP+?)_KYM%H@ q=mkj-_%.N'^F'1AA>n-C/QZiSii<@B2&FI0),'8RVf7!O`MhZ5Ok^#]UR ?PEr?0!!a[1%j4pe'<)VnWtP$*?]d1M/p_".TG%u68=u@;55%ik Z6M44g8MV#PEY?@8@3Ll/+nVKGi6i0fOSACP,)DEW1,gF54%lrs9B` 1nm%VXC92+nJ9d*U_'R)$kh+ak]-4e3FZ=cpSm/3P4'Oe$iZ?]6OFrQ%')fgW\[0]7O%4O. A0YtsRU%'Z7[fNkp.^^Qsod1G_]Gk;KTepUbFZEC.4YMBQ*C7.ccoY4783+N3)$*5'jWuN: >qQk#/kolRJGD,R?65fs)j>^m_=esZi#*\\4VJJ_on?MULh,K2*!*3$F!WTj1KjCA=u.m:8 gGD8$4i"V%DgQjmNrXuD)TqY'Q[84'43XTc!7['i6u=D2;)4Lh)>Ym+$o<8oflca)`T+1*$ G4i!M0h[G<)oG?iY-`5kG5dY@-t.3u/PE'=U'(&/p*X$UM99i8P`M?kO36=Cc@l@Al^BKJO :t7TO5P,+k"9329@e@A7P]lr^31]_24@>5bQ`#E.A*PpSRiU.P6b:6RJ,uiu$[olIm>u&3Y'EOt)PlGo`,S QkHVO"9,FV/h_'2]pY*/RTEiSkq&o5cih;O1FbT7qS)8XcD(Y=8F;AQD5>rBr5QoTeD4B0k_?2-!X(eKBk!$'t' 't:)pBn'ImPT55Y%TWafC?-7?p'(.%@3-\hs)\[r[)Z_o,[O)J-^(auE*FX>+QgImE= ;Qi,.AL*X2S!VcKg&pQ(Vs2h(0uj,>2>+S $;6O[BWEBiI<2\G'_#=qTq%N$3gtnrOqDoU%A`MRaI<)&\=Pab?-+!"tY@FY"JTck=0_D01 CPT_'$9iq4"H+L^fX\Og]->tTB>Dl@;f'XK!o>>'/LEB.Tr3G=?!59r)5E`mK,JN+N#YB`' g)acG$_c.WWarY!R^JJT!!OYfCJGWDLFn]*8q4u8$&egt.:cE5efsViN8/6]dOI(QokBMI!PsD\&k;FB=oHW&R5EDB9hWbS_;eW?nBp_#t`M4rN;\#M<`NL#Nt8p]` ^)LK_*d3jXV5\73:G'*+7D+Q&!bMB'HG',iA,%A_^?co)`?Og_f2[SI[)?R*C>AK[m[Oj6O+io-NhB_nO+-tThDb(e^fG-.FDFbR8),$3>9t9C<` U%*">FBERDj?XoQ0g gIWS]o7Rq5]sRm@&.^O\$F[S,%6,*Yi*m)r"$$GC@9;a=i*p^>t'_d^U2=ef?j6_E2YZM/J YAA]"@"_`8jG+m'dGPSG)5<8%12!DFEJAt(gfTR%'d1>Wr6YT.4'VPTe#ZG7O?`Z'6Ua#Yl o=tiGIkSjPl#'H;(qF/K:8]]UYaVmo47#/[I++ba^(>=J>e]!.ZIEMD1b8P\,pd<2oVp"pm :r2K>0ic+rbW+^k8ti[)TY)1O"pm>g3Gr(+R^n3$mAkX&Y_FN6b7Y^Z1('Jp@[N#m!DaCLH PB;!JImo$HK2EYSVn>mMjjIF>q(^Ns,=Pp(H-'5f[CZV'90[kZ'Km">9@N%$kFLk6@j'\Z) YERn$>"NegG6p!DF2Y"r%)FZlO4p4%I)Im2Xj:Qe<%[rJAqT(@iHkfdVFillg3H/!DtP[qG sT_,n-,5f@q:\@o;\*OTfg;n:`#9!!<'gS2a#WKt0&])C"O(E%5E+hQRg+e]nOga"2^EZ>+ lR(87I0Ea=KFdRUB,.XJ_qs2!<$7F'Uc=fQd>]0`Hcb<^ ![;(.df#HlIS&V*jrNEd(`Yp)A#LB@L_G/9jucecF^Q0)NY0u[*s(Vt;Rdf7g)U;U'qBR5I !=ef%\KHS)<$9NNtjE4M9,[iaZcKA'rf;bH_jnKV8:ub!R)J@;p5TN>^WsGI'`1P[c'8ubW aS#hUc%aWYC$\R/ThJ@kTebck'UaUk,TY^nr!c!FPO&&Wn%;_3,<@--ndfcQT2rfKQg&#pG01$.7?@b1lgD9&.T@pa-8)+(&\b*#8?-/AfceVsuh*:PQi;aWrE$,TX@ dXC&J\bb+GZ5S!$&6:HD2-3T]%W$1U9SsmAiU]h7cX$l!mW:4E]BO@kA.d!pO>Ei',d%[Bf 2ASRI6t@JpAQ488&[j%!=\HC*F=Mg-mKT9;b^''Zu\)VbsHolID?*DR!HK,1Fd/3iTZ"ZIp e[RmjL+D7*TMQMWGrFQ$T6?&RIVlLTA;?Z6h*(&nMi_I;rdS1ZH,N5]:I)#T[].=ZBM*ts% QD`OB7BCm)Yj8&PZD`6f_RJs4AXk%:\HQ@:Q@C+]bV(UR6ms2V(Dtk:n(CuAAj)Ol7Sl[S5 c0'0E*?LOFnF(D/)(L*UCU;daGC1FW(OsKanp1*ap$*j'Yr2E,rpPWgjn8EIrh#7\kP>#T5 >VIZ!5J"8Y[!4/+fJ8S0O,=s61At@#/Y>4.1&>=.BHI?m3AM>3+q48Go`ao@WiR,>Yc'Q&Q DsM7IaVm(Ih8TB,a=F`+^5]n_A1,8+H5(*lr@)M'5Eq6umJgjh*p*3%*\9Fe(oD"Y*-mXKO 3K1?>\n960sB0MHO%b:q03,geDB1M#)r9iH_JINDC74F\G#U!e1V#'&.2(<7l(;F7`901/( U712N1n6rn3O64hd3)VT(,t_)-[51G(FN$77;mccn;,c!k6W2EV2,dISFZioH(IThi=](H\ (L'p_]k^kSFk(hDfCe6V6dN`q5@[gh7?_:cD!C(f(G`P@6B5Z_$7X]'RA<-)`b>>k>IOLDE *RT%arD9D^f4hSiC2@Ah3W9EG[>TBlZlggV=/h>2s'RZ?[)JGJ6qA0!#V-"Y`XTI=ABWK'> mt_:Q@E#.>d&^&QhFm1,_4S7VB!?CH1ptWa-AFISZ3i)-0t-AbfYBQY'BTB9SiSZ!e=^"ee aoB=\"iTP/WeMkK:q8PE6J,jBNMC"dHsWG4JkTrVnfYmb"MKGM&"l^IObY\\XbbHYm$Yo%& 4jDga!D;/sc\SaL+iO`uSYj+H>j.Q$MDnH#I^i4Z;$c)90-P=78"??$UO9H[c",n9Y(PbO^,]8(2&rkP9(9)m-='g* 3>dQ>@*9q60^G?dJKH5EP4_`h7)^"%iV[BF5[]nB_VR*+_Cf*s80h'7s%]#f1a7"sC8jK90 s]6)ZCS6n$.c_?aYg=AK6s6nZ$A"Ec"i/S1A3)M9=O9FVBVZOK?25F\ A1h56bT-eUE=X5P5)8A#I)D%kO!rm.?^\#EV&ZTPfb#Cg;-oBJ-:Z(e*%468fe,_59,@mh- "P,.(F&3c%&'sh*^du4NuCqh3DV)87&uSNZuun0`]W-XZR-n6Et1bF*$s+FQ]_hbbIN!raY ;\>P87Y%H''jo<6L\n2J4#'r',sEd2%M1o$)H^2GZ0a4@( ts1e]GBs<`Vi<=p\/HLeu=(.hICA/!4f%H H\05!p:(:Z%9,/i4s,nDm"6&\lX4E^K;uk@C>_Q%08-r=KR3bp(TKGd6nu[=M#:^)MHHlju !?(*.h1N?6O%G)^3)5c#5*9rk[+?#3]F=`!f^ZPihf>J"`j:%?3XG85.':!:'W1g#PVngrSFS[s#Fc8kVcln6bj]8k&%h7$W8`#tf iNrJW3ld5,AgVS2u\lMFe&jAhAQ'RIokh3!jpi"^Y^R*s[?b?>f=aaJhQkoiupuja"r4.9O AcKNh+bR\b\Jig:$UC'q#@RfT_iT?XiOh=0@(9h\@j2cLG\;nBQ7I\Def2OEIh;.)1P\gC/ n9.>NahE<`u+CgA))VJ"2LrTJh11sGh%s4<+Q`<.Q:$7Ce4iY-7&enQ4iGG*f'/]_0J<"aB 9ONA;4TVq3NgJ@^IIN+OuZY[S,cI2Hs_UiYpj9H=$O>HaD8lcT1S[kL#SRLP?$p,B.jem(4 r.>*SB6@?)bUW3QkrY&nFW?*%[ 6ZdoeOD2[?P<41-e*eUh9l-jo78*KI\is*P?H53`%I`U2h.qWVrSNhg9pDeg)h9e8J[V60n gRDtrmCg3CBbGNU.GT7[b,@02n@2:E%]AWt7np!05i.b:HLF#a^3@To;H4Z\DuJS/C6&GS* "JnXU$cg,#7KLS19MpCZlt%G@p82#BF#`5>$!K;)+!I&=,Q=bGm>Rt4H#Bn5Z(k??RoP09M G\[#fX?@0cZq+8Snp*N(8EB(Sgk"9`ah,YQmOC%,m`a[WuV6^lc&oZM0q=jab6hn>5iNQ:@4>&I` <"-]IJ(K#(@>I(2)9!H!'mj;-$*eY.pR'Fdj&h;%rY@]mR0VaL5E1^kpot_,V^:DrS3b)l_ ]$tc3=XaW*TP@j^nV=%q7RH/1F?c4T9&SUO3geCGb>rm_tRdCi?g@Jj;im1_Ir?-rVtGus- LN/#*=#*Mp%+LG_a@f^B7!A6Ueda#!c:`51BVKN!Vb>$:([#-b+S[cub"MfJuS@A*A 6[OGQ'KF!`3@U1H6<"?1bWQFCXp6XI"4N,eTPB-.-FhL1L0-V?Mj-V6PJh7#7!qHa$^E74K nd*4K-Qc%b/4GY;M3@1KiB7`k][4Z=pOCGNbZbMK)^UGPD50%)<0&TFBLY@=upn+Kp/O=KO $X4VQHVp3o")^$*Ll)iB%HW`].Tm)m`"4Tic14+(is\^3F=]LLt#*?+ H$,JV8<^IKfiYA='Nl/IHeF,-g7SqG,)N)`!)Gt4ZUYS97@b^CQh8Vc=sNC3uGGY'Z3cnLC )Y^e\:>LXcF"2.pj]pmZqI#1CO#9a]m4hQ_:[#H6')a4+[4n9Z!ZfF[sj2ih4aX!(Eg+X`a 1-UAX5'V_`E*fqST\32M:!:53^c^PhimN 2X(MG_`MP5MUA'bcFFlF[,)7LT#XAfUITQE:$ge*ADb: ==A3Nkc91,^9KG-GQ3JnP:4,4)i,JlJ2T,o;31so;#TkQNAV91b7#^V'FR[5%nO.IjQs_0D E(bdSM$&-"3L[i&W,r3A9haL`LM1(LG^]mbGE.>Ua0PXK+Bo"o?j1&9\n)"5SHQp2TK7\U` S=_;iN#E=X[X"43n.V#"CstXYJsOS7Urf%pg""f4[tZLKA\iqZu!@.(-A"t`r'_F>J2&fgr CYT;7(?sA?JPO^P7hg6,Hd;<.!%6!(X.9;Bs9.KdBW!hZa@+LCCSI!(b0VK?,PJK:#bqX45 44MF`FS8=_E^lOkp/N4mGpTl]&3!uY$AhFSEF8OYU;I5skl*jQ_/Z9.9lI6<u Ce-Lh[Hj@V=[!\T?<23DtUsrm1K]l>=]Vs>MW!d)q^_?a'D&q-]Y0l?,<8_p),b<52BST]3 e3(0>9iP+pNh:9.amCETNEK8P>"c)J#I&FX87_rm^!$(U%ers,^flAT_G!+&<\7iU0Pgos3 =n_Y:/M=QJ9-HM4h:4`L7i$P[*Me.cIVB"Ii-5Gs>mKS?LS1)&CtD`nf%4`g=*,ibK? =WIPD>6>_XMW$aB"T8hG+dCc5hF:rIHoG2bld&fJS=_KnU97>R(.1fR$@Ci,+,i0M\s3fXY i9;/ZYH568.]f_kcX&DF5t/o;6@Qp:biaZGKc;.7XFFVrjQ DFY')a#+i@7C?"C:=7bV*b&VW'dD'p\m(`;=jc_@KtUAlC^4p&hja_FQ@rK=G)_e :oZpel*$u;[(6?le58hb#:90dnM`!<0't#3`D$`e"+fj#\:YOB2dVLKP4ZrW(R_@(gdBc$!LB1tRs"^rUeV R!+4sgBHMV#-_#?Bh-eK(0D%^fH(hDAV/h5)H]0AfL]F/BRVBno\o(J#EW3p\8-aG.Tj&CK J4j0E'Jp$F;Ir=fd8+VIOSD7P8Hi*"P>?[AGBWdDM8'N#=r,(*6nf!E/)2==j20<'`q2h"_ 2DCj)LiJ-rLsh#\0tC3jkk^Y!"A=W)2>8:t0$Fh5aBg6(Al#`ggbGK'?J;(#'.6d=+V=i(! ne;M?((>>6'k<_UOskZ%%uUXK"ZKt?$Y;<9CAa.=Aa9FHVpQJ;I2##2qh2(Kci4pB#Cdb>2 cQF)N(Ym;G>he2m#%_'=AmH)2a]^FJfLQ20CBWR(#3]$@5]HtKS;_E' LEq(6ctEa9mg9fdh@8B!(3NSa7LK[ckBm!1R$ca245Q8ukIu:UaM;+t6-a_(,M:I9"n1XrE o.(Q%?PB2BQdrfL1kI[BR&Z!89!I7?d%YOL%n*oVN"rsNShhS#1-Y.eS#N8;^:)GbFP)W(j :W6=($cL?uD=hI[F0uQ%a1)#;C)S[LR$.%I*9h='cD1Nfs^XH&"(pL'UQZkZ*8\([>lTiJ+ :4p)2htWaWoJ@Cq,H:i;!$Lhc2GLM0kF2Btu2Z51/"#&$/%p*o!\Om?>_@\JE7?mGrt:4l: nCUo:W&6=H`:ktER##Spk6_W2pT/o]>g+G>N:;gXu;FSSe>#VESAIE=G4lbrq>*_EWV5rZ( c(!p%j@![nA%,u\dN%YZ;2)of^idFF:p7T3mClJ8``#c1YANT"+(/=Xq =nVWT`fgHAY*$f'@Htj<(L6DA^4V"NQCOQ0ek:ggp.dZ*b*4iA$La5Ap3ZU?L[)l.+>DOh, W$3FkBu]?8L>$kNmSO/eI4pTP$H2k=5Af]/-7G8mY8;1QH_eKDIg@f^LKWn324.8@sXd4k5 4qV6Ft.V[75g$4X+HXcOFQ/@0]u^kba4Ai*:okNq"`^EB]Ep!-&3^9hmP""mmWAfQ`6 T@YLD@n\1FUQQ:(_a+oafL&c?!/tZk?TCOWZ2Vt+MY^-LuA!pGAKtpWB0Nj(5E.r6t#1->% QD\JXVt/^u2sfPhY,l[\12=CuLQHW_Nt(\_kQa(LKVl$,\SMJ356;s>"1T4aB0C$[4mQmJl \U:LGY-ODW-*gR`luMK#&%?pVSKbN!Fo+2cosF2cGa:D;T6AkFSoIV^-1hZVX 1b8FZSMm(=)SZc>@SlJ9_C(IIL$j E&W]YKWjW&\q]En#Cd'D5EU3sTh#$0p4&UJE- -f8)23l:L@A4Gmk=7p[X22NlCTkZO"pNu16bU_LTkps?bHpLDhV:YF,=X`LhHn[*sP7ticd V.n&9A1\'I$K"OJ]A5KOb3RY7/B#C'a4Z'(_d8fmE;7.7R12r+T*4OI3X]9YtA+k>=+?N)Tbp%Mkhb#AS)+8.p1p.o:LLZo[@ ^&G#(-&?fr5Y$PujSnNsg$FI]LMq(.np_Pdjo*?i^N/c"FDg(^Al!VpB(>ngA:pm9"41$PB L)f@BS9Jj#Qn'T[VVbjYZO!s['O=)(TeKa4sLVq7:MC(S7UjVIQul?q#lF@,EbW/dWn6X\b\PC1/lbbi[AW`6rceS^(l)jmu=\S7^.3Zq<2&O\;IuBiOA/5,D,V<%?EZ]iM@u:c) /:VWE9E@'NjNQ?sXLc"aU<=)KG`qW,G+4(?U,^#h%q]O('Yg]d9QJ&1&^R!^e>$[6VQ*tl5 @7jXAA9&<@A`:GiMc;/N7]`*+@UXZ\d\lMAd`YWO)(L)Z6_DckFSafGa&Pmo@3o*X'467,i:2)?Spqi[c0FqIrSHFeZfUZOr -k8f[t1Wf2`TM;!Q]!iE!usP5`e);"Mh6Ep3a:Y4/B\[]Y:e!roXQX!;[gc%8r)BdGsX;kEdAVc3Sn$W'9)*7:6W?X4I-4TE)W: GR4N=m`%e]"%YiA-3)LAi'1L$"_;9QM-68j%StQ5tfkf[`-AI@j#t\5WsXYmMr6!h#uR$)W7T+ IQa'BOhV37D3YEpC55agt*:gEnrZ;eTTc8IFi`"f9P(@V1e?6*)oM[C7;l=XQmCRZ*"ST@?s! ;`cf>,CjRe^ZgCsTfsL.!W;^.aK@+hPm^o@`]^Hfrn%S6ppA)7c,WP?sE1Aio5S#06niW7$ D]d#?*1nOt&;0d^7?D(>29p8jmlErMALU/9PQc=8:3@RY;q:QsDdh4??%6M>p78rr>88J(( ;tEu;\3B+Vfe)`+(o$2Oa0mWQ]_*XJ!oNrhNsr#qVJE\l?cjP[ukpLs2"4&?Q4lM6=lRtD7 ,@-9LkKT_#Ri2s,Z@=I\4CBr0lZNBPIucTP4VH4>[.BLD`o("2JR^!oR#eJM97l5mSJ6@&+ Hfcq4^4=>Ku13.i(LQpD.*5mX.m,D=F0'LG*G)MB6R%H8476MP%!+d=j=OPUkmOPV/#0Q\# h-6GV]Ih6'76\s+s,Xbau&`QbaM30tJ`>G-[U%igH,;;=h_4DghJC>,4cte_P&K'OBAK^N! 9adZ)0*ZsmGNKUZO*A[M#12fZYH68EP>Y3a&R(77Aj@)f"WueFJWQ$7Ar)R11PHsN)eH0C( 5X5>,b\[!`P@RoZ*ZVR!BJ<5p">8uP>0+Mt#*`Et hTsQs&I(GG*"l'?93e=TcA[&7ucJ0+%Fn^%P!0.;]9(9(p)@=Rja1C1Ug+5W/3?;iXe=m[MI HKXeiA4c*agc#3=]Zj++V`rno`Nl5lH7KlHH"6&1S5jW'9)\W/u!\X,O&h!h0RiXetEa)-" UXke1;HL>)5B^VGPVj)CrhiE?\5@4N5Gr16A^!#MbDl)s;f?X9N>OX0nNW$WDra1U-a>g$G [h6Lupck\GrGZ?V%q=U7^\@m2i78Wppf\-cS2#cf^)_doSeY]C71*I6/r("l*FaCr$t83q` R.$h`Csj%EMbFFiT*uI_#u9CLl3$:#_GNZaVjXr6cdZ2;iDm=.?"8Z*-/4_)c>V90J6?]Z1 :6CR1Ya\2I4LoIQr\:9K"/fAWg2f8sTc98;>DcadKm7B+*+WF/F#C"!h\;gnJ`lOR!oI>$O ^+"e]raJC)`g>E/0`T(HWSdFpfUBcSI<(te2D3aQK6PHZp`W,nI)IW&s=_l0sIUX[?2C^Y4 EJ412@<5Z4dN/]0Qa2$gVj0W2$l2@dJm_,83qd+(:Ks5_Gqk-n)A0`>4*!5'Z%tW#b;-fqc p6O7_RpTmVg,5tV]cOpmIH_7#E%8mfZP*ZP64/h?:3U8/h:1>,DVASqolWd][3p<>SajGg^ AU;aen+6o"i/\Sr#XnBEX]cB1dnQGX4;g*`IMh]6bk1Rgg7GZRbu+Eh\tO?QFMnd1)+NkHK eK^kiDd5*s)uu!`16GJj(3KW#%$>RSY n(6-:%\4OgT%e0fn%3T!88GZ$JQ#kgG#H2OJ<00V@ZJ2#!u#'K/'Of-"5pdQ0 =qBn%V=!-r:tlG@hVJ_*hb[MeOQR+uq$uoZ;uOq0f[j6f&DN]Rp%2\Y^Bj9>;s_);\(:p8/?'e9%i6.Qi\9LYZ=)W @!IJ\W8Af!912k>$@?O`qVeI'URVBF^!.Z&7bBL:&Xsl&h5KL8O4YDX()m)F9nYNisAHXW% KDlYa<"k7JZKo]qOYm)tjb#joq@BT @1!k_BdF:%L5]=110XF8>k^d@`sd(1N-r\WPp[*'-SLZ28C3>efT",?(kJ^5:h1IFe/]/;c u6GlDo!mNRjnrc.fgJ#_4LT!2LGTQr1f/ZYF$hdGI0d'>#jmg55dhXtljVk$&7GYK'5Ir]D$olPgP"joV"O[VI]6U)7LXm4mb+Z^&E;&*%45QSq@_&Pjoi YeG=+6)@/!U(T`oGMZ:(SRK@Z%3^u/Jn%4(SO/0L4^>jM&>BC)(q6nZ'OWoT'A&.)D7^%Z* PA:ZPro2_="uU`srWQneTWl*'juDiE-dA9cb"$*V>+.0'me&_(:3;)?ILGB8XCOK1ZaW8lL :5C\9d]Y=erV,Je=6*qW*kT'.)*b"Lh&dTJN jrSR(O#!+Q;P-poUK#[5'Hp3j19g^TZ7Vg-,b]`,@dP^GO]N99=%qs#6.H"aneg?0*0irpP 35rqiE5,*(a6m=1p^?8T3;u(dF0We6(A\]#6TU])e![rP8d`T(L-JO>XR]n_.4"+_AV;jW. ES@!I%^7+s4Yp+(=4sdnO/t94&?.?M3tJF&Or]rs7\A$t7LS'6.F/FZ22l@.:Hr1A<`WUIp gr:,'QoE69.$=qF+7%2luKo@*m?62DLQ[tM=E&8N -H4\Q[&j_`m?su9#Im3RW5;n--Tp-)gA/h4.5Z(TsQBi"(]G*WtNPSL5iJ\PgqIBiH*$NlS +b1KI`[E"J6?F_F<&8@?0l7,/6]Qjfp=htfO$qRZ7&s^3'N]2%<4=477Mb_elZs&aM+3_C& 0UNZZukZADAN=9&-5Qt&uop"Vc2"+2N!Cdum?%*40.q1q FJ`Bfj.9C`^InbKhV3'1@^5?rFu4^kc9!=#KRj;h[.Jg+#5_JK#=0!!Gi7@`#7MV#kit5QAK:"s,X2:)5-m4;ur*3Rm7#"(?% (lJ`urAO$UVS)1fF@(;lJQEa\AQ!G47ie:9&`7KF/P#5"3q052h:XoJB< =&ADSU#M`TG8:VJSH,)2A\Zd'S1iTJQNcJ\e`,R)u2*+2Sp=4[N*Wis4*VcU0iH<$%1@RI. u6g>"U;s]iGkTV+E7>6:`%=a<$b=VHu=@AH-qHlkZBGaa^>61>kf]H)QP't@t[QtNP RD6<2XLDY5j"rO2M&5 2i.FJ;'*YS[[_lBe`d/-%K+k[qiFeU7*NIGs.A'T9GCb'D+@S)ljh/95]#P7(H<9)-\#)?Z 3Jd]K'\F0tQ^(a)LIV&A[cN\UkTdh3aUiR60T")s_LSRAR7S*.U1'u?>F1NnIA4B(P6&06)MqVSI3.(7VFj:5QS%[G_UbDS*NGDPqDW _j20K]TKh=TjSCk\X2!#Qs8D,R>&@8Q+ihU^;k:cqt$\Y\/`of^X;f+]EdQS=\=+%k"1*=6 ,N]='H"C$_D3;EiB[#43Punj_f@PW)<&LMJ*@5]`/f,7FTYHYKi$Q3lb3cerL_:akBDUId3%(`6=ZKb+dL:@REGtq9/ ]JjPL.1JgDtaoe1Pt*F.FjT&K4a#gk4?k'ncLT.7UO*$$$nNe(pTSH8?<#P7m"eKF&qJYpt o>TMeG)#l-/Ja?m14juW*dbeWb;c$!_4g(DupAr8Di6WK*s4#jrp^/O.'%>B;>NR#j^,lm% i@Grl>S)In'g!Lq.Ugr"J,:77qd"eSJ`n-"@IhpO1;WB!Tu%hDWY^.Bg.A"XJTMF=TG-`5? i@Oih8S.ia8Z,,).;_5TrJW4!).8Xc7h4/&e,/#6K%@c<&tJ#)C6g)NK;%L4-BFp93\HbpBpr(lW+l*oSZ6EcY,A= 93l\Y0lA#\59,r\[8$Qm")=2U<)5c#o4/_WBI3'_\Jp%sL?L,5kgW'!$DnFl>* J+m@Rlp,=S?SH",G@urEj3ppO4?<]Nl)\0CQ1G)`RNiJ%s2,Iuj^25Sse-i%tLd&/GDaGSL $Oic43+`C59(t6O8'H Mp[36#8+Tu6hDiK,:lh\Z1+g7T_BNQ0Q)o)9-%"U2(%E1VNeU`+(OA]O)bFf$/nE,$HZR(E ZRXaZG'OREGCWtZ:Ga?hHW_,IZkCN9c)7??jmX+1%L&q8i%V>9TbPq7T`'H@4WHgBV,eZW( I;W?>9p3[kttKeJc>SDb^GLQkK+$9DO<]N["Xo$jpQ!n^oOMT^EoEadAY%`:b8-f:(0"m7j Rb2WjVZK/87%:-$EV8KdFC"5T"mi=n#/1,)/<`d#fd:`[MOdn.Y>I3cr15%j6ZT@='q,P8* (;S[rYBpCEMH5/e:0Q7U+*'T7rS0VkLJme;BGfWa'J#`A\g& 2(kat2?k*H eg,=??gtCc.!Q(+.!@_#B5H\%ZZ^/%$fLm]7]<+)U[g =q]3'VSnFRYe4j,iiB]UhRZaTSYgfqC5Df*b6[glik3_)tcDC*>FcB)uM&AC0Bpj%,Q)X0@ gWH<$[e%4.CloPH8o'L3?H1+4??9,cG-LL!/a4,6iJPJ4ZR$J^Y\3g_1:`UX1mCs1Zq`u&> IisID^_d"O?gJ)LE%V6DUSMc8426DeF!cKk[!7SXN^ZB).`3#l%)U(\2oV/:L:DsU_g$5;@ [pK;pnnd7]MXSA<\;<.]P*&hFVa!'@uM8a0b@d+.7:o7(rDIGO$UoG:m!(N"KIj<2,$`$`. 3os$RfRKV3OY$SJ6)_7-1rkQXi4huAB^Rg)4r_,ks[%BDJtbo)H3'13[Y$NX-N gf4Geo#/Z$aAQZE@?BKZNmAfc[?P8^f/>o,8OYk]B"b%b7@bGBFa9V<@IVf_X)AW"Q 6NWHauQ+2VePKJ,b]iD+#^oa4C%Y*e*"g'YJ[FZ)Y1l,"m6&%F'TenQ6:pAq'#!d8B,:#C- _3c;IB[!867ZZpd7%f4K\/Rbf?]DNdPlP3P6,U`gG;&(ua-h!3i]jP9l5?>*%?82C+)MIYkOsP$F?YE+H4N MZ_T4VF0qp%b.-_bgj-j]0mQ!c#lkeZihHUG:f)#,HllC/PFoKDZ1[n&HqLg;" :oK(g/YMFQ'GIr:X]Y'#beBhL[di*#6a/$Y@CRE>Cif2fgg1[\e8l$Q5O1`tlP]iGNm/gY)op%CNdIgLAF-)eEi8'BhjgO"bd /Map0@RLK/)L.ao*KYE6V:!r8sD.?uprZ1Q2=1-p.p,3^#,!l ^]H+De*js366/mA,JLM5J/LXaTK7H=D3'"E<3s8Ak"5@EGE+ZtW.^ii%6GmN$o4teXD1tMi L@A<"=DnAsQFBOD[kop+'K&6d;\_Su'kA$j5^eFOIYFG53D;QE_-f525.C_[\.h3Gnt^rS; 21j!._J0LZE0)MF=0G6`.SRfN"*^i8t2f)LY.&>j>d_6D[1f:_0f(i6r?>$;8k7%"e)t,Z+ *3_R3;OECbl=Y)7T#AA 2aBOM(&Z:;1)`k/Ore83.cCcaAq]486$6u]b'E!(VC#:M`fHb;GiG/n-;]A(!$lt6VD^d/r e_)-O*,J](R>Qn5QL1"2?E,gUDEsB-R]^*j6;pEBoKZIt`YX!PjQubcnMO@Dl#FKdl&84)> =$F!P]mK&M0OY+RDM8ogL58NTKA7WN&j@"r^'pCC,ah5WRA-otK:j%cQo;Z^/j==s8cW`4! '(94?NeT7+]s+_)$:*DPDMhq_e_2c$h?M\oZFN49#!Q"L5X`9.^f:M>49_5[V9B4\UqsjR$Ht3^5f?8g;i?C_EsJ a;%h*m,eB,bTb.J.@-SfARgrqHsEJKX#_0A>%,'Uku<^E]!"6`jATJm!MA\n;r_@5)6"PL2 ^.lIK=L-Rf.83@#WAV929_PH*VXPlo"i529?_UE8:j)$o30LHO0#+RNqPc7ERW6Vd7WK:s% 3-S'SOp3%LLD3W$j*\cbo#(\&6ko71pd^#8^Fb::V=Zm_17;cH&(2CM !0,>aF);J;p['ncp\&(W,YN0!)ReCd"MbPOHN/MF9YYOTf@&s(edC5@aOKQ`[)0mnZE)+=p '>\"V?(eY]`j3Ef+]1_q*lVNZ@uK&U Xe'Y0;K4d_.,3Iu,8>U[f'sZL>ZEEtH#/FT6i,48,6W"T-d1*V5*P'pT22;HKKWFLp1 $0V2I#!ipdG5eijh]^e_V>I:;=u)1"X2Z"["f2RK-AedFX>h>-X?DhZ^u>t$O)9f(U(bD0Jl>MTPin9tVr`eN,h#*<$=%GfM#4WuLX#5D1#pk&d\:'2 5"4j"^,h+?I78R?O0hL(^qO>d4%9KltLap<_,#[%:)hE?SHLObQ1F!Xsp>m(dGM1n@=IYPXYLM9M<88\Yp3m?FmTX\FV"-E^?@Fu$>6 (NRZMeC[JKOOQqfJkem5\5S070[EdKNMl>a@?Gj4G7T!iaZQP`J\3&.>DM#"E7t+&4hOp6A 2"Ec@(i.4n@V[1#k-Uj#_;!Gu`gNH3]7R#KQj@D]"jKk_Ba7h5g=A8fk"+R0XbEutL?-TfL/$ak:?:qub#!*ri+n%N3npf9gQkf CVGs"OE/#K*jS?6>n9V3r_qZSC>W,gJe88Gb`b"h^jo@!9=>,Fp5QfQ\>eXb([!'lOc(9Y$ i;RCu"&.M^O"EnN#;Bos2:^jNf%jqVk3;i"TQZ(0=N,6-LUlM8W-!c%)u?GrJm#XBPNGTg17#68?@TR7!nn-;-6@n$"H?1 c[5NJ],Y"Vk4uKj2_0?0O6C"pOm2`g)J;[T55nN*TuF?3+c;!7l*WbH:tU5YSNP#,T8S4; `U%K^#(DM@0$.Tub3Yjh:=]m$G[2&dXBDtnm05]?(-EA+D3jLAA+H^)0^h\KHKmuOl9cXdKcaC?FIB(?+?LIm1YNLG34l#\uJ%]07@mf$JH/mdZM?efM<4)cg-5X,@ZA7f0BDh6\UCsH;JB^`C-Dn,CNW/cY;Gm> +(n-3fM%WFs@ITuO43IlTj#^>#oFO7aWE/&V23,sYV7u2D-K`F)eGYA0NI+2JQnHOM`(4OA g/-2>p8`f9pat\YG;hNUbZ53gQo@P"LaLX.ptBQp@IOT[(@@D9$L'\*;Y8-WTFCM-&p#.CGd,[sfdFG@A]Lco3l70 L,8"F*WFQpV"LB6:@jlt4:\(JscOa7V@3n]o>N:K?bho!`"Nka_r-fQ:s'3c,ATFh_27g8H Kee91GY3*NEooFC8D1A3Y9\@>l^Lj_Xe#:k%&jMp'MQJQe]XbO-sF4Y7%f58U-HH7d["pdb ;Id(a*EVD2jDI>@-3+IXRN^p\&"tHuoJC3,aiO k#V4pSBPoT2XetIh$kqAn9<=d!Vj,)GfKkJ^iTe-=1o8n#9)+`c*F*S+pPC?"d]MbT9V+bf `]%u"-A:maA.@X%phqrE?>b^-_:(^'8D#s!RDHZbt\O\Pm7H3"aF.'86 ^fsA9CsSeRKusp5a4]NJ,YUMN8op)_]AN,O%SlBiSPf<40L7Qje_;ns#peqB R'j5#_l!6G+M;*Qh\CA?j@RWI)#UZfDW)H[ti=\2]$-CWl3KmK>F5m\5Y@"%u*Iqd28ZS/J ="2@ki5XFu^Y(aC6`dZ/*dK;n?+HVsEU:s-QJl;`UZ)D)[t[B2cA%p3f/u:hT7;UVYg,><< YD\lCMP9rM"U<9g;LX&H'"CDFFoG-tYZ=6rs,-%aBOY.BoJk4-*nD7A9&(H[o5j*/(@0%ZT Smeg:/SdfS5+q"^3_Vt#eS7WudMoXju)*F3d,F?OqT8t@b$U(-/BP26QHQCtS=D@FhNE3Mk YLVu^gF\0+D7//92d:^ekBXi"E-JrRZX'=\F>fEP7\Ys3cK=`p>oon2XjcV/HQBiPGI-2pG WXb(-]cO3oQD8CAlaiGn";n;cc97`QJ62Rh!RWB_u0PM$/tN&*N+b.AL0cC:/euJC/G4%OF />[_N9F&$,Z250b)#h3QtnF`o0ZVL.E"F8ACdD?.A_2+^(ObCh&O XrX:QHf%nU4b'h>Mf[,^Af\OQ4/kK&HDY5X,sZGm$lNfS1K(ig?;hM.7C*1Q19qmQ$?gGen 2qQt>NVG%B8q:R't/?+(sj9C`K?i*D#Lbh$.a;#DT.]m$fWOS!iG:crhch6QaWVTef`nomgI\38"\pf>*!(7KkYPS8@oDsIR%KF 4G"Tb8A#D#\u#!dtb!oSG8Je1Z`$%YW)?4bnE0Q#dba>F32!8JA7lu<]fj?LX$e/ccdRDRT Z$e`HPL![gX6TAokTu8gD0\qqQ!Ra-'A3js?I!C\GmepM27u:(i-:EZ\'&n:5M@iT479H<" ihT&*&\]nd6 4b2jP\S4K%3a&C/KZ4UB++jh,KhX"/Fl8&8NA@JUr8O^-)@r8de,!KoV!r/MGP,Z_Atudl4 ?8Zbf\Bd.u_EMQ;Y_+(iqTJA41/hL7+kpk*[l7"M^=%qI3,3<,kBa/fk7^oU^>r1Zif,RBo Y%9hD0=:C-\96]t]HiUT/;Gi9UYbkqf.b;i(Kn/IR71QUMk4i_6p*MZS>VXur5Vo!DF;r2q rOj5[M(u5mWh(pBdUaAEc1e)R=)$GV/NY8'a8b>c7;-G25kbT,je7OPrYiZ>AocZt"JMAKT 9T!OLithbdI*]_Z3!M(7(P:FA-b=,cBt1,Y,:I6>)LV?%_NRltTi3G@M,EOq8Z9$KNoNGP]h\@7eNBj>-.4pRd!];pPRXt.f./u@jHfE 1uS9E)U25k$:k7=el@0on(/$Xq]lLp5GW`X0XSa^N_^LR([UZQXiUa)#*qm07''fnX4;/YB CNKqlr:9P=ZEo,bd`Co4dpCYn:**(.MfP5A$lj?VcIA'-@;0aKJ&_h)h;%cQ2Do\j%:M05R JdG3>>F.F&l\lV>E#0.eM*E.o>Y.`JtJXYR&A`13r-L_:,/i=[0\p(==hn0dm-H-PJH;?a$ ?T4eRD1t3%fB3'>]D[2_"oWf!aEN\ldUhSj-iri\^%_GF/;_(70lE5iU0=C2LD! C/JLp*#)KM@i0AJ2;rDnZoSr("l8`Mt(sF`OO0_%3`P?0LTFmU[3D:fWg(7#!^12q]]PjMi cr&i>t\a*9>nGPOaH*b#qLi@"Il3#>!ekY4b%jf_:`mmU"*tK/$t9*]XEIRR.+XBF?"l5I. G3Ms&0-%<7^]o>I*D;I;TMSGAfKnQ%51Z;Kgg9;1GoM9s5WE/,RO3WoG0Q5WM$kt,ZeAXp6 T9pT)=90oKC*h_!9Kr*"EjuWdSfUDZ>CMM[*X0lQCeji\\%:MsmU@+Kt6hkm9iN>+/aJPKj k@)^RJj*^O\imt#I#h_"3>B?mlD^M_h^4H8T'Zf*Q:VU&@2sQBagmbkae^!$)\*j=pr/hJ8bDbW)YUL-:l>9ieen?E@.nQ?']@=k>.]>iP!if1p0fq8IIlbLBZrc@' ##fU36OZGA5WBYrD=NNlbBV0(H.e*MN?``U-X%l*OU?X9/NI;_u*h+?3U-H_Z,g$.BqWS0=mWV%=9!IEX&q$&Y=+,sL7*s&f3LMfV>( ded[gb\E'hnSqn#NA"2&gp.fU_P+m&q&>!#iR3s)hXN(oe3Gt50$V!?XN3,JW)J,J$j*EoP k??Fks>nl2:R^oR=H51<2ZBr*ReHIp_UAs2XpV6_nB8nZirrnB>hSbg6R uEiClT^n/]?bs"GiL+mp=Y[VJ02cn,%rXT8ON3]k;$?Af0-S+@+M&QNr!pt '#&Q'Bn8+C"2$0O:e#p@M&:FefJEu6'R/tkXiHWpj@0nWM$#O/YY`tSBef4^8lqZ[alkUD^ M[M+n$Y,\H!GjqcqT>Ms(nla,@;m"Obmb61%5?HDiS527;B4Xh&YZuR@.G9\3=bQM%hSCEY k\h!pCK%W&5`H>E=EJa&J1'>&Ffo6T^Wmd((;@h&4!3-E@VZa/J>ms&7C_?5mR\"4VSJm'J W/n@/L2qm,#!HhN:qU0j#:Nl3*f@%U_^@EGH>PD&4pH(NF'S.SG@6bI1boIDB*AQ4fESVW 965&6p(?'WW!H]/um2lr/+#3R5EW$tW!?\TL+7]OMiGoc10]KAQ+Yjnp791*gCoWL`j:Wa! N_\Z<;'QFZ=cQagOuh^)bZgpXXbtos/oKiM9Whe<%k`1l&mVVOne7\e'lJn;%Zoq8T-k7nl ,se+0=(JoGsXN*MJ-%&48kT5t*It79!*IN"RU@@kW8g_1h `1Ek0XJH?gB!"K%B%tMA55kGEUm8"Gb:GhlCFT#!8!Dg**:\=lf[0]\&#>m>f;,mN6!9a`+ pJN9J90o!VJ7B>E0bnge't#n6@?(hJ8/T/%"8,)^Pt+f];,m3f"6#=O!(7_*a9FM1<`NX1@ A43]F;ghW$5IXi!Nm"7XrF&m%Um!`T]oRdO''qp=`oZBiB.UDOqU+U'k&X*!DjE:X]lOD>; `rqFhM!Z^_$TP'>ZOLZ54\7d9Q@p>h.Ke5qE^9Bd-R=,)WC%Ou4HVnDuDc,LuT8(&SRBrYN jq,r/>*Z;+^l(F>)k-5IG*@29@SAE^=;-^H2/2Cg.e6tDM34VQKu60Tf;JLQhEA5nb'@tdH @i9Z3&*MIqj;i:6`A0)-fdp\aaiR^0"E5ZpB48*l22L/s/I:t!_'*1S>08VPb>r@q1Ba7IS Y7WQ(/@uQY1_W;7P>,aLZ"\BHCNd"rP>2\\BY@Hc2UcYYVhVndXZ*FT3#5j\o8RV\gMRDrA YI&M+n&tD@M_VT59[Eq1Tt`gWGiNUE,UOEDibVu8/g'5BCitfiTqX0qdXgr4dRO+QRl`7g) a.MDZXku+mL,7q/eFeFAqXMF7pW*m"cHtC8QI[&&6'kS.J!*uC$\j5`CVll1M['U6X3=:Iq`&V*/< *l7+]m%mE5ehEfE&4$(35l;("\.;uV;0Y)u(ctT^6%er$K@iam+g;HlSkC[2KlnY6@,)"GP Ra?d;g<"T[5j!:C8,i8<&I`W2,/l$Hu]3_IDA,GeK$CYSBGT&Rf8ciE9Hof3LA`NHj!5V,L[f4X,.4?=A%%dPG5fmT=@,?a; lW@.4ceSe*%q'4CqY[L$@;&!6Ju-+4a=lM(u7nmI1]-Hc^)q(6(/0k1iEEq_"GJX@BmR-QX tICImXfh3d'OscEc[?@G)f&BOmO;hWPmB!@#[Vp!5JX7/hQ[*_?\T=+r5SW1^E%`AMQF1M3 .Wop.1R=pq-XUW;:RLsSR+\I,)5\:&";9[k2IWU!Th0(2IY0:?oP[B>H!ciid;E+;SEIC!k Kk;hB4V+<*F[E8QMkb_nSjofE)uu5iLCM=4rQ<8)OZ0r)0qSC)CQb`)Q6`$\N-AX/#"]&LY #Ok0%q)IrH+JcFOs0\\i,"gX<""dPr_L4\kT!p>TTTq)l(7hTnX-QH_r`QVH82CU(H(16D^ C:*!)J(&*P+OoH,77)52P+f;X("NN"a7HPa;n\%/L4Z5b"N%"ZilGK5*bY6P.iGrO9^6c[_(t>1-)U3a-d=44,4Q4R)+^3#[^76XmJ@H2oRck^L[M>t-_!DUS_9rsI&f^oH%%&dX (e96=9+YB'g5M5IC(t\!F?H@5E2&Z\9iq>\D6(p//1)(NglGC\F7!'o- 8"b?eG3Yi:[d,TFdeN]a&j;Tm`%]%D30e&V0P:Q5@3qnup4;P%t9d3AZil0tnu#PBnOL#&k C[U`HfBD"r#M-Z+.PG:B42Vjdq$?=l'f/dR-U' La%gb;Rqf9&RQNIG\ZNg*2k$E7&qQaGJNYpbI5aZXH!/;^q:!/"DoXlia%!KV6-mAh4riPH *dR+%H1f8Sq4Ds,E5A%W@6tlV&/rASGhaNVg(Ge7TGt`/^:_"Mgq1;:fG[&i`u7Pf,PRu2d A*5\UWe<,!QH*!#L5Hnc@"j-6/9]e_Am!['B-#.@,%QL!N(8KVTA0NJF)#VdM[U:5&RXNXY r@/jr2($WEPA2]d_ChbGgr(WRnK*E(h5<*7>9BI(HZ6K.VKf>H>C9^cbcLVM%cs+g$(>XSl _]Yac`mar(VXf8Y11%>B?/mFWG5JHPU1WOpQ/ll@7YbTU^?Tb%XE(U;ekg3XdmSYQc=X0P! CZF)'6KX;WTj9D)8gj;':]0-o+6*tlfh*I&25X64FbI'E/@CPG+X+AMM7EO"iBA*W[GD\rRuVAPNn^=i(%[K5WF*18O?!Mga)PoW]t@Z?]Hu+@S '@)P:_c8Q%j>.d=Y%2b@D6&WZ+K8DhJE'^oiS;;>!.QLdCqY_6=YgQlBI]&)@?7T5F;:E$37$&FKfM !U:[+Zh8_f+2R:`+gD,T1"+d"-7:Qp#e6Y'ON^r-X)!m8K,`tNVAVR2"Lsn8CjjON``b@5u&(tSmF!0m!Skl 8jq@s3k5bh0>oNF[9Pte('l'2Tu7]B=e$5hql,8fD^Y#h[3q\=jsaYnto#!n6Gf4q`u)M\q MGrg&Y?*:Y[np'HA9ck*aA3ut?K>QS$fUPDa%unP"mM/7`7fAH>u7Lpf%5!5*,'F=fUYX B!*'h%Bm6]U9%%QkM\!;o`[j:OB\6Vtuc%n!T)3>"XK*((?,nMF/W`'pq/@@*jJfbd1UN+X )!Z,C>s7e,8T*_5bmK-$S=1"q!snjJZf8TJ@2-V9*HfQ<\Gd:"Lsd]BW(9/>S502$?`].cp "'[&2So-D^>9f$>32bd5(Y:%V:V!C*;o>L5`8dFVYC`K?eIVPBAnYgERZonjd;05eW7+(X< +\,EeV'eo6<-aRBSC?a$4k'',p1G9+=\_s9Pr2E;eMUo>=&i7S>?KGKQ"sQ(opp/.=&m4M: )'S9&5F+O'o?AO[OCE3R?gj@A_FMGT4qHZV5%eZG."Ym>B[]lD-PTQ^N!L;-,F=-O!E*FPN =O.?/>06-r-4ABej@.\%+8,d^7!hIo?%>qg`(!((5ZNpa-T*@5qg>A",tCp3n*k%P*HHoa- Ru*/0NdD.C*T4cj3"(/'aY7.gpu=SZNfQXtGk>F9#JQ>;lMq5/.tO_"!P8X(Qi1f>72),P0 V($:^UBm"]A?(=n$e9E&j"Ga#BneSL2CHCUeYA7>H]j@R\bhleofee?eKTcVd\>'ID9RQGCA(ih"Ud1J_t]9-\p`,6WqK=P6bNaK_ `\jSqNYhM.hC2eFtujH[b,0I%;W&g0g3/@=2)Q^H^!8I=G>Qo_nf&iV.dcVs!r+?cVL1rr: UIr]g/63e`B])o90=^fV*JTL90=:c8Hlp_a2WF:j+d:('?90a1t/"rlO6/e1_M*(NlnKOP9 $_K\WZ@5KHf&?Zg9fO5-uB`&o=amR&gp,rV)a%`PP2oF:!&)n9eLlhlc`&N'("dkSp_WX=t G>/cW/5qE<;CP%:Ync9J]:aS0Fn*#iT/>Kc.*PZaP$Po4'k[N:Q#WsaS5QA,&gp.i3=u=7B!+#9?n;rPY]^5f=F1KdCb:/J_Gk3rEN6Vh4`FI(OAl[o*%$ Dtpg1#hYhAlpBIagmZrWL>g3ZAc`lR9_eYX:F_;78D.tV:?V"1j,q/.e53k(F;hQkNI-\cl 3'LP`@%=q2&=*9b1G;?b:QCQG>!;@Q[ntFP@Y>DC@gUgO1m+qBH3ld'P[F^[(MrDT5m@/d; QaZToqq$46Fn36_c'&R@dQ+KgqnJKks'P[)J8c8+^kqE&NhN3cii(KG!SQJFN$!^Z4qb^L: CCT90ngWmeeV](KF2EGoPkWi*s9CY?sHQd;kX"/G/Rku=8`'fQ8-C@!ug2^D2rVU4+8jj!^ V&gOE(OmK6\7VA8I),LELgNA#)Es(h3s4Q;Ykn7k6qdCPnYC3ertuWTEuQQu_n0bR'YUMW" jT@XM_&=gL%VCu:_'L3(XCf/UaSei1Rur-JP8FcM$=2[7'nOKoNe83IQYFA@UQ6]c6pBcQ1 =kkcG(cuP+Se2,((+k)T^LIs-a.4$%1e2idj&M^F._GmT`qQa+anX^^$`4FN_pKGc=D6A$$ ]9\Wb@r(mp=2oJt"nO:Rbi$PO#,l8B,@!?*6LnIknUN;lO)%K2Y;m"^W=m&n3e#(t9>nNhBL#s5LNl\D_h1W1u7UK0a7;49L9.3AoUP_ f.`>$";jPq#%.5WfDm@"hFj4/X'BNcFo:aD(&"]@V+e,;GKBCI=>c3KoeA5%0k)QS5>KBup mmqOc7EK=*i8drXXITZ;TU8GEh*h#QTRcq$Qj7:oo$'q;T3cbZ.8^&SH$'%No/Tua4hJnm)IojkGMDM5I93B?I](bCp@9e)n Cr:#B@6U+EUJ8,]D%okd>jp5/i0`,)ri&2@B;-Q0[Il:T.fATVh-hG^jX\ANTkk":-6J:_Y ;r2f1>Gu49ep#`rDAGIVa<*s&\I`R.^RAJ)QQ?Q:V"Ia83Vl_Ar_4l4@D,/$c3)^\e&)U)Q ;d`j4Wn5YIK[;jkF)+bt#B"aFm<8@p'eiP<&eZ_S#F`!nuu%O3rY#>f-<."$f[GHXP@1fP2 HA/7",(I;4i#@M\/H,U$8H3\,.LA5KB:pD`iDcKYUHe\XY2!Xuad J]%hBt>]iPO_$#:#"?9)RYk*PLG/icK(Qj#*>\^m@C.IoFa8CK*Bnr(4M8j6m"lf0fJWq$N _+8pi4;jZl$K8-;j/u#9`rqAl_oB?OM["uU#F!G)*+$`4?V*&:#*R4rdh]?s2dT1SsR8dqCc)ZL'+IL!r7,>7!N(hn[0CPAE@5(i"?PNU)YX%KIp#7 +[iFV+1%/l&c+cGV9NqI7>JYD,k3!AlS7(`8!p1kG9W!YB)K?m1794Tai_[ a[B7PWT@>hfQgP4)5pr,jh7<==)?qgaEnp4OS424saXnAC(jQ@jI@Qdmb_4#+M`n,o#2G_K*1GD'SCK`V#,l\MY]tp+cN`TA">$QQgoJudXB"lR#:O'br85Zgl\CjI6)@^b=ZW.iHNsgm'F7`4I; 2E?CiQ+B4G'ZrJdghZN9CRmB`iT$:=SU_h!E_USMf3j2?`Guph#.D ((4M`Mbn*i5TS0AB7jkBKn)2d!)eI=37".s6c3dE861Dj8d1#JKd?e)* Xr"3iD=@s:io;>J3/EtAjkH38#6U4%DH'#NK82lg^I,\&4ZiQ&B/5!&6M\[^f:qlR*eT4d< -40N>I_"9iSK+LErG<`+%?#cW?CXf:Z5=/"qa6@tr^@;nY3I>roP1U+cHne87P5 :?;W>I?*AGqghVJ.e7pnL`TP+j0HW+5('f\sB+Dauaem2;=?B*JsXCoZA`.pU(LS[5VFGSE bhHdX(KW%`PS;XOMg>>'Se9+^,C?JrM(i5Q-FY\XKA3a"=M0bAI3?rj%.)rP$)* r'^[BOD!dCZ0\W@?#*HQ#5+G)cm4_f+&dPg('eN4p.'mbUmqgD?X*qd:,8ci^l*6kZ*8kI8 %V2fD[4$(+J7%%L7Dj*o].(Ouc^IM9Uc.@gbYZ3-#30,_sSTLOa7H+G9nf&7^-P_A/BsSX! ]XOpO[EM/A^7VEP=M`L1e#bk[p*B6gR_\=QokKo@"^#M :rU02'u*Sq_,0i9&"USm4V?gm&Ea^O$0hd-eBkRN(n!':=G@Rm!Lh5F9V=D e=fDhh?WB5WOhSouUuK"8mH8duqD$eA8\m^si4e3-4L?@-B=HtTs,?Wg21aF/j:q.Y:pBnc AOWpq2ZB#_e&+b*(;9ne ,%+.j@TIL8*RBLS>V8iPK8q>2jso_8.VsPaCl0ZsW-AOC7YgS"1^)Ll(,,%Bc=7,pKab?l? uUis:?p]c5.HLT(V(u"[h3lr`AV6A@j=WaZ52C)B0%pa&$Rdrl5d_q`)MWJp>) 53@r_I(m:2XrG>0QgG5ZNKY85I<&ceqjcIT^RVmV`#,[m3L27CHd786^gSgPFmBW'Q.D5(k Uu"<^):&4=o1@W/th\4+2<*b=a%AHU"U>YPfL(eB:p=D!k6k+6@-;%:p-R;dEkL/;_I=ib4 [_Ik5)E4R8cBQscYdp5G#BU4OfG\m[JdP!M)Bh";+<@\49;[16j#'PR]#8u_A)KE9!(I2_* [74LuKneN4LX:JS&8TpJ&b-Y_E=X?4D*65IN<^MbhW7$-D=CmIno9&9EF1;34kf-tMM<:C"^DnVQfZq4*//!0F3(3\9Db>;25-_"K&0`[mBX=Wh "BSL(I!p:(W1gBna;aeVio%J7\uQ[d.6;FM,*KI^sRg\odYVZ8ciVW&'3"5sP(WiXW^Yc3< PF%."d4Fa.!n0NeOdI;E+FlupKlpKi!s3290B=P:g4//*d9']TF/D"hK,qE'GQBa!@/"t2f mBNkR`Ad+hbL2^?!E,gUd:NU5=D._Do*]ml;;Z]_JmAAS>E$(p6=mbq=pQ'QCR&jgni2.W. "&K[9J22\S?itX%jPK'E*p2mEX)=$;6dot,W*'9H;f;m/D\%[!T84kln_7ASpre!P7CcWg? A8_ODk?cCNqr.G1gB\OGsLu`2ZJ&>%>8p*E#4oR=A))D"E7]Nq9PQ[k%o)lT.\2lObeIMmg @k==`DtpqF/fFmW5EmFRicaniG1SG@;u1'_:,sHHNaO.ci2&QVuuaEQ9!p+0g/B`2mWcn`G O=@3gUXXSR^^HC)0TD<_@slUi"3LOaU>N,fei6A1!0RN4h'8$-gp_gErEEq)t\P`YBiTCY" _<5akiAu#V*EJFcWr6I>"f/T0PA;<-boT.CJ+4>Qdb6O,OL8S@3(i0Ac3cm;IF?eH,Lc)Ep 2MWtrKdUhV;sWI42(q;"Y(W+F%l.Qne7f5BTp+ok#DAh kbejUq);#KkNgG]ZXc>?%5)hs%cuGi,ua?b(oJ2LNmY?njIY6AUhJl,Ht#L\7UDeBSZ`fps !!3)2gje*YSg51tO+!4!dSaA?"RNBWPMt)3.02dCB*t5i"gG>=YF#Sl7&&94a:^>fL&)QqZ Yk=iAa21M\"&XYXYiJO6$VkgWd)&sYt`1en.=6/5=7WRRr5HF7@c>HCmVH8ml2-:iVW\^oT!J8,FnCSI)pu85EU+r&%DEf2A9Ht;:o]"+h XBI(gg"cRR6)2hAF?4gsUJ7`=CA$;_L::Zrfkko%I@fV=]$ho=$Zl_uGJW8-\=A",-]?1-* K\JIU'm[Ckk+`-?E)HZ_*4Q[845st_r1&=OQgA?+YqU@HTci8LVMs=qL!aJ6k]:uHgG=Q;fp\Oc;T\d3)7ogX$"^,h"a.[d\5TF*sOa4EgOe> _aDg.728;>P^O?=dF=F)8^c+j0hPAD]f/X6Pl3a9(rjtIINPK[s&@NIadd"7AN<_-NhhN"C"g"lX_c`-h61_N`]WTr3?Z)VSC^:12c-5!2"l!#4NZL$#5W-01a ://1aRsnAHDEEU7]'c'%kIg6;f($HBg[>0V(8gW1IrO.,&]F3E?Q$lRgj^Kgnm%e9b4=?&1 !K!^=h\/]L7q,`oK06bMTXoH]ZdH3B=n'9 [6.jOB`aP($-J&n!Ub^euVES>=;ZQRYTubRQnZ[2.G*/B_S2Q;Z:=96kY3M_T-&-/N#1nVS <;!4<;Ee5HTKaC3:VXe\#q8G:j,iP9"NcQ/)PV*G 3bW/V1GTBc7OFWo5!iStie6\*5*@403RZ^Qp<$r9P2J\PjY>Z4K9[UZ:*J<1gV0'$SC#hCSd -dQ*g4N2d&n?WtNDgA8\2jkF^)Ec'LbUre<,/0@WjPQSNM4WZW]EpUWkG+W(5gKi-"cWR"Y1;+9=%`+n"G"]0_N\lfG':UOl;A\`k^Ep`XVr[sNN3gYX4\ F4A?:KK;^5[kj[GI#i'pK^bb"*s8?.LQ_3t9Z\NX>7)4,PiDsW@cuTZd[OWTPIZKo+3+i*MS$Sd?)?OG`$o%f>7C[5t1,_Sar<,Fm+D`#b&56K b.AH!NDSICAQG@eP-7[r0pE\E>eHCaRU,3,RGMO)N624:)NWi&M*@ ]prU6aSP'l`qMll+oCH;g'5PIRJain5i?nQL@'#Pdd0WXV;J:.8`qY9i7P:8a-F"Uf)D[,o lbQs3m-]`u_t=pms7f=LS!H079Ph!:VSe\>9W[kCj,&Nl(NgcYBs:#qj,PB?f#e5V7=WT1@ 2i@[++8!q:/giM&BR8E_+IdDIX0U,<.Zmc`KAR.h)%go[E^Cr>=^O5:i4ph,#b^&,Nf oR]+oJGJMMZa>X+7J"4FUs2Y $WiNO%bT']"eE5D;i@F,m#\/PH>c7J2\YTD)/+HGDK)Sq^P!MUCGo[%FU"->GD_@RUdE"51 X)$*5#n4qA_0%'&;dZ#ITcs"k*nd=bU%RL20&)fS-Yo_hc,2hu:i@ b3EcNLboPT(e(i_"CmYL`Y,586s]LMPC=iV]ZiR]5_K'oo1,Y,J?H7T?3ZHVRc40lHE!E:/ EhA\jrLTetpBIcsXa(f?1S0o[$-kRlc;)GtZb7JKY)ra6o"(%J=>dB=;tYj)EB@cfHDVU"R hh%rr/(GX)NdE]2?ODuG")PPsU1#EW6i=cg_\7)s_Z+b7pOrWH'no#`COo6C7q]Jc8DkVV" @DO#u'-U6i+d*cfc8Zj'ar(`^ro(d5iA_alA.=T.,EHC\cXS453dp'4;O#)/s%;1clA *tZl5W%)M*n\.1-P]56J"i0Tu_q_5\;Zr?Ti-P2]+=&6Ub"?SWe3%q)OY^u>XHEsE@;#3(j c!9+40JM^2Y1iS@0P>3^'Je"GQ'Ys2DUbW9C1_2jO'4CSC+[cgUcO-Y='Ys&E_,(W7lkNpp %tRmq@204bP77&L%+C\+;k5q"(_bq\%F_?eUR)GkJ3--.44*ENe%[ukoad8,&(A\X&IB")d \9J(6&kb)d1Sd^GRraj&eQKTe*B4$5n^Hc5EY#@iHuOeg/QE'E=-h=EjJ%G%m`rC]^@m(!K \7/bo5!96Biia`?6+7[hbfG*>-O9PWDpD@N'e)XjN>#d?-j0O%!#CY(`;^d@BG(p)aYR(dY ;EPV5A.[7=2;7tqj"!Qo4VW)YRi6khjVe3-A5lQ&J,)I^E&F8[/Dqar]=8jnm]iOU'eKQ0; n*^Sa-EW[GK_b:cb9CEoCU%TR-[7sWP9pFC,dMs8.Zk`/[bMffE@.bdEo-+h/=s #;MB;:kA*VOqCF]&orfL*^QS=P'\QsI8X&i;NcSZnr"q31K,#I;Wo;E+Qa)QRLdi>KJKH&7 /&1\'.['akDc]p&=(b>NU#$`cPTRa$*T=@Eb6'B&nQAkU!N bW$!MgPTrY^:q0NG/-[B2."'H<`t&bQB*E*"ep__Li&PJO=1@$ #04RqSA!Skbe"k_3Y76de3(`9CC&"=InN7Re4=UY"OS`W$rh6S#As:bWJKbV'gHHBs&O[TU T`,S1o02[jBMK+.[&IaLr#R]?EKgo4PS[?.Tk[2Z-:\L[.\*LQG=NFXCKA#D/lLeD2&=]*8 G%gVKle!%9H*Op(c5;_1g+]3hel;PD1OraY2r+uqa_3bCY$$d[ek"X.-h4[<90ZBQHO7`cY V)lm`,kY!R`%?P=i;1Eg3G:k/)*3$<9C[++a/[[)I+Ya`J=hF@PO7iStT<20Du%FdH50%@1C>#9C^n5%p:#ZNQ,-^M1GX"q)ZkFnF#em?5 T(^4"]a`=e`DK"lSS]t%ffiL!;HkO2@lI`'4CM@UbW9c4#YXo'EI\4.A.0DeeI'-%X&g&Fs f8:O^_7G@^\FVei/HZ4,OlP2?=^1!HVe;7,(!1'@Z"S+b;`-_e#4TTP`4A[UY9iAS0TH4Tk Lm(3O8uGi)r"&0W;7+TrI%MeJLPBPn8DG:R]Or#B.sE/,0Bf?'-ka,s0KZZI3S'I@]VrK:; -l>^B#B/+4H(NDGlBVA%2'M31cj)*I>PZ^V^&UkUtdMeGA)?g!W6,=J-.<##pP'L_M;7L*K ?Vr`mEEP5efmB)&)JnBb*^TCZ)38gk".;WM\J]O7jJj$T`#KR\R[6U7[nCftoGkE6S!gmXf tT"fjrK#TILO"+6*;!=kBAk1G?NOg@BLARg)T(3'UUJD_E&c)kt!hNT7j-b%+<$e3I0<`;O =!ModtLd'7/@KH?pEY/8biHaN&+KKits6=3ZkQ';G]=*'mmBpX^rTh0t^PS@V@hN4p;u\e_ ,C*j!`59\Fr"@t:"[NM3WrJNOj%N"Fs<(?"/&Qli7FJ#D9G+p''^lkb9k2dDf;dK-Q^i1kr dUP&]#);s@$(fQ+_Z4TAf(PV&hJIW9:_2Oc#ATPUK=OXPeq`ORfNOpU5Gi+NC1QGlD& j^aR5qS."qm7s`O85!-$=Xpi_B*lhid*PY>@4-TL3lcnC@PAk=_kJcDR%/OZUZU23Id6^Jl kKI)ECBR4--o+PEa%f&B1/B6)0^'$<8opYr$=,3GlAIY3H^NT6/tWRt[4K_7WXn[g(,":@] 4;U`I'C]pha0e+cQh%A0Gfo"iqHqsU!.o:$]kA>]WN[kkaG"2J.H^l"1LiHqBEZl>]p&NS[ <]H<]7,'RJ((EiINr%91ej;Yq!^q9dl@Gi/Wg_bTRT\9^j\dJ9-US6IETtFU'>[2miE#aDt %BmGp=t?$;0=Dg*[PG!#iOBUfmA(J4_*!XOqFAX46lmN")%.qlg4d`J_l,]9Oi\ca#G\7ZRAj:F-<:0dJD:DKV-R9%e,c!J?tZO/Z-QU_cXNl-J6 E[1p^(-Gd$i46@5ne5[M+2d$UHlcTY;*?p'eOmY+7#iR%(9B1U!?,Y?a2Z])@O#XUUZ-(P+ +OJU/$h;q1nIYko*=SR8X3_m0!aeq<.kGhKCM"1&ZuZV_8OgGg&o"qk-1O.D,gerRNAg1p_ Q'73jqgj@(iUY5k?F'0MM412P%ZeI*$C]X$G]77ITJ_W_PAg+4c>EQIEe(kUnk2?pdTpugO E9PmDr\j"5j?@Qq%c+_6+gWQ/Q#4iJ+QUOmg(9^:G9Zig]]%g [X:HS0#=)j.8?mhEM!kr#_9l^0H]t_8[B:5T7IP^K_quga2(15/?+nbkd>?+dNj/q^qe5S) O2biTM<@Or$5VkaY?B\e2oO?g1m\l&8^a;fWsghAuGDL)m24T!&i%TG1XdI?MS1hS7/r_8s Yp+!Kni,kH17jiZ:kb)"o9!NI"\(`D:S%\1AZIdc^]o$Dsqd-VKk;GGCug$hof##K$Z?Onr P7Ko=Rc^u0HOFS,ioEQBW2Ot;Y^Fg29!Xo)r&0T=6!;Htr64]a5'S,fb]e-C:;6HHEdskTN hd+^'@[nH)YToF;HO:JGH.>-%eXq&j)\oWk@JDusA_SG@o?#S\/(Y6i&jZ"CrH\5[IC"L'& 7['CE<0(J)B-Y85Ol^QR=*7*XCJDbS ,P#K>#gjiW+*lZQN(8*#9+kKgDDoQu"Aq&Vrj6nQ;#Z(5>Pi;$k6WED"h]Wgf/3/:s" 3nbY5L=R;>X24i30R^F'Zku=85Dn/LnG8mC8m9?ef/o6nI5E ;09:(E84Oj`5X:Nd!.Kc009G?!`S!Nmr55p7:(7J&1+6Gl4.?2kSL^om6S.hflioZ@"diY" #.HmJ-SXJ"OLIo`.4\$i^5l-J\00N*dGlYrV#gRa6q:*_3L,g4(2Wg#QiaLLGR1aRW#e,tYCQT-_W 8FJUBXEjVku8s7\gFVZ7m]Jkai"N<(=F#;&s9TrH%29dpfh`":dD!*cQPEbAq:@m!&5"oU/ KNXq&\a(?aXc_g[R-/a:=Aa0W)+RR]KdTC=[$<48;Y8Kq:/_l"2c%o1"\2EhV1H]j&gl"&3 )t*<=]\VCnT7+5YU+2gf/9sY>ZZ(@HXKp@'n9ZE0G2NE'b.IcR@hNVhJF4Oa\H]AjW1C;g= F6PD-OHn^M[9lotta<-BU9&(o/UN>7K_'BJnW?NT#.h\#&P=h`%t9Hs_*jqg`%@(&rjB#(^ _R*6(97)b,'q)K(Z>.C;5FpnfX#iqV(\Naiq"2im"0#"Odd@_&R"LrPh9+6@cc=dN_\L1ck 8\X%*$B)-G@2M[#PmM'=1%Y:9PsiMe*1r1R*PHkY[F/EC)jJgRubhNrteN3tIhCrP%au(B_Nn*&1V_O[Ys?=)iV+) 96b[LF:.5]U(4mEr=NFc>t!"2p_*/#=m0`]amoeFWED>bE53gE'TV`hdb@5?(hBs(PK%a?B jPIH;p6%pP%Q#A2tE5&;3?'ja!G)S*5.sQ_!Df5+rHZ)FQkHCAWJK\aOo1#KQ<2^DG$Z&4Q *l4Vlpfh=ggIQfIpk+1LG1rhPA@=-M[cWdi@rs1fHX!8o[8JIhrs#QZ216m.7"iWr:F(afH ZU_eX0AdZAa0aAiN*J=uQ&OGA8/VQa51rcKD6C:m_iGkM2j3W2q1%m[68u,E?jr?ar9b/Ds 4bs[K+[bI4HO#B#+!VnFNaf=.9!h>D;+;s&31gppPZE[(?7cV[c9'?[c5GZD^IC!])%7KrN =ha>7Uf%>!1+=4L`-76hjuUPmnK0"*I?4RGN=j#i,m=k/NJ6;W'*Do3#LNAc6X 4WMR4/msZs&Wu@S=h23@2\TjW1?>;%jSp>GFlKNH1Uj8srg3-$615`Y?=^;8>4_Zn6u0k$1 Qh?S<_T]pKH1cjV(r4/Eq;4qMnA2+M?A+/5. 'uNd)N(Gm-7&T\^+k.um;!Kg&*!3K3Wtf&AAueq-"?T*b_' VP=I?/Bn3]ll_I ZZbd0h7OPEnQkYt-j@f$]ai+P$3>DkSgEiMGK&RS(QS&mS(>=jhYfT=QM)BKjF$_-!+7b0p E*&oI]qc8@%8)5E,^tiO;7u7HmOJS4:;chW'Z:pA0AhG+bZ58&OJTMLiF[YK[?H$bNrAhjp 9reA)8+kC5\'d-9%muiu;KuG^5)/[MsjlGRNK132Go0aVc0H8\CISEc+A`q%S"54Cia_"Cd Z7Ale#m?^Be]TG5:W4paNK+7h=qDpE*,Kr5>OSQl%$V]ft?)G!sST&]Ti)kFAP_=Y7q-JL\]8kP*oic=!"Vr^2TM cg*5d/@MTX\sCKE-jbC".95sR:35`-H=kW.97$.!n[5HoP\5MHtSN1IRhG(/$F4ee$jNRmGL)7iI(Rjn%Q9nr d$dtkca[]^qQ_rHAiAdn9;&/(cD'H#Q'3<[M/BP9+2<.dP"!*QGgNC'B3qen=_0Xe/p&6l- ZLj8"MMkr&9E05Ge$tGLelr*.3^-\2j0sL&<$BnRt_=p]`_3*6!><*_`c55B`4h)FVDR!Oa ,(\C8^uYPi)%p\o[&s1e&TZ\h(7+A`5$Cbk<>%hP6;e+,bFnA'DA^m#+]i3!FVYW+VKZs3= ?Hhfqn&&@,91naDspjWJ:Ba8G82"VO!<#32Q((C$YLWg0hfR'Y1=bcE_[@:8aj;l).=Mb1^ VO2;06lJBK,Jlho_Ghh\fR8P%H+=>3WmG\h5Y*ed/%1Zn[YufT^br.e8\.SLW)PL[^itOK? c$>1_4Z2]J9?W\@>0V`2dAA\PWFt[GdkmZ\)]\2e3:e25EjiO&t!irpf8fQBa=Ff6Vt(u9C "d:lbnHHZ.O,OTM7DY9<*&m3!b$^+M^_KePWAK>GV" __-#K]S">I,_=#mb"+pPa@jSW3)>7Nori%-]__FpS'N-1j?5!kaNN!bl0Q)f!_E4=0JW5`M q>Y,PH]9o"`k&7bM1-Kh4I5KKG[6D1n),uRm&>:+ZpQ,KV#%0A-Tho5(lKqFJ?^4UIl\%Np (qsq]N0`,/B]S8sH9sU^B_]U*ASM%kI@i$kGts&2NkR"?GlPW(9/Url[^9b>\Jb9E.6r3O> )H"X%Qq8=,AU7jN[X9!#):jLrb.-D^K7`*6C*Bc."=> gb(LH=T`&QQs=.H,Vh9fI>>2'9m#KqOF@G=H&$o\L!2VGUNb"b3Q&cucI>'Rgd"Wqn#:Cp. 0+XJTOWcLVG2/%auo@>9_QUp7L'c4"ADKK`(ZGlg-kl:cc#e#i,=?p9SSpEKD\b1N<1Uq;$ O79KRd`in3'55#K>L)7K!P>Oa..u>_BP-L.[%m15&+iW((V8;%\cia=7C]2Za+r`jHQ/;4E ;j2hB1m;3Z#sS8lr]T`u[C"\Z7Vi'.:d\1QW&K,f,+Pp1nbG_H\pK62Gm/:3k5^72W3K=F! 5qnpj^l'tG$;Ug?IgkF2L0%0jM"fPCSGY\Js?(LT48>S2b[5Na!d)a`saQ5Fq4HNLKO]00K a[D<@is(1+#g%3Sa_CrMJ3aC5`6#tdah:-baqDhOb06\QV8O%&C_Dd1)SV1(:OPr:jS)&mf fmmQ54kmKr4^]-;q3a)ZA: lc@./iSG)'>Nf9F]bUsR_pdY4bBZ20:.D1:+0J(OpTO)hE-r;KL>@#!lRKKS,DADUF1h[o! g"h6\?.r"=r=,-3EK>dU^UeOrSUY%H"`;s3Jct*>nAqfG+L59@C*jW8r+8eH&=EN8K?u+QTJqH;(<3Jh;.5mtBK6*a)VbK7>S S3i*--`=56A^U!sKlRA9cNK,_KYT>a6\>5Ws`W/'%nGInFc+1,Wb&-#)6gBjX-&^H;)'_!fg5DcY]hb6.S^ n37&SB[uMJecl"Q(&bI06o23[#k16gYYkWqD5BW(%m1&':%Mb9#/9kAL;7gTHW!1)Ct@_Wh j+^:m;NRaE2Bu+i>(Qb-0Yj=?pR5B%=iU,Y^9HBHXVXFiK\bMY]RE>'k,*%iRT$p@:bSB;q b6I&,:,KLee5Vi)jiP@SS5IY]'d879H]@fXZ`l87mQ`Ik)9U@aOfRn9P;cBA#--isLcK9pa OF1KelWj&%hiN&`>mS-P"h6WK[`juVAU4-X]-"h7H6,,[EEqq>@"A/6<+p*'Y/Bnd`n##JT X7R_qpCPI@3>."EtoN4PD@"\5d/&ei*jg*t?ZfLIZ/%@JB!+CPmUt]arAQ9>10pD_k]k)o1 jcQ!d=??P#^t^8AjhnD/+?P-fLbHUV3_FUJoO6Qq1C)"@9Y]=6<,N-Q Nl;j*`>:j7Pnm7u;k\dBY/uh3C=(&HgM5]/6nD"K()I\Z1@@j^h+QJ3DFpD'MCK@k/B""Y" Hj?COj:4L[?s\KR-=Tu1lbO/;+ALj\N,/6DLT#;!f!fHOEORAAKk<'m5/rc:1?2[tCmN0/U d!gV`s69cKm8!#;fBNb3b-0em1f5K-s2.g50p7,g,?NQ*kCZYWeT_LKU?BUpc%8W7g<7tQD dYkSHFVNAHZsbL"JHJ%cZRKj(/GT`Rnjk6%p.eMrd[BmZXT(YW7;)=PM^!d:bIik[]=U']n /emg`VANpd!F?A$lR"W0GY?=RS:pW&0L/e[/UAnF-h]URbnDq8[97F#N5DAoq=&#JC=bB7C6/h)a_c$crm)h>[r+7X\q2iTKO]kQBChY(PSCKZV5flF.Le [;fNd9^&r&m2m3<:mt_hnB-KYkh`$'f,i,s?/N1,D%piNgOOQ-Lufhl )pM^Qq;u;Bkc+/O%j6Vh_+Hn0+#m=C-]5mB/9$21CML+TqHj#0PJ9tWq1t"F,fC=3-SAO_Z j4b#<&jYk-9"$ZGHlS#7th?5=5!$6hEY7LOaINDUr8+NJ+aRldn_oaUX'8=p'A-ljbK:k.h QgFbY]T`(b]&:K!*!I0X_5#A@O5NlPsHlg0?_op3_mT$"OfbMs0[6m,M8Y]#8t-#El*Fr)$ \k\l/g5]&raj9F3/B1Hf`EJC3t#!bLla>E:u7V$INjA+QtZ#^^IFTuehK8/H2-KT,@F8%,7 #,#6(k=n;jkhC<+XEr'AB'a`M=h;[e",bNF(Okg#J"!8'!ClMYBOq:e*/>*6'(4'mZr0.r?]Zg"%E/0O"oC"qlkKWqoi\doOD'@S531/)pG[3okPbGMJ/[+!8/)[A"b]2#:hXAd)[C8b&^H,'SgbG4`S7>D.qnQVO%: Md)'k5:,*YZ11%r`ET[Pf[jqB2&c>>G/9d`kbgu`lHT28&E_jJ9%G8*p=1l>9kR89[/C"4\ e:9@Nt<@_'qM^7^?Af\lBo>'I:HR,Q9`YA7Da_eNAXqs0bf&Lta.1iB\+rKQm^Yc744;JXp V*Q*OB4L'W)iVgJEZ$ug=!a,4T[?D$6G#7LcKFh'*@?D5UXSIM)SK1\;m4bg2;9.KcY]uCD 0J$@qQ4)b>HAk2Xqqb,`T2$hWhn^G;pFLs\fEu$=/4C3U![ZZ+sDZrn+XI958T[(kONoFl" 6)%1=c,H4oZV%cgC<$I=DMj');Yn(=2m\!'j@3#m7t^9FV.k"K:ro'B@27#f:PF.1=#>bUX .>L2d2b*Db`_5oRZZ(0?ScjA?X\0jJ!"`Xu`m(WLHRBcG(>aZ*K>-5h,CSWWi&+@oB]M'L) ^9T:>i&mUtSaqA6]-_5t]UirA#g%p3AP3fk8bS'16Fr`1tbi;D-9[bfB;f(,Gc#\j"3DL6X m5iQ,V"Hgo-Y[U')i$`;?Q,gSHtjWX4VL4\<,ELCd<(?g8Q$7n/P=J+V):opFNlgAe("mh; :H=,78hYN4]PEY-GdiJbVb?pB,Tl8:/r6u]lRF[5PGLc M<'EpM'BNQQHIa4^)fS&X,lDOXiObHbs=:=6K9qejrnD4?"9\F,i@mCDZ^Y493o>OM*tmH46(GO'W0% E%]U:DLk=S8TFgnf3]:amtt*/^)?CiUhGdVQ!+,)MK8!d<%Mn:"&\T-WSXgI8="tp"bHoD] %PLW`Y7/^N81S?13'rpO3X$iHQCcNT0aT-^E`e-OG;oUAg$+l(]<'V<`H!^UKnu<>_7VA83"#a01^S^E/d&o A'a(+>%t[VI$:+qL"Q6p-K+Mo06.dsui%XF3_N"OZVu6p/_!r;:pjWg:nG6BtoGQ[04K$8; %:R,#LG7R*6eH39"e_A)6D-;+3/\@m1eEN9/3"*tFYq8EXX9 aO+-kb`=!b[cQR-NT9A+SDb*cQ>@l-:M0q99cd)uqBr)\[#Y[%XQG+'(<]*\Vp."iFT0STd L9t@oDKi!=2AmTKq8]kVB0oRn8CtkGYh)f8#]:Ms8H-[Am4m03A(#qDYM\4bUPGu_dLLBFE 3XnAMdG-k)VM7pY*-r+blTM0$rD?`I7F0*E5DT%;+M'^+B`\^=6<$(@">kiEjX6lqD%@fn7 "5FIK+P!?)Uhl(:!qKNVT?^t,Nb`M.K`JF<;iR%iT<=mdUPtX!iA?-SIXq=9r^'7VN*BI/- Y7;($p4*e]'[PCB\(HcY`X>"_]hLi_Dn=1[ s/[L0l)9+,.o22SRR0#OhgkdHiSrj#2hAr2(02-H+I@1HO`Nq)@:m0.+/R!I*I(p&CD0/87Dh&fc"pdDiFiU?j@P42?o8 4)Ij=EN6uM^Un!Lm;G0=>*=8G32Moel019KiU+QPHk8>J/lcIgI.5\c,-%Y,,NBl>3V2h78 )NIs8=]R@HJ3'$CY$YqcJZEpD-nE*?Aqt>A=TRBh/EN\8bt4\6p%6TF63oJDq7:"C0n:!j! ("nYSN:CQd@G@L 6Z\HZ'p=\FnJ'9PMuJCG?$^s3;d>A:X%UZOJ,RWCZ0bdkTZ(o(V^O0SJGfd1UH(>@Ja5)jC ^kbPDObWL_:T4;\=:pHQ]Wc^M-e>s4'?M6k2Fho+H`eBggn!Ii"1onoI^GYC!YI/Q('JW^J %Nh)jK\GjTd6#Bmmp-aD//r]lXRQ)GpD8e`57QS!7t_n8d!PLNl$C@Rm2^D&n+g2$jnu$Do %n$)2Sj.\H2g/"rf>KR?VTe`8#c.`ZuHKoa-lNPYDV@Z@#.J_mI3?M_*7&=4;"kNK>&&p=C :%GO,J\sR,T#*X6+faS3=n0gE!$`@Empu,G"SNB5!%=W^TpcU&S/:,?c:HIdm,F!jGRX\ D(]`n@+asrQRMMRKd7kP^n3$n+)$Ec%"E7'R6Z3:$(TWsV$_'j$B9cL9p40@[+OCK&E)ggi ;OXmY)/']1V\6#HPXD??YS+Q08+&4Au(i2FVccWmEp7sCIhIKRUL)en#lBQ0o[%sPS9mjhE^uOTq^i _Wu=a:)KDktZ*7NZ\Jo,P&Ks1Q_+5:a[U>"MI)5=8`ZS_fIiWNW*O1.^+fZN5f_&#,),ZG9 na.DQO;j5ZE\;e__0d.EgD"Z7'N,ASOq+u&bT3Wgq8^i&Ja=H(3qH5u,'#7+E\ScA/0,o!* jQe2nj+NV73lnEoV)1&_6+M,%4,rtblOINTrPqiFXD$R-BE?tiOfu#&GY^N-a/LWdWg)3dM [U>+2R^oE_@i:P\T1J*MLb!_1i^Yde`O5IOnh'YJi"IYq'b5/$cO7b^V*_`.-+1'nP]k+gC U"jV>)S(%U)hJ_1b"VZ3scbED/k&mI"C$SPC[^Hne46*;(+$lNK"%58e(/DqBhF:@,e(-o/ B5uJ"TOqn&6"HtD?o.L7\1Ga),1U'^Y@+ZGBL(_?\"jga9n6dOCXq"j%#EX!ao3F5iQ4AFL #a9*2F)_K$==bS,);t);+RqE)K\'\_/Wcq=:ocT"64a.B'VQ$FOL$tM$l%Y/%tS$u!>Q$FT fYUq1JlmhnCp&Zh`PtqSjRf>"+`&FC_]68(U3KonFepTqVBO$&+/*_DNkb2UQ LbdFfQ4;ake*7BU7)6,]mc3`]+9+*$g?dIak%R-A,Q&:lGPOf:l+Y=MNs89BerOgs_X-51r &)Y(o8B@*uc5=Lf:7F\;/j[QX7B(U*/7hiX+oYF$Io,jkW)'Q:,'J3$7'2eQ*a u8jJc6b-r5:AB6hEN0'ol'ubSEJms4*Ymkat_XpKD^8^;7T'!Ak\qJe!tT0]A*0!5o_*?4( +k']=oe!D3WKK3Z6Y(1>TIP;P/HiEgZg?FAg"iM%+GiZ,dr'MU/:&7-YKYR[=o2DB8]o3l& /GT&j$#JuK)1N*Q-+tJ5).05_F!+)%CD[DV[@t8b0d%HfuO(<CpY>E1ac!sgMLPo+!e4.mQYABO]^3!((k*nO_gVr:J /(k9,@Csf)]gXG3?#X7YPVO1qu^c&nV/('S3ST@."XnSOf(r8G=W*[kP$cP=ZoE'Hs;ElSa J-b3\j)Dq@^*Zs"<,H#:kInasG5(L_;b@db#PE^?d?2V!".flpKLBd&c]7]TM/(`?c0=`jI ao^d>Bqg!CMCk6gN+h`,%V0[?bHFKts!TY7eTj"iE>)9O)iKOst.8ogjHu'',iFWPY-kt2n <#=;;npDIOW#$8RI]o2g@IbHn.p%e<<]+Yo(]T"CDh(a!/2_X%oj<7ni.YiK+fj@"[c`6#j Xm1?'qke6o'M&XN@u*]K=ACDa&7iZ_MiWL!^P*L_.F(+L_YH2>l]_8fO8&/L_V&)?Bsu6fP t6MF,'I3+ebhN5kl:l&sLdC?m8]!_5UjFQ!lY?28Pjo+E(_1F(-;U%g'NVi+*_@mg4/!MmJ +I_/^&ORlM>-A;tsN@0eNJ[q4$aRt4lW_&GH,ZTEEr%%-?mp31-dooD*.4Afc,iQBq8-;C8 +BXX%:d.f\GR6I#U4Z8iq=Wp!a&3mV&5WLA]@4n@a[m8V*&s4aYTuIXp%;_?VPdDHJ2g:NG H:gKU*^TC8'KL'A#D-)hjPb1r+en(,BGE?sB@d*LpJ7.m;4'u$)Ze/'f*nf@(Nt(k[[.q'M D,Ql-lNmTR^Xl;pG5@ulk39_S$'75@6>FZ5e5:f@HJf%R=h%jL9*,i(i5O]pLTpVQ_%'8G, HN(COLDpop&\SD..reon?LlltYLt*^Sh3Q]n+(&YXE;DrKn%8s,cm-),]7U:6p=6+RiA5GN 8o)IZ#Q!Gi6ic$[)oI#!q*@<<%SiI06@V/h/060'&4/Z*>M=@)'f_3KM/=+Aj-Vmlc*fEnK )6W[A'VbaB7iJ\Q&:`_.?Jf/4#q.cp?r"Yp4'd2Uj)R,$b3MVs-X/N0@6)G=^fZhbcc1;VX _29!NYS]Z&#rlFKp!^&<>T!QK$WqVUpj7dborf;."Q?9k+K^IK;O#"rPr9).\t4;#Bp&"@/"Z?J44Acc@OP8pXG*!]_:TbXAL:!-@MoqLgM+JQrOJJ/#eWY$0 l6qVfm_>T#h<%(c8`qX`2Tqp]k6(r6ml+fl3)V6E9Q)_F%ubsATtA[*7h-g>:^+R59i+,WC J%_tqNi*cpr1Y@%/fX$5K!;$OgX:0GAft0]bJD7I+gH$KW&A\CTRpBWNla@AL454hbh8.kC EYkKuWki&gLhu/diOCe*Bj6RZGoaF5,IoDnP+.r(\LY6/2rA@O]!f=;JUS.r/%bUO]=-'V] NN5L7.l*[/j?dmQr3(:e^'HfN"M28_U<_i]LhDLD(UCW)f9`5Q`33M>5;%MJlCYT +=lhI5OFA?];V_>1`N9.[Ch-V=cmFFH=3IQa6'<#iAL`&pKL]M%KQOB5[`ET-a9U&5`)?/[ uHl=tbfU"P"P`(U\H\pSkF?GYt,`4KH>*9#$*IaROHea6tU*hhF0]UR:@WZ"/i)Sp"pgo7* `nou]$%=u_?iBtd.\]\=_HK!9i5uJeUo=Wr5nY[?K;Oec?kuHNdc$q=i]\2m0^Wl]9+a5YlAd`%%'gS,6h)3Y'JVDh1# sC`PrBpBD8blJ3(nh]N!K[j8H5e""YVlLd@B'e;M6U?!qjhC=5i;lqGrFS[R$2h+i-!\>^Y %GoZQX?"@%H!*64AE3&2:AKJ+;6BneJtL&O!?@$M4BKJ^sT ^-Ng+fDH*\"bjg%n9CH].hJ(1X&J2H<_"O#b%:.sS??cYc9NYG=3V'[8#'Z=dL,UZF&fZ_hGoTR\+.(+3F8=W5Dbm(U@PqH;rmu)!h=!P`Ng _neO[o"g4T8\XYLW%4qu)EX,2$;<<\,Qfcd[)D^1nW@oDnp,0I-l*5YsiV"MjM+)[8Ut>U' J?:kU2(6EnBW%79R>1CceAoKs,,E<3pm*2dS\B,Tl8:/r6qFC?!*0r/G$7T%*>*6.NuHQG] Igk-\>;?Vb"7HE,mD(edrhE6s5Gj7hfP*Dppb-Jsh/P=IPZS'FAoYW@VEr=*89[b952,,l8 QodoN5r`K%1S!Pf:@kjR8!E(oL/\n"j1R`TFh::JF^6q;dLQ)89l G,(r"HA8DuC:_EgX_QSPZ``O_Tu^s-HR?qBD#6[;I@b(shIDkl@=2)C4.bQFDYoRG=Hgboh C\3.rr'WOHl!1+nGFXG_f7eO(WUN#LE">)r0JqVEr;Oc^`>kK8%``Q#=$URh'YSku^(f76ohkGht*7j`s%&Olm\&d0l9:Gupu2HG7 G'm2Q=]1h[^NTp/iB#!m2`(o;b_@2.]eJ5V2qGN&;q5H!]AIUC.\+rI.aW+HE&f)OY:!.[l ]!^Lu8!amhlJIjF=5hI4^+I!CgE(11#GV',-X;cd'EXb=e5mQ!fb3<%Zjcm"q6M+98n]#ttqn/85oUH:%YqSeO_CFYHXVJ^s>%UaUR>%<;(:)Y"dV3u q;c[WB;YXUX6&V4rDJpB6^a73MQnsJ3E_^[4B8lqdSVE6?%:KGbc-a"lPKnLo\a)EgBtZIk 0kJ](PsB!T!Zd.DIk-_uGbsL0GLSBSd/"_W8l4"Q6GQcg3GC#N3W2lUF\C-D1Ip[E+f(?SP >XG;8Pk61*b4"@U=EUETCTVc oab.Z/KhU*NKmiCGFfg,`$p"gk4JdQ@c:.]el3ZVl\.=_gVI*@&LKeb)D2Brs@tFk3&6C?] $idPt:-h2.,2`]Y^rK:mB'J66Rn@I-ts).R?)5M^D8+>X[!j1cmGI)0.e[i5KA8mLd1c9uKChQNAj'5fMd4S/6 B4H2@VBpK$QbH`)$U39hC@^jis(@sDo,j)"njHk15T1<&:PF7&5+3JT0JYD)S^= 4[0(Hg,u4[J=adER-[n!:$ctm(di^!=H*i1I_*<+%,.r]/OLnBPnKX(fL`L;:[?'43Mp%Et :Cg3:n8W\\sg&'&228.)sWV&Ygm`L7sVZ6MSG5Tg2um@#Frge+^n$k8lj-O=UJ2+bSGa,%P peOg7_Qa]UPLAGhdY@,*#\d%FhR0Q8lOkY?jD^h\]jQP&4^8^(>(11kpSRWB%`%\UBcB)&^ &,+pD'J_V*^5][q*Q@"WPpH<0Uq&BT(H3cif5))'"+1,(*'ES+f$;h3OjIDOaRSQRJGq(9H 0RT(IDGJ=L7k(h]U!tilN6=7>W\mhTeXE;#'/F;sn@l6G`<:@JR>J(Y*kNoN*bER_JZnbEd &43S@a/rR2J2=6fm>VqQm3S$-Ud(MRnV+qo1M/>(ul0Z)LKf$_70.QqDX0*`9qsa\nkNk*M ^](:kQZ>GF#VmHIVQs;/RoqYclTgY)V#8!Eo1,CZ(]nK5`FSV1pIZ).PLG=,nG1pl0RYM!C O0c&>rH+I=!h+-0C(5>sQI,NN*p1P]rq1Fe_AWg-.$NG>tr0*p&I6a).3?5(TZf/Z5k0QO+ Sq.nM)VW(ktMY(d6dX"5=YHuu/kC&TdjOR72bP4;@gr[nEUh6^49pIjQVb\Ek1Un'?:Yp?TbdeJU=XPe]oq&58qS->&DsNtdhU_jVC_,ccE5 raSn9U-Bab2UV_qq"%HQM.i/;1/J_mk?^I*gi.]FT\bInbo_+f$L*R)9GE(g2QdKIT;h4oC ]I++AT`0QG#1%66d'AM;m;Iu!Xos4@'rDs78-UaHBhn7.+W*JV?mJtQq4\0qQV1c$pF5YMA I>R)H,2Z`DY"0`KGPRA[m0*,0eK>8A"#TY`!&2Xe-1^"FW$9&.04b@`C_-0-Y+@:^E9=1`n 6'N95GZBDF68\"'[/s76,Taes4uG,t65tD@.t5>t+sjHpLCdZR4=<<8=9i5=V?:-^dUL)'V mZ)-[M1=1k[?@oN4),.VOM-THo!Zk1Q5F0K@%[e1cI=o2n$;?VfXsXa?^!.5_RU+[gR4Dj? G$HF#ps"3i#'-:i?S"dhNLK_LtBB1e*?0MC>ch66mf^dZ-?+9KCm%\`?K'lqKnD#R-l.#5b 5X4B"["<"ZW6KbKD4&o5$CB"8=Q3@%b<1g3>[P(U**\RMPWkrJs7:kk1$Wq+e'!+H/JE^^+ ,7-%oKBhFWK:G$X]`Cs4A>\_9kC(_J_R$`,RY^SXOE'u6s6mQe6P\u92cn.Lp#=*@BF1'&9 G=RS"8"=fTi*HWoDb!KL8)/P`m!hP&]Ea78#)he2XFi^4KGeHAL.FkJ;o_"2LId8iL9Og5E MS:Eb<4"-aP4p0iMhTOCB`dL8K'`c'LtbX-d"d`LB*1FA>_V<&>"i4a@q5XY\gXQ@tg!qL&b/(1\/:Jo1J qc+*_4J:a\K?Zp2dB5K(!'9X`,L[ieoRZF%1D^h!W;*ep=HJcl6MlitZ*#KurhL4D5a`!`< n.#(P[JTJ/5j_E;V`jY=DnA]WRD9Udi%J*&8VN[3QRG? dp4gKn83lp503CW8F8H/eN0.tI0ZG[dcEYkl"LCDFU&b,L'UkMUXVl:RE;j*<)#h]7%:lcS k7G'e=B/M^fC]MEJE/%8i6<;btcT0p'#\XKh+6sHg"Haj1^d6;\SF"&8t*IB*FYX+'c!B%9 lI/>Y?%-L,`69bdbiM?qYoVCd:g/K:! L^OCX!Z'sjhV,7?WXUrh4Na]D2X1_W241INK.c3%n1=.IXhW^m:Q6\E&#[.7!e9\*;CeVKI A:UPdKSV'_JQ,6KI<;hP1W-&9^hSQ[W2<<^k/W2sfj3WL>37,CbI?-`fDhQ8Q_i9gSXR!=4 D-9Cq#%0_"I.:?enC`Um:F..2r?8*.l]03_2iUX:m=pZQ8>s2tfKFhIi=^jkBElOZ"u'Bf3 +.Grs%h/\d8d2MSZ>UkZqqTTKRcdOLf4IO)c]7^_g3:..$]a\1g\6EZ!Wc \g!"hQ7G:k_%8&ULUlURF3NX4j\W>S<;+*+V)3eBsPcgg.2?AK"B!C'9o""uoTdOD,XnALq tn>htk(m@1$M^_VVg(eB#Zi-kitIF=D2;N97*Fk5!&D[2)Bh&Y3TXkR-pg_`;*LZ!Q8+DQT VMt/*L/;!)-"GLa$s"ti@(m*.apLe2re)+.L&aC<=C6^-'F"P"JOjF+J0!4KCt ?<;@=VnkYSEo%'F%Z%!Ga`IQtM&rFB;cl@LaS`;a/#c'dM@-KEsG:U`.jn-O!=6KEZe?h1& N8eRH["fH$\qm=\Xn=&#_u"c`C^q[&$S>_SH"c1X%^aK=+-iT#a$fZgcu6nlntO3WJC$l+m _Q'0G"l;#<`6a1B[,'d=VQp^h?=f'I"k!kXZH\^#$Pl1782DW3uq)@.`iq%Y]J6dncD-C%K "V>!o3)Kk;;e7pe"e]H3D8KNf=BlnLj`kaucpi]0BEYh@L98JWmBS^E9LWNPL8[Im^hSM#8 6^MQAl`MJNb4I,49V4d`TCnbTM'tUC(ZH>]:1Ln(l^kY&WVE)f,R.pci9nI@Lc9nI*fH]_"`[[1uhp$-8mg.-KAU!B8^A1mTel+m>ti7kMt J_j7SURWcDVa3n[>M"<^%l:@D^Yg#QarA:F(Z(j1UoS+bsAp4_s =Yo3#C!cioWdmSBn7ZF_R6.ein2D,%7Tc^-7&p4)E0bY9Son[`GNY!3kH>q>Qq[`L@##;;] ]k9aH`6-Lo(#9?]"hYWJ9Db%q.\MYL;@]iL50H'/+V":(X[[b#:X]n0QRaZ/:_s/Aru=+1i !q*L=fjd#*a1WjVb"5Kt'2.IlhA241rX\LG3N8+$Vj.I>:@8LCcNL:87AEU3'/*oN%dQB1H d+.E`\E/ph pC&HPI%`mIunW2GBs^I!LO+V?0uj`r0iD<:BRPH-`'n?tOCs"8WP$H5R!-:hXfZY$1M&EMo [Fra:K#jp%iXL5ui6h[b%JWtO>Q7Ge]'ls?]rB*B,O*[_Z6^hL?_U3[UlHVe\:0QIk&8Xhp ^n[GCcXA]9.;[0HukD(,AV]G[7^BPJrL'V8nn6tM2IMd2,eBGRHqutk&9eAh Hh+YjElZGqe$FfpH',5K6V>;J1bq67K/A3IYUDbO%8JRllA?8"rLHtfQXriC@o8jIi S3U?=2,IigZ4s1O6Pu&DA#;I8OND'SR=(T=/XjmoPmDHb_$Z=PB f(-9H3"_\4!->Km;B[MZ.a"PgHDjM#)ZS6(#.RDqglZDEHjTp-R4Vmk&U:QY(ns2cepHVCA /Y"@..BEqn:;LLV`$>q0ZLe-_JrRp3JmY^GDF"Yu@Z(T3o@fnb`97IkU]o?4c1#J3jhP'Fb 11n4X]'_9c.)#/UL'/85\!af>fe0Z5gY_iXdT&Aum%#XK9F&G00q&QD[D`R/L1(.M/KB,Hg W_,a?m,uf".7rdmH+37=OM&r)'!@2eUZ;CcP8^^j9@1Yi#?9o6fXKO-I'&9lIb;0"+0MBk' aX\.G8VUQ?-Y1ac9lk.02pP?Dkr?tpSF&Gb'AW%?cVsJuBUd&)s$G)^4V3%4LJ-@r;:KG*p X1mH,jq+TO^M@X-$uI`\s3)i:qB)X:0!P?+Yle,"?AkV'\.&-=&p',AQmY20hbsijmf9g=, .67@%*AbLLF;N4cO")[U##-=]TC5BA-C/WG("oSZQ__(>Z03gK+!XDqmc!Ao!O)aeKq5VCdb e(u?p+j&l"8O5sFR8W[K9*`%s\).$='%g8#^6kb;mAX[4VY&Tro=giQLPbt]^!_e0+/U3cEa1Yr_5c9oVQ[%9)W%m)lR*"7E1L0=ag1-mTr`HG]3Z#Vi7i_6\8Bu\l +,_@&Pd,)V#c`LP@bU/^i0,]$,Q,N&N!H(-5j7!S0r$cZZ950rQ:K3OkW+l;s-))F564Mc? *=k8'pn!4R@)/LW:dnp"b++f^,O/$="P4l""\$?-d`NGFeb^i:jr-J`:o\09P;j?8n;5q7^ 4,kkZ?mTBc3KRG"k=?Ji<]qqh@hnGHW8an#Ae5LK-%?XMLY+%O0&EZ0WRjnaFUYOVMi?aok /s0(hi5SsM%hu!Y.:`9C"iNt4i^ss2DXp75u*s>uI'8"S'$pduO"lRlK*((!)%Y9cli=mPj E0_2)GZ>'DA1<5:XqsGB@1;+B224r])FJaAr!+J6LX?#C6l:Uhe3NpPA$%,7+jM/sW8A'cE 3htGaV9Xa;i8t'/4E+;(#n"OMiiHA7Mr`SirinO;3j%-J^c9*)!i'UXuAiVh]-.%F,nYj4@ `NF*TPXtO-0E)a;Fjs`F/E[N=FJM6(Tg\S;gFH;Fj@C,9u94N?#gZ9+@Rk*$j%(PB(hC8bk e&V'Mb!K6UZ-=:Zn>9Cj,J1e\@`HlpA,Z42n/CC;9915/h3(a>=kOO=n2Ae`4OP9+/VR>iu !,etTiUm_r7V)2eX24ASiC<_%32J2%&S'so>MX\\@6jPFno:2LLJq+14#^?M?82l1LZ;mfu o:Ep-Hiro;)Zg#l%H/jU#4Sl67d+au7KS5[.MQ9(AI5';/r*9^W$$\#M$e?,CC"=H/&WiO1 N\#idM"W3bh/p,U(#JuP>5f98ZObHigu?>50#$*L,DJBAPl&TV,Z2 ,Ank0((?2u7*I<32/KI#S!mFUN`D3F%!/M:tJ3qu[%':8X['n-1=:7E\1>:bq\$l7=>RPt! DC*31f*^Ri29<=p6L),)TMGn\Yh`NKe[h)Q]3T3X]\#jbXLEThLN+Rq=^rnnf9Z%agWt2L: $]LEPWXd\Gg:5s42.'.8W"+Wct#O4HfLoHO'@ffmOeUWfG=Zu7_aHYX?pb5WpSaa[=mtf'Z *pK]FA:#-jEV(E*.T#@M]O6>[*1)j*5">dId;?=P4`26H8%*@>sQ51<-iOdu@eS4YQLlI02 0F%VMU1Su+lrfbYoE9U1b2?:i8"'OD7]]oTIrEQjTb=RER(dp>_^YO1.<`TLH5>RBH6uDZj)00g(k9\iNP!+p5RJR5=WS) O^A\KkR[dYE!IN#)78I=e$5NAC&LJu[3hTsV4'9]f`<5gAujJ1$WlWL@BAM9oG_:+6G#_/, ,Ae?WLE\.lhuM_LBt$oZC>As4d.=<<1B-cX#3..`\bX?h\b?4C^YdZSY1ed(#bBdML_*MpE [i8ZSQ]@IEjOc855S[DK"tAjh,f7nD;pGHgaip1<#&^(rCAA$h4-'B3,8-,m[t8?sY\4h"R DHkD'dLW#L=*g'tk\D[,.-VoHet$8b5.EZ-%@q$/2+7GMV`!0]k\="F\g3'me"8g-Qm+Jb6 [Rr`G*,:QKekL?r-dnYVDH4;d>]cPUDRn_>VOk)T!CLHfUJ^jB2jrC;EWLsU!ekcfWX*&cn FoK-X.lV%P'q#]/HIpm:GAOC;cqT:X=^A)#Fmb)(,Xe6s?A?OS&QT[`fREq[log3G*Zl?rS 8@AD_"o.T.a.K;X5qd!QW#APUianI:2N7t'`sUoWiKEA/UanrJqD\1O&^%F>-M'P\R$fQ'7 oXS[.`A&gjQqB\UbmJ>G@lsB^up&< S!A)Z?;ZQ&<,n#thbU+B(KlhR=q0[q(^]Ag8V,"qJI:n-""9=en.,s1dZXeHQH'$U*Y<:)0-_\r0%_[:(#aVK;Bm @U,WGg8[4a]WJN=Jg'(iKPo^>KGcVjG!f!b/%#!OI/n#8I:O+;gf`(ab_%#L4=*g )gkj3RX0QnsMNH(`1#_*N#@Y;aABsn/m5V(1FipE+oM4a#m;D##ii1N05-Ri3K\s4k&:P'B ;8Tk'`s"++a&(TrJg2PZ\&<[u`KFlO:$<.NCXQCJ\IM%[T$ksdLe0>AY-I"-QU%!&"nTN.PDk92,fY&UImM@dJ2l^6o"d@&A\;gW`JK(H$@N@ATAFP5d2]I(Ci+2H(,r(+rrF2YloGXMGA[ !NHX'+Yn461:Bt6Q;_=ene.-@1NP?a#&4e07N-@)*F\"MefAC()/"+6=Q.cF-eUBkBk(2#B Z:E<_6Gp4FZ5M6C![Z2'7g2I)`VIK)r]EgVpZVpllUAr3d&\_p:Y8FkT0ch&i;G#iIi2%`B ;VuD:[HZ'@C\FWYj^=LUPTK(@uHFpMZ$6*l6nW;u8g9s);$IE/4-,6)#%BUHmBVB6KVSG1:' R@GD].@NRnn28p"pQ/?gdh%J\f(*Objd6W%47$Sq:)F6\/_2JtWYSQ0]EMt]4!F-%!L(rR0 9GbH:f>1,>&fJAI*SJ8Q9uq?`js&"oJEfHGh@,D):()^,1g_7U=earE\W%Um?gi9>n37>*WjK\/qO(e KE`7N=!3YbcKNO[Z$f\@6\RMGo @&t&!Fq!F+ZpQ&GRO#[0#R/Rje0GFP*(86/A'9S\!OkCJ4)&n`!+-KbWP*mtdGr(S6 C_u'-EG6+).23X;7?i@qP^,uf\PJJn;jEbJQ.]6(q-0.&B9l\9Q8rlL@F,m#Oqg9!)4>i# +Ni\^2'kZ!1Ab&4(s\A>rfk^Kaq,9,5Qb=n?GW7N)F8?&LF^Fa+Z7XXb.Lf=:!#/k9'#@ro>48XUnZQ-nY F>KpHNUH;4;NLK5#9u5)Ejk,5I$8iruoJ`Du+kTLLW6'BWqMO+YXTRQkAq63#b(rqa!1m9* .#MEO1Q_iV>J]bSUAXF#iu2H1eU-@)`5c*F\DY8'DnQg)ZLB\(9ZN(>lV[jqb;=++aBr>B@ >ZQarTT\]"stiQ<#S%<-Zp\sol/oUSSgVn89:K&NpLT]^A4/%h@l][nomJa=C#\%2CjD&5c J2bZW5bR^B1M9)B6)tS4LpN;u#MYC\+*!:As"a9NE*MIuu_=AT)_0?8&Ga\fPol;#1=:_m- _U1UeiCXPFXqcK>)Sp(rf<3F+FI.i3Ql!`\(W43n`Z[X*'k!kd\)G>3A&akq`lY"o+]\ueM A&7=Ie;kC*.Q%7K?0R6aP;Ok5r]6<\.df\adepDTt1p\jr?Zf&Acd2!C=Mk#TSD3&g=Io5h jL&`QUHbbhUCd*6HH1ccpjdc(*\9guHYlkKY(3bTX8,i8bkdTG-(aItH sH0a>AmG?ag%3-AhZk`N;mahu\hXH'S_ARnV`*9op_7US8$,$/Y]cRXP%0.E"U_][(g>:l\ &9ki+h7bHl%me(]>Pn"rp%*P.NC_aGHjB:K$hTd)f"n#A6&i`G=2GHG*Plb2EAe:h01``0' L9eZ5rK(DSeAi))Bh?Qrr.KmU_WsS(sUgS4B_JEQPSR%$_2"PHuJj'VtsB%&(BLT_'4t?4nF4(P,HU5>$sp\eY;GcG/hn?h)G!p]"UtruqHC2RX `)8/e_hiFSk@NC=gF*tF)pi_`g:?7;RRYLKT&_Ok#5E AhJ"s=:1od$o]gujT[2h$=sWL8ibUV\YK,u%s&#aplBPP\?EmY8mQGKL%8Q8#pc16WR3M`#q&b(?@phrp)?sED$Yu"TTbkYmdkkCi,JGg?5FQ;a5a:e/2 c`^g!AmS3aH'i?`2TCG.Sd/pNOI/nTXn[*g>:K:oh=dNgG(V@IO!h5$qZphrjh4I_Qu>Oig mnjnVqY(55-a"2N8O(Bm+/9HOI*&9K-(5t+XC:D9Q2'MXep/3=B[d0)rO7'R.r&k)s)$rIg p1g:d8d=c-M7^7nj)FihFP%1H5*.K&$.Qi8*aAO:E,=sXAQR#.c<1>:-l%.?0*m4Da/5%bH [V;8pZJdJhZO,JfRO;5-*\uP)9N*ZR-?DdCsPjaUW>2=60,)hf_=D%e3-RR`Qr)'2M>-*fhW8o3X.&pO$>7ebal(p_EaZ3^uE>GMZG&(PZ@rq>@1 X#5Pl&@^LS98E0Eq1QGr^p,A&m\HYQdA@W1G8"(f&d>);DG$gVK3L4?gS7ak5GF@:m Jhs&Dg'TR.BY#OOU$4TrQ)&,?G)gAT"0&;&NI%J(Wp9H3Z`\'^p:%6jV\+SSSH_Y]ZY^XFe $a+?G1F*>]8kdZDS)e7\aMVgot53ip@*I$3G*QRE4e+?`(NVZeoeE\PAS?\/[<_i&'"t<0q 6(*\'8uah`K2+r>.WFF?M9IdrdfD=4?iU='aC"rKfur(<%0D?PS"0Fkl_>pNthBSeln8pc^ 'dj**9EkJD&!/.e+NZHBA`H45A8t kPf%L@:Q+@d0IN:,W(MQd!WS,k5S`#V#A^(k3ZKs89/6PsMG+ga%[nCARH\9/'UYuUI7 t;!H]d4.4CDNKTD%"N\ONhUf9+H<(aNV0uhl.<@c&,b;D%:a15\R;WP=1UrHYtTnb>!,%/V TJMCaN`\Bq:b8H_91?NSFRKd_2RU]<3-D]6N#-c]>$+T$XnDt45&EOn"aDrXbj.,_*jrELf ^fW/TSeJh`*O3sQa2qFHLUlrh(WelPf[L['^flVX?A.Mt&toS3K[=fhKuEJQ'LFAcd54Qd& QKXALp7mDRQ3k$ni0(TOC*m]GVk0IVkk$+Pfh-K95.rjV0'["N)Gs*LZ&)rN9"\!jMt&-iF NSdPsD84M,WQR%8K8as%.UbuMj^5(=Kcc7.YW2s1:1_ SU=0*^+>AIeg=I$b44FcEh=3QH+7S^p8 TfdZ)pm'W+b$hRd8&_]Fhit/6aKiO)ZdQ+=eVdu*fWEQo6CMceL[>^2Q%M?BfXgPXI(?XFW ]6S=3nl[#DY\QgBRrNoTLq`L(K^iuCrUpA&oMjkk!cL@8G!_ 0GE&n/GjMhqkuuHWc8bEO0f0:$^qX`#+%F6.@\P2dq2Sjo9K`#6/'^!J'!A[eA%I6;l1]sGmN095Ih=ik`%/bfn:#VW'FfUc)FgBj$U[$L"NU\)?iD qi:_Ejff"a-HLhR_.W$t&c2$'@7pjZKB)@V/]aR:@aYS@OsVp0*6 FW+-/'T,=mkABb^I2.g8T&r&rO$KEsC#(`?r6Z.#h@a%'KJQ7B-L(8H\Qs9rs(SPA?LQT.m 6YN#.U;luD&N:oqkqXA:maRtq"J/DITq!uU"^TUrI3=c;Q;^D(m^E;2HV93>X(h:1/@,+]9 RUWVosD`ij&T^7fqGT,oZo9+8o.4-M6P6-XhM9cgC&Q:->,foS@_+0c=tmA2RSn*p18f7_9 Ap?=ma-hLCXl7E%D2!XJ&jqL2OR=]1$`V'D+OZ;/PPdGI8:Ek`Up'%J`M"W^A6Z5pODZR" KIKe^+V=0LUj!(8pINOECUko'E_TD#7IMl4LNXRUMO1j]?BAU-_J'.HdMU"7,:=/W#pZMH? _)GlY=-&ff.AkHRn;'6kJDi!Oi.-]F"%G2n\naqYjl]rUFt7a3Xc5j'_d5+ib.W%g.b`LZ- l:74.$4G_>C3T=K^\Ghj*#gD)q#fJS?g@i?P'2<02>!5E\:J2liXN<*9$L)?fp3B&76XI9( foDZN,&r&AHK"E\AlS(Rd"Mcht^dJAl[77L%LM"7U=8Qr,t^+Gd7-"p7Q91/EUC? %lCHLBF$Ve0h(R=!`BCV3BLN3-R5aMm\3iM`Y'!`%SO"0K%$Y[G,(V1L@sYb_51B2C`K0F> f+ND*;+e*as&rNm2' XLI70Bo9%#pO[^$lWb=p-88Po<->H'Z2FN6dl\q?uK)lkMXGS`V_#>f6)LgYt)G=2P=`!h)boR3g6EXD2&$V]W 97JENfZJ?\DY3]d0&[*1P'GS4Tur#FKK8KT8Y-TT[4F4e+OT.,+t\4p.0jK7GR<"K/sJW4i \>b()(X,NM.3j\!Inb1#K,X65,RYQk_2K@"`E?qro([)>YG`'Nr7W)5bt4bYRJ+2BN6LeE> @pciT.5C<+=OfF/?=T_c;"^!:K48qo@s3+.:bZ)TTct%i\0gKj&^k;s:[)u(Tb07aTL-SZ= `!sN3d'HV+,=#%VTOn?m0u69._*$;T]/p4Q=+ba="kZVnbhJ]0D1upk6-S3%`8ADDi1pp$K q%:\OAO%]P+"."UtSSN_G>lQ@>3cX7\j,n,>nkVV_&%F)6e:>W-uP4n;D*96O`P'*&15S`' Z(4:LdbXBZCPB3&WTPVPH4E45(."B*9&A6d'2im/FohJ&go+:`/C#&8DGkQO9a?b>[gf+BQ $78C3Sm`/tn;PbhAEj@2NZknsD `q:t)"YZpHECV9q"QX\qD)5*YG#Lc.3k[GQ5[jrU?jF2i80O:RBPn'7!`0Upe($Xo(i"g3H -YB6.D/ke>5deYce;AGm>VUeDuih5ZFIgs8SQ1qVKfF2ZBNGH.IaO]Ze`:@8,lCHNUHPDZK@"Q>LbDB&ABL0K8u/ FY]WTMuBM.B"Zh*>&'Bi'hEJ0]ALHnajR.l;_#1jQte_1/Dj2:i)tc%Ud/aMGW?!GBE\!'eH)EL? t=s:kD;0'L0/'9XVSIg@g:;$#C(P]X^7EOG#%uU;8i$$4S)?CX0nJjcZQD.8Bo%_q9P<%%0 ZQ/"ga2ED$1^36eq^rD7>2[!7UU):b/g^79te9#$2u<`*>dMI1">l^aNb%K`Foe]arKO`8! f#O^/T)FV1SM;T1atg-s0<4j29]b6bM1LMVm'FW4M[>RNM]"t4Cf*RiFg,$e1l`\f$kA;:? hEJF[V3Js7cXj#S>c!A^=#*HPHmp$U]0^saL.r`BP`HCG1:@t?Y.jHFnN:1>0'Ng[6=+g[JSk#r2oa".1fDAeWa%'\7$uepWh7Q5AM&B\'S-@AL-dW,i+270dhu="YQKgpVuW>_R-6"W0.ifI5 @I^>`0=bMZq7n0O`B#M9M8fHr(M'nHQ3,.lQ%_1nqKi"Rmf D=AlsD&_S_eA"AcmUt5h'=p.#+US)U\YXquoR,f#JfpIEt&7u'b!EnJ-69($[E*S)V?A=PZ ?-Z'!pg;=a;bl0YQu/fu"jpla/_[V6jX%!>118htYKqYtN.=].%C01X3*S9OVXSZ)#Zu`s: >9mj>Cps$Q13Z/\elW;g3BRNe@(Fo#LJG;>RkA-QrXAE;2#!I"Eh^h<=icVCln#r;(]iNlA q(];dIC_h;30_[W7-/FGGfk]kD$6##N^_:'P*Hh*olM:3u*>4Tp`i?\(Vd88X-dI>?U;7YZ !J2KN-GHG*HT?4Gn#*A9ntj+`(TK]llOFm/&/Ms.i4?D`b'KfB8:HO&&4Qr%l0E-u7-Pi`1 8e(A"3P0U0.:(l-ALVA5pDOY!^S*AO4T^!;dPe_AFcragZ!:!Scl:?hg!+c;) "A*mAL?Mor(('9G$K.e`i0\\BTNl4YYe>>%AYucZ\]P$Vr.@0I@:$BXErf]dC$V'%CS!]n? 5__1][jg0LF>k"+En!nHZ@VaWb=qX;Q+<`W.t[Oaos3`7hp&3:PKErLELsnYq>0WLY`b!`t2!P7Z(lek\ /R"Eor>OmZ'f&lDus^#=rWtCao\Q"7oQZF'%gMYW;!5QA6;c"K&9ck,ia79YCFSXq*hjnX8>'rnBq?*/iQ 7_qea%\*Is3eoBG^7_88I\k;D'CYr=SW,`$Q4b\tqllTQJcrZ!)=TneG"Xl`mpeM!jDZo8b #09L@0$3*Zb0/^SKV0Lmn4E_C?%eR]m-`3e(=6nGDtakR#$>#\51XpIfCr%kpL>\,Qo'OG: BG^n,;"mWi%0UrmIoK4kC<6q2MRKdUNf^[H9;@=3::\JG\;_d0Q.-q7Q@gD+Ad$l%Hc7PHCq2+ouLbFXHCS+##C4u?a'#rY^"h sdZ54M(j^Hb*3'9]n`R@NcaPAH8TFbo'KW6D[#SFjV>D@=qr1Q1mGF)I..Wsb("Xr+^5DL= 076j>khLCR(6:MdD?]h-E*5iEFT]\92LO*ZI,o^2!-IHQOU?nW#=rq5V`jXte'qRSXfp-#G LueG^'CT[Q`!7M[mg89M28BRL+#K4NDrn3F24tRFMHi7-f^[UGR!AAI?3NT^JOa/Z[RdLLF >=gOj-LB1r-j-&^ZY@hs1f0S"TTPjRIjUMVgK'[5qlOa#/Up^,mU"%=[$V`"Nd\Q_f4*c&&Zd'3t]C C,Xi?b&Nj&,6t@GD?P#TPD&C94P\D)VdEHAH`t@BC6'"I65!5*.*/c"3dS,cLaRX/3<>i^U ,]uQ(T`lr>'!/Jkb@Z#(7ht(s3AAZu'Zi/TdnIqBbnFX<2O;(3/H\AePXQ$H(ab[+qk%M0dW_$HKdfYm[(5!bRcTrD>EpLcBN,_s*D9:0eP/n@eF dZY=&jrg9MuQ.#ol[(">+V!=#Jf^?J$"SKjWJU%>eTIekM'6fbNHS;&=pDTkR[gSZQY](8\ ESgNLiO;DDbAVJa(K/'i9"G>6J-h"P[9G?pP`j`oXKL$a0BpT!sNn!h>q^$kje!Q"810*B,]S4=%,P=7ch@@ Lj.+j"aeT.S4W*2.gt*@@qHqO,@^j$`O(?VNt3*A:@?oj)K=fCaQNmV/0rT0M*)*RAbGSk" f`hranBGN&='08&<[Sk"e$q4:raja%tc??i(icZSRN*m_7]qk!8in,+7<`UWku/qeD<7Ji& &rL[HPjF.&HiVEI[YN,NZNT$[0R`1rT2+<=:J.N%f^c2c(?jPI&!T\>2O\Z'eHk(`>:'j3g ,6d#$(kU+H%RITf#,)/?KJ7ie6c& #&&KLf":@%Uf2T`qXN]j*3M:\="#)Ceopc7Ogh4XVBd-b`P g::.RrJ,pd*#m2!R/EseT\2oPK9)o?\X8i]Nn,rDJTnD-IWBlbYi.0js8$8djAZ06&[;qZ!8f#9W_#lV)>-Gf:,]NDG>u$2T&Y<'Z"%^ (6ZfpK\/m7,)@`Xd8Cj@.=n'[&p_e@krn4:p)F.h84Q8LA4Hp4&Or_N)Ti@PkVW[>Zn0L^T k>O@g\?6Dk)*"s/8dr@d1h2N?4*I-3#\8_Uf<%r$h:5VL;;mkU[W_nk\EiUJbgAm)26O?'i !&<(./A0'V``s:[-t,Vpu(i,6W+LC.1Xl8GO;3P_>55I8R!Z9dZ\NV\%hj5T>:`7&J\NS*L ,nXAs[+V\J:[*HSNg's=rFf2On'_#-BR77kUD.QPJ`Y8BU5=/u,pX"4%NYY)T3$;j, `M'M:%o+R[%(AbY;2jJ\b#q0LAG6Sl>YBcjDFMTV@SC>BLS".@K/t$*fR$gma>HI1mBnjXm TmHBJ$7u6^ePoi\G %c?gsubI6Z?Cn;=ZjiptHe+f!OC>fnHJM(W0?f%Q^;B22?V2`(k]-O4!_RhMok#=Jlp?**\ '9$@4"\kcRINq'RM"]U\i*LS3`IR0,?Zgt^98]K*#1c6?8Yl(+OkkR\p0E/--d(j#me cnU/=BO(qoc0%IZ;bo:J"$CnK+JOJrmQZ:.R[r-cB-TOg8H.8Sq2$'Ypmm6 GQA,0hNU#9W6N?T3?"AkViY&CmI-M>&1th0uT_M(SXS?9B%TXp,O':ZR]W]h4$1nL\+\\;."`pJ"mO/B"u)SS_^JCdd@MijAGMh/c?sP)jh5lRd1tWQEso 6;V'D)X(#eG2:s'NhGXi"46YKPV0uc$Qp.F=I2i5:HW\jtYiT"!jG78K"3CedBc2D W3CUQX'^D>j5$c?WKgOoH4)X9tg>igjcj0dC5qLN'P)a1?IYm'81ER BrIQ]m&#:.)k\T(P>7rEP&hs.6iRW>][gXh\LMBR,T-6Ob+&tlY_*j.2E"^G6f@D2Ju7/oN m=$>d$Z^XsfMPG<6W;gRpEZDj0aO'(_1#Mb8AH\ac9Wa',aEjH'Q1^!3;H2OifV)gILZp]K Yd5F[1PLX5g(3POEV'nQA($$.=rF69oacpn*#*o1&kF^NDDs$u1QUA/F4dI]WCn$C'P%!%@ ZBC!=H1B/HbrI<_qAg**Q_8uUP#lq1=!:UR$/:\f#k5\7+!UQE[%P%U",^t<])8S-J_.4"6 Y(7"_J0DuNJMt_K8Be;1bj\=10Mr!m:*!c7(+b.?:h9iDaNcDocE-I>0Q@>.X;qkXdP.@$d%^p70%6p\dkJ$6kmAEH3"Ve?(;X,'&B*(lg_Tun*8 t!4Tth?bpt!gIeo9KsJZ]YO^t6s"Q@YJ;TTU.C.L.Pb&+,H'8V5Z5U=mp'&?ufYJk?`mN%< /ggWd\LnKef&.2!4DR\>r\^r.(hdMW'N$=T57i4ps>nD<\/hU,17Yu38AW"pNF*H)#;!S/' \9H,-U%F,UEd<-6[GVt&X'qjJ)+d`os.0;5`(o)*mJ_h>sSf?Y:VfQ;53fY_AGS?*+?u1_<,LKlQpRfpMt7"MF([IYk!Mi[dh0QlZ*TRMAsl6o^\+mns& e[Qt1at)2;>pO8`_LJ/i"6)^GDsk*%/JD^SGn/+Qd^j5/emeY88qX:gF+c%(gJ3G>s59]/1iV"8Z[34Gl)1f4;!J(-S$Sepn1%3RH%]g\U\LRr# )^3uWZDRZMV),G<1\3NE!GEFg[/LTr1=K)X1K?;R=N?!N*)^4 q1r'(4b=oThP[]M$6h9"d=p+1Q]hsmN&"=27&u;,OYi`FWU.T3q.A*T`c?cndU\A47JLt&< T(gT$^B24Ret+&>q[)kmFZ$$IdrskkH-K/hnMY'Tg>a_:BBQ80"=$&V7S._!MUg#n@XXeq' V0^o7h.C6g$-&qGcS_'fLb!801Z&5AK&nJ+Dj3>")/,XI;&5bSgq-PH&C7.a2B1eK8!Adoo J'VMfNTi;I5:DHiG7^R.MFE@tc\/'W*huUn7i@,SJG2ZDY8E2cI^t]nQNY59-8b6[W!Ql=S 80:V)pV@COj+l.cV:e!7'Y2]PiWp'D&qo6*g,JY$ E3/eYg3?+&4%ZcY+\[7"R8o3;"Go/-WCt]72k.')p.eQ1*7]?-<9#1,-ijH1-m.m3E(&`,L 5Ht;G0u08Q;O`n.,ZkPe+4fTH"!_9-O!miM[`+'eC)$/(JViX'E(@AE8<'*$OJn<7)Zd3#R :j.<:V$[?4U7P[ng,.Pj@H_<`7d@n]8P]+o*_2/QQ?[9KN"(i.4*bL'?[[eOd#/KmY'7cG9 5kq7,7/lgk9[Gl/Rm4U6b?KWLK@B(.&L`7M60[gRS!Ilhh&M_fN@($YTlIu.dX'3QX*T?K/ o0Y=b-X&D[@^@s4iTi/j*FlN@A+i2L6.-^'B1`hUACaUM/=[[To^#)[m_!4ERu@&=!M_EL`,/l%Ul:Qi=[%PBF_Cj7eCnGpI00Qjr+8*%Dg% #+Y_=F^_T3@8=*aUf4$V2^)/"0AN!=q8(J\H\e_(0-6_VSlaIdI;Pe,4BFj2uPg*<0cDND9 9m<:*f:u')j%b`k:3#)2&a)qHo1t[5#=5(Wo`]__r_=(.@5\RC0?tABTH-=jrF1'`gi>@3uXr64h[/<#>Rb2*ZUk79%f/,kqc^_-@i9JTsW=(c#D;+k@\ZqR.RC?_PYoe\ ,1S1ga6pp.X<[iPR&[RG]*@sqAmNS*3<(uu]gU`9EsGmCMkiGon=]7s?>@[R7Xq#ktOU)d[kNu8Ol3>IZk @7nB%G8VQJ=XA8A-58bM(?"@ekQ2_IJ.ab_B,5?K3C/mT5(b$P*iq_kR8h3bKf[i#Q2+\2! R;5>OGR#3C3afbkeh/DZ'Vo.Qe&L1+]iHf^R2IHdn(#[+jLdq+UnH!*!&568YSNna)BjP?JZ]la-lZ Tt'LAN2+T$8)6(kdqT_CtdTqiF]j;e8G'WBk'6+.N$j`Yr%G$6UjQ=Z4>.E/;(usBl_<;s9$theTtD9:%tN`KO9&WZ)=C2&;m$*Qa\#[]p:($)kdHJ (WfL?b,dH0NVM[s-VtV4l4nl/*.]XViNsBJRsm@8D@hom`>,J9oUn)Uj4?e61E9X nWF0-+4V`:`!Q9)gFD)_3u=ZclUA>5[i+%3qJ.G9sC\.*@:X._2VP8AU1-g&E/9]=C$WGS$ JM7\@>r>R0N?#Q5q-nA.l;SHUY0eG\>]WN$@d(r`fU!KG<@0Sf-da>b EU_fuamN)51pX!N6j/$6(.c'=n#TI)=nE$)&7HTfgTE0iB^c&i!lE*8tuQ\h?Vn1J!)*(4c (lh"8^^n/d/-5?+p1Pde#0dtiPloTQ_o0O*%H00qK((j.8Ce*HMVobJI2o?H)Pi Xe)ZLe]HBjUc4GO4(*NhFHCLn)=a\B<]%a.6"Sro8RN3P8(W!fu@;6`EF;lB.)$.LQfBFJF @B@EE?pc2!fT,V e`QL)A8a*@N-i'IHBRS_VUZT6U6&AfN)# J0YIO3u;.4r@S'4HV-+YXaA%MHU6&7Hn&JI1@`Qan/3jM"L%^/>eVBGlBAeimNR^15_^r3e cid3J?)J`\"Zot4UZ]UjHLVl4puETk,rkjqi'!JA^E42/G"l(`bK@A4FoX;53tb(6i6_!f' F\\Pqk^ja(Q5u\r"p#r!0m-N]I]gop5b`]G!Ql`nrMjWCRpn/d^on%l!_g]SZ9.L=mQ-a ^7oe5?+#LSdN-4b$SSK@A4P\l5X5i'7m(u5l(*;WYsc?%`,._+W).aX;!e7pu/@i@B\Z1e] e&aq7iSoC%e0tdMu\1&\R<(4R+b3Zk`Z*iSd#cT>W_jbSoG;"s`pj+m7dP:`S1hV4Q&STuE lLfiWQ9V]@;9GH'$eIFB;9+:D^/l"ZhQWh@^p4=1pRLI.^HePeI.P'%oZ;0^;o2'%]Ij)Q! bjTLrPTTbOa9VPN=Q:p=\)0F#/[T'K_XVYO1G<2q8sVTtNlV.1Ca Q7'^YrL/"TX[sQBZomOP]ms#fF$NYmt@ 3J*JVmI[FoE*N7 Rm&m.l(Ep`(=k%uJ9`DkDtX_io#`g2j_D*f!O`e`h4fSUT1'\_-@oqu,+S8]'cQH2SeV=0I FuDnMAf=+A9Ro(me6hk.+@nbi1sL3_34(Zr@8!l0mS'*LU?4<"Gict"4)6852Y$USgF.h"\ ]\XI=M7d7;l6r=@_'1B)n8JOY`>Z2CYB)b09Vp3rXR.C+!,;?Of[4;&ol,04d] P9`_:WLe&L-Xl4]Q6m3,8!@O!Y:Rj0e@R>+o%_,99N))71JG,CaYcc`>gkT*o5q3+P@b[F9 Gh;#/7K0$R>=(j"sEb4cnlaH65Y@f/n'p^eJC^&P]\3A;KR=;8Q*M>JnHO^ig3E>o`[QW;q 30];UfhH;cHb2dFrjf;8m$JMB6i <;>'?aCCKgGNZY`oijh#G8pBAHS>](GWEuO.3aD)E5a_I)RqDK7CjmC;>!.om)>8]UBR0T8TkN.,O.RD%\C>F+ing<+l5GthWbVC%Z `@kF`j`-e])]9^(<%0D?PRoGdBi4%B%OM/>DCnBmJE48\o.D:o=JpF`qR"`V"kL?&js\E_X O'S'?"m<3:LmM".?Yf$tcaM.N5*"U!.R_cSs0k]ZId2OhYKl-si]:KQ.j]n]bDFo@ H29oXmI.OB:%hfNEBJg#M6#"@2l(\k^/NT>A6=.A:Hrb%qf(SoDq?kf=_YO)--f=UHtrnkW ^Hs[-!o6e;Can:&]?dnB[-%NdC(5#uWqYm+roDF)f^\dsokP5)8'EN`G!Wt\I%fp'*p)0US 2@Y4`+NH1V'T?"4%"Uf'7C[>gE%2A`OOc3VY\b:'"?qfrSgDD/f+`2,(;e-u$\lIA'#Qh5L @Lic6Ync#@V"`Sf-!iS#rfY 85t"CmBfQ8$='aVlB\BoS7X1C]IM*![&"'2/jf7qhD.A'B.X9<<;s0nPA)n\?%FJ9@Z`O!7 ;;^D`l'C^s=r50)U[B/3L\8TF_h7sOhoZ?6%:j8=AE=J$Mk+A@bt9e%GOWKiXL=%]H#.qO[ CQ;Z:;96k/$#f+.c60MNGfmbZP"N-U*(1>@3M)$CHL*2.AB+Xm16qDS;,0_HM1kJ%KPMn5b@,+WK#CUqU>fG$WK8jA( 4oA(,=/8&#bb3UL)8ksBW.&eU5"hgd5igl"_bjkdNKhD&Zdt4#jWN^HutDMlUR+L.Zm]5QV uOG9.=95*[o0)*g)19a./g#P('#q'D`i+!8'YPC82r@O\ojf8#]KHUS6)@ZRV-`=efYFNmZ HQlHnl=6f+5/qS,^>"_4W6Pp6YkS2E_0_AE?uBFE3e01H:f9srQ`=*3J.X3Gmm Vg3lc^*CEqO$Y!p0MGYj0a!jY&V6#B4(5";\:7Et!/C`sk2KI'qgH_`-puidLC==c.LcIsG ;l[:3f2YINCMed3[T:oo$rP5.m6/(jQM03?qgi^('uD%;e9&aCOWS)pbIKPej]pQ6EeaqF' +?aQN^8IJR9M=U[r1Y?gVJ(e(#QZJL@R(XfJH$b^lWaMpKmaTNS3&LRdDU$hg)JTYKche6^ 0`h+i#&6j'QSh(BRuf_h'Qm@r/:A#<0jLhlqPB_Dk=!@92=E*#"9N:,Tp!0d[qGpl5fYBL@ L*.MQ.bSAgl!(HMPhj[,?i'!41H]1d4(n^Fc^iaaaT_42g':rO&toNjZCUQTXe96s_uke0K fqm)FQb)`kZAN[/]El6fP,+KkdZ"=n^llaMtQ4N+oadMa"+;s1k3">D4-#VAn;/e?MArP(m Ktq[HK,?t8Tr9?tN%iV?^I&HmU*dm)YRWB[-g:LLUgf(BdMc%UBjEG(#,&43"/oO`;6VOfF D["@QVqRCh5ReU?lM._E"$_4FDc9.elpULO$VPZOg+U&6h"LnF.$/[@)j3RR!0',nU,L[n/ MPCHrJaM:ZV_SPd9:Q9:`8pG.-/[)ff6.S\[%i%*I@h!bMg3UUk&llQR!?rGM=b1^"AMS,: cTDgB2o8\Lh(g\6.2ihALAR8ka.f7QjcZmCF1fdoK_IF%0Y>`5;!TmTmrEG?T837eu,S7K= \)DB0Fbo#N3Lsh0#F>O3H@5d.&Dd#MUbm'QpOS]ETF OFKZ;`Z*GhV=abXe7rVpl3L?_%-0Wi/WHhK'T6P*&ZdttD`[&%Qa1d`H!0H(T,8dQ98h2;g Vpst(ZOXW$aG7i44S]HQ1qudjO,9:TSjI4i(Aqbpn*cSLp;Cf`d%@qj",&2ZQn7[gH9@rl6g)\)?XnAl+D7u"6p0QA)/$ZIA\dth8T(h,hs+0Z_=Rd CV5?hnrTCRG$bP;)pJrP>#*JV)1%I?Va?@0rjD_KlB+*6gthn[>=_!`8X$hJgjBmfZ/qu*. jpKu,53Wo/$)r\^fi32[&J(=i(GV][kq[:1A$pYL.5RRh$dgj/a8;"EiKO?Tj\3beR(U7`m 5b&3:J859).#-)>K.@q4RiTW$@$&8cc7E134d.C`#H`j"c6<_5f/ne/Uc]* 5T2Q"s?lsHTX)h+L=`c66%3m-u&q44bkFqKa[='\d6/5ri:9+#-_ZlJe`tQ6*rI#_V7:q%Bb"4M?N@s',_<!HbRUS^_7*l"r"ie^e4kK63NZaKEt,]F3)K4TLp 0E8fPmbZcYDKUcbkaL0/E6e>PgsWC>UB8r0>K+DVaWM(Lf%#J8\^r.`AsgIhs\/Z<^qTQs/ b[7ac595M'q:j!!+>/TtrbH*m#]XgbPIKoRWKQ(d^a?REImn=_;9IoSU4MjcWGD=1H974cR GiCqe=$M(6bcJr\TQGhm4bj;'K*2%djNpTt"[DV]5TJ4f/CR_D)p:b4HM4>p#)"&MT:"uoN_W+cE#0Z0tP_mKiu\hF?P?%`p)d-SA%OE?60=V[\)UaU@ Vdp`P9G))H3b_6iJX@P6sIRKp&`3`9:]M-_k:;lKp`>'I`,Z1FD;ajD)76lLECs+KIF+bZ% Knr"5Z[>3T.#C>sb+,M$dt"qFWsZat7NF,$+KYd.=pD3,KqM\jHt^Oc[4@<'\Rk6U-\g87bm77cOJV0FGLT#3\g7OC\R9-dIt?6' \J(\`?&PlqXqT>2?AckTU4-=T^5E:E?cG/[QVXBSFMgfK`26M2I'2@g)/i")7W:G[1E=C'H Xc_YjF22(?t-kpI-mf)=nnlsD,dGgcQY;YBKW&8MDHNJ%jAKr@KF5Z:U8oi$#+d s^psI5t6.q,=-d7gsBu'QZc3e?/dd#8sjJAQ@XtRDRqFSi,(u;5[fE'94 4;ai2'/J3))qDG1UD?/IF'DPr*8 T:ip+$GLq!n@hphc0O4n`DQdq1j)-ecIQ/,DHA@#gh$uMP*]r0iK3.87#Dd='N_a3o#DZDf"ZUOVGY!S17 frpeASn+%FeRLqd/pOiKZH)U=DWZK224q%!e=Y]W#]'=@9U*JSpd_F"g2H3YNA^T"qX`8Z)%JdEQs6Q!e"#7tJN#\sWP8I!g_6IinW"TRXW(C$gIKOr/9IDoiQ`oig]#&% "h-t*8Z,3R#kL.G2DMcS3Dc=e4+LhrtRk";5$I-/iQ1@g"JJ`BE;HIH49q8X_VJKFg`'Q0I.a>[FONC$KfgaJr.o 0OF@'L:B[+G[lC<;['*bKeQZpBN^!J;?^(olE0gc!cnTm-Ybon43`a4tE.hiT-E>&7O-8SDjug"7Sfi7bD06fj\ "8m=f96DC=hn8-K!$Nhj4D`1U,\`EUUkEL>[5\[Z=g5h.\3uoPTdt#*Wb$iUiRH"@XK jS:ouRmLN5'FmOhLmHQ"cl7Sid3'i6X>AApsC3HNY(f:HU9a(Hs lFsBCs'KpYq!.j^FtTqO0NJB#?&a")W?(rN:j%PTHYf$`Cl`?n.[/@c8qlbP#EM:HqkK5R! Gi7\lka]`(;as:Yn;b.@dR+47r%C_GnMf8aA>b=0,4Z[>jU=mpZ<iZ?_=YD@%nM/A<1pk_CJAghoLh)qoDL/;i,#EWgFOS(T,#*ATO+WC[5IY[7EG?3 mPIcu'/ecscO9%T;Q^RTSn7YgJS[;PJT\"J$D=U0b)#&rLUJ8L#^pNg0>H=lp43o^G%SU-b #)MRK<+j`^.e#Act)Q@HS5O!1C44]Es840LBph2rsJXZ:P4]8n@oD$mg\d\ ]\2ocJr"2qM>7:q.WK5InTBM:2]>l?)eL`CET\?S8&mBQp`GhGr2sf*&d(Ho-,OOe#@M6LW -X4aCkqM/n$(acaEr[:D1uUPk>f>T6U`hE0Cp"6I@o7]3+<%.-hC)]kKmZA&0ou?1NRd",C <8m#\4(1Tl\!2([-#OBl73L?h0d"5=tLUQZU PI-Cs:FaeOU[63KcJJ$%r-09Na+TK"5MF_C^[!_I.Y7B>)I2*0ClVHLdpYfLoU(k>G`;Q8/ "'Kt 6sckFm?Ze_nG@^cC=RXLB!kjG=)6@_b>H:G?Srf]>?B&+DRt9c-9D2[@2 FGrT5pKZSm8'#kLj8f2(F,%6PNEJQf@nLRHL71id)(<&"U=VsTTN+j0Ld?JVha"b5L*lUMZ /n'p^e:f);E\*=ta\js`,g!>sS7.W#q3G>*-Wtb/SW_4+/PD9)]eIX9*5OC(;_6(AHle&0XF-U08^M"4p8tN6>8H&&DVI)J\Std)%EWVFf+l\Rh)@LIG28L5f6H-&q:KB sVtp7?b+@)2M_RN[]hEfTn7Lj#Fb1KH0%QoPb:- !PC@LGqMmVAJnfSQK:,U=dWa?;/B+2KjJ\fQeBB&SS+AiIA#c7*eC&!=tYr4kiYfd;]MWZ* cD`[Z+*Si3j,ZeCDu'2CQX4rW^2L]%`bhjRm,*(m(6TO[V]5diOA5ZG1L:;Ji#5$Qpbn>@Z pjor$<1JY^B`>@=Ja)E;WKL`UV_b+ia(8IjN8.S2kmi#3GqY,'0:K44!P)%nY,ih&fG@oc7 C>f(D1U=kIem#tuP2KqQoLNIBE'>'GDhHf+U)%uK4hhB.gI%CR)[!J=!.Ca1.L=r_,r?#+ip&3cdi),t5Tg3:WK;kGCNPEg6rI9n,s$.Ct!8mt_ J5@!a5^4"ETO\@[YV$/H(a0%?G\\-_KtI`mMD1^Q*.r3D@gXoW22+S:)Zlrr_K\ud+]L%IO M2II(gRP>pqdW$+_E:(E=UsW4bk`i=V!gP2AIY&*TPMVQ6FmEbYnLud68s.0t'-`\Y"c!L+ F5F3[2N;f+A'pC;otc(aB`+N00\d`gG!hUI8mWdC)#(aO7nYn:D0;g,hf\miH!"H]QS>5Y' K0*Q13g(1MYRMQ%13UeH]/dPaWeaX&1N:sKUR8WL't1r]bcKFhV25`)aP+GAgNPd6HN8srO +jZKZ1;RBX8ObTFgU3)^#fe!S_S2u>u]c4g^>)er$0W#8rR*ugYM'6Ou#V^iR,Y3^8)5/km TWJgCBL`^kD)S9M24LpiDb_1d39L/#'Em?jP`h"ek>^i>1VBE=17BjcBVc\9S7+i$5!Fp%` >^%do:An05\MGGT[X=%:g+Mu`fT.?X8lQE(p=^RSJ@&>9LfM"]Pcrl]q`U.9]]I'L9DQ@tK,-'"C-Gkl.3lP(ci'%o0'/4YK=,D$j^11!b^XW5o%9+52oUck6II-mU s3j:ERJi05(7JIs(oGui>K>t;=DK3jX2tAjV$b_9lXae4WBaSpZ,&$XUpdGSik/> ro3L\4IBSL/Hk2tg9WTG/)ah8]d[F'j7aD.TZReumW*!R*F?6M[r6=EY-.DY;V8]O"Y4i*6)4DltD&\@2oc/KrSVY %>kg`G'lW8N.tuh:9*'?Kp:8X`g(fkR\p4E/--eb\n^Y]WB9J1Ic3.Y@C/;XXTtSTm/!+&@ <$:S6UoUeh;_Wn@dHPRuW&;-V"`K&<0XL29)tSn5]m3c%3F7(?pLVV@g\t9skEr#SY3KL'P Tr6j#P;Lp76&&YS>sM/\V2`1T&0c;,9dr++pZN\k`.A^.gL@ug*14a's-*b5\,kJepN$1Bb 4jHl9tZ:7L/ff(7;&TSm^(r[/T*H7%DSh(,6iYhpgHk04:3laM.IIFL!Ap<)[L7#L^O@fc@ *9!FGVKC*df0!\nopph>WXKGc5XF30#Jqn4'VS\Jka5eQTp.5MK'Yd-%4,e3S[$VcaF5]e: c8gQm2fckkNX'UVZtXMU=<)!`L+1PUPs,O>.[mOh.RlXVeq+3,KSU[hi>rO'^D+o53\G$][CVm_pLbV^Xk*Z e:dn=o067O14d$:-MP&YDgotGY4ptsioFABs:41H(1i.VkGN'U,n7^/[,@q\`!0t&M9\G.) uN3A88i]V#=*N+:6T5kE)aE\qBT>Qo3gN?IJ`n?O*3hr'WH6t"/@-+2kPFPN7Fj9a>3As3G i)ou4A<(X%+(OVq.]kfrL%s1<>`Yh(/u?Yn^sO*D$DIpnRF^Y1?)^?Dpkt7Y/k*R8(8C"WM =H$86pSU!@N8e]&ImNBR!B:/NjEqioiZY!H1.=(^ES!O>3gBdn=C]0p8"^Rlh8ubhD`N#s! ?^eYP7Fts1D?l+_i7\R+W4*^i'S\r&F_Dknen=rPidmJPmJ]@M3+`'VP09VR6G` )$-rW%P/['d<-N_LED5![8J/nT:F%h2j9 SWh2Ka,n:#/Q<7^p;)kR0Us.#Om'G%%J6pGRu%B(u\$]@G2WnEZW'F)e&XdU%hSUnfNG$)r YJT8)hbOW#*8ScHsGS0Z;:V`sg><%1pU1JW:H&XO&O*%Ii3m5u7tA)%On,L&n^u_"^pg7/) fBpMg8__9a,e?M`%[&Ht?;/PP9oAEE2Zeh(SK;'Q^5B+go4 jN;N-?@)7p9JL&q]>1u]G((I550.K_RF<*Y4(W!i@;0J?.Z4__))^-%5iKW.mf\S?Ch@Yq, Tk9ae"qolOheiAMZ(i5"V]*sYS.5VYmKX\k%%[dd'^=fqXrcRT+WQWc*$NNC0b>73`4p2el 7P^N&a(34lC]PiT9-!Z!HoDJi=X@F&[DHYiE.",g?4V/kL("+Z54YbXqT*4oM8/d@D3d+i= R@udt>CVOlI[KkSHOZ)kri?.Z3Q;\EiF=ln6%`'b7%cm &@HRF@)mK!$_:BL!jMXV7<.$BW?:BX3A&Fdj".MA=E!FQcg]bYXknoCuNP.)r6oGaLLbYg' N-1i;TSIO )a_%V_>#*\dM[U>q\#6O\1;bb$3q]\\qpRn0'1WcN8Mim\*2*!8!Pf0&\ GZf_2=K2s&-FhFG5i]`%db/DTsPQMl5Th8&AcL*!A#5lE"jJ:'u:_+JO0jN+Z[mk3Y3;5-G KWO.g$Hg3l]e`J=mcg$j^9n&HHMJF2nDW65SSn"i5-i5XZE>+pF'6"d!(T1Zl^H@g9/W583 KM:i==iPSPC`#ZLm31^=;*KGi`b%KX9\@4JeGda+WF)hEee@HJSar#[*M*T=RK!DNrsI15qoZq0U./j+l43T Pr$pN0&a#T8?3k1r\O'f'%EZhFJTW?0,$'#9+a<#W9t6?o[iV%9G'i1BbM30:>$ed&JPI)#)]\Cm<"[:4/g_XUmm=4VT7Qk"niIo@2c\C4YXZ.>0jO= NGjc3Uh'mE6p?4d3m)fcm";AE;S)'M:,)C'kdeWs)VOrWH(8HZ8qJc$A$[%J.@-XtXV9nArVU#fH(p_j1_*>77?@lAlZpEsu!P_/="%ZI.B,$$_mo1gRj;\2i1:&]KDBX)QYtCdFp0@$heI%L5qR`0V]h!I,2!;AUJh"6Gq/k4]FV&:)5u%^eRMN7<5a2Fq(M7n8W#%_m*2/B,.t#N+@NL*A )I`IaD_e15i#TY;6_UY#@3uln>Rf1SH5'/$1fJ^%Wm2cT'k#9TnDQhQ\-Sdk'S)ns2VDq<@ N-Iq%O&b._)H!bD10uM*l6nWG+3r?7N178*n>U=K/lOO`TtD=ZCLq_T.j<[hJahp,T8D3djC*3M6+RdS NYt,<5#oKGouC=Fc4M41(P)i,_0QWtB3o`BOqm#?=W`f,lX)Dq?W)46Q.%tmN-2e'c)k"JM[` XXqQ?*C7sI';ke%=-#jU)E:^AQ`paQ?CN:=h4LZP@!(V(f6`%@t(I8rBpI1sG6H5?`5Bg%J qK&Qi?HAe;G$9NA3ekbsSpDc]HDTd2JT`*ng)M<;NU&JE_9O$OIXPY1)?DZ5!FcNtVlSFOX 7rTp<(Ilm;@Ai#XV\R$_4D@6\"DV[%Dfn!+Y/tkTru^d*5S]jd%i.Zc`bE])SsloR'hEFqg ]L_J6NNs3!k-1$aJ3l9@t&d=;srEh"rbC&7K)\8O\7'gU!kdK/m11[-(2kmbEqO(\*(m!LH TuF&8?5Kf`d@U+:qK4@0/oL=g9rHZQZcG8iCk\/9Eg2)eI:*E5"RLc^Ys+mL-6*r s=J(FmAfS=DZiP0(fCcbCZ4s"**B:loHc=HIm80*9L+"gQsj/fQp/\QFT`Z/@*<_BUlBuPI<`uK.43i3hs=g#DeRJ_U0U# I'nQoa3_)aT+GH+h=iQc[pp>l0s/gi^blYFR],b8W%V3SM&qdL]'e%Y2ZmVIMMeok\pE*$J o*m2-bX:(4t7'B$#2`rDa&l_/^pU"o1`g):jQ<#Qo8$9%QqQM_\q6#\LsUY8#/qEf"LW"n:+;`uH"r^ii*As\L2A'=h(Rf2)SOE]cEMn4\Vd34c@?;5^]r5"HW1@8;9W6+Q e/]^$'nP?`iKPEmm39eDMF$YLb@l@FnZ3alXF6544dL\NN"hq[XZ*rI-nYeAW"f:Z'Z!W=:,XE,D!HSJVbn.r3j4'GXrZ'Ze bbJgI&oYEgM#4:FV(,+W;*sRC0Y8KcVJu'a]S==qMo5hV3Cd?8pnN3uV4@\2\N"@7Q*X`OR $c\Qb7s6,9-*&QLop^-6&J%,,Z8?&aN*FKat]-)&*m[r"UB)_&gM1I`9,ebJ>/;P9/29p%_t2+(-'?PWn'o >VN8MS&;u/PhtsH!L5.k$cIMm`8:X!iR7<(Xf*.Esg58D1f(/Y#CnD>J]?RCXRp>Xo?Y 5Q'*5;lW3X]bh.*s(4<]V!kRo_oD.:1q8&X9!1@`_XeNVL)dtt+7_?hc[6(LbZ[+W8cfa'Is!a4*jc\;=^0raa9]^3Uo:_8IBIf(dokCj_ 5bHD:PWCZ/O[Z(nku?AJ5*o-E<2pZo[8sP3W3_bd[N^Nf_GCh\<_FI!d:]jiXd3!CN0`$oR bJ1ED:I:q?D1V`732+%I_]@\=Bl=X$&HK.EL=C^.j9nnj76<=S$B(Pc"?R8h"H4`U![QGRU %hC<7Q(RQ7Z0e[pQ;jD"_(=No+O=7Anl'KZdGF^u+X+S3Ak>Oi?DOq-;ch5F9GX+IC.odbC nVlh5[r^@uEZh=1*b8#;ArnuD>.]fs2T\)H]LHdtgN!_Lqkr1LfShp_T(5S*Jh!^C9_#"Y$ ?&NL"\OB`_161C*Z$:6#sCfHd5l(W>gE9oRq6nng7&&b^B?=Y%O\SuDKAZ8ni% ?tKt(6#o5T`LM8sa3k*G+\8mIO!7..1m97XEUa$*Q)!Rl:Cr2a1ej2;/@-qO;WPSG9JYtT0 MIZEb;;oa<6[p:QuRn6-gisLf9^RYt/Su73*=;dF B]F`g\doC`K?Q8Pn(hR;Qg^%F(L!=q/HGC0Gec*b1]#!Ieh=G3uhY>W2i,Dqqf:c#R(`Rgk>d)D&,V.l[.L?`V4df\'=r%?l/M=Jm`0[`,F=2[EK16%1s2`V*N&jk5B$R:a!iDjk;V[WA$QH1lBMNl8JY30;,qM kfLi7[KrcV@`;f(k_&pWG7lnX/p(4euc)j3psJ\Cc_jAYO&k:c*D0_t?&Ob"o$cI#^"%5S2Oea+O8C\9&5\c*7eJf`PKP!MI4?!7!i#.0C^R1kh&)&k,?1B#qeJ\Ifs=84b6T,il=tOs9*YJh_Kq6"%;;@(oH 0.75NF1o6HMP#Y,"="6Z&RKhdP;M7VQ/L?ppQP/.\95/Z(AaI$qdfs2R3I`bq'YG8lUaD3! Qpdfc':JG]B+U2s/VAT2(h-M;%&$KZ`k]>2"1W@^nneGn!:q-31)c.gBHbO/>+P9'XNr?S4 Qj*ET+fY!%'`bK91`tPF8g_e'%SiB-rqu'E*ERqqC%rs%sp-!mElh$7)^#>*ojtU;7\bXB^ mPjL95/f26+$CftBEO39\ej=\Z"*lTNN7PBHT]c!Q09\D9TAJE[]ZGV'1 $d(Z3#,pT'XCfj7Mb(g(/Yf](VUR=dW&Vh*qB(@`cC(ABZY:W7[eAjHRpe?6#:f5Q$b"us) i8P%28Zm3PYd>oZL'8cZapY"H]LJb8hHSU)ZuIO>.[RSV1#Kj4 6e_N"=l%"YqMnF]i"mUHi<*(br@2C$0.'PEEQj)sm3SK9$:HsHQFNH(gS\iA^hA"7h)`mEf gA'YtP4Gf2@2Fkk,,gq^H]Iml`:SPBdMe+H=P]F,c<W\/qVjV[!1FUZZ$4GO3e++rKtB+m*bLB,q]_lR2PTrKY2bkdq/,(/mO)8c/ m$K4>nK?uX[`H\9s/7V@SL4R?$70Zc7H!cYR2mPH`aK=?iVj1-LVE)n4]=/cqgsULQ9KBR> k7k\$`e16bWR!cl']P\4e)sQ-#=[kl'0^NJ2E/PkLT2@aVtDkq<:MJt70ok.\'8a1/T+fR# hom L"pOf"(Z4aiDoqd(.mI]A&Z9")fDA#KFV,i-WJk("rG[8[_8#12J%tF%0T->nZOFV`!5Kbh K^$=a]EGK5"gLH"^f1P(@h=A+C'SKo^(QJ3n>XdCbL/;"T,B^I` @5h,,#&%1m?u:Vm7#,Gj"h@B_fRF.aIDVqILWFTi!+,n?2$Z*H"TW4iE&Y:ZL;t6ga!>`H1 j"VB@Kdl$35^Y&,^9])@>,gLL0.^`5]I!i:;P-n_;'LFOEZI6A4EYPa=tpEPF"F+KoNF-3R ihp]SJT&SZ.gG\b_geYj@$HSiSuo\h]s?<%gSrrWFW8Knr"tgSlZ]Q)]J;0flBccsI"KXq? I["d!B/)mm4=[E6pial+I+C:OtM7g.I846*ur42&d)V92c7X=M*/K#Og+a/k3>4C"pLCob_ *;24R[L!2"]),e-EjNAgRb;863@b32`fg*&N#.)iQKSE-UgB9cML>1EF]Y$ndgIp;V'Pn>s ,f#.*F/L"1Q;NDB\VQWCZbBo=LAU/JMs7sSD$6M9Y<`teLe.cCCVJ9c54eA?"7aVDo?AQ.R =k.H@fF,ae=)$g5O?urKDnT(f:,G5^`3>K`7rPd!X3gZYj;Y@":.a:#L4UQc7-a>]UNA,U3pgl d6,u:<`c`Hrg[/A7cHA=1hcNO9HoIJ#u!Q+d:aW1K1+qFoL5m-UqK:"BeEYq/C2$[5h"X%g hE(1'$;$40f;"QgRi(jH,/co!<;)CMb4@$g^6:=L7;053'I2:4\)?skAJ_O6-+u4aPA:uWY `<9&W%3N"Y?3EM-`FU:5>pQjD7=cjn7AO'EXBJ'">t*j)d\SJ5l5]$[M:^>?o#CponjSW63qqL31>OB,@@!.3K=GaDn>:ma[>lds5`R%&n:ef!c?pTG OE.b)F6VKBAkZ%jQ>(kX%"<_Rc!'*mR44+5[K8=;ri%i\Se^6h:d8WA.AJj6g(gWsU6o\ZZ 0GfH$7"H7I,iD(A87)Kb(K(tjhDHDVQsBhc&lM+t??PD+YXO*h-NS?#UqKTs.N$aB=0"4l>?c?gU$b!3)jR/l X*A?moN=Lb2S>1gjVnL;7>Q7C?Ng[]"FcKckk2NPo5R+bkMg#H`I)rD?QH;H5mm\ZJi]D,n Zun'ucZEgZm:Kg-B4>Fael?B FE'Y,MCuV:/@]aKV_nO^u`!,@'L"_/\7PNFX1"Suf#3^&\`%!mBI_?28j)oZXHfZhof<(!` KpZYAFamg(4cODYL4FBu-%k7o5i`2J#-6Q`c)rebFGHoFi7OCVW-/E-I"dYo#8N4lR2T3"R UR%-#0i859p/X:PZ_m%fk+19G#Z4CrE5B7j`.%[KD>XsqH;XEg$W&*`7S5kTk3>Yjn&TXBO h>'VWK2%Ai6FI6jJJ'%qKr]LY.'2kZS2a7-:>Jk,q-b\8<5tG33[[k4W`727S?h$/9n9B/X eH[5E\9AHuma"m*O4Ktlf9^LsEgT6bJ+c>[FCc_[`5G(AcX%gSbB##ZEEi)GI[=G3& [Kd]+?*f/W0d>"SoK%8FXIZ.sh:>Lo`h4<:g0LGl.@0AP)hL\;,=:gl;&r#O;JRDi<3#GsR j#OJq(1+f`KSqS]IUmaAhmj 31@A3*Kc#(?W,g&^;IbaPj+clc)p?jGmY-tGA*$N&W'Q.DCucmpD_=>hYYjIFCN!X.L7!,h B&_0nEsMb7U>-T?J6J6)t6RUk[Wa-AEH)knTPb1i+E8XH#+VNL*1Ml(A?n:*H C4X(`6\:-@G?e+n@!)TM5%aL;.@k-$!KGcOb)^:j[t2E9F\[kFX8;Y:H7GG6Y9Xni%e+ma# P_0k_Xa:`t,j>3uNE>Ys'7k`sS;LH"$-07nY4kfq_#ZV5'#OD+=@"unr#N?SBUSS?=oJJ_[ G5SQ[nia+Z8"mA>TB0p=Q8`"?L[V-Ciqe>=1mcm!1o\sA8#ZCdQAd+PYC2NMI:hGEc2MR#q KBR,efQ*A+PFV'BDkLj":9R#p7gC/A"N[-jm^-af[.YkUMJ-&nBOM8Q\)8sJL*0FsJ7SoH# &CDWp8;\\H(mgXO6cg`nlb=N=D@@+EL:-HCd.,a,B`A]P\TQioj X%:fD7=Om[FV4CE%3&6fH8Lr!b?7aC@<[<[%[N8pG9cN%*LhX>a@n.rQNmm!H52kZLV;21` [EUIY13J>I;q33`bYEs;V=L?MKeY;p9gjb&A+K_RIscTHZC48u-@kkummhBbkHT.Cr`U^0G 2O_nR;jl_+I61H;eqeKq[+e$EdA[hk,IRHE:;QrKboF[G5Wn>A`NahMY1;d0Z,B%u\BdEd8Y=5<" kQk&^B)*iDAoKL%8Q8#<\5]A2k"HlbKOQc8+T,7c:=q;kWDp\VZH5F:!^p\HA-a97^-Yl>8 2"9eb?O:2Kt^sGadFV(>dA3lDjGm$l/:o#HG_[sI<$U]V>8mmhD_6uk"7YqUTQfJHH=iF6K 'RjTY4C)f(d4&/`)%7*k?odrU2<0]UH<7R7&>ufGJ+c'qSLJd ,Z;K^6+Pb^hHI:'I,"++G.Q5trn';f3\5SrRrR:f[2IALW2QA)GTg@hYRD;/+YZZ"Taq+>C k-'>cU>h;EjFPW9hh0!$?D<#is=0:_6Rn'1EI91XX>'Z_&g!4d`#1:S>)2?i&?lDOLH>&k: INsYX=KX*2icra"Fr+b9ekHrMkpBT'3?ChV&r!Tr72?)Hr`#7Pd7dnZ=f,i#k8D!VRqJ/7H _'?R%Y:>:qC[JsBUV,MUul0l/mo/70nlRkHBtP2lIsOaXm6nXkX67TkoO=#7OHS`fhjO/;+;T!,9^q]2*UE#4JZ]Zp?_f>[4VIh0Zmr81;nos,XlGM/RC.B%>+ ,sUYkI_WYjr;WD0r;PUNrI>Fh!C0`h!T54/JC#VI5e%g9TS*c(_o-JPVm?Qb`#40en9'bu( 4kEG$A:*^&OKSk$/ljQK[?_56F^;/7nA7D",oJM!PBL@kh6P5?6'2hbV2H_!$&lf:^uAW*e rUF%P]:V`2K(;icId2_Jh2fd4>nSZri4UAhHN^]b[@G?&ULe0h,9e)<2]NM^'cAK;"GO6(D kR0u>pZJHu[=!/C^Zj@"S:q&cBuIumP46:_Cl+QPY=OV095!\njB!C44.+GrWZR4T^q`/9a V*(>HVGU1+M]9Eqc:s(dl$cV=u#3,\]KLo;sV/3?$;T;m5$#M6T]X=(=mTiK=F"cXj`tb:Q LWiX60o0Mi(STc&%'^p5`jhb3!fV)XiFG+W\F"oICk%M.dQ#9\^D2G(EYI-K:W_hd(W*+cM \,G\MVR`n'?mZ+.I0,E[/$9q*)hQ3em$=6s.DfF@>[=51'PI(0?*@6:q@WQ#2%*2n"KG=W[ UC#[2BZgS88PL5d+e]+f&(tOqMc%3%LEg_:h#,St8llI!Q ;ON=S@sr7"[4;3/Qe5A0[*<7kObL%'^-aCPi]9!!]b@"K&d>X=6%(+.#ALD>FA5`0PpO6]+ uX[rT&o=&DJ0KerS6Z,!-$kpJr&hcj93`>Zo[?S+I8j>t;] ZQGt+Hk):).\N)AJbc;Ok.KN>F,"MV=hcu3iR0Lc?=UuX2a1m)-O1de:5-7i6"jGoU%B[fd )[>O#Vbm16hk=6@IPhch(9,qlp$:[/7XQ7^afNr:l2cE;%4*m'k9(8N>e]qC;!oQ[=i"KOh *Sh:hDG81nbK]N_IQ?2m7B/^Xu`e@Vd'CYiJ'\&R^btK'>k5jZKN-Er'*9%B6c/[b9BHDI3 gG@Mn5si?3b0>DD+40Z47L)Brp1ma80ca%5>0\NG<'j`Wi.OR=-a"BWlsrAh@jkU49@>m_1 <.t`6EiD\Wg:TbYRpid*+TFR_*dF#J)i_NAdcu<3(A^obC$KGjj%+> a)L)V]A&cq>`:HD*@\HUg=oNjBheF/5Nl)$ToE5s:ML,*ku@YU<(`5#l;(9V'e_uJ>mrJV( m(cj<=PX!80GkOM\(Jr5_ri(+,%+6XrX[Sp=eW_]4Z'Lp!UJ(A<%dcYa_k&m_\_A&)Va>J+ -JE;@5,aSQ!4eZQ:d=GhXn3]O7KU,Kt.K@TkXE+Z-TmWml=/4m.4pVcI;hFH7%"jd!pd,[B r3qV-5[NUVcA@rgUV>EeHW?aoc2.d!m=J+)q=_-J92F,j?WG*j3P@-f1ng[&.%^5(#J6L8I mk$`^WmJHc&Ds_u1ZhOIE5iU<&:E!\]*+:PAjh/HVi)(EpR5W^-Zi4Tk1>">E5iJ aORFaQ8FgjfhScE)d(E>TZ9"]'#S)!P0,llNZ_?#;"m?:iQ_ZI0Z\`*i_4'E/;ib!:%fD#r %JJD&3M_PRrBI*2*EDJ\DYf`mX'qdh&np0Y#S*e.fa;(1A!.9gfq/4q7Ub'&])+X^]iMfa[ H,%Of-DB]L$S$jL-n&E$TP9ofgeN=YE=&2=%o;#q3D('J&j&jTXS#tgHh<83D>gCYSAE?u6 sC`"ipnjDne-'7np)T;<#d&nZ`lnsV(N]1aRbRVoCA(:.p04&@(&qV1s9D OdFB_M@4LAt'&f(0O*:71]dpD(pEdQJYUM--/mTW8)o8tk94h76mN4ak*F[qL+h/N.lM6!] q9TX*E"t$\,Sf:$)o4KM_3,F^E##kA']E1]>""[;-J&)kM=i7o9Ep'Zte5VTZ48:64%l5Y@o&j`r?!9DWqZkL7 $%M7A]F%-7k> Bh\_g*9-iDB(+*]4WmdHM_F*?NLf&]"&]DP\G?/F"tk51A^\!Pf7T%3X^Y'I4e4JINe9,pJ UO,#U!;;EImd=]P#Tm?0a\:?iM/-ki9l,uo(6[I.+m@'L;p?+]o5*Oqkdk=RpAXEd_) uR9B*,:EeX;@DNq7g0ar1)PP,!Fh&r$]X7,soX(#^ia"#K$!d&+*C3:8iR9=J`Eh$Q/1ZYn iN2e&NF)*&*?jfT@mr!?j"=cQ*?\'6Y4_:AbKZN;b]-8D)F4i2.m706$O6_Fr Cnq@?uU*eq[[WLrAEmRoROT`@;t8dMm7_?PA?42Q:G&n/G*pBm-n"G.DC_;B5eH()6-sf#_ `Obltr?*2/C=U"UE9F$00T4P&UW2Wns6clXFh*7hfA@oY]m2/i*VE"t9b6-Km*nf/eM%,nW *5dlKP@>keKAf"kiP*AI)f3*6?>t"Eq 7+>6@.7lu#CNf>]G8+_WiK+f4\0/VX(?"$f@>GJ'Z5R.58@45!@7DJ-80ain4k@:=609):O \4-(HSh^K@W!2Sg_rIb%WomP1Ed)o6N4QjCg=co*c1.hrLj2%`]1)!CQ2;A&Frj2_hJneMi9;RePJ2)B2-mQmOY&4& ->Ti;SS1_IP4'%Ko)F\d_$=X(#tI'ZTGdLDtS0&pJFuTgSnqgWe#D"k[2jK+:2P75q=Qmg,U`Eml,h;iG61\JB#@O6Y)MT8G\Hus9;AMQa*#9u4eoYk24r?1HOu>[jG "7^rlS>nIAGJ#m&(:DpgL_l-@NKs;IQ5L,bJ`q7o`_o*[*5 T[1\Edn_H^F4M(kKh-)/knQNL9).8O;Nh\X@sArL*#P*l6hU-`S6_")cesDRm/mRCSe7r#O b%(cd_K@SLdn4`GTKSLkHp0VBD:!"L0`%tME7n@>-Ym"]PnDJ4c\ThZ+aTG%&3Q\A$0Gu%Q:fts)UP"-m*Nf)TkSPOrGU7rmD1 ^Cp;YW'3ZD";bJN&j\2__&s9)%MDlFYrH#5Pui^-A[2+QZ8+.i&jf/5%^/u_Lc[K#4#f nW7MK88(_qsc4%Y8J9o4+c[5akfGb._ti#Yb9(,C\E&s$8l]=,[^oO68Ag<:gno!V`RN>mI O_&aH0^Q#jfNZ4-ciD:HgJX=E+'qquR9,nlO:)W$"@$V3>[M+rg]pXR3e$NftI23P8Q6lG#2t\2Af@RCmd`,GtF6G8!M\*]\E\+/2@ksH5Al?*B@]IHb[Cd^ g^*'\"cP7D=s6c/\2oV\a4JTA^@j\`PPkG`&pFh+m9rCBpm\i`B7#:@gl,KqB([iH@bu9U! ssr?^ohjRs]:H]QA\?dMY>J:PYFXGR9norQ+fbSH7(K5l)Hcr!d)E%q)l1dkmp@JS5W6O*nW,W80ch!L=I. a/R?>TYZd-+No5)?)l;P)M*bVr)Kg.>TY-U*IN^qB4Mk\_B+&ZXbpJg3o/GWi&UYsY1i2>3 %qI]ohtY`aXmuB_$U^K9FV"R&HM^5=C9gM=0]8PZ?g!JHlF6C()X(TFfleYZWhcrMk1T?b?p2J5K"`7;S@^m?77a`4rM 2]\UHEH?8rk^:)`fm_X)KX>GrHKYS5ua)Z_W0Tr\k-HlBg<(La<*5%j"DC`2"C_7k'.kMV'#9>8-6PCBqKuBH(FUt7iM4GC%EH,hn GKX76,FMrnS;Bhg0)bm9`u$$"<>5Z%`,pki6!!HpMmjJoK92HI'3p*ZTR3b(a1"?_.4!`U( h"=bZ@=.9ir%dO;Peb#GHATWC+qCg!/4kcJ7[05Df/bN7ci&"Mo)L;:RgaC4nSVc1OrC-_#kUSr\']?7 H!n?7=O<=p@$Rp74JjH'6GZ6"-#_tb*nCWCh$JT-egl4`BAiCWg8)r#7m#F@WO\'*sGuU57 kA2W?n+ZIoBf2ASk7a95mWgsf:ZrK2'b6'hUJ^7iRL:.QoN8M,o_OP6V,aNql?/Q%]b[5UU (]+_"cC3-ZWV,\93%S8Bsq75f,JS+#_HD+O%X9-lLTA;?Z6h*(&nMa804'Go?+*KN5agt)# T[].?RUdO9m:7f/A6+kOY,^p5;53dlGdQk.2P\[mcY4Lnfhj&qE.hP'_W&j)r&lDtds%nl\ A3;_7_!N^"nZbNEoW*8Z`@V:FjRqL+sECU)XY+;?i 8J+@q6r+Ocd:?/k`Gm?^Gak^4CE"\A_9-qf`hC9k8($[Q+\4@6JKm^+4GtITjrq$NSL99[) p32sWu@T8iV]h$C;dWa9="c90h][B=D==Z$%Qh'"o5>[:"*q93DMB+iB'eU]^%[UF4C(Lch "tLC`=[_\nt9N4UjeVFB'8JdI^uk=;tl";JM[)$(Pdp"u38O(WNEk?(.#n8Q"!F78Ho%KfY T-RO;ZR=On4PCKad3STA":*pTC\mbBY3 ^K>ag#Zo7aJJYgLV@;*@F%O\Scbklaq'3`q-l^Hfk1$+33WgCD?#*=i0[m?P11q4D,JNEEn 8sR^MDVKIFhq N)22u/IIfWMMrS`riRW.Y^10at1umt.p1PP>L)+/(O%H5esLQLL;6b %UV@K]&S;&1:mGYe^?+M/8Z]O-NbH8#LN7#Fi>.E,Do(#m_DMihU(`ONStL(L?k@i/@&Z'6 mIM%1Ha5Y;KjXsi=`EfMm"3K?tT0#uWA8l$Km'G:1*#I*V5U$KZ;jNM@4UH(Y*P6j>0Ap00h!3[ (d``sbLq@uV?F[O@Y>s7EF]jkUhcB>1l4p%R5>+U]a]UIBSjbW2I)L$Eg(Th%P`_\k7lsHP Ed)G@DY.U,%7$VLp!$6jBN(_nt)&bHVZZi>t__Z0U)3Z:\+p$N&c_MAm0g`=qG6R_4#]=tes`co_PhoM] hW:.1J?&SN$`e+Wp1+BG0cTS7-<(92%V(fbZb<`+!DWtfZWOdFo"i.tcii$4fFm3pa7E]$S.d#O0STJa9qHo16lS,BD__/XV]) gDL$m>Hm`[`?H(RFVuG#N^*2$/QYA%' ,0FDNd(=Qs\2@g?Ds+_G\Z&&NQ]$=Rpn2oark_&.A,@JiEIE>BcHKA:a4Bsfm>:+Mg$ZP?s )@>j:3qB#DM5E>iR0d"eY&'AuU.qMWD 3Q)JU*$P5:NNi0n?^pQ/R?'-g*7:0q9D*c0);9sVYUos1!R?c(Bo8S#1PEhBK.pLoBAERlo FqrUi`%"Xi@56[>UIj[PSZZB<=trN8()]b8SNT%VDP`Le!b.j7%G)$L#brE_K6ef(r<4]ri =Q]E+"QBN%kKT;AfPk0hgRH1<&HmNWP)"7p+b0#/I#TUTA.[>b'qHi;=W!&kg>@TsOHWRG* !XC.SHC/d.EIgQLT897=XcG7NNc;V5Uhd+'j;1rG\b[U=bcN[qud\DEE:HHdK"6,nGl%`Dm T@dX8UECfaD#h*>RIM'F$.,^Xs+,MbedS2.tG1t%ZmV"S C)<0+Tr/Hd82Q9F(_oKDM[RCH7L(D)c=l#P%\`efM&K#Xc35DfoY7/"/rr^&:J9pdWg]NJE RY-\N>"WJUXW&Deb[fbl^_S\TRd;#`EE_NPtSH,?I;cQs(e[k[]jr#hqP0PmiE]pKTn4F4N FtH)P`2$GP^@X#7/0bj,A#=iTK%e#kkAY%u>K!+iDITQPi/NaB;.^jo!_uo83Ii2QJa4Per lr(5gNGdrK"Me4GLNn1O]E#a;$:([#5e4UaJ92!2J ?b=K_#&[K$kGW9_M:*eKj/(4pj@jQF>=gP1NXHh4;Yhu(r;^[LM1CUYaI3+$pj1i14tiY$S 4;C+XhS%KFi2-#Wd_85(a\i"5#.\4#K?p.71'l_NQlDZ-nCM@Kb.@TE5)0phBtO1Br(uJnm WXqa&+m5+pOQL*0*>dnmrO7\MjW[.@!Zb>,t)4@@mg6gR&]@o,On7YTbp!NT8>93!i_@0K1 J"t3T*^gr/O1UjlM#'aSZdpJlC;25-hKmH#i>TXoXIg:dD"s[m%95CuC<^ftgUqft7^fcP6B6^96\J[:aEj$[,GmM#VT>Qk8=YVK_l())NWei=KYU5AgTO0gO\% (+O6WO@>,Jse#*[H9qTu>]C;!!b4aaV"A@0%'[QSk:L0/K2 jLIM.=9Yp@#9Zlu&88gp^-?,e(>3T>S*7S^_9=IH9KM7KZgLLkmEBA4(cd?gJVcTRb!./o^ GO+O47p_fpIjkubi*@A87I=\\\HYC9e=deU=oi+G)+#4,Om=?kZW`1D8:5tc+F6TbhGkAg` %q`LN=D/I,Rg?i_CtDLJ6FAN9*>Nk!km'c<*r!E,l.4^'A%["gfjIV!Uq$mQmrC:>6uuaE\ "aj%h,:63M^49Hm8/d[nfMLDW7.E,PjB0#FtF6G34l]_tX5/C+(Zc7FX9I^-,k9[,a`]Xi)9iA= +d#K;S6=6b[&ZOE<\C$!i05D(fLKLA;/N*`a(DjIQMNi/%9QS6S6<"f17q?hn9QrJWGr\!5e8g6ObEW;l63I"!KKqF"5Xkgb@Y@i4\XT %u]:DJe;H4WqKMY'i/;Q>%<]VdhaNTRmI9BR-RE4*P\rcLd%$8RfP"@fDj["0jp5Qb,[ qei]>Ac"0JSA]_o'._p4_J8J#,[&[B=]G55plbYb?`)Fe<#HGR0'ld1NEX-hk$@kGI&8b%` X3/t:'DOeGn8![/>_]1=KrAbhTNDDk3"mu("[HdT3*aXC[9,#4=?O"D8Pt0A@aG8.9hPJ?Y \&YA]S;58L"Kj.oo2ZHR][:_/i:I>,fEgpP$&^cbZ)VVAB3A-m4Rm:Y6sgDbfj4[bLrog9\ dtIc&LE)i'2a$L"#m#KqVUsU.mc##0:g0m;Erb@kgC-g3hc2N8@a/W#JQAUW'(`c)k1*XbY h_#H^#3Fg5-[Z;,Y0LTl"-qS!3AjA,(2>CEtbN;m+O*s[%-V[]e5aJ.!Kp"SgWg\B/$0L5f a/qZE+_M%ek9`3[FrS1QP+11BhaBJb[!^d.76MP="O>VcC;$+-0:jYG1\0M849*+?UJUIsS 4U\WN&D_18h0fl@NRp#K'&?2N"lN#SJ7&Nl+Am)c21T->GU\A4>QZ!);cnX+^hJJSD\T-qL R#8Od%L][F,'oGhRt7BbpVAr8V\^!K[=B9E&U\6/lL6j?TW93E&NFn;1_LrV=7oI+=.4_>_ =Wghn:l(^bc7@IKp^("U23d)9.GfFG>5.?p"FD&8t&JEkHN[e1EsoNX0$[Z.)32a+Zqj#Y9 TtH,mTgi:tLFOlqKb63IHbK4C9Jj\H'l709DfKMXI)1kfA/;Q/5="@,3%>ufEt>#g;!6_#eKog'$k\8ZDB nKMe#*qbiL.CbeC^.h7&8QV1Ng+f@)Q&85bMqH:7=lr[I$faELraf7cA`Wo'L=)s[EN+]NGDC=@k.R a+`N!Oo"GNB"'#lilQ>pOYE\$@"#B4Nf%Wtu6!G?3Y`iNs2g^,Jk^^&e?#&%&lQ+1%qI:qt s:@M3fk^:D$EorY$>Qql<@*jQ4EeF]Z:REikAr0c8`osPE:[IHR3+N15b_'KLkktS?J_bu^9&Z2D?Z\$?UaPO%^9^KAd)9l?[?(5&0lp&>A?>!l[ @i0Lh_Ym5Nc?s#nVK>XR^+T^+8;.e*V.tL'Q3d$#Cpq$Vh(;`XC_G>@?:te:u$m9RML/&d/ 2O"?8=E84?r`.FdQ1Ktp-/kYD=X3+8*km68u%YXF,h*BG0rWC@rg#2*jRg,_tPaQof.OA77 m-11)-@UT;g'=$PoiaSM>.]t=3hCS(ijsn/i#C(&[+D_9:G?2o'L:D7d42gIL\qck:ljiMp U3;4bAqr9.=(sbJO?NipCBMRCK:o,pJ5tZ4;rj8AA>VrecMR(]8;'EXjNdg:`rT`,K*A2d5 H\U;89SPU;MH$&=M@bs0*u2T6\U3/jb8n;`slUDl=HfWE;j)3"NZ5J7ciK6EB[_!9q18]$0 F/_9]/TH_tidk:hFVbE)Q[hn7[SjAS-UembjlGLjY!'D/q7HB&=kS0sHEMGmBBQEdoKXM&Q \5EJ=t8EkZ^;`cfh4*AHu.#7+r)p3lNS0lnssSWJ-SpF0:sKBQ?hgZW_^(dCfH2[8J/K'%p R[Yf.P5#9I_1)Otb!(c>XbNTO(#*;f:"$JI%#9^'6JbWQ)UIAnI'6LA2Bo\\TcC/k+Rrm@, C!TFL4k#,K9ED)$"\:"VG.<>k2[9=uKesM7G^bFXHA?HK"dZ:Uc0f`3>uGWaL%&)Ia?=;Zo 6)ak;UNgBe6oa`A0t?eF]W7"G`%'8^NYEbms]<&hL+?Z fbra)$bHGBh,^?pFjLbO!;=K#Z,Qp(h([(i;3]@AeUckX.B8f2Z=T8=%rg%u#7(L..L!i[% g.^deO^X)7RgGd\pXFHtjGj6eNLq"Y.dQK@o`j`rK@O^MsZn5`-KE5q!SX(&OgN\od$V"X& PLPu3,&"RVMX9EA@P=[Xlkr/AB5i`tQj?7s;n2CMG7doN]7T@Ks$>Hp8TS0>`K`Bh&/A#=*V@?Qf[&[/$r$L#?qTs!<'M,Q-^M^e)#)O3;qndW0S^#; BqI:MTIHen`%P0h?Qp;e*Z@'*gd6*="Cl2_og-hL4)1#?YV1i-tK?d`MMIo6u?%/\t[756E l^K@D=@hs#46l>uFZF8Ql0i*?Hj6@SAjBaAGWBJRI^1c-126\IIAVO-rd9(^/"FRT!HkP8D U:f+c$JUh)1cl=@q,";iIL]XNNa^(>Q:fogu&IX:[@5.Ie-(Mb12qdG.]?SLuN^mU,q#lF@ ,EbW/dWn6X;Z;*Yh<^EUZ$`U?9dXpa`85VpSk`q)\b-/X6_Db><,*YOFJ3D!c4'A[[\6Tte EYRf`DX*FXk%9QqXoTTA$?nSW\So-5Xi'm=N]XA66-ZL>jg2o`RaX)]jG3L`TaYEdS;e@ME EdA%uJ;8n^spt2^=C*AT7(h)[9<3c=_4OrW>HAFPAb";iKs#:= Ga%3mSJm>WA0ad76FJ1^+%Ld$-Zu7*sF`&Ok*sD';AH<.-,bdZgHXGFInf3DQA_EThb9k,H :-)Wr9dG91l!=]X)'H9QQpkMpVe[ah^(>Lum"H!FFqYnUXdKE6O;fS6phNtq=I,DtDBXaD=FMWRQR6^t;](7_/mXiTZ#u,g3Op4d>('oMZRZmXLjB)BOU,kW1naUhJIWRAK0%5$(Bm(4=`[-\f8KKKiY)#?aiRuZ[BDO\B-]^EDgn\/pGmfC2m>PAHn7Ii$(f"ke];)g!^7V+aH=!e[lhb"t\`O\5!P@+\ Iilf'r80`do_i-(g"[YSU!UtL?>l2X'$!rRhsZ$iKkGE%`83X/-QJ WMns_"]2Y@&+?ccqXtb=>:$IA,D=F$'LGnQ4i^sfJFL8i6PDjP#?^:47n t"Z.!#mW`'&lPqAr$!KK;LDJK07A3/u;[(WOgJ$Lp#%`9I:`R@U:Vs%i.>G(5%Kf[4L:H1^UPs8SdFLEM8G+"`fWYf04AQ+mRO*PNaV(9U?O8u .0#XD8OchapaS@,-A>Gs8f2lA q(*?&E]l%M!l<7pH+;ndLUjZBB\N:7,eb^7[$7&\/%qB'5:,_P$D&cqJpM\-;!O79st@8p2 3YgS5?iY&;j>-M#s'I!Z(,")$pZQ\C%M:)9=8(G9qrOog>ntt5Y( b?9bE,,pjoWa"on9u*gJ]L3;+SI$aK7e+q(Cssp6&>%0-#ZO "ra2_pMXa_!^LEanhT&E=ELo&-=Pk#XLK*R[F0KgTjF!$#CMiVf#9 jW'hUZA);(UUY[^I#F<]k$?0`IkX&Pi]9PW*.W=+NTQ2ERWE(Vc.T&5Na](?8E8^NUYp>+8 C\%?>WXGsa5C&2+io?lFt)3Y1@bjdCIc[VgYN.0<>e(;YlaQQlJL#2m` _U32ZDR]l=iugk<%kVgRjI/F&-NU7-N.un t'p_;9t[''*7/keB4=].X7cL<.`pkZ0qrl&!3"lKM5Ak`T3bZV[qid>=+:20RRg-6lt]Ut>WSmTYh!S= &kQ_!`j\9F!BpW`X__Xu"?kZ/M,AX\6tj(M@Ot^n+UTd?rR\WPs5/2CX76) _MAJW\n(p.DnpY5pq9.8h%&(k)0rpT\(W:(G4B[PjkM,md]C1\5-nY]8IhbZK"lOm\K"k[W rL^d$i7oc7Yda6'hpo.?;%PG!n;eEf9Z2lY!"]A8:^S%u;#E![r"'Y@VImPS/oqGB!_dG4D lEMf;KZVUFm!4WCkBsY56M'`[Xn8jTtD=\XNIbFb)f[.&6T05>6Y=q)^3uWYX8WAD[-hp#= :Zr6+Ri7;[94H_#b+_^^oAG)dr@I%91jHh[RrleSsIWE9)oD>0t+"(SMJmnG:a5r/X.B(*Ls@iD9j >J/"Z4(Vr3=D7\CpN=l\a&hTE5NO7Ee0&&*8'%&KKOZ*ri'Ehih&g1Kt5sC\Gd+lmp'i@la TgT1FNY[/XU*68*TthQi2L[sS*Mk\&KifDtbT#sYi/SBd;2Z9RNh+AC']PPkDBTnC-Q2=rT E1&e^oA6&8dT4+RVkCOEP!0P^>t.g).@h#+hS]//I:j'1#^P"JS,e(h];kr(TqNFY&II&FQ a>-kHX[C/qW;%Id$3X+9T@B/sne:P3MD/%rS90cD_u8)QG9a5Qh''!>Z'GaR!q&lr#_STb7 k'dd;'AmB5aB;Fp5=9-k3G8$;:K;HiN44;)'^&[)KfNrp`)\?UTm']Abl.jjf7IdqH/nZma A%j:GKNq3mFo.lR[Kd[kU\eRkO+&V&JO#ln`G95/sk3l4@Dd)hmdLtMf*5N[4!Qb!9`@UT. pG18N!H&lBhA&>VpeQG8P34IGl1c%=3`n\J9"#UVr2)#Is:_>Fg?SW:&qdqZ'P7 7SWD`5TN(dY)@TpQd-i#@6k*isf4!VFHRX#U5\(u`a[OCJICT/kAq"nSWQ%%nG'a;d""4&` UMPI`PYqB(:VS"WCo1Wp&&cQ,s54NHS*U#$`J(`nXt$Lk/]OK1RokZ$de9,OR#3Zks?('67ArH&>C+0D@\H&6W!cC+eBFo/el*^&HIYUF@I(_ 5R4!+fPquG<*MeNR1mt*7Su6:FCRe)DO!M0&O8l'JJn]#H4f(C(Z?hK0j,5*NtlbuR=U*cT oKlGZ7]"o%3_kl!=Y^cp)d`4*]*jQ@ItTAefCH7("&!XFN[@BcP[2q*.`,D6(et.h&8-1)A M>,+^>JML_PB*h9Fmu&\T/@rD4*A):Jik !Gi#VEc3juM5U$C$`=s$&Y)1bj R(Ag89Bb]=0"nOY=R&?(kG]p@@A"l.O+.5*59!&V-tKeT"X<1ooR B&E+@*Y10RA9j"f[=BL33Q%^NI?WelT&E,/QeXl8QT^ZuC-ZXQ<ZJ\"Q,/C2 [STkn'e3$F6u:`Z7poQVrno"A@-`Eo`d?^U"`GjA_HmuERV&-65ZQ475bnW3JI>L/6HE s#jZ(Qd;_?6Nu"U!@_F-647/(rkL:[C\q#Ao\B,P9HLBhHp2j66V0u6I!@Ade&E+'oA)KU6ap6fXGTk[08N;")/o*!M/rgSf-Z)iTQc A]/s(4*DjcbT^!KSq@%4(%C\9hQT_"N5G7icN"dbg+iG3@-ZqHoNZk,3^rR@d:'l,WUK;5S RQ;9/8-iXK'*)ZhP[/L+>t,WcV,rAIQ]%]>7hcc&"X/7*i+%'iK;SC:82mGn3dZ2)Z5I(A$ A#Ju@.5.ETG-TG*WaP(=<8c>p)X9DIG1TJ3iRRPiZ2HT'g\o:+SC5.o1kYE(LZEV>0DH-c% +gO)e#,jq8VN)ar8)k+6!/Xq=1W.g)"2)*YmDkpb@DIs+=MWVDp_l(dEZsC_>Ut'gX/W@5i nM=0_O'+n],q2-pW##9rq_ZWM+H!>H+(#D]TRL_toSR"_p"MQZ`8M)^Y0+Y".mS[J[@'L^4 _iDpGuZ&8F"MVE=EpqM`s_71G6Mh0:sTqedfN[02.*jW&1[GreN`"CsL/D0R*R-hJpn[dJ] /V+NMTth+kZ]EkYO;Rm-GnI^B&%rhh']G,n7M`ZDMH^d`ld=]<,h=2=/I1tcZ1G&P3Ol'D5<^AIQ:juO>fDAf.mQhc>L3K%U[Sf\`B+*j-^)7 132_Ah1/`EB1ZRA\$JPSp1DJ_WoB\Se`mC`mAfL6-^ID`Xh"_M*S\H)@amF]?D0.%GDYQ6+Rk@"eo(!NZkJ>5h6gH=pnb l']=tGH99Ebmh$^j'4>aS]_[c%;l0EpV;2BQBiTE965Mp'"LNIYH>09_+/_7HVf[cnf*UBfNQVRRaNh5jtL9Qa9VhfTu7cFVqMAt(O.=2O&)t6"gAh(YT!nQq[>P/rXV;*%m ]h'JIE'?4gI6"Z5?ZKKEL&b/QPkcZZp=fTcapWd>-QKXS%(N*W*4WrNt5_+YB5N"rsM[m]'k@:Bd6OqmP9ia+N=R'jG.IH2?"jID'ADs#nt],l0'5ijU[`K4O1FrAg$j\_2&XG+rL5"_;RnPOU_U"@>tJ+=['njb+>p6*fYPR&sVk#Khhn#5,O;*5:)So;\*C'J<U63&=-D H>U'S%&MpZPe/bCA9'+ESkUYsb2j8X<463gR7jE@)6D,#3KZ-87qX&D76aYrW/XCi)N.+^; J8irCLR6?WDr/J>.%\A=fk`jQ.kn[_-sTNm$:j5T$^MB[U'=WX1mD/\(kkf4136$Fa'S/m; t[+X+.qC0N_R,*s[Y?@^-c_FuLS'`1[`8j:UWnQd"SJ=kr.h2k`JXen;>K[.8TEC/mfGg3F fg9C-hK/Z.EB\_?KG$$D+>g;QLFpfpQ9(Q-(!'pH_6Jn5XZ1O.$,oiT=<_GpjE'J?]X+/q"oMiT>1!j!'d[qrrG>0!CBhJUnKpT6',=j#XRsB 4@p3^Bf8d!Yf&C-_f560&4;Qo57nSu)$jT7A#YVm%M<5W(<,g.@i@fKZt;997?ILhQK8/(> o!XTAjf-%1i">UnjJf]%ORUN;9ABfTd`U>Uou5j1:4G?960[:0M@TD^G3qg,gS8=#>*Q]/M hM+3)28ok;k/lg%^%;kFqNf*G;paE?8^XY]lG2M:k6n'KKQ3SKq?SEDc@f+\>S=V(YEh1po 27;fq[o:fEVo,X%FTd+2/726!B@(P\n+?(.&_Kj`PV22c! IQ;ruWff!E6B3I31VF;:jR0$Q["1_`EP(h#29,C&<_f=I5--pX<2_EX'?'eRGG[:'/h0NBd Xlk%<2oYNP`4d%V2jQrsdTE, -?.ZnI@]9G,8EV$N1>*5dST%q4N`LN*M?6n!TrL%q;GU?kL(nTH2ZFA7V^3[dEVV%l:8\e1 U">_nJ/(?4[cMp[857QA.#@h`O6Oe+F"R+WB&FDHm+[Q$`!7P=mP.Mora(lQc_$mXh^O0S[ M8/V^V,W(,X!rPZCOb>+a/<,e_3_2h&,pd)\Q]_FZ:kW8G.72,/'k+Ic$E6HC,oibH&tVo( iP%!6=[F-=J6fo]BN7Rd0.#DeQkKC,9Bh9eAh:iedjAU!\W8OY<6gnq5&!_/W A@#ZZ4I.Qg8r1kU+[p(0(,CVHcl(k27h!e?1o?eo;DV9f%<8 U27eW*FRTOIPq8#&_`8acPMCo$.>s";3m*h`=:O-#tYK4s9-Bu\^;alGFQ6+"IRi,ZdE7GnZSNFC9$"[qZG#%;`4f?g/TMucs(W/deW 1->Om4+"$!l/@qj[,lq*Ncac^=c]UBVkn\ZQ&2g?/)E)Y-%*'\'!rAX7`9q(7iIU(Dc+;Fe lEG\@!1tfN/Hrj=:DaeJCP+>7;:YfIlRKC\NGL?5q"2mkBh=_[J\cEIPp2Eu2OVDY[WYl$P .j%qD\hR55%[IkUKl^_c[.ZW:ru_q9nc@IQaFg_;P4.$>Jm'M8ebVUR<.'uLJZ$fRtSeZUj i`#"aO[MHk9`YbWk_['>&_1F9DR(sPKD\rqgIPo/2e?\l4*FlJ;56pEN(8H+k\Q:QJng6lJ fdA!)]TJC5<_[Q9@!7RSH'NEY=3DIo/J\rJ2atCUbRXq4cb.Aeo/:(&)3s-?dDdk\fj#W:X CmG-fpuJFG("Yn4_L;\Shp(ecgQO8O(%":oJ,P=d@+6rc:fWrNTr': A,cBK3Rs@VskIa/qh%sN/Gn.*WU"bt2*M]?7$H]2&3&_$"'3BkVIMKbFB+NpqW*Y@$W%8%H hOGQuN,aEA/-CFU)?OShNH%EE7PK=`S>LT&\a.DKD_1"gOCa?sdPlo"QH\ddF:FpP^Ua)'d )+j\%iQ83BNI\W'KV+KI[SX\FVa6%^e5BV_CAR1r&HVAsd^+3lHQg)!k9 ?=;Wb?@j8;[iJo=7fbHeh(q.ZLn?8+rAAMtFumV=WuL@&GHLQ[Yq^2@T?oa-Vm@i:4t#F lTTgS5)E*W)Hok2>r\qd&ik7h9>A%c$B@$D2784/0`#HZle[PQji7njRp6C_U'e8e9gma`- IjaEhWq\jf@?_dMS_3oX>3lMR^mN7"hLQ"8GCk1CUMC'#>h,Yi2<1oDZR9rYM!-"rX^$3u "r((9r3'Z'uC]UDUhs*l6cCL>ZEoTR7!6gVPclS%)s`0QJq$-c0pP6A-]&N$lK,.\%nq#9\ "Q6nQ::0#I31LZj0l^iBXX;E;rWZV323<&MQm2P(2##B4NHj$e]l5f9on6c2+*bWE_l5/Z@ LLQHG/>VF#EF!VQ`U>_Cd2Tm@E-LfX[$ @Ke_;[CfJHUfB:jg9BG@5_(UipS`]Re@" Cn6*7Q3/:[k)3I:f7@^CP>;:\$Tt\XDPG@DBr%\jN5@Agb5hRT 42i]!Z4L\7"K5'XK!EL,9rfbMX%69llc_L@(TW@3Ks4=br4TcOcqEkNKud3t:fda`]$$ne] h?tjPf6=+fZ\0NXD5g-OFAaVP"`2(#Q*=.j5-m7i'%h6^-p>m"OXqGdM+ZB5$R88KBCEhe] i)-"1VBd_s^C;d63d@Jd=a@(PVuC0(t#&1LZ!RcUb2o9I0[Q0L0.GCr&rIR5 >j'VdPW;fi,j]]s6/L4sChMK[:Z,X'm2o>XdI9`UuVfrC&W370+N:UUt A4<+JI(9%9\1`bTZcMfK"E:kCrGKfCa*e8EeW;R`$1KkNLncrCT-g4pMX'"OS=qI(i8HRTZ;"KpY;3-[YN LVSChZ`.!c)"D23ej9eEHk's11fY0ANI/S*GWVgbm$:Re/72p.kS,cLo9(gAAZro$8&oYRL/" :e!^gpWmUZ>kQIJE(PeC&A]@a>t"Web6lSW`(k8F(^0oUV#iAr?r08s:i-Hne_K!Bg]em=" orrSbTbb@ij-@FLX:Fqoaotkjkb+k?@*uR(jUmrj'K.ZhSRG@E,l.7)d`1UhZXtUrUC4P.g ;/XLOa8s2(d6>pTbb06:QuN=\FTuM\?]"b(oeOuC!n/1mi$JR``A= +dE/"or;fHITLbo;iqi183gmD:de?m2V+HY)^&&=bGg]f<'F2Q:T-m4p:8$jMcT"rIJ&RUq:u`fN(i$8F 6Pi70CMb463MGY#X,o<`mXK%s9J"*Cqp\dqTis'ak-f*>=DA&m;[:ZtLTWi^25XQ"W!C;@#G>[4Y[B$tY%Mm ZkCp*PNd$7dL6I+jhL#T j]hrK"?9QgrP`&cNp,Vdc>Z/THi[K;aBY=#kqRirXRf]:Q7s2G5cr;dmEfRDcfqjb0PEb*L h9pueEQAN5uF]I!+CQ=?A9:pL*Zl:Y[CbEhVI#CC5/YOQD[PeC54KWB,7SFW*Y5jDr-MXhM /8kDR!N(Ad:SBC=]cX]$Aa1I@F>DMI#!5nLOa2q&9NY+7dMSrdd@9Tecb@%")R?Y?t&PZj*\7"JqF&3KeOc[jpb8 _f'R)$L%%lhi[#dX.q'b7Q).P()lT^)I]sliPJ)1dS;(Y:gsptiZ97% Qu`GH9;\(W#Inc.giA1;C^+c.D[%f^%P7&qnYS!^"lkc"GW91K0amn3\[ZTPJ'aEq!peMsa#E:C6)IaZNsEKBPRSVFjq)%V 2,XjL.b6k7N]N:!-4+4(P2uCo?A0KtF9J"=Qe%7>YT)ua":oT/WtX*#?4"Y8N5faW7mhc#DRC qrd&WtH1Q3)F+pb#Ct.Y"3p5rn5*.cg^4Y0a5$N82#*$6:'tV[%A^2WZkdHB4^I:mg5)"pl >VAY3pIT*=rm%n;(abFU ?XqjNPVm(U>\QZsTKHj>FLG3M!7HU6)f/-W5'1WI Z*s+0P2K'_BI+Kj(_cte?63ON?u!iTL\0I#mkMX>VGD0oBmfNpH,@Ns+Rq$,Y5K5(E3COog PDD.7B-^D\`j@4r82csbt4*U+Yk]s>pV%?XZE-8[[KnlPoCeQ)Abq&6!U@0b1D`=J<0S'KU @q-Eo-PCGI2Yb?YD$Hq83La(hctr'Rnp-%f;i(NFC]"@,CqQq=pX=E2+!ER 2h.V]Er>cIh&B"Md\BhH_Wi?;$V8&Uu(s?RFno.:ur=EfO^d=Bl#1BRN:eEp)6KpFcF*`Fe 7NB*YgOO##l_1YT'?kAN,Z7DK"uUN,CQV-nJqQDsPY?LYln,;nAri_-.*KoakMA_*OK>F5m\5Y@" %u*Hs89Pm$'#d!Y)/$m'2E;h=a5g,9,_A`8PK@AJoD1V9I7LOh'.JmcD)IhX-W>[="IAK*JV[KZW_1R]1'$2e8mHRpH ,5&mgtMj70Z"^/m7WcfT=0h&`IiXjZQ YHTci0GIcVupj+PnWgWeaIW.GP8$f2+k[^[l+"r]$mIgC*5@8otkP5(lcjT^O^^qap!l5F1 'a$a`9D!HJ-54u;_MuD,H_*`i_If>c@93\%&6qR#*6$knD%AtG;&)MS>[8,b&S,Gh`c6rO) og:LCE:G-jE2Nb&c@>)8,?_6N%CMaB>#s1uEF%/gm<)c ;Q2/!n%u4S@T2;S7I%@/uN)j)iW3\JEnqNXeT9Pj :"aaHf8\O1Q"JEW5oJctgO.n&ebO^PfF@_+Q32]DBG3kgY#4.[Af$2j`d&b>(Loo`Mdj312 2pR_`]]=Aq!LG1jB4*&PN8-$9pFb-?MgP4QJ&1) Sl4r%;9o=T!GmeOWdHk-+kDZiW):6G_<0?!C.>-"Mi(p"(6cmJl"K85o;*R#10[gO6uj2fJs2olh_/:9Pk+r8I ;(A-\YBo(.*g_$K6@aL(MWJ6Wdh-iM8Gfd,lB:\:"a?0^9NLrZW2!jupc;k8hIuD%9G,1Bu M$(^!HTMp\7\,.(I0nRaCB\@iZQ"C6s@IPF;oaVj+YBoLH>1e,"+.gA9'&RsC47l]fT,ID` W&aha$f_$>]jF<7h#!tie%3W\&KGJ'F22Zs],@l1^OqLM]8Qd8ajJ80+dUl6G\L\]=:t$#. ltT-Q9.;/DWKe+!;p*cn.tup2&;&\L#D$89_iUr9;W_9.WHg/YoYHm#%U_t%Ke[0"Eu5&pU WhDZ1WhQ$RF=W?9f]=4VSq#S1L=omfss'(gu4aOMJu]WWnH'hd3/Gpb#slXX(*`rqQ'/-e8n`nfU,4us#LOOG8bErKZtuC4att 3YJA`".9O\:T5#b.A^Dd?fQ581Z>,cp%VA.=D;c;=3LUcl1[-jMag3d;Kl/rhWG\rn%=DFi n8Zdh"Qpn@1&[T8j@3sQ&* X2ad]&(/l_KmFuI8;b,(gA>4Boms=_%_nVJdP?MC(ER_E`Y]=@"YmBsL5[d>l/nOO51fT?>0&O >,UM/h#s`jm;S705=Z$:XHF"tG$uWZ.p[m^:`Z[r1O7"\K7o+JB)D6rSg4IsKTSku\b)oNo LM3/+;k?;%qTN.Gq4#H73uV;Qe56/jsq&@&ro%=2DNiIPr;#JjL]#%3q_3ecdq)Ig??0Eqc 9YcuIh_749>YpRA.!tW=:N+e0$!m=`$.)elp(#k`dMt(sF`N5kHMpTm2`c.5*6_%tMg\6d" #!kS-aelHSNKJ6K:M?k%W]"J.PM7]dak9+eLg_toKF!bYmDgh;r4>$pX+SVk"#7;ZbhejDS 8u0Ba_&RAjIEiMFDcf\kqI8("+r&og>%q09[KQ:I*gm;i%rq5+7p,:',C";@@@fDJN)PV=[rOs _bo=,EkhQ'5G&G"L)T>s$OW2S4mn"&'GK0C7>Kg<3.6oa9m$cj;#D,P8#Jm3hTTi?[=7G&a _rYQc(?7;W98S_Kju40G*+OuuWH98:OM76TNcRs%:!#C[-06,MQ#b_[1PNof&-Ae<:_%>,H +a1?*:KG>g$_2)0bC$!#)*YP2aobr'BrIhVK@tV1.1Pl(pnLe;5/>,.2=*>i`KXqOYAK-BU TcI4ACbea=r:oW#.A3[SorU9tPUhmN'NW%5H!^2Q(ih=6sH-EQ_=]O+F;P&&d3#C@'M(=I1Jda9DinLG7B.+-9pe'0fb XZCkR;AiH@bi_CnfmQ2NY3?Tq;+Ds4MiEd=0MAV@Ujmj32Y$E 4!)'SPs+t8rn+`8,^p(ZJ7k;#$[OuhdS4X;KY+DufWU)`Bs)!NZAl#KcMZE\ u:8/SV!YQZ2&>:Kh@1Xi)_X)0_m.,u]EfBA1b3^h4mS;XgZC*00kpd=9(ZF?pk&VCQYq%%1 )o:GQmh5-<_(5)pnFF[P.[UudL`XO7.oP%PZJ@+mINH>b*%s`5Y.iRA`r>-=Rn0I(fa:IlNM^)95b).?N"PX&MRV0jn'I"Hk9+k6#9"0+f5olM$Pp_#]q@ZZme?2 Hl?FN&&Y+__;lS7.7?!\2F76nE3VgtP=5\MC2g]l&A:N0YfaeX&4%]^!;R&I^IL,"DJ[3"o R.1uJ8[^h%uf$KbhYhZm13%j8T=\?a%UUf&P=bfF^Y7]k7Z/s+F#Uq'%&L.PeB_3^j<7E'@ AfRoZRo`1_O5O'nGG!JX@1fm6Era*MIQid:H)C?V_8H:Mjna+]oUj>Rlm8eC=hRO`_L@&K! A?(j-KhPno&3W#K/;+$oP(D5eCIZJ06.)<'Wn6)`RY],Pb'<)lLh2,.%m:5ok$N`"7FeQl1 _@3"M?&-65ZZ/m#=k>rC?P:dRl'mu:/p^[C3imJ,U;?9n-O]^jm&clqg;B]36-X%-3>#hP* .D22XeKe$W>BR>XY'T:AL7nV2&HR[u+Vkqn='[Re>uG$8Jj'\G'H$oE&YY%.noH1!H4^0/c QP(n(&]Pgs![RA?uhFt;Q!pnV-u-S@eC)3[9J[,eOX;ShO#f2lD!6c=3BFSC5(')00F)s:Kc##Ac9='+ -1P[qT?FV+\&0OJ'&(j^O7MgUm"]+SJZ__U6rGXQo;^$`)i+O!Z)@3%2&\sbPJMIU3_)uof E[?/RiFEL`ra"LH)fG-eoLc$tkSjPlF#QZU(JR-':NX'B'k,Z0_,M>(?k63D)F8BSL(k>$) $^R>)I\jB1adM>/U.saGW1IGiOBc!*ZTa2'TXbX2k=Q&'8pT6m(^(B6Y)K][_e9 ;?<^IM,H%8c"RpWH)ALIeZ>8CuN)oT`"TR7YWjcRee9[&"?crXbb5d'U$$oX.?!_b9b*J9V 4FoZ'YTbCM%X&:lGHiD()o%eSitFR;j`0i+/m:KTUmJS5Yg#8\*c;><^[fM,5Q;1tl U*.cNTlEaD$R8\+!)H!J5[8D\RD20uILNmfo@8IfWcW0XLLffL7/aO'8C`FSM'd9JUpmkJG Ss&>(*qAm^!=Tb&S.?cN(_r<EV:4\ ET%D4;jTLeQY(SV!F99IJRs +ZA_Dn36/WaHLM.k&R.cf5[[CiTTkQgF)I[KLK'+f'llL`!)I_,5Tj=)>URC0*C"B%oRE_8 4d;#J3)SktP9M>]-L_)gj)0W]0!7i"'=:2LeD#*n!H2RRugMRo53+7%E?sO0aA9!mh#R9&HN1MfDO$`$\1;bJ=@oZfFNO8&JNDS'EM#ETfO+.AV0\7[!4[ >QoBXLDbp$.KIqUKfMdIu2MheouLKfOhRu+ZPN>n77 **A32\;.WIMNGX7'g\mX40=AZYSodb'oj(P.9[;!E#IU+(*SKr*gd>S\B%tS+)R+mUFe %PY?^,tR'Z7dFX2d=r)Nna3hR.MO=qcqk6OIQW=Hjh7q&!8jgOeE0rJXd<]"uALL`/S1*B@bu*,W^.EL)5F(?* %JUX+#Z@E:QbaC=W\61,chLWMQ1aa&fdMTnN)a-AZ^(>6OH\])_e_jUVu*`+SZ>dtgU\/9k V'ca@!08#d_eXZQdSNPFZT_8`OU(>&((qJb"+E>][l"g"0[K)Sbq>5#Vs3NQATJk]S[c=$E L)3,m"NuXq[dk$2TFntHU7Ea-r@=V=6l3ZZ#!nCa^kJQ^6#i>\EV`=KH;=Q-Z5$d&*FX1,g 3-_phAIJY+//*DVKFKoj\p;p+?e=+c'k+fl_'Bp"@LaQe)F6B_[rho6Zl6bI`h :q`]re<*Z)[c/#Jmhe5r('?J]OD#^L?o93m$1H[7-FcX[]T7JH`1Pj0#uVHp-_AFF12snU0 t_8=KG5\(e,Gj5:]kJJ]% DDAD,*(#a$F+^c;KE7MQpja0Y^]2!qY\/'W=[?V(6fLNB>A[VM[k<=,)@E';gMDh1%++a>1 p*^nHefNeO*'r^(_6+gUMseUd=;N,/(H%bt]B?mM!Up$l>3XMNIgs0)pn"Jg%\XFN[GaU1$] r"2U&5Rd=Vr%3)o;Fs_V[Ak+$IL@61_iV&0W?,R5ad96hM(QPIsW/5@*rs@&BXQ*hhEFIr% &0dN66ja#n:\?[;DA?6,a-*oCo2^Q!NVKGqLgahO8>J":.ZbSnCCpGl/+J[N_:Z-+5qRK;= c@>RB^cl[FY)gnR\J'BeQ:!K<\c%"EkX#M$up'QA8&)`#ahsJ_"jj,*7(-p-jhu"T(;Bl5H "G+Bt&9q.m)$u&7iR&Kn&U]uc0%+5(`+h(IO%*2AnOi$[,[I/K9B:?6HRkE*-.<`bc`cJs&\hJ`.9*VTqm_rG`^*)9QWQc\B 2q;!*1:RKdK-6:COQ5dBjms"[N*uC![jn!cr*hQN;g#mfK?gAK.^ZG+`rI5o=fA$,srXi]: Y!`pMX9SgBO>IUR6#\i_6'A*AqFDFlOaRSRjFf)n_[tk1'? !`(9T_]<^G*kF'[&0CjA>2,&EKMZ6P=H[-9i-^&HYlHF0tI!cSOYV5>P5]q`rL"'am?)oGn T4;,ft#5nF2+>!A+&od%u(5njLqBh4hQA51c<#Sq`Tr70:VPgJ0>/mVElMB)DX,Z4DUdLIQGkP7,A!'l!D*) (S[Vbnbj0nB&L?Z6d]>j@X"49gToj(?pf6+c^=kRrrT4?SurO6k$O6&rf5a02qpdU[c(Q%,G ^.47GGi!(sk4sIMO@C+?q&X/[7#@F$&r(ZG9:>GrU%%tjcc,JQT/Y6kI=FK(6^"<rlpgFS,)#YPopf`[I\1EBug4rMq*Q-N\&)n9eLlhlc`&N _h@RNkFnMV[]ka<+DPYm=#67YH4Y'+6<>DnVe01GZP(h47iN00@rNkrLa#9_M1ENV4>aP@h GKQE.Cei?66koJg6H&n*I5=`6`+(PM,OAZiZaE[,6`rN`1dPUTWiV5UW8B_g$TO`q*/LDaU R?NeO:J%NO-Y3^YPZ!fF8pNoVAMgEP'!>;.fjQBWPcp9;TRMram3AAKr#XnBH&a&A,fOT,R $,Hub;kP;Ajjf^_XL8/T_&u]K[Q;F:254uU$ sFg@0-qY+G'h3c?df.m6-2+YRJE#=U%`Z.Y<2d'YtWAcuLF!#b;<:5gWBRd,2qm0r/c6"kCJ<44I5k^F0M34_ZOFe*3LkuZdlWn=DKsS2NOV8rBB5VS*]1 .Up7>J-+O_tdu\7lNu,]o36d^@9/=#DM`oU7Cc=BcG*/MZ('c#sa#JIo[Y32[JQSQ'Id;4! Pa6 @_.k5rZI?[X9ku>GlFb`W)T.qT%q3+8LN*MC`'\ci$oS1&fII28/1b-;+kk,mAi%G/eX#6C BoXpV3QINU+(MC&`PjnoBfQp'A7gsdnlA?(R3A+/EPrg8:t0:*D_#C(Yh(YZ=:ITeBEhm;1 '6u^76+]BXJ:Z-s6a?O= Ppu_\F=K@#A?M7(X0Gm$(;Np28#=LoD18Uh!eg:h26_co`.SHmAAln(kUk_@p>d?O79V9IY IDV;<$)G]*jA7!LO+U,X@GRX*sVO\;V&)p;2f0i7ehk8-I.[!DMd4U0Qc0CYe26W)i!L'OB QQ(QZShdPh6Q`p*p7!]<9Sm]UKp)Q%F;HH4s>XiDB%TX@^I!Z+hIQ,FF+"uds!MV!WWF/PW94G/*cU0AgV2Jg.YSlJDPZnS^#X_76-2j $3D"Y!V8'K',B=""nOmKMXHWbQ\_(0Ea'sKM(]sHLS+3$SQ#uYA=W_g^Gh[pQX&uPitaD9) GgF;_Q?/5r`*P\5%aa!&+CWKh,;N3*ZW6#;BC&6+e3lA0)L/G(n:DL1")8ZO7P\$C8RA6;% m,>7s85,slDr(GKMRBOcdY;[))jKh,AO-rpLJ?Nk[NKudC#\7PsR+0k,S_`TeD9K#7+2a^h /_e_,_3+E1\-SepgZ>;Wjgc\$hRtJ4OL;PRJ].Lr@6*f]f!ru/P3%b@/@=nPW"q*>q>;sKj 915jT7%q/D\5rj]_1j1"712?!)a6\9;+3$876/_J5Z`[J7l4IPZtri5QsV\&8Hs-+1pBQ*W ,0H-9=2l:[/3UNi'mod;'*R@"Ii=I5Xkmmn26GD210)FN+kb_C**^L"L)G>n43``7>/k'2= "O<*-!k%?a`U>7mqJX>]n(\G"6ibL3R_^1))q=HUk\mLA6"KHZM+sIlAX'8*kcHr..Bg+bc ;%#2"8-fR:fYLIcfK8;rBK@!`-?EO[NN8BZS*gl+ebNC`Dt,NsO\\9H#_/u@KO\MKI1F-Xj WQH3TR"sgnm*]Vb13lb%bXF YWW&LA-"*C! N9CZfH7`D^H9r\43YMF&5Ig"?\FLZ]KF.q,fRDa`sKOjKQnLAJ4BZ>ah3M%be)$1bKIQJcV 3P=KjZlu86%gSdgUbP#)H^noS*lC)Ma\q##s'bMqUn,g.f65c-+^oOD"h;dYol'8ZUc"R+2 DfC4tp9^1?>#9]eNTk>#7B#,l/;I,TiOEs=1Z:<`)hd!RC^nNS;fXR#HhA+[N=#et0N^QeC UN:p%?qQ8fU^V'=RJK"a?im57:5RA]$49A=Fr]hgd12Kh,U+,WJ]'3E!LLd`j:?eL XVR1PIV/6f^AY*ALJD5;H>+"c.%a1d]Z-68IRS!t\=a6q2nB/VNdY;oD*mPYB$.9iL^M;s[ 22J6Ra:t7#%7r;[8%:VhM@n13ULSDjbh.B]& 'aL[cLX^rI*GSWGCIfaf`[KRFZ9):L<*EI) Ae0JC^'a1f?C!ke>(XUP_[+451H//G^+u]PlM'i!\K" ,Lsn0NfC5lo34b2naXgSN'jYus2p=\Q*D)l^ELX+iT8!m@_JCTk>Y\]]rCft)ij4/%@Q.>A sCJn2X?'qs>4^ru4C96a&0`5^MI``dc1M3)'IE#AjN7fj+Bg<@dpfHs;IcckLT>55:UpfN1 `h+b]4#CtQak^/)`ncuC<#/.@tSD.8EZs15U$`J9(86jDLm#L?LLZi`5!*d_cecqdZ"C1*7 KuRA'a%h''NhB\\88SR8:Y[YS#FKc@rH_`9cQRO\(]cadk;>hQ`h>L ^H%u*nqKd^>`E)["NA-H(8WeD^PPp]Ia#@MET;LKmGcrgOj1=GhJi6;ZW< 82)8)o'4EL+KMYkX#W;iOC"$WP`'$*/SN>654Q4!n6rW)E'gL[=5iM,R1IsleW*e&&7H-I# @R_SO:*ps-5r9fR<5'eMU!luk:.ucQs=]M=U@m2bMSi+NEp Vu!+[C'@AjDm,s?rfF"efHq`hE>B6"U8XZL/lR\*R=oQE5/Ka&)fJk0@)Lb&a$>m!(B"t3FPNMBZ'UZ]@<9FtS7\/ngrW9=/0$,Br%E2*b/ X\?`fBK`OmmY4pScA*fPKVc?9W6C$9@YL1u#EX->n9g!fEX-8b"_NVG`enIWPA)#iN*'2;i -P]rng_.p+kTah(h\RO4ku'f>_\eSDOoR=B8-sZ>f+#Un8/>&L'OSSl;"/\Y^HcDdcu/)LN #T`fOb6Qem4QmlHZJG`:qTDY?eQk"5Vd=m]oX)+l3+UCJ=cb)(E?p"i,6`"Lpj`;=1Oj#Mu $8CX0S.fgO]$>(fFIL)="M5\SW33X#F%;oTbohX+7g:uU7RiV)e[%emb@eF"qh#],10>R&POL%oM=:h'_!=pAYYL#?YM!)j':Cu ].6@o!BjD[LHQ=bMT>7c\Ijc8kC^3odq=A*,oD*t`KC@Y\'3#?I[@>^QaGi8fA)A9So%?Q% pL>9Uj%]f-^Hh]?e&abSf%LR(eX*`2D[:NAB<"W2RkMfj%/n;$Y/8etdqmj`@M.lgFS#GYr `PBmJLH3Yj6#>f&eO"08s1@mP"jq_KK?=NMKn!9?5?db6@Wjl_%3U(SIh `JfI>6M7"V>7!kVd/#Sp%kaG0Z\>88/9)6Y[7DLELO>`8C-0F&(5=l?1O!>jr9NG6KC+L:B n]!*t6P8d4@Zh1pDnf6sd'g0MFsCB-h>(:/6;hJ5TglW1H09`WNW7?[AS0$$:1m^k+el>," 0lfPj63*HGM'%!oQ8nD0FQK\#+#_Ves2IH>WsT+E237X)9;dDBH!,^(#c=@UU>>q[Vcc( ?QLu4p?IRDOa%2Xr;2tmV^@\H[ZuDs13+j]'h)Y"/3+*VYBuUpNuo7Hk%E$Ld6Z#q8J]=Dn [_+FBsX@s)82D"\<*Wn5tEID[##%L%&g^&']Lbc2@%Un8AR$QdTiVddX`pr@Dd@<,S=jqB* .,rJb-'#82"egO69\A(YCK(.!./h_pRTAMQ%3aEH2fK8*K.IlHruTCO=rTEkSnN5S#B(l0Rs+qG!76K-:iKJk$t=;dNb6X3qR(l_$qOnd^d4X,tYjO&]cbgOU8( `99iUBsag?n"X1=hNI.4.T/nLp&85(Bucqm*SD$d]&K-;\`,+@Ah3>>.n+E>HLtB2> ZEdXMR^Df?"Vnoc>fp>:k$QKtcYd\m0-^4145@CLEpWN7;h^U5gR.n@2.M-P;9Sj)J2f@o5 !bCatFT>eXDsS'>Se3W/#l4eZbocVDIMY>M=LlLileL9kHpg$EmOICA10gY+gGXk3T.`T-N7I,5Z$Q%[n-W7oK!V*^[Cq0cu7 J#D>oq>PjCcdVso^b>Th!l0m[!c/c#]@]usY^>+16-j9!FdasG0atrrgc5k^d/60@`).LG' #`0[;%oPAdJR+8VgMbe7Ic=N)91'dgesPP\M.D-A>slY8-P[c8f*-E+C@\Q<0JWMdVPU(8l C&7.*@^cXXqW#ORtf'j2h!q9G8,X1!J)td5"Ep4P)9LUZ"%#%tqUW3_jatnN5&q[.uhIjbX =&R&!i^6-utb%7JSX>n9EP<-9'KdSqB37>k^((-3*S[!H$X)$Hj c+.Xpf%G"8'8<])<#+":cZFQ3W=;sBA*iPU$12GJ5hm?&UJ,]RVnaqC)W\?Wp2XZWN9jgcFL(Cg=F*CloP -bZL"&Ea0b3fBgMYqm'S[dV7@(t0mC[?6cM>0BgXcJ?n2pXR_XO'[#K6,e !)I/=Na`d<(pD:"8gK=bJJn7L8'U(L<)7fliq$D;=iuhf7Ls ?13@%pg*WNi:t#.H:=-s!A%LnIW(kAH6/]TlM<]ZWU+rfcaiH?hUfU3r'(/"o),+Ea7T;e= .DgIjq.5bQfHIe?[eWVlhg]hW<-':,#hd*d82P%kcl"8G[6:`_CpY>$\>N;#=01M"Q4YB*$ UbT%@*m!`693Rcu'C\fL#o&'IAEoSe8i,9a[R^.tu?Y(dc%=,Xr>o&d&,$M.)&^`8!G0Yjr l((kE7Wr'_GhBN,BPL,R$K98To/-UelG']OL?MG[P,7t8,c-aHOENmoa>F,@X-Kur=%aE>/EM8eQ;ZF?96kY4A `U@fddCJcfmtj>'ZHFq*a=Yu]ImbXc'/>*I?1)M1BgnE)'YYf9o6&3B&q^9dqWhrfu#c3'] kjKSoN&DbrVajl^cM5GYZBB42j2D).KOnO.l(k8+?Huj0WcciN+ZpV$3GI)L9\U'gcSF#bf a#E=QE%-AKln$M7AWd:tC*kg^]K1k(H_$9^po,pT58MNh"B;b?4Mf+2:\A-``o6cbNMVNfk ldsuC+#dG\R`0-c+H@o#Y'h'>L-s6a_N[qun`"bR#@1$t4:BDZU'd4u8$Qu`17F5X4#Sa6Q 6G-E9-"F$qMR3d83Y;PjOTpO']@Rt[>g(rD/n5G_K;"q_Jl.T4`\P;s$O'p3Od%\G*77lP6 XoCJQlJH>73-_#G-%+e3[;.CM]40Ym%p8YepbnJ$U&0?-)3=F!=QpKqEG5+i#@9XBag+1=7 )^a[`BBAgKSZ8mFAnZ-j4+>i7`M]&e_^q7cXn2\2FL5pE%_^B3cIQFRH!U4QFe9O2PdlY3" D,_miVR_6PCW#e`cQSKO^bMNQ?8=A*kLpg2_:HgdD/9Bi92?^pS7dqWVll,>f`lihoY,(*2 o#tX!>+bJ48%)H%'6OL(4)3k+8;h?Pg#Sfn0PsW7'b4?.F$q5tl-6Q@t#XaKcJ?dZtcc+'h (bGoe\1s`6`iFN*M"*;S"fSC8l`G;?&R6p,8?a)niIWa1$^1']:!#C[-871./qn8i('3BM0 `8;rR4BLm)1O;O*4j*,4"4`W[?n337P@SdWB%=hU;-:Gl:SH#4'*dc91#=Rc](0chCehm339fteaD[ `'V6YM6TlCD:]oq&;:W*o6;_cf!&_u1fnhFe^jV1=REf*[neJ"74DklV1%3cGFn 3Y]>o8pJa=nH+T)kl0S0Ndlbl_o'hu>H4K-d@aE[_2;*:[?).LrM%+0)8#&q?f__>GQ$[l+ aSRnoES((Jba.?h7Np_4dW4L\Odn+XVka1@rn`*bch`-(lT\lE@Y`]uK`@tA6 )/tYO4j-R^ZYRqaPsf4qRa[`]AZL&TshUlbe5\G85L/:7#\i1klO[+!fQ4CVsI("oY7Uf", lrhlip7e$NpV1_!E2[n4pgH;Zt&X(h"0eTfs&rhSR(l&g7kuCc58S;T-dL#Ad$XX=e06PL,&'B]K/!F-Qk-k/Zle1F.3%91j)@b!2De DS7ZD-YZ^En8W]f+E-AZ$:M$mM3Q[H(g&I0ojp!P1`]p)0(oZOdHf5H5LVc$\=T\6#%;]J. obN(L\p4Tl:ZRIMZEn)'PFbJYjCRbhR3i*DtPH#V^m*ingg#*`;5EOma?2nq3V;&j_90;>; f<3#HN8+H?GXc3WDB'&iBsi\D5lZ5Fh,^`=TZ*=r/odOtR9^`Gf"j_e'Cc;Pu$4!ZRG,Z76 sU$Nk0pEL;P-'DIYdU%pLnE\A]kjiKPdVgIqE@0+T-]*-k8cL+I/0Aok3nJQn':e]d`F'2b+f!A%m['2JH?*1' (M.J/lLd#cRSL(,;0](00n)+_/Kl-W#238)^2'lYN?c)VA!C:)1`S&!;IF?H4=Y3X=mKDmo ;.W0!,/'&tj@?MX*(eA/HI0#/QlC^l\;oJMgA)21l20DiXUV@l=EO)^/;n!S/('<;S>OqNH 7bPCGN4K/_853!6N.iK>!+Td<8m[:/JAiK1KdeN-L\3cEh8Z`cERZ9CRQ)5.uJbEG$VkT'c U-o9%/c=@u)o)MSm)PPseck*jjd/gT:5#^OUE%aEe/O*&Z5ATWgYVs7[r_-`=%q.6sE(*&( 6;Q\F"`t[e'HI?G(fI1_;^FU?i=ZX>8.q#*#V^Tmd"+RRK#Iak(Z?JP6)=m0;[HE(`Xn[JE 2(A%@gW61'L?@>1iCB'gC)BM8!(VYYffQ@oGtbi($r"40[aD]`=<)F%T)C"d.%WCp_:Pi&J V8WoWJi`X\1LTc/EJhnLYD2_b:cb',8P^<6Iu?_%UfM'Tkfu[,"IkgJ1$5(*U*pJOgYq8JV nN:R(TLa%$omE>TDq(\J.PeIPK3F:nUl(bqX#eK5[:,>lu;;?sK@6$O5T65Ul!'g\!"+_DV NJeu8+i\a1B%CmJ+d2gWeh%a!ka;Z04ocFe5<`Np9Q#>GQmb]F1haheG;@?RiHQa"F=HXb. dN_l%O]^hGiaIm1oq,CniZ>(o,go1deZ2me8R#2u,N6K\6/u-+_d$3^>_u,q!RM^IHRDhF> ufW,Fl-JbKH0T!.Q,A5_:fg-#qNFX//@t2ec+s0n/]?b6Xfm7JbC/$dMlWK)I[Jj(&MGU+( A7JSJ&mn<\H$_1G'A#m_Ph4J=[Uo!XEc2nTIJVQ:`;5mk;!V5=Q?>;^>OCR2C `ZX3G@ASa/7%ACEM+Tj]idl;O&34@RYe,sk.!HqEI5dV%f=)A)))+""@68s6X"Ul,s(;bbf;h4u]_&Yn-6[;WsH'C?*@1 3lZI0d2W7?gdYQ`g^;>t.e#H\K$ETg)#nZ$]BTaGc)"'RbBDK7,S*al0rLTe/h:>n*$`8[. LjnFI00qA57p96^8+=8tp\"+Sr+B5n_"[*O:;c%/jCJTqiZQl[912B:6(:08rseDh5$'GeO #&)gh5T]?ggOpeO%(77`j\4obA"&RM]KpYqqeIZuA$5RK(;RgL?Qu>lIEnJnp(mQsWPs&(L HlBDYMP5nHTn46BfGgOX+//BIiRAo+?WEJkMG_o)2/u[IB8]luMim?;+X8)ZG_YV_=?+HZ' o.U1Q&Se-NL81SW14k/iZ-Q'NgD:5_8I;cZWigkO')9`Gl3``Q5ph*Nk#OZfah>r'Ga^)?9 &seR3,`Q+IM-C*.a$1#s]QjfGkYS@Q#[!\Nc:/hAZKE4JDNkiT;1i`#8rZ'tH>iffbVr5jc !3@obk4SW(;SWB+bC5uYSlL>E]L1@)6Z. Y'/=PI1#\'++K9&g24Q\H/&?lP@"]>i+>#B8SVlD[UAci)[@UF2SneLG(<)m]a>>'[(;V;7 F747_F*3pqFa%29G@Nm+dLj:j5h$Hk'GCVYH$ B+MWJhVsY[.oLgf*/A<&^"d\!MBoZ;l+BH9l1iQa(kJ_lOPU`cnnne7#H_`"qub$X23kP]q P%j*b+o8!J`CiL1MrNluY48b_`cOSsZr!J#M%YZhKcRh)`f]Gn@"Z'Z]>\/hjo++^+P(g&/ <)_ZfT0nSB&&OC.O!<K'KGWU#)d(mRfSt_)Q&1]j4MdC(_9n.J>J"":*UVC8)o%;X_ 2GqBL&ho"olf5+D]f'&+BKe/@4RQ97g+*)DkldN'Kq'c% E$@GDd[IDp67`>hUk4Di+F^Qt:+a-gebfl3e'U_tXnR!FV2]Si0QQ'jb#,=.n;5iru9NY*G A)PKHm=g=cMZc`mC)M)i<_3u(rc5@ct$Xnu.5bJsF5RA=MS5th09%9u#h.e.tY5i]%b57d# o5!%F2*(,t>lSVJg)V>]'RC:_h%-0l'@>PMd0hE_Ti`B;d,jLc+2Q5XWGWY`Q4^\kURF!fh )j*gp)7A(&A53rf,p%SClZ@/_u3d=U#mDibSu,O(;Z"LThVD1D:^pp!Le#+RWWb$JkK9qW& fF\_&[^1NS.BN:3r+Jg7,'iT#"iY;Sb+e+W:pn"fg:aWr9M1qRLorXk[+!giorK>1%]1cs! Mm(EmB)iENFTi`sIWI@B9S]'.9[ckc^l)kgjZ@?)(r6kr!U&E,kfi>o0B%BuE;iLUkEgBnY rIM_l-Z/.":4tYcc0+rU\ZJ.1qgGe0u&[T)6Zo^db]2,gu;mbK.d@4X"*ac>5`"YLc[iT=n rbo6iAe'T,&qP,5hLE%!JCrV3;`-MDpjs<,LUio8iOba%U"1/koX0?7*b"IY+b1KIa1FFDl ^4fdgW@*W_n9&WYCa/*rd-I%`fQ9F2n,noUeYGhaR 2[9D'H(a*`BW\T@Gd7dpokn;e%"q2+hCN$;^]R3-bGTqE3pn/B-/&dsQGr3uJ$P!-Ih&)j5 t@,^q=U&!Z?1;T=li5?KV8.,:C$%1G'cW'RgJG&A?pku]QdEc`\ceS\q4T`%Ln^2jL dD,"pTC;cFg)e)C)Msn)+oq=Z\Jg>b,T7$qBe^-WV:hR`&;S25OZ9^?0boYdj&+IiIQ&F28 >HkY1mUuaN&B<<pA<[sqg#s8E-Rl&@OTB_7%Y"3AJ,/?ZflMB4[->VZ.//`qgG(!J$Of/0+mLsJk^"5oQn27 ^N[0Gm.l#-IikSj,->N';_*phr;OJ#'E\D%&2XUo^SPX:=-eP+>mE\-Hm8tbE-Z>#Q3TEh= <6MQ3tK6V"@j%lYmaD@71h@T(.E3Tem&tI,d7_F0t $k::&154\rEFs#n^bo`[TWF>XFo:m=rj7F1g=I)sJA_AtL`_i** O]YmmG-.`Z>;jI0CYQ;J]l%'K'uP&s(H'6Sgp]_R72CUY/6s*:L#mR9GI?aa?C042IG[!Fs *nE8mK\8MQ\dJ'Qt6SU@227'Jm"N(!Hr4Ejr(Xd@i2p9Nam>-23;=Y%R5sjVWiVJSOU`lI@ gkW]QG8!nYgEhH*1kNB0!tUS*.?5I@b*50lUsDO4c=akrL_hUhQ8uS#C&tQCY$j3j,B]CHB JEX6SbC/nPX4JUt(BRi)u8Qpc3Y[;DC>gUInc6%b><\K:4%D`bE#]Pi/jqnR-?(B;5?38'O 8(ru@dX7eocCb'BgS\Q_3O=5,YUMHTnXBm!G>U]C:1I( VTBe5*=?4QMs\3p*g72oR!,U=]BJ\,sU_mrnkcjrI;T*s*p+2s$.D-!8o[8JIiS"^j$Rr?t 9e!E(1'u-m8`OZk\3);@Pp:2[3[N++qpos,LN4-AKln$LjW$_MD2"@:V$FE5i\]-t*PCZo* UMdN(ZJYTAChbRbp#@L+)r&E56/Ls[Op7(A9k@T6*ZOZk3_(o\0<=Ki4O0Nn[j[21%B?&TA E0h(/,7mZSJVGPh4I)*#>"hMu2()qYT9GFc?jTYO01:%=Peb(BLu<)*`-=fk+ugoB) .tLsUplZ3TWD:N;&p-id4Ihq*+!6qOeMqG7QF,0o? 89I=oU`%2[5JL6/$:6,8\IW[C5,9bsIf?B%gN3CX;$b85`2Q\m3]*M_.2-:;`g$:4#A7ml[ @'ZQP>2^CNkYj!+EN*R2KGZY=cA/+.NTbe&j>cJr\/u@@B(kWW'.WnCa'fN"XdiN*pj]AJ4 ABpU:*ZkO,Y,hi1YaX$AC^lNG3+i<#,_Md ^o]"iP8>6hj+XJIGdr0*b^J,LGhcq+WE:,U#9Z!0($e3rme:N[k(I%(4)l% O.S^k=g?L;$6\=c7b_&TJC<8K.HW\5sa]ZQm:$ZX*-7>TP*MTK/)Ms5WXYbr?>I7^N`pp70 pc+k.f@4_M/]%9sf>rX26@&srln9,7EQagBV>U[ClWs6HY?O\ZN0J5g+SmoR0@gjMg1K^+] E1!K>@^bjLR6rGG%(46:_7VfHr\nLMje-+rE&_#?7;GVA+QPGkOYR\@aVc0HA7hPYKTO,gX cu)-.97dbK5\pBZ+2ee=c/_%?d%,X0'5:4R2d@3*WqRoB"ZfdF)aei,G9(hB6=k; qe=nXhVgIT73JYR5QPJNo(1YTq3Ae84f &RKDF,Q/<5e/`OjR`\AEkYPsGu$*TSAU\7*bij]E:BY*pjNar@ep8:PT.M&8rU$%,3[i(kk uigoWF>)qJd_tit+BAcDeBHf\[WW[!n(`o;I!0?gGVZH]Ff43)Q9nI8]MShn<#2p+NGB=K?lQ_,[MI=6gZXXI^cDenWrCl[Oob*^7&kYne+n0UWUip:]) X2[Pl^ir1BDJm@$HVpE&>LO/MZ"Qe2)+A*\P/C,1P"gUfCgn:!U@q0rq$S".mh/h_TXOIdD1K%Dh]Z hL[]c)">[kO15>RKLP%iJr&1nR2oB/c6Zb<*U">((I>?T6_pgiej?CKOaToV-#=D4mb>(G^ 6Gu8Y6rZOl=m_!cJOB>k#Kh`XX@fn=9/X(M`5GBg]M?Dp:IO8>`=`>3dpb3K?punO`BkQ!a ?9U/B7ot(L*/djS6E@c>IL>37ER!dZY^p;DBf-bK4&B)n7r598I!g_.3kl_@s5k5WlBC0,O 9YFUO,J:HH*ff,YCM$BOc`5.AWt93%T'FpgXI--3gDI"#+Ko#Vu[H8-4F%8!AnPRu>=nM^C 2i3:qX0%":24Ad6=VK6VNmn5Qr_K=S(:3OFK2A;&$GKueXraFI9GE+4NgIYY^c.>WG.i-Yb XC5!p"#-_V@,GrR=VFa.Qa\7o?:c&BTAcuXX8X*hnOC:P9S&rIHLTl,\=E'$D?b8_!]3DWH -u$;G\\!d28kPleZbFS'^.O$jb)=$7e%r[*Wf5*'N=3ZT*3QqA`]TI*9,#Ci*3cJ79n`R>] ^*j9A'L%\6A86AKP4HlA(!M-dn@'\bJm/M^BJOWW6>[$`!OP1]\AG="c_V(HXU\2#%@H'oLOaBdbnADYb /:`;_lPjqAJNU73RNNr_f0Q^<>3cf)puVESiCtM5\EK%+2h_5`(_CQ"X17j7g2M;dF1L=BP N7F:st"n;Nt&,SLDp_/(1gVd]6VA/60YP0?$pF+inF$fI7"q5_8Q47Fa9E")qk+3&7u4/-[M!Jne,:=A]-uC]ud VLKE@>@%&3EHpB?=Fma_b]_BP`F"4iV>(;s8K3Li60sDo4ZA8aN(l' =LsoEeY]NKg_b07>)YgbLMSFgXF@4^f^ckbQp^ld2rNS`'(MmbW=%'K$smVaK8 D"X`V_0]ZsZec.U%\g!uRT!p'UHeCk&T=qoLj-(rs@-9gX19tdCJc)/b)VqP^\9r-U[CuES *X3Lk,Q$>ATbiM(fY?M$2K8Ec`kYJuWZd+iC5X82l`:$oPmbh.%pE(#AaYgB-o1 8%,mZmdcd_HfS@h+bcB@DW4B0F-[!j-5";#<`OQKeUrp<+Bnu.?WGr"iJ&6#jr33E)b?'6 L%n[RaE31N2MZ6l"t_$S#\\nGU'"\9@T@,O?"qlR'*FO&i&#&#k\Pr4I0\,E?EPlP>T/BBE !'-:j-=q#SU";MI7hJ+N6QfDom^K@f2rc?==&U\*^ \1d5_RN'":.q[V2)_6M--Rb=M9`*V2aQDNfU#tfbKUm$HS<3)qe-5"di5BBN>[Rb(YpQK`G 9Z[))th:g)p_g!3`'hHAsIb6=8DL;fp!je:f'UZMbfKeQheg?.+LA(l*:>*`a^;t'qR?s9\ 6>.!3PU@n^$=GFet:-Gf+A[(=ZDj@gdK`GQ9:3+XR@=ol7>E-,HSos4=\V&O9L#hfl(eb+[ @S]ts:NaHK`R`jGJ".Osgdl18Y^D5,6jKB4#Lj^/c,mfg*l7g#BU-g*S^$An,QnZML+FYj0 OR4p.%><.1?O(#-.V6[k*EpKC'S-h?2g8Jp6sgoRpGj7#2.47G+RslT;e?@#J ?,>%HcMrUZsb5hM.k^W-=!YTH@u)LZ!:ZBNJOEn`n,plIGE>hQ6#)YFn>ThbE^joe<*)+/0 5>lW*cH?2C:tqhAWi#)HZ>k\God8n+(fldi_tjojUk^Yj:N`jfdfBKh2R>_P0QLN$LPBQSs ,:PU&p"CQ,$=?PO"3/4A*!o=Sj:j#83cJbe5XF_u.E6=H#5DCB>V^&KkDGQY@g4Yt-8T.,lgD!^" qYKYAiJamG2nTDD\[TYWi:r#4Cct7N1@"[me59;5ia7XDjL0Xi+7Uu4bX_Y"c,\QGZeQrm, W[d"b:1FSkJ.I9Q3K(O-WLNmS7_@!sKmlAKFb23m2)8<_Og&"jFd<-H631>&aaNnIAaUcs8 8@T4S$:jnBMP%i.l2*!X]#k"clWB,YcV)QpkN"o@`NV]OufEBgUAk0:'kmipp",A-IMK/c_ _-?EBm-^Gb<"nm0'B.EJM/!hYF(8+9(fn+n8?A9:pL*Fot=CDBCBa+Kbkrt9p6,:gVC54c_ BLmEd5]makB;s_(^2m?"dhpf#Zh-OCBWiUL6+n,DU3P#cDDZ0iE(T\G\r.R3pgh ;GZTRnB%QfrKr3dR#+C/a@l?`"G'/%E"s?+sro&+jO7!9hL5*?akE>/XT/?ROoWW]Jbn5_! U@,0@DU4_rUUFYIFmf!of6!l>M\"__1oYZM(E983.IbG5bl7l>Ba7eC%H6%:k8OF6Y q5MU\.go!8>V`jYG5'.%mrfeQ]G)b;aZ*KiKL)37,&+9E%n+9.jLN>e-=7Vq+bQY4hL?D?S k>2+rp]"W9SaZ0"Vu#ZYG)$W;FasA_GQ.8;J2J$Y8/)[A"b]2#:hN^LCB')X@So+\<\5,H7 Uo<*jE<[.NB\L<=$nE5k[^[S&ueR->qMF:-;sZ0`b@B$:1giC`:A%6TMOcMl6QXm6_dOn'Y 6FcPtn2Tl;\`ARWC`T-L!*55K5PL&AB*Qt:#Pua#`UeHbIJQ8G)-?oAO %i:SSkOJCrhQKGQh;E#p921+;\*:7%;!^1Q_f6)J&O[3N9bPDW,ZP9p#$H2#+,AiA)9.JhjE6o)1j"DkBO#e8S4 8W)B:&dPP[07]4Hh$^;J_aKa`f @7*m#[C3R3him5rW-bk-^`-dh'sSL-Y"D3TdCZr,3"71Vf6P[,:u;A5)9A3FCVeXs%]sVW[QHcpAOJ?NI7>c:0bApk>:!n+=pMJH)?'g!$Gi"d@g 1D*fd;32iY]-]6q$^,:gYR*IdQj4Oo.Ol Q6i7?\?1BqRqZ-,s)SA\!8$R-'fkD40P^Y&U#q=mg@'P[sl;=d5c.M5+aq5*_r.RRWjEl2# :kWTmZiUSJ\pl(W?:7q#(u(UrpEZ##d+bH^Eg:=6K9qejrnD4?"9\F,i@mCDZ^Y493o>OM& bR3oqc_!^GX7,SB!e;oDDHF?_!opCiORQ7o.Y- SR5[QFrbKt>F\))A8Mh\;49KZk!+.KGJ4$1i:rlKNT'[309PAl?>k@)$fqDB/X,%`X6P#fc `um6rpR8`HNPE^?]IQ`Fn5J12pq`M'CM,1o3inR s+9+L2Sh)6o.ZDD9)_^Od"h#f/JP"^o7_K2>k`_3d4fi:J1FY`98]84+oi]%6OuKH2$ktd.YLX0*"E04Ka8nW6\NjU+p+;O$=dUZM6tr+dnLrZFG>rV3_Z" P@BMPrXPQk(G>%1.gD/]^G)MJbFD8S:V^Fg%;peu7"d#Q#Jm^hQnK]*/fT?U&?q:I+VB`s/ mlcq2WDumNHk2A?X%2lcTDH'G7jtk\#b;^)R`S^u2/0/"Y-_6PeQZgCDm!*Mbpb@XgT]!?n$4kD:KB2<0lW?.WnXm("0e*2\+bN>D7'^qS?RQC7Y;P]kY6Eap=+9\CJFkLL@&Ro$86H=T)DYEI-b`9;q6Ff #IIFT>^:24K`0Pku0DdrK(_6XT>QW0'E1.ReZr+5SWIpYJ&&MF=$=O.Ei^KN_)boK*2p=>? YkB6Y(lo3e>XaLS(o8%Y>]mUt>j*npS]3Y().QocNU`T#`n9KL\jp=mh0qV4/tL`+T^M6>A ')hq-RLtBS!*>``=/Js@_KgsQ1D@dHk1Mm5"G&?ZNad\:[^&N*6S/Nli2JYrW0f:%P\-W$P kbG3^CpS/4>$0(./Ena4UQeF9[6A:eh_AZ1'lX,``oIXE_YXLCeQNObb_-,K:`U(UUh_di* .!C#(SCo]06g@SC9$SP:$_30b2h%m]=F?)r+&XO^Ri5n5X+3&FC@f37TKNWJ3'-$6GY)[Bh g4cQ\S7`F%B+(\'oA3EhH;@8u]sk0=hco8mDiO_0acuLkg^\f&=nYsPOF.@E'L;hi)8kZf&>?a4M%!5c% `V%o#h2[!dB5W%.+K<4en^FHIS4;K7jg*7VO19H=j))(dM633E=4KM:AMjmk;;e%*3jB37j +94UPMJHNee_](m>I4GXr%tZm5_[g^9fI7tfTu<@Yac$&?IpebZu2lKS?g6EiE.d8=.aVeG HtcaEJ&-s-<#UIup<1m15>>t]JA<'q@bt>(?#Hdp^:9LOg3Z&$EP8lr\MlG1 Hd@)F_pEa62eME(>H`2;h;Q#=0BIT9a7FnRk"nC3;@C<[/-[fV(ILH0M4o#M0?*hd5E>\k: W<-46Rom=+8,Wg%K!nM2%mcGXC447rVsA&_Q?`E\M6hq_0j35"N9d8`/k?,E")h%&B!Z2)X MF`E$58O,f`_/!\c&)n1=\MH??6@"0@7[m#&mIG02A0"K\3un4>cNe+0bpWRB8-jae&C)io#d!1pbjPilOF_t%)W>qlOJ(/YU=O!%)Bm0>U#7! .hXcP2).C)s%4'?j`=+=He'15gnBDCo5n-Z<%;d_VBZej2eIH!t'7kNJ6*go[oa5[6$;g[3 D#tQr#Tmak$]tl0lUW)Up`F@Afo[9-E?Pq!,8'Gl&ueVG!TG.4&JK.E'gVRj=34]OjN2c/KI^:'Q.%7n_i NVj;Qu\&#%Jh!DMZro]K*HkHXk'iBe-ZO!&=u+Frr$+X@PK\.SegWJ[4G%^.'+Yj8I-ld!B 5_7UN`r9eI],ECk1Z9]`+73g5P,U(kXiE.0Fe/W>*KqZC!EaTf:6lI5%%aQ(@miNo1*@GlH 90oj%DFY^fKcQuAfAX=WP)tfA9HKnQ*C5u0J[Q9=9(`gp.^)Vt@=B+<;YCW*/!"#GV,6nA` :jncp9Mj8CS(:hHS$Oupb.Bsc\VAeik%Xrq@`/jo'lI/LB,*Tk#*MneGT("]LBa1Q_ghP0)YAGG)M\iI_>5V$8` S(dQ4XODP4Y[0Mo(ImE:K_!o%1r"fBM&4JDf!J^sPeHo1+$$4iao@V>S:`9@S&$Z.!n>?W0 RN:ARmo#hJ9d*4/L2oPmAXFYg)e)G)XXaLiQ<#0Kb]0U)Bh"-^t0sAPp]Ru-^C&j!LO](j%f7>>,+h3Ts>BknfK8c8 QEDFiV"@EmMu>Z):G3.;Qj@]WEiE'o`9L[;R\0ajX^#fp/9'bEm7rKn5dub/Tq"D7@a,r;( bc*@'>\FZL]^>ojN"X)$(K[iNa$qfH+IO(P3hK@C.'\*YcGD*&AUFo+tpN)e:9E1(u)l;_; PRdB/Y$Jk0=`NO;cSb2Nr,o[ZP7sQ"\Mf6K-$ Fa'Ue,[LYZ+)=rnL8W#+%d6ha;s[o![pN#SID+$oZD<`Y*gt;_F&.=?hHo$lflm)hB1B2*_Q.V@gV=<@Y=!fO7dT qAfTY'GYIdtp"$PPHlEfjF=(pd #\IFZ=&!8jiOPplaJN8kg,E`oi'Yt1fiG9*6^)%q.$c-iq5e3*S6^/ HWPX0I)@($lf(^i?(Q'k^=\R6"7Xr&;r$JB-ZfkZoLDAYYV$Hp+k^oeUW&e/9p&:ja#5mS# fkSO>J+sF63@H_^iGT$V6'5tWr=g;M'8"4*VACa\Kp/.><#AKKfT9bh9\cJGiF;$HRa?^4M@CQh6>ADa"CH+;#j<"A(@?$D;5JS=4lI<1JUSOs8T6Udej5rK@@M5&%? ':_$dc_0\q#T9&TY?.EnZMO\rf9E"qjl_%Tb\(iHc:@4r@^O(dYQOqIuukZ)_s56p\MaR_[ X.ekS/NXLEJVpN*GTbSrjt:--:pqVeS&llO"$)u,VC)Y&-"o<.JoFlDSf9r&gr^_rK^Yd_r _pW]s)%C'+K.JM:a\(1oFY+R6KTXX07=6m1;!#XZ##N:s[dCk&hs+"& JW\rh8nb*S-+8%K[[8TdWe)4!/e@_?\%"_VeMnMu4]DF$)^.9dTi;KO=1Mi;ZbYg\G^[.BV 2)[\\i>!W!LO\+q23p))pMNZX;TtC[9MH_+kdr&Ts,!)ZkE?V+f lW6;2j/V^RP1]"VZl?gQ!-,??PXqq!2:7&m(IlO*L>YS0>`>e.A;\&g8)(@0OOG1W(1i_n8 "Ir&;PV4iCSk`-b:t!?;\["qol+&`H+h_)`9=$krPM`ggWU6!AhjWZC%h)*uaa_/LB!J]M) KaC,\sTth.h:)^q8aaBT"S=RebQk]Y'%fEbWtk:6*+19 e'/l_c+M`S!;mR_Xq0Jl)]\+fh!<8`mLUB!&3Tj85lMIkSe#6\(VL(jT_K.nGRqVA(O[1Kh &Fc?*Y73^(P)V8]e@gi1"0QU&3VKS5qWsZ6.B1-e9t'@4B<7a$e.=@eQl>.rDXF2F:c8@(H lK`h.tU#1)%KI'k'QJ@9=4pFkAj4fNj?dN#4Oj8/G]CfmT@CSXnGBA_:$r1O7VoQ>@BUmFu pPgUZS'n.6?YNZ+>gTA@cI^!WKYc>bd-C$/9bq@fQK+l7MehRY#,T\L6tNMAZ4"lRZ?be7i a^)))_4IScX2WbU&O/2VVV*5orSfcq&=;Cq9(KtV6kV=$L_oKUU*B/auHfu]]!f!XlW%c>5 qNIlSM<01djf"CU@4u\*SO31G(ER?Z+a`5f\Z9%Zkf]"`*nT5hI"FnY+O*T<' ;Jb$0"g)a\T)SW`sKRua*MnM4"q7Ft16$`u+Z5TE&^&K$I,hu,tjm8sn>TrXOiN*ul;nr5, ^`Ui!X'qHE#@;c`p+jP%HkH??'N`8)_H\,\r$24]-c3Ml`1QrM#fKmR"U'Cm@1[Z_)AriI, EZXr\fi,h6`3msAGg$u)NI<&9%Gc:Wp`qDh2&JFMH)3mb@RTj@r1)!C<^A^BuKF^4e0j]PR 7!eM*n%7W>&N%]fsb#,a];BNC'IAW`A>,R^Hn8>H_+E(!@>@Z>E1;:aq\C&N%>4>HP@2Q,` '-]3Odu>K+8aRp_rYfEM[+35J*;**@Ct6#tsV/mNYq)EDWf5H:&qFkQjq\j5G"q<\BGFFmM q:l='uX&H(N+a$=eEoU`&k2oKa#+0dK7&6r??F'ZBN@>8BZt>[nR>;1rR$7^ 9mG*Cf4#-=%SNd9(&lAO2D<']qN=,fpZuRjL_t>b`Z=;M:qu9!ZC7/P>ThZS"f25e^&36J4 LW9[bQ=2,,l;d5Od@0[*H3j,mGL%Y\V=4;LB$r*1#U&U7Ij`X-*D)!-kqOjQUW)+RPGKc?'/GARSY@25Oqa)5e(2FWP0er.!>= rI\N\FsW&V=S>1IAQa1fRqGmt)8LA9-1RpQg:"\sCg2)5XA]o>aVmjA(DY&3gp]_uF^3O0d rsPkFlR^QGCAe&?Iu%BI:"qpnTGIsR>a?C"p"p%Q__0<>[\qp0OGVBaeiEG[?`>#@eI/]N8 kc+4-!hGhF!?7=J5Q>F/psL1?W`G$1&O*2Se/D.blcFe37Ap4Jt#H3T5"BY$ ZoV.eRpPG[SjG,)!NH@DohQff7&RVR63]_3 >mEmKFM119eTCas;q?*iG@T4tI>;OiG.kq7h0.W;F5HY>pOhCF#;LHt)ahuUjEY'-QfiY.J ?E]!6D9]1#UU\t*.'m,[I/D@pVZFsIg=*cI(r1tomC@#"s01#0T]n/!gi$urnkO(qu:$Lp] !J1!<4/Ts*mCHB8Nn%28pOAJT*(C5kl?&?u-L.&5ig#=>:!;e/![uAe)Ye4U"^ZFJk@K2BWDm-e6.YrQr44;fIqq`@>o2`1(JkW-jLTs&`\+<#N<$?"*iH56+/gEB^.T[ >\&nXRQj8E!?Yh\IumPD6:cA,,%NNfOV09:8D,.2,a=@QE^iYmGqC@RXIG0$Zs\d]p,pBBP %K?JE!s,`ig`E9Pp:B`#uR!A6V,?9@A6puBko<^e@Cp/ia5?hIkPC:_jF@<@*EnQ1+"^$(h )P<_?ln@k*42\F%-ZLn[9r#8B56)[3[TiVu+/Dl%P#?Tr8-@4i(#e4;$E@B*.=EqJPg5as.WJ0sbr;P"p7>4ZG>88hKb>XlUCb"s 6Y]%_WBpk[Lr(E+#dG3kePqRZE]usL#pU^kOEZN.E&bsj0!uf_\]WO@Ve2bYne0CM4oW*a`WfQ624IhE:PH3jd EGuCl1%%"Jht/U@<2/>H`1P`RkgT=bdJ[^N`3?i4NkGEf%V`H1+Jk]iVR 9$h;@e`X(_@=46p%>Od*[&AoL^mf)+erIAhEV&5u#;[cOLJacD?_,r*ai.4]ZLHZ+U9rZ#H@argB'/3]+,6T\-;1KViLq6E?)+5qX3 KR5>6HC#T,@k&AOYRK0;$.,fAG/NX=J3kX,:%@A+jW,'els#%FE=S'Z^>e8hcq])IBW"`RW CB&bo*iFB&)@5`)r?DbRK0.Fr?lR;J$^i#]4-(TZAqoK@!d<5j3V&PQiPl(aJ6n&"L,)FI& -=M]csL&`D0-ZW,CWG>;lN2lLilU=:*@V[lYu5.%JneXEsKCAhQ$8'puNZEdKrGu_"i[^t' /mpBkdJD^[Bo,QK)@qd+U4,4clGPa=2D"i^k[Z8_g>?>QVIAaMs[bBITD:LaMNq?Y)bhS71 C5:0-0n^*"I4q(6DVa7IpQ"]i6QAFG&XFTWA-%4MpO7&U#J`:^ck@RaBSit<_>$e3iESuR`q?Er&Wf2h3iE&ND9\/Y Rj@I/E#Z?C]Afn542%Uh>2LJWja_n\ARSZfDD?LckKf4j\:o=anU!T3ekIdip6_Y?>)id=7 SnGYAcGjcO1r0NQ6j*3NeSnK*63/%mWDpJ1)4m7;!U\"JOd<]_&l2=\_oq%Ch#XJ)@KJ67A Jf#n_?Z5>Fa1M(PpY>ZGH13uk_>'VSAI*g<0>pC;q-Pr>r844>rg1q,T1A2F5HXX.a4pIjG O9hI\1rY56Q'>Y."5OLq7fGcrEm&+rr:[L5BlYsT?mCa0Cf!-JCP54J(;5#!'gA^4_t/7$j &[V"$fN]^g%"-?p9>rfESQJ"$g=KBISZQ7KS5O5h$4Xg^c[:&4#:g5l;51$kbig'1#;)_-@ [?A.XH.7=u.?"B[n)S/T5>)aV[f6/3EqllACU4Tk1O"2I)(9Hle[,/QGg6;/^m6mk<+-c0[ J6C]JkX=1r3b_*\n"Y;5lj=S780LG[l6M*$#$o5^?1IFhm6X2Fb+?]hR:P7:_"OoG!UcH>o 4@?bE6aT$EbW`qs5(hK_";![!!(2CC;hR+k`(WV<<(99'7mr;*`)oH].-H8V@g$UA"8P<:c p\-q:IPC^`=,Rq^dSGe2MXc;27C6AibZTR+63\Pj"; kRe*+Ho5@n'.&7U0HCCh6(XAk%/^7Z;(OKPO&ICW7JWKIC8]^dA;?DasqK`scuY*-4UaF@R m(a#nK7Ci=sI6\ZFAKX5a?Uj:"^Hq1\0KW&R:Qpuf5In0]la:*Yk*.pcrKLdYIa?5/ICkbK .Kuf4.8N(Bb(8A'oaTLX_R4p7g!8%b!T[$+#(PK>A?8R.NPCm<%hQ:Zar8W9*0 S=<*7S4TfPah407`-mB%3eWT,"+WlG0K4Yu@`gg/b!`'uCo0gPV94ap8sH8HS?#8`X@f:j9 "_:KbcXS9VupEs"u%cb87G4CZcb249.45$+@V#%15'%D"#*6"&2T[r1k^ruK0ZA.jF@BUN! /o]"73it,f.\U`(W;49Jja_9ZG:]a%VH59Us/IXN=/Cb"TIm9UJG+3+)mA<j"jukY>[H"fP[]#Y]q3C4sZ,#,LW]jR(7ZmY$s'L5S":.lU6c36t"a:JCIX=`Tl0@i-qR (fNR7=bR#eAHh*]1edmEh#B3!s3L'4'ejN\=DbK0"Aher(-m5%i-gq5];I(NqCMGd1ERK^)L<)LZZT<[t@K[Wr;VQKFlZlD(p&l3QL-S ',+o-_JJQ#3ldp%<#AMmD'3)b5c;ft-"NB5OZ4#cA7"6^p55WjVj5?%eNL0-Nh#]0Z_.gH> ;K*=\CAOY*c85t"/<-:f4NCq]k92s/0<8C3sm7gRQ:/q",K/b@ca=i-!CkDmjut$C =B/p8q>?/pOe_OJ1j]tmR?rd/6%\FK31j"fNj/4AUq`"*E3K);uMR&'oQ1rN*)p9=M9^Hc&Pp)O') pOL;5a"SSm+DD-9;F=\Y2b?'e\oQrKGkK30d]QoP5(@KXt"L&aC$[t.D5>m6VHS\O=nksKn0s#]5_Go7>1K_.h61#LYZg.n>5b].a?0Ut2+)5fgKZX@ A[P`Z\6FBl>BRM]NOml8]3EOm>F7L+-p>L65D,V0"9CVi+BI8T`*=n5>Wp']861BT5)$L5" @0BMTKWK$@=tLDgs++!e]qFucNAtg7M%f(/^f8_e(maI?!YrcA^t('fNipY?$4k,NS<3ZgK i(Z?/=8kmG2(@hHg*=?4G>8V9[p\csB/e?D>%=bp"tc'?^:CnSblcrr*Qd##'`I."T$HDLDYT !:_$r2*6dkoPq#-BW!pP\E=H+<ZjN3W_QbK4 $=bNL/=9Rq^0+X#CQHsC(cg:)HD&o5% W%)!ue6 c#Ps&3kgr@:"uY?>qh*rR,!Vls:b"hBqXXmd4okmV`&E/t>1NXk "H&E+ZCiW^HCmN:rm%WMF[E=W\%"rM=+3!;KV"-cT6TLK,63s9M3K>:!r>e+=9*+HAsikHN (fJqm93b+3oEXs@(QQpMm,P!K5E`bO/W*a'g-tF,Bj>SQ!7R^j";rq=bo$8q/h_0$%0QQV9 o)CFba@V'KC$!?VkD)Alh0.:HrGM5NXqC#>f8McU2e7A VRF4LL+k1s$q0L87qTeR]'E:Ljk-L@!"n5FPfi+`>aTZEe^MjkEf(ZVc.6#<-9Y.LS/gFa% l9bIYZR'LIc!1 ODH##q#?HWn7IR3Zu6bgD_ JNq:UYV"[sO+^DeHA&Vn6kJp[FIM"/clQ#6F_r^i1+*qu=K[0>`)r4(&lu=taF% XB@-.u."qb8k&b.g(r8/.bkKSDB'CeR-EF<9rG8P=]49U1DK?-Rf2qED$f):*MK9/S--Q_g 0gi;N4nbt+\:Z$2"-%6B^rYOLA*]A[i.=P&BEh5GtLe`[W7>?Us"\lAaLr,_?)oFLpX6Uce5!V#u5^ YmI`6m`WVL-oCrpk2*_'8f4fdu,+7DM:HP;/"I*74+9mVGh3YphSRBiGpdiF]uI^Z!4>3CGktMK"YTu=R=Th7@) D8[9IL6qd%4kr-Z/W(OO-`R.5)M*=S2rrr[ef@;qT]*[_DS`+&8hgkIU2O3-I'R=)GU/"=a q1KiN)Q< `&U8TLahum]hZ%LZ.nU=HX6(&J&UC;GWahI5F9d`om;*Ns(B7*naEgqA@CI([,Em05EGF4s 1hG>#lm6;*"N+e&6oqS_(^6S#XQgr.1*be!7W\A@j%4VMukh!&4>sr8J/ng'N#L^0g&GO`K >OL(rame@2[)4XDo.K;7q)ma-$:J+NLc-JKdT2fYf&*,>c&\_GYcP.)ODc$?$B*d@r]-d`f 0P99T4d0[$dB_(n\_/C?8u;]1HV"m,7S'M]=+j#PE6XRS>I;nViec]e;*5gQeX!Bh9pfPG( /+nZR>;06Xu8((@Z.7hmoSLmOa'\tE;do>ueC5tW&V(,Hp/Q!tI2*@aT%:].33=9@@nfX;% i-eh]28s]Ef9Q;Y@+WsEJRR3^/WjLF<]ud[fp7&*<0+nq&jVJCXflME(>ZB9gG]#@DiZ-Z4 ?O,X/^8BBpJ'=`h:GZcG2>0+ja,dM^#se"f@BD>hq.8sIUH7V#Bu5=YtdNDKjasB'tA-'LL M*l-&U\A^+#"MfZ=7[QK02#@:TQS$]pCe$&1M&)-0\$jk4NZ304=efKYaKY&BeB);]M-k;i NeTP)sgM4s.e(6P?U3^/h+l'd'fW9N$%TpuU\IT`c<)W"o)CV&Z@3tPDc)JG0n0$gk@)d_( 'Ns&m]3=tBZ"]jFXfF^8oo\!c9E&nMO53K,m.`\2JkGCAq2htULOM;\0C+ -#@W*aaujq-J95isl2XN&_Is.-"(]l foN$pstTaW0!d$>@S+X/:'+Ij-U5Z8#`[OK0lgkLpE)T-fB%UnEXLX>H2_q9MOiY4h;0chN ,LlE$VA4qd,.O[^;UCBWDU)N#J9T9=_(8B#WMpZ]%7EEFaiuDKdOe+?uR*-E.6u7i[[Q$bO jVstjE>em`;N3D-0ud%V(S]nR8-o5e?,"a^0"#@)F('k[i>KlSN^PBdFmte;WZ$nIcQ@d"VthN&_)r=%q.E2-#mtRT#)[J&^\`$:u#+ ,V"D.W[1$2eI&*O>*DhKc \$ZZO]>.BIqmqAo-JPZds$?g"Sf+`B)IQ2P"biKu%M)ZK#2k"bKqt@;ORJ[C0,ig08oHDHI 0j%`4Wf0ZH%jf[[rN2]gs`JQg)rq]TKdN')nS^NA3$?4FaLRPeIY*H2)k!@LPDU?/*hSY?gLR@-St+.!H9gdIk5?fo3250uhkjn V4:a0V?8\IouFf59Sr1TEH3cq&TuUN/a!@AkU8!.jtZ8/2,sE,g+e@'uJU1$t5Z%MHPE^Af .G5o*/aL=dLsWI+8hIR%5.8gGh\ciuN3,Fj?E43Tlq"StirD(Lp-W$'BZhUa1T>dKj(aiIi gQ&DEB^QUf2H+f+arQ-q^#8nj8:,K:k](^&QA&6[J\od6La@k;^3Bo=]'AAcsOY?1#F@B@R A^)TLi;eqqHY4^qjf5m$T:+=)bk6AoX>8q$fI?[fgGiflIqe/`eg,2=T!8>p%CesH+[J&J1 gRE\2DB6>P753@0JbW[[3Z1=6G3du)*'o4>O118! kc+6kS`D26=IIZh'c)%u+bC#;s\t='gMbqA2Rr6NfUTlNpt#2bWDk2lLi;3\nUW5o\de0(T "L`Hd=A%=s%F#8!i9/B+=LerJ.$T$Q-&7r,Ht,V*'$j_HGTFg]fggio@[hX0KPn%J>-0:RB /(gY;Rf-eLAD\C)-p!:1mKK]Z-KlqVChO(X9mcO6Cu[U@@\/e p@pC(#mj&NH*"pqk&?WrWh'q"DG]o3;`>sE9&8Jr_:NW]D,q:j88kCompQ<8djT!-O(VlKP [rJ_4VL9;B&HU#KbC6+lj[rB\"kq#`t(t:m21 0=rr7e+&IFo&>KS/V[(I5*UT0G&@2`U[b3@H$VcEu_;lSTW=4CH*oY`jmD.LreI@MW%C"Fn d,PTIk7-Ge*+=d>_58"kmMTG8$r,If%G;:[KG_N0#@j2._kmc8r=P%l&Zu9LnKSXn-P?N[) W;/76-^$lr8BpF'(;s/k^s!.j9b ^HN8a@]A5jSaDG8Q?[(p7uD!KI[UAE\$%kg>paOeN\#p]cbMl;=Z&%\jsqU`'6s#n_FsZ$] O]^?cu@Hm"12Oj`XBgDuF,*O40uJP6TiY3p2n*ii9.mf+A)!q6g!+*%6$MgDkuK(/4D+OUW @%i/TsR.80aA0Cj_Y9roQ-tXf0-bKn,DMFtmo(En7eI9mpr?(BO*:6fN'ONA&r:iQ^2-O/$M1/fb[M+AS:INH>r-nr h$'1+*ullT[.(1FipE01HJ=#Eo\#ub(VJ\W56pF#eh,3?cliiF*5#jZ7AF3g6a.e$D*A[\'8+(a1">_/'RsQkk5(&$Z'FE<=tV Jtbjc&BZX=OX1XHk<;i14u;Xk@@e&2W#NP]%FI7&%MofH*?5b$*)mFg,T`tY\k)mg(/u@kZ lp4W,=7VB6I%oqTV4X#'!\.?%D](_oKsJF7i;eY%cD^O@/L1jTgb*97F@i)@>k^^FW5F<)c U_ooPh#8Yd1Vp8&\IJNl2d-nJr5#8C?!ku:-jWJ1tPN$-=uaB-V$i?i>2+ kkp=jf-8c5Z<=r).%N$jFEsFQuockiL,q$)MCpb;oDjMkMMc5e".*P+/0:cp+Z'm!SBI)_/s>a,eWX,NQWWpLL ^`"^o*$f]#?l8N>#h_a;[W_L$l*37"S3L9%1j2HJep_')`'3S'/*Wi1L69oPi8ng!NeAik? `^i*+?`C(%XhG!_eZbS];.)W>oP'?CW+^D:F(^eX4TVJ n!4X#b$4g)<'@[2"%N.Nr&P)IRBpP>W">UpH`^@*`6<::)f!@^:[;-7KW^)nb[_b>HZ49-h 6rZfqp8r1g2p1i5`@pMX+07goe2j75EXTkm+?*.ZrSa1M\BQ Us$%ERu.M(Dp7iJ."3/*n7"R`Q:ae[r[lpF4@R(D[$`fkS83YFO\3N'ZT[$RnWAk%gL'MDc 7oi%(M^Ud96N7?]p/InB43)D(K!%-Gdi`YQ]`1@BdVGa;V.I;Q_PqU\e/A%Z>=$.\dh!0YIM[&E"YC5gOBl/" f3R$%KU>O>o/7Z+oeZ:lL!Y,a_:foPoj>4EL6umd_IOFg:`lZNL%p.R(kO4.Ornb('\4.1p lgOOQXU$A*b!`.=G:49kT7Rg)*q22ejX*dZ\t3[MqGDl@DWk40H't0%TZ^p\C!FcrFQMo(n h-=Tp-,(OV(WBB6`fV\F5J\o%torV2ALu+UAW;NKBHi'Gh.>(C?3lT^1lhVtRZa(:TH-]98 R,6;^]R7%'/qS>P8D%Y0=O?6#7O+WlLH'.Opi3AR`[7D-*hhi!HIK!"efgaU$s8pS=IZHSkH4lk$JO0 @J`%JUM2Sm[YIaalqZ3nLXq\tr&L!SYT\5n0$ i>E#:qa7_.&!;-][(B)23N5:[G+oo)(W-@I&_0_Wr#Z#e.`@B\WiLP\(O3[$G]B3h j%>AQ#;``j.VRQJia)q 15:i"$t!*a,J2qr=."kF3eO9Xe5"_"nVQh+s:)],B#3):b9?#J_k#:HSHEVHJ-^!c9lOT3: X"*$<%#p2Ut;_3tDB)?b-8#SC.>&Jq^!>XNjnWI*74&RgTkeOuW_0;?*\`S=\;#KNP73IY- mrL-6s)F_\HFelhSV&E@1RU)bbVoW%H'4FEMg3':jQcWL%VgOkfeY/p(Vl5!BW/ToSIZ+Ec5Rp2co'r-6091l"k&kBdb>#U*@dW=a;D`W)M)u@3uMUSe'spYNH YHbJ<"pUe-6#Jik?pFC;(`?,tc]mJ/bqpcf.gV*>S^0Bp_*Zn&PmiePu+r?T^ %oILt"i.i6j.8KNL2EH.'>M0r_`?epRH_SY-c/&Kjjas8X=;$a2<==N_jim.'g9K*H[>T_T r_Cji:7LC?cAUpkamjT5*12#fFa1h][=uOeaQoQd_W(+iMk 6)(+G5>eQh^kr:TVf+ssF.f,kn%+#==Vcl6D%d2tU#>ncise='g.o2BZMJYj4]2>*Lnot<0 Sej2CH_)u!lp>&BHd0L;SfoBf%et$C'^OQ#cK&>&M5El&tRmkrDQaAhGg7P"i?_FH10FOnV $!ihL^TmZARJUN()kbC^T;-A!WX`F!gO6L.*OE6cHKY7G\GtB&_"n5*dG9<:rlY]f@.*=*Z *umZhP(!p,Hq]2kTh&S#DGKQOGJ!2*t=#oi_`g:?7?_L7UqRjoP-Z4Ml=t`Ue1dS-^;b";V >Tp=#$%8:FChci:*S5:8]nYo_*huThjlo)C6Ga8YXYt'ZsE6Thh2M:?l?ZeQ.2].r//-h0- VAYue#m)_I)pBs_(1p=iTY`e$CVd"mDkf'ddp+R[9L$P*,c^Yj'u4>mQZKjgKJ$q"J%LQBO ;10IkZ?RM8bB!WAfp3/fmd:`)t*@@CQWRC)))U2;Rl%d5op01cff`]5UUKTammdkkCi,JGg ?5FATa#Kc[4MG_iS^HYCq>FWd>H-6AG'fd?pM[h&n9Fk;?OrdNk;o?*4F_Pgho>G=ra0#nh s'q5,FTuZ=dV.1"utC*(pG7p!l4;)'*^`6F:L6kjtPd_R)>=-@ZI6uME;F4..Tor_oX&67$ /H^'L_Ij9bp/PCf_EB0na0U`j(bF)Fj8HEumg`oO9clVAR`M(c!@r,09=SP9q+kR35iI,b] Q68s5^F/5#K_XY*7%m'eWA1Bb`Obd/#.1.qb?<\aG?e47eU(\*p(`!Y''1R>?Q+\/P@`EJ@cUA9fe!P@ZaD=-MaVVTt,sr9S)$5a>M@aqZ_>'iA@\@*K!N[r6+R0LBLis$NIPAbI`>N/2B8gi- 1Ie=j)WPpVNY/QW7el-`"upo56MNeIM"Mi7gjP7rr]s'=#p8 LYl0jKt29&lMFqGrI'\jI_XaL/,lO5q+)oV3M[LBEpeb']jF;)aV7j%"\UQV6M,.jG$o4\T KQ:beKL.!acL96m';!1RSB_Ac-:aZ/ H?iggaE\JIU*4%mfd%gM+K(mAf!bYW0fjuCu=ZX#diD#^,l!e4#b#sd]3!]!^6H;M0>4\PU \2b3"e+)3,D"CTOc+rk#4RQ,Skl0+nlL6,:o5=oQ(-9W&XM[]4M95'kKU6NZb+*74,O8t&$ BJfsdqK.9bLrKo++CbX"'JY65N'edL&#'baNm[f"WYI^s<9gG^C9:F7eR]MO5o_Tl>"G_0I ]oR>U7,jQBWVT4[8qV*>&.SK9k!fi$m?$+``d[`p#`ng[.p2G!2gbcNDN_="^tC?LTm'g_c WBG@dJ5p;h@\]Yloqf-L2a13!4Kb&1u5/ioG)f5&;1[Cl[DPbsrG@p/HX0Hj $Gi'Pe^?&Z_aa%e^kIh\.V%5<52;,eDRf1K,mu'_:V6^iB/9;0UZ^sEkUakXM[GDPc+cPJmkC(,(p2?lF1I 5o4<@lM_nEL&N&R,8ooS9^,Lp,`Uk4@FlhZlt&]kn&FMroCQ]P98p]IS]qC`G&Zonuc':R: e$]XKe)L+D_GgF>AOuP7b,ZA^(f?2!029Rr`1[c$@>gAl6#D7h/qM\`YSX]Y+>8n88U'dm6 JE#9@nEL!^eP77Ns<%u(pL"d1?&krg>hA6tMKk_L5$R8'T$k+@n7LJMY:6)aH5P8aP<.HdY 42FD^l).D/C9J's4FgT'<)V86[I3$+n BiO,,*[%-:Vg`m#2l!nKlEJF^j#0$hu#]q+.?pgL1NZK2"Q]*qL_W0/Or0n-p/[<[8m#]-0 5kOQ#_=Tb'@PtjC8l]Lq:HeCD'@CQ+*;bqVBJCh`e.#q);AYmpCAuHKb%m]SUVt2(X08Z5l <3FT/8hHEU94h.9$45u9ImE1.\'K$O'?5M5ilAaLM$b1\/0gMJFd=s@on$d2e`qmEP0iiH^ L]78^TkC0o^#JbRJs)/_k^`I"DH!jDcj*Yo>(aG,]hN'rOM=<\f_ta6JjF"F9. @2`F)5>V=@Ve^16XS4MK1'&OTr^#fJD2"%Msq'.Z8.*A5lDPoo],u%qgW8IrI;l^%3Z8u#8 i1*\NBb$%%mQ,lR=]%!41_e1[G.X1]jD]DZ_sL#08I(K/p`##JcN`5b&+qU^OuF%"^0M!sg 1X!&XiM!^RM&[:!g'LaP#P6aU)4_.4:sF;6#kB*5XaL%ml`91q+[*5TQ6U\I%S6W1c';F2$ q_Aj]8,U9-6AHU!qL>XtAe,fj$2ZhH1JkKFXj=@Xn/AebG6GtIQ&5`Q1/iG4g6Q9J]E18b% 1q%aD6Y&&A@q`u2KD`8(fL(HP%.s&W2I4/)]E7KLF:C`7p#7lqbR\:l`th.(b>GKN#iFQFNuRO:n+oih7hGUFJMj3> 7Q9Cg4GsQUTD/7GM.ejBnp[2\Hdn\ZB8NbFU`lAB%#K\cFEE&7N-pV+-ZE`hT=6BLdaNBY( in]$tUY`,EZfE5q6aL>c$q40uOuF@T9:a'<`,@:GNa[k0F^(1:0t=D,7H]LU@fQO.ZE,JcJ nJ4LB(aPaBL$qM0$0L)>Api-\*AS?GJ4#KV4H5\1*djN8.u8fQka1nr,\U.SC[# 9[LZphBuR4MIR'8t]dMYVucJ@>"o&#)Gu<*3Y+,;84(@^H;0SPP@d-[*(kFb<35V;]#,"!Y,Sn4LcqP2jbo9"S:d"id*^S7Jbu71<#X3fe,>FCHc(lUZXP(k(9a5Pu![91 Iq^R?U.70g`6L<^KjQ"N2jA%N`K`F>)'J`F:1JX-D_d#,q[-GrT2i=YM2P`E0oK5nP43nW0 M_mREHZ1?W56NKW`/OE.#fERWI7.?9`,%n=[/*S2qM#oB6kaW0S5_nTrAY3]72/Qp,m2LO" OJQ)\9.euFT>6gi5JeX.Dq1bMi^B#@_%G(d,\S2lsETn&()+&.[W4Gls`gX,/u`W``3dDAJ UH1B7qs63\5&9SJt&#)h^aWL2^#o88ZB]E(;2sdNp'b2'Gj`67e;B7r9TnI!8JB-V&6d4+/ T\0OBL$E''.fa3?6&]%ATtg.3cGa>Ga%,r=!ggBWgeLQ%d&FZ5]/FpG6u8@4?)[5udTN)Rm cLIcasXZ08`5h$N7LU_Vb/=/qf7+=Xoab<2IE,r/JgBFg+LHoKO.!#Xas3r&`RRhXWaC*.a UWQk=eKn)C2,R@@jG*/3KRd]-]W'&@B8+MD#!bT]ct\7CYY,\7e^Uk=1q-+g\(2:%eg4^)1 pmO46is$"">Db>:dW@EBZnoE!'c+L6U+f[*[F;daur:L+#4dI+HPRJB_:iL*/X1XP?oGgXoK\fM.)GaD(gE-Qr J-6BGd]W$P25N6Y^gc;fnWeW0uL:]pJF__%%sLm:`22U9P4fi=>qBUXW/5(fs)cOBAI[@5d en_(kP:IOgX&rf]RpGXmN:Xu2cc(iV(UtRSV2nbl_>lVc;#K435:dkQAXfKfKXBMjj"-c\4 AI$qK#`[b*KQq0_cpu@57YX>?K>:"hr=Vs:\5=9VgSMI8[CHmS%]],i>NB7GTLae8(f>^td ;lTT'"S4uAPp.[dET\Y^h/8P;TV?PdOca"V9@Z%bhT0j3odD*"XqfI.:!\8h'9>JN@RMnd] Gob42!:;crC9C^/HmGh4<9K7GC`XC'QG+eE,Q.BRC'CIKq9HLR;_0:illNE!GDehISiVFZ\ H.k(_5s#?Z*(p$:JRm'%3s#%^;2og[gB7:-Mm]l8%I^f]#o-6p?OB7mE0L&aDg?%?#u-mRqcK?,(cDCa@G/6I'IV'u%gp)nsu!na.t=LF)ijc AFk1ZMJs@q/dIrK5bil!o^;fk*:u?9>%B4B[Z3g"&@?^->cG5Dt?.g$Cm1^cR2`pZ,>P6m\ X4?:X("8D7&?`-nNl%B*J89Xk'j\.u++or[J=D)p0Qkb\-$,.&fn^+-,6K4_V>o<7USE5Y[E,49a4>3>^gF"Ztb8] :kk7[gr=5:eo'XTDoV]r>m>?**ckU=-W6ach*ihlh:G0@IMWT:?,h3H^3e\5Hl';;LU_S9Q @H%kIi(_#LU_\caEIl&@0[op/pca'ik2,1/gtN>#KP5$e`_kh-:[Wu%jSc69&s_lmioN^Ej^)!LGX7"eC' 6LiL9O&KaD1/tC4m^&L5oL"ce:@gkEe]=8EM8D!"lWc6j'FuhhHl"OVMT0FLM1J\E-cP'e&h)ql-D-La"uu32"NHG5&alCKBZBl?3@EHL.Fc\cut,'"RnZn*L$3:3C>i@D-(WB9Jl-Kf)te.KkB!)VV-/PFLL& \:HUfCkX'.DGf1>kDD->((OL$IH]2(Hg3-/$5"uLUonH6,DNBDE-\KAMf>5kW0?3!+ol/KA]@V!(,I:"F6=;E)2pdY Y_D+$@150H/Ar(j/Cc!YIb;SE5rFa/p)(#G4>ET"R'5kk7YhbI"bC."m6\J[heh\(TmIW#I 08+F,& %CLNmio6+[@@"+.WN#P.#487i$<2>idtI%N9DUZ$tV@tb&a8s.rPYVq5pf7qEVbdR#8d+AnMoDG'\C>[X+-&k;-\ V$Jn>2=@,k@@6Y$ENE94fsTPh'P-REeS5FXchHWBZp'L]aB[M+45eku=*_,+VB)dqTUYPua Y]W`CV"RcSG#>#q;WX)oO/Kk7UDXVSN(!=Zh+TNHCWS]^2@]3]Ba]>a@6F?#p1L;Wm!$&6= UnQ;;n,9;]_j)Q#"Q<,;tb%\h3W(nb!lVhToX-DJdo>]j:XbR44]'Xn *DKC2'eN?_eQ$Hh:D2baFN?H =<:SrMaR9[_9(bgQoglD;4dO_/\73/]2YbQUT/@h3VF'FVj1saC_(=XmLJm(X;W$hjGuSnFI_FWCXr^2=]Ul*ZE.ppMo:j&k_*O5lW44cn`m*_hc.)(njOj]Q J(QfWLQ?(#:BSlB5?k9^_1kF(adTBI1'Kq[_!/rcXj)=c@!(^D4_;19 gd_mnnXNr,`Gur:,KK@[Y:7ZcI*XChEua(#cL`+>7F1US%nY7Bh+pXAS&PaWB,8C)Qs'r2E H!n+L+*IGRY:4>CQs8IKA^u\08\`aISYsbGog=GCmd\uX==!pW=eEArjT0"qd/`tn,&^^^$ trl+3j>(+"u+7rEjKrp\fT&hOr%RGn6#2oD"KFj.U6 9@0o;30Ec'7&#&>SLf"@#6jSb`i]KYd&M>@tfTR!.A5J-17OghdXV@MJ*Xr N)7qX6TE=-j#et6+i#H7&F9q&FE!60`]?ULm2Vn>FcS964\+0#+62.-O4"A#83%+u`cu\4@ fS`FOaJ8P7$!Kd6:jaO.4+&FR?Gud56?Ct*^TFjPVRhf8m+_7jW(7ad]-8=\Qp^sKWLJ;^0 /VsBeAGRTGYN3*Xfd_%#'4a"TlJ+9KA"c-8`g[1DF/Ncu_XPJIn8<5&*e0X#/tGfp`XmCX( P?2l>ZnS5Y/_:')7["8H4K1TZX4_Eg7SYp1Nii0tCZkrn4:q4=D3SeL+6:l=LFTJR(\cq4I -BLN0"<#UB),03rdJSCiITL#(m<*uTC(SaFs]a!Lg8'N%t1fTKs;G'ALBgjDG<1(a(j&&;p _5oN6p6lrCCi?;T3&`#171>C!:X8o(4>d>;<'$"8W^T@T6-M]T&F(H/!-]#b!8!.up*6AXP 8M@0r?$@!=).j95R7Z0,,A(=CIMm<$F@.m36E\@WZ =aj]?6bFg4s?_V*ZoBl36XYuYW4?*!:'kdg`;$fnGXN)QtqSFi7i4j(W/tZ%UkkhL@Fm[`#+OGi`WP>NW-&TR*TPaOO0Rh3aB8`lA.4HZniNlliuh5/EHiTHQt mT!n2h(fPTuaoU3Y'D/j.@kQLb#\H1+2s5p:dg#Ra<RhiBL=48mB:2.C)VR6W!e2i( SL%($\"$g#;3]gAW]j7@eTQ:C%*^XXJBs$GK\^oL#>\h#f1;h0lPC!d5Ce6K2"pfV\dc+Hs h3kV2cHb-*6YUC?="`V$^R-f(A8U"\\+\n%(1IOaeR3_`k;MP[;jVXpS_:XLG4FD#c>ncGr ^A2fn)%'TG>B[^4u`E9i#E/mcdI8=8f\53S1B=j^)OraG7ig_i=6ju,?;h\\.;8=^X8N)U7e9ko'rQh+7Q c2!tlkPY(J:'-X%LuC0ID7?LQ^967;cW0:ZJsa#K!oI5.Cp/PCb8N;_Ap_^]Ym!tH(RK%+H qUm;IRhHS?Q/45-0^CQLXBb0jF4>A)Djrdknc^?DdX[#J%km^r#_!iIUC"gs!@F\"4VXF0A ZO*L[k@Nc$k_)kW1FF,/iC%rdV]\s%i^qYQFjo"<;um'S4aQ_/O;nW#m2L*JNdkYNZ+#!$1 %$(X/'F/U'PF(b9\do eidL`)Rcn,1C:o+LQW2'()e7&M4YJRMauTgE:#B+USB)]\G59'X:K%Tl:PcAD W=,h@X$/0jti;?P]nX(;^7hJH-*1ptmfPheD'qNWU,9#oJ[*,n:?UmLnMS*uV>O)=AjidA% T]MW1cn)X]3p5kGV*5i],_)m2BdmTS_7aQ7Ed*-':EZ-Y9O9]cEQk"]aTNc,tYj>KVTVp:> F/r:ZFN?<0>q)se.FOTlmq2:^Be#s*';:!oc[@TVXdbbrmlZL&n^li 2I:;#n[a[5kGFM'FYl;m+gOq"`YO7oH]W74pQ'd6Lcp#0f_T53>92Q(MS=65m\6b_%e\#7' odY8W"=7r!*gP7Ib(]&TL9^AO`q<'6/44oQ:te4Q"PE8+DWW_KI<0%M"Vf)K_)[<0\AdR7T 6))PY72e>4)aq@J8;)t#j^1pEa[eP!0r9C^V,eAFr^)PtS0*YIWX1t>;MD!*EokHXnZ1&4R arhuu_(fCM$lDYoS&/XmZ+a!f/eH8V?";el_'&fRcKDZWqr">!?,Z6j)2'Gk<5uP*:;Um2_ +P79WKd@*',uRrH0*:LA9. J86A22(XcVY7EW.b0In!LOd'\G,Zd=Ncr>Mk)FWW@\je/QJiU"hGT1a;KoZ!`Ms$-2&E-'O cRTq[^%R!P:$cfe>;>0Ql>[[GtQcj;3lf>ZL<$2>(QA%EoLHD`>4>Zq#QBc/BR6UD2N5<.9!3h5$OZp4U 55)6Ff!T8VYT$ug$),6FG+WSoRaIh3%Nq$&2Ut(Df0NHn5p;a/!-B$ms$C]JfYN"I^fNmhq *S3[6Zb.M^j;?_Bgbol7/%9]f+g^tA.WGp%uD)l2^Lq[-Uu]:Eq_,SnT51=G8M,Y,W'p?1k A1aE1arG8CX2Q1m`>aT67VFTJ_eJD)j+&a!#;YSR;2q<J[G'q ;-3FG=?%mb3&"H'AQ]j5.YVWJ6%<%I86CF@)'O3.3)s/W='Jd3\tRh!J_+AX.5"9?]g:Ejk &M5[l%c\0L\9bb3.6TbJA8q_+&bsiR$EMQR9qVI*p2MtQ4o.!&W4"3MO:T)fW]4Dc5Rp-*P o`460K?*[>F[IBHcRZ_5h*Kfjjg3A9d'mk;F>(Qkb23)r[#&!R_m;]Gjr`AX6b9f`@1RCM$ U_OS3[V(3Pa"&q6bHIjau(er,]7M3>3]$PppL2P$%4ach!4KE8jt+Lc.%PA?R\CH51+Gu0C ^EX>%K%7%[l\Rgt\EuD`^\\T&gE"$qPSF,oi2bA*ofFMBT'c0Y:pK*r1?(RBiT %WT^f4/uJAe7S(G8^KTEPWVrIs>-+TXk_[1qap(ktMtXU%aZ2eD*0HI86-&U<8?UNgG'4#u ?nmHe5fTqF.2@8Yc@Y&`J$GTbnRgmLeE3IG/+X\n-;YBr3q,VIUeZNphEp;A(`jVt]_2=8S q@!N;@fW5Qsq!DXRN(TFnbWRrAnqP>U63##pQK30e-3jG_s;-:=m=SP-$+^u=?VhDIM/#Ag QiM?6n=fo2@Xk6j3Tq364QWs71_0*iqe^"%8G5IY`YP *hhF0R(%uX.>p8>Z?n71].dtZULCJM)8Y_^@Eej8*++9n+(=^\+dNjFjc/##N]UUU]3l?H1 )>H+*Bh4>E [T/lA3]N)p5=\3o5)]AE%_!pB1"*ZkDU?Xn8>]l_;GG.-DUt!UGGE&=UQ,o;Tl/@o%pRb3L 2!H08%`&hr%\n?d)l*7"U`?Y^r3`>rFenk4V-r?r6#7#S&f/:H&V55)gsr;Bfr"]'c$\BNK NL[]@=D;BVrW:;@4E)a@jZEoW;;G!4TWoUL.st7WZ;\OI1rVD):(g;X? +))Tm@W.^_>[ZKPu4e3mP7cU:I=sXrUBArDg!UbT29!0`+IUU#I.;o7n0)*._gb]*m5;"kT 4QfDU-M-;GE:b\(3kf_prc-AW\P_m=\Ig&!SZ4e:;4TjTZ='j/;2=NDS8oH(]+*[/*3qdnQ 0A)+\/gh_!P!OXOh#o=hnB+P0TQMoQ5ou3&0%U[ 4r*$7MeO-@iVVf-]R.o9Sh]8=K%.WOP[5Tq40TYhiX-Xl^74TQ*`]pG&s6lI^ SrGqTo]cbHbc-TR=9"g_0QXD$ZXr:_;#pkre-ZhPD%ae\ lH^-\1n#_,$Xb>K(teli+Ta0rN"bA]=er)glRs>\^#-GK8Rra1gNQrncc5*Q[+)aL'[a=t. QuQ-$1oarI7Q_"\N>\a[8u09*=;Em(:*6^d9gn@^N7f[GP@f@oRXK'SL`-7\bKrW de^fU3kc@QRMqX>XOp=&4]Bn%=8IEJ>iD+k6'^+m"g9f.>oNS:]mK[*Jc)'mr4gYWlgV\u[ NCGSqk)jH5NH0;rS%4Jrr&nt4fSI2nc+P/+:a^kal;Ms4l1'hoD/7_LI:&5(mIcE'oPN@&L Z>`gur:Jj3e52L.NVR8>Qr%9V,69Q:p=\)0F#01Rh*O'1p^1G<(pLREG8nM4jco4^p)-CTX >dCagB@]O1V7VnGQh2]6_\_HRr]H,l?J &UO?H2N,`2lk?lpNq=jY/>M2=6FW(++Mm,oDJQG#,pZ.RNo%b!^P*`%g>6QA.]&4E-rT16? &/>#f?),0ag?&j>RT9k#h0nQc&l$&k(+u:D9)tkZhX/+nT+Y`Y"GN)Fj7eEuRVH`-3:nZ35 Fr8+I7>56dsH"r*@++AjIWdVPO)8i!39.nXipX"6nae@R9S`L-iDQfH_E?k7h\cSWl[<80< *o3C<7:/ci/4&3-#krhf5h"*^*oCW2Lcu]Et5tsb`!&BZ^#jFfUe86:!;Db3n92]l9niRT' _!k7N[/E-a<-8pK:t4O@mS]*UYtdNDKjasB't'<@=k:""Dd?Doj`=b[FnLAp=EXS#@9D),O (DHPAW^V.G(#in&4>]"64jD:YADr/e[o^'jq.AU(dk8(@GJ=Tc#d68e PWP@Rfc99eN5nfp7i03c]S@BHEVuFRb&[Eh1Wo<:a#VCc]a$dLF5832de%ohj@:&>8 JGS*]mj9K&k2<\8f,1GH9DmpnH;OQ`'HGlPF`kR7!P:fNT>A6=.A:Hrb%qfH9S7)lZumXX6 f]^W=hso`>MKh']i3&npK=Jch2]NB@6I%It-5JIXd^Mq#:;knb[f#kP,!@VuZj*$ib`R('6 aFga<7Bf+F`fBL(2l"/(;\Jl#JR_0@C5+LE#=ODYRpW'LYs$m1.!A4qeWVD![siIt+6'uJU 3$fR=&L60Cn$dkn4"SfeM!aK&iLj]gXr'?.$%O4@bE$e$C\JF3r?48Qs0B.X_MD7jV79Hf0 ,1K\PEFpglpq7MRlsktdOtfF.d2CtD@i[q\FHMsL*+P4SNeCAVO-/uka*@"hj.(,t6+f+0O PQ!r&jaTA&L$47L67WG7``+\,\2RlOn)OE8SKV"jOBT]P%%3Y\N_HQ"J_2ZQ;G_L8Lc#COW =PNH,j&r/7k'PQBKg'96kM0A^n>YP4i"=Om4u_+Oh*H%V!XRNA>*6bF%lZAPD?V1ZjqLRZg 'R9f]C7B#NGn;g*!%q7/I3o\l=(NcRrEd5bi5kFGOZEfFL&4%Bjs*eUt>&&Im$-1q'YUUY& sU3T!qo`HSK(4f:s#smcT$)*S-G`>R@4bs[Y+,"!5Dj"XBf(R'[X( $tMZj1k4bH.ZA5Wl"89RbO=^*SB&i)uh@&Yb)q`ealoqJ f/Nmh0.:bBTc0i5?c)a'@M_7C/mr3qgEE_\rBW\EDn>U;/t,AXB!E ZBO(5,FB4CM\ee9/?!FRVma]n#MYV!=A\bd@h;c.7!()VZlFa<#l+N##pKk8O)jo1I@lMqs ?[M$d0=CVjQgXl\V@@p-+F"Kn6'j@>&V9FM0>TV(!Y#?e0\Q^EB<9p_1e*GP)H0=DbsAdkL@h=6dc`f8n<#iUI$Z.#YlNh7D']RPu_#"-I7(EhddM3 9VMJe#X\eiMu%liXJSG>@\c$t0Vn#%QE2O)$C3be]We%U[F_QSN/sMC-:nn:;,h!Ts=9S9& Rhc5G(kB3atto@A)5U/4UE3(jQ7'I1tn#=@W;%AIr4%YX>K)8g;7U\'d.L1859NC\s?1sVS HnH;UG&Tf]2aM*WgRo='-;&]+&Vq"t[bG1PF&Rs/dfq0G/Y:ski?ZZAmTdCFHrkM9@OG &I91]Q\PihAadf9i91oKm<&+UEFoE+iZafB&J]EfQE2=(IP].$_b3hKlGll_o[`!).KOh%D diaLQLgH"3c"M#m)Sj/L'7tPEKs8:!.0)Br7-;Re#lTbB]F-k'Y+U%.OlD#3^gOK;_,d.ZI :d#=I]\(SK8mO^*34F08e-V=a2De,#37)r[SENNg>6CHZ724`@NHhSIf*&DR\F1iS2pU"Xg bC?d.QD?fU0@69a*mWKDYG@'gq/-sQ3ad>8D]+g,'5fO="m`Kd$0B+P/M=H,lW*-o;BfqZY nogeNq/iVf;J<]R^uF,'Y6CSoDY$DA!d2oi"*$bI^e)/+*6gtebU9(:sQn%2t MK*d=W;E0kP7pTaW9*dFq5dBrsOsiiH)XEC]p++7oFqlP5ms4.CR6)oMh5S--$t"<4:#"C] &#>R3)a#r50]5`?&cS-qU+$p`SUK4%.Q&_I1f7>;@<"LqpHb:U%f1G^!d6!P3l<#@o;(nO8 i"UJfugH;h'*5UDM60oUXoH$UI=>'-T_6[%o3=X=PN` *MMdo_Wso_nfWWWA;/c<_^eeU1K[",2+(%q2-Mo5H\*Qd4/9q]UZt(>$Y[H$BuA\>6gQs'o KGY?5su,J6j,]-i,Ju!35f&k6u5@]Hq60rFU%&62nOB(]LtZ9HGnT47-%'1lqg+J;+0ta-[ 8RF?uQ;0NJ=*S#JbRPLkc7DFbY-C3-8@aN*EfV>fGK'#l&O2U5T;DI`5uZ#OGlS5][,SP/^ ^j7Uq]QChO2^r*-;WTeN7#Z4);8pI!3P `G:JDf"&LWTcnL&MYIbKsa6TtMoR7;YX9)XQa-;3HN._Y=C]fbF]?@gue;),(LIdqk/(eJ: ^`g8n4Q0Wb>bndfJ`peAcoP40JiAp]CX4`oU/"C#)T>aM5>q=VZltp^\ku6oY` ut_ou)uZ"*m)J[n$>aZs)79W>Z,],X)Kbs9e'^uWd7r6J(GcHR=<",KF$+?0LC@tUFF#%0c Ng_ihF(X80^c)fVn\a>&ImtEQ[63Q14*8eUAiD'g@:'BT"!X0]W.8F+rc>4lRFQO]u7`*A" [%-D)YZZ]oC:*%TcKssC;C3T01f#)KcQkEp/G)_!/I#unW.%2l>rCP^L!sEt*(*N?r Br48cclAar;TS%rm0eRLX:FpI0*'=roh4oq&bL(HNLN02VK O]7_lK@)N.kSqW+Pf\TEeEp"1r0Kuo>(d.t8`ZF6m8MP0;cR+&':;CEr1M1Q=\:8L4d4U5] A0Q2WE%`Re`enhQkI'Kl6\'&o/95SHFSSQfUJV.W&L0 -D<3+ajl^"47:9B\SCLhQtt8d:qSKWo1o3)#(26j1SGf9g<++A2oL`Rin`fAsqQr5HF`a1s 7K9Us:./VF;7#/GW69a&mHD2;;BM-+nX=Gb+Ocq&mN5_Q(K";"4\Qo]nVAm#Po9n_3Q4PO" ,gf[@;9t4"'3,HkkiQaTS=fn,q]p[Qs2`(%j:5tl@KqM1hTep:0::6ilXe\:^:^.J=cK1rk !["fH:ph;7>-.AM[.RV@o*7g3#H6Jkd1hd,t`Bab*R*sNl(L+#1c]h(dAr5f+8&RZQ3Um+jg:LFo6?lfDAG[1FH)V&D! r_$eE&'g`@cG!'-3*CuTCKc, S>(S"'87`unX6!Wgj^kQ*F&t5\A-c:e2T5BGm.n'Uq_enmjmBTiot"`6@:g!YAd,W\[D(cu AS,7\2Xknq+Ca+p`TEb+B!''b^1q9"CM&rTL;6i%G[f&KE!U"h--1:bfOhuO;BC:4]r+OpBhqd\XkT5@SJt&a^S_dZ5hI_LUI5&]Io%tJPka m]GXY^7O1P2u].dcY;rU&hXJ.I_d._tpp^5?VqrW^_/!ep>^IJ;u[ph>j!L2]3TfOY0++CE qsC#KodkWT$W>(dG&?m_XV5,7$gV%URGKGYC,kWXRK$"/4]i/XgP]@6t^5ZNeI@*Yp>BKcO .:kS6u"^Vi#*YWL1!(G =D+j%,$.K]f4\n%2EYGd4)C5*@XcJ[[" kGQkG1^Y\fjepQm>8jCL,ib@bAGmHK?-W=G!9F06>di1mOgio4#$kW:POToA<,g?IRn@2k> "/#jOQul^?]=<:0LCgmcNsA#[rH';K!O.,%t=N)a*b0 -.rGTFLDpJ@Ng.PX0D26nVAo@cj56Ppt3=#%pL<*D-h[!iG$"hKjE/t@qT*m"%#mX:F"g`1 QNQPM4JKph8LQHW@G'7-r'lcd4##J8(G\dQ^*)Y<"V43N+!,X_2h!s6NETVdL2M#Np+_W5I BK3R`_jrgJT4i-iBSRquG:6d8M.jnoEi,(A^FLdF4+c,\!_)Ql(6ES3ncn;5.rQtZY;?^XC 4i0(l)'j>I[Te_2\)6C!lB"[es]QK\=CZe o;s'+h#>SoB8f'#'9POSij5QmHglupHdT&+:uATgj]G!Kg%QI"pTBl*D?D$WUbfK!e$ea6* cp>9`I*]!,lEG_n"D5VH!):WNC3TI;Sp2E6LW+aj,6Wl>-DC4FgYC(Q(Aq_MemZ2j8T7CgG JTpuQKW%ZNVX3BaKl4ikDVe0,pP5HH>)%!3mj:s-]ru`: jWGJC55_pjlZVhIfK5(s*:6(H)I'7Md::'SU'+aAmZ,=cO>+1$i1sK/@F7RUg-pU"r/[;l),ndcr8+!Z,l-q< DPLFdE8GJ%sW]^gP$.ShVe:VZKc_0cMB;n+H7cnPT/0lmlFBaAR.)mao6^jH-$"'@4W^Gu/ ;3W.bp?[e:BLt@B;3J()"_bgu5C=qm]9/WToCMKPZ-WH(R2U+W ;/sg@UhXu0.?8'pBrV$>F_-q:BHmU'IM8j#pfW9ek2Pk2geP48r@kX7qB(O]X#'WG,d:m]k I3,:\WmkeVg>.LiAZseRG+3ogkA&dM.N<'^b=*>;BQ3aZ:,aP_bN&2>>jc5hV:"RM3o*!70 eT;:YF:ImpOg6>np()h01VAXkOj(!9L]q+HFWd!5(?q[ht?^BI8qUcG%$kOqum-eE%DS'_, )s+"Mq+ NN`j+<=*_0)oJKMs1oSF^3Z5eiLaV%j>-HT/-R4$-TN2\3td[[Kjb7`U<0$?$JBPK]C*CWlU2*FN1<7O]G1!Q8OS1fiCh8A6IJhT4ZdmSY^)T2SH)+>1Us/@\&79C3lETao$U[F6l;AT#Y!NDO (L[Y#4$lQ/d/Hf<+Rh?WXr8I,C:hrIEe8*W^k#==t27HEONRlWUa-XR!IS]s-iB*l##I>;jU0m9nN9#N`poRK(Wc-`0siYAB)pJom[Vkqc1B`Z6-a>ei 7oh$,HuUFofYfFf(GS`=4m3%QXSS@h61hPG?qt-h"RB>IGjk6+*_]5U=Q>_NFM^N3s]F`nf N0!Q_WgAhQO3LHX=Irka4`qE*A>h@:2D*+"tt3I32hHpAI4*g%^!QO6QK>hjDpmD0LaX3(ZQ3@N00W2L`lOG`#sjQ;78F'ki!NAP]`!@gc^HZL )iYjH]PH&5=cXm+QNBROAZu`89kpoA7U)u+ol&+_#GZjSqSIb7nUqkb!5]44"CVNi">E39Jf#-m?jBO50LN@1):K@2b\<1p"S6 OAYjC8#[dXUpQ/G(Qfsk7Zk2>FLmhYWae]dPr5G'hO2i]D,.(HW"XcACRp?9F_VfIW7;ZZ< (`Br:>+GdPs"`i'AHJ9RHPE]4DZ+'qL7_[?)rb)>E'ePL=!nNXHf=der%^UCLq:`a:r"kOa JcNd)$\gY]Pf>`&H-(?q]&D^fUC:?`YQ)YdP%Z=ITn3log?5<]\5F6$,(Uo'!C1?HcQA2.l 4:S[6mq4V"a2/le15JE==QM3JKM e>H;N">^M^DmUaMN[k26OThmiUaMK#D^iPS,r'.9urZ/n`C(8"`.9K4I][rJA0WWNGY>+>r f