initial import of MPRF 3.0.1.
The MPFR library is a C library for multiple-precision floating-point computations with exact rounding (also called correct rounding). It is based on the GMP multiple-precision library and should replace the MPF class in further releases of GMP. GCC >= 4.2 requires MPFR.
This commit is contained in:
parent
f85f71e378
commit
efee5258bc
|
@ -0,0 +1,19 @@
|
|||
Authors of MPFR (in chronological order of initial contribution):
|
||||
|
||||
Guillaume Hanrot Main author
|
||||
Fabrice Rouillier Original version of mul_ui.c, gmp_op.c
|
||||
Paul Zimmermann Main author
|
||||
Sylvie Boldo Original version of agm.c and log.c
|
||||
Emmanuel Jeandel Original version of exp3.c, const_pi.c, sincos.c
|
||||
Mathieu Dutour asin.c, atan.c and gamma.c
|
||||
Vincent Lefèvre Main author
|
||||
David Daney Hyperbolic and inverse hyperbolic functions, base-2
|
||||
and base-10 exponential and logarithm, factorial
|
||||
Patrick Pélissier Main author
|
||||
Laurent Fousse Original version of sum.c
|
||||
Philippe Théveny Main author
|
||||
Sylvain Chevillard Original version of ai.c
|
||||
|
||||
All authors are included in the MPFR mailing-list <mpfr@loria.fr>.
|
||||
This is the preferred way to contact us. For further information, please
|
||||
look at the MPFR web page <http://www.mpfr.org/>.
|
|
@ -0,0 +1,75 @@
|
|||
Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
##############################################################################
|
||||
|
||||
Probably many bugs.
|
||||
|
||||
Known bugs:
|
||||
|
||||
* The overflow/underflow exceptions may be badly handled in some functions;
|
||||
specially when the intermediary internal results have exponent which
|
||||
exceeds the hardware limit (2^30 for a 32 bits CPU, and 2^62 for a 64 bits
|
||||
CPU) or the exact result is close to an overflow/underflow threshold.
|
||||
|
||||
* Under Linux/x86 with the traditional FPU, some functions do not work
|
||||
if the FPU rounding precision has been changed to single (this is a
|
||||
bad practice and should be useless, but one never knows what other
|
||||
software will do).
|
||||
|
||||
* Some functions do not use MPFR_SAVE_EXPO_* macros, thus do not behave
|
||||
correctly in a reduced exponent range.
|
||||
|
||||
* Function hypot gives incorrect result when on the one hand the difference
|
||||
between parameters' exponents is near 2*MPFR_EMAX_MAX and on the other hand
|
||||
the output precision or the precision of the parameter with greatest
|
||||
absolute value is greater than 2*MPFR_EMAX_MAX-4.
|
||||
|
||||
Potential bugs:
|
||||
|
||||
* Possible incorrect results due to internal underflow, which can lead to
|
||||
a huge loss of accuracy while the error analysis doesn't take that into
|
||||
account. If the underflow occurs at the last function call (just before
|
||||
the MPFR_CAN_ROUND), the result should be correct (or MPFR gets into an
|
||||
infinite loop). TODO: check the code and the error analysis.
|
||||
|
||||
* Possible integer overflows on some machines.
|
||||
|
||||
* Possible bugs with huge precisions (> 2^30).
|
||||
|
||||
* Possible bugs if the chosen exponent range does not allow to represent
|
||||
the range [1/16, 16].
|
||||
|
||||
* Possible infinite loop in some functions for particular cases: when
|
||||
the exact result is an exactly representable number or the middle of
|
||||
consecutive two such numbers. However for non-algebraic functions, it is
|
||||
believed that no such case exists, except the well-known cases like cos(0)=1,
|
||||
exp(0)=1, and so on, and the x^y function when y is an integer or y=1/2^k.
|
||||
|
||||
* The mpfr_set_ld function may be quite slow if the long double type has an
|
||||
exponent of more than 15 bits.
|
||||
|
||||
* mpfr_set_d may give wrong results on some non-IEEE architectures.
|
||||
|
||||
* Error analysis for some functions may be incorrect (out-of-date due
|
||||
to modifications in the code?).
|
||||
|
||||
* Possible use of non-portable feature (pre-C99) of the integer division
|
||||
with negative result.
|
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
<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
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
@ -0,0 +1,165 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
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 that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU 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 as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,389 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<!--
|
||||
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
-->
|
||||
|
||||
<!--
|
||||
Do not modify directly! Regenerate this file with:
|
||||
xsltproc -\-nodtdattr faq-web.xsl faq.xhtml
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
|
||||
<head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<title>Frequently Asked Questions about GNU MPFR</title>
|
||||
<style type="text/css">/*<![CDATA[*/
|
||||
/* Global stylesheet for visual media */
|
||||
|
||||
html, body
|
||||
{
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
div.logo { float: right }
|
||||
div.logo img { border: 0 }
|
||||
|
||||
div.footer img { border: 0 }
|
||||
|
||||
dt
|
||||
{
|
||||
margin-top: 2ex;
|
||||
margin-bottom: 1ex;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/* For testing: dd { background: #ddddff } */
|
||||
|
||||
table { margin: 0.5ex auto }
|
||||
|
||||
li { margin-top: 0.5ex; margin-bottom: 0.5ex }
|
||||
|
||||
dd + dd
|
||||
{
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
padding-top: 0.5ex;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
li > p, dd > p
|
||||
{
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
padding-top: 0.5ex;
|
||||
padding-bottom: 0.5ex;
|
||||
}
|
||||
|
||||
.block-code code, code.block-code,
|
||||
.block-code samp, samp.block-code
|
||||
{
|
||||
display: block;
|
||||
padding: 0.5ex 0;
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
.nowrap { white-space: nowrap }
|
||||
|
||||
/*
|
||||
dl.faq { counter-reset: faq }
|
||||
|
||||
dl.faq dt:before
|
||||
{
|
||||
counter-increment: faq;
|
||||
content: counter(faq) ". ";
|
||||
}
|
||||
*/
|
||||
|
||||
dl.faq dt { background: #dddddd }
|
||||
|
||||
dl.faq dd
|
||||
{
|
||||
border-left: 4px solid;
|
||||
border-color: transparent;
|
||||
margin-left: 0em;
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
|
||||
dl.faq dt:target + dd
|
||||
{
|
||||
border-left-color: #aaaaaa;
|
||||
}
|
||||
|
||||
var.env { font-style: normal }
|
||||
/*]]>*/</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Frequently Asked Questions about <cite><acronym>GNU</acronym> <acronym>MPFR</acronym></cite></h1>
|
||||
|
||||
<p><strong>Important notice: Problems with a particular version of
|
||||
<cite><acronym>MPFR</acronym></cite> are discussed in the corresponding
|
||||
bugs page.</strong></p>
|
||||
|
||||
<p>The latest version of this <acronym>FAQ</acronym> is available at
|
||||
<a href="http://www.mpfr.org/faq.html">http://www.mpfr.org/faq.html</a>.
|
||||
Please look at this version if possible.</p>
|
||||
|
||||
<ol>
|
||||
<li><a href="#mpfr_vs_mpf">What are the differences between
|
||||
<cite><acronym>MPF</acronym></cite> from <cite><acronym>GMP</acronym></cite>
|
||||
and <cite><acronym>MPFR</acronym></cite>?</a></li>
|
||||
<li><a href="#mpf2mpfr">How to convert my program written using
|
||||
<cite><acronym>MPF</acronym></cite> to
|
||||
<cite><acronym>MPFR</acronym></cite>?</a></li>
|
||||
<li><a href="#no_libgmp">At configure time, I get the error: <q>libgmp not found or uses a different ABI.</q></a></li>
|
||||
<li><a href="#undef_ref1">I get undefined reference to <code>__gmp_get_memory_functions</code>.</a></li>
|
||||
<li><a href="#undef_ref2">When I link my program with
|
||||
<cite><acronym>MPFR</acronym></cite>, I get undefined reference
|
||||
to <code>__gmpXXXX</code>.</a></li>
|
||||
<li><a href="#crash_high_prec">My program crashes with high precisions.</a></li>
|
||||
<li><a href="#accuracy">Though I have increased the precision, the results
|
||||
are not more accurate.</a></li>
|
||||
<li><a href="#detect_mpfr">How can I detect <cite><acronym>MPFR</acronym></cite>
|
||||
installation using <cite>autoconf</cite> or <cite>pkg-config</cite>?</a></li>
|
||||
<li><a href="#cite">How to cite <cite><acronym>MPFR</acronym></cite> in a
|
||||
scientific publication?</a></li>
|
||||
<li><a href="#fpic">When I build <cite><acronym>MPFR</acronym></cite>, I get
|
||||
an error asking me to recompile with <samp>-fPIC</samp>.</a></li>
|
||||
</ol>
|
||||
|
||||
<dl class="faq">
|
||||
|
||||
<dt id="mpfr_vs_mpf">1. What are the differences between
|
||||
<cite><acronym>MPF</acronym></cite> from <cite><acronym>GMP</acronym></cite>
|
||||
and <cite><acronym>MPFR</acronym></cite>?</dt>
|
||||
|
||||
<dd><p>The main differences are:</p>
|
||||
<ul>
|
||||
<li><p>The precision of a <cite><acronym>MPFR</acronym></cite> variable
|
||||
is the <em>exact</em> number of bits used for its mantissa, whereas in
|
||||
<cite><acronym>MPF</acronym></cite>, the precision requested by the user
|
||||
is a minimum value (<cite><acronym>MPF</acronym></cite> generally uses a
|
||||
higher precision). With the additional difference below, this implies that
|
||||
the <cite><acronym>MPFR</acronym></cite> results do not depend on the
|
||||
number of bits (16, 32, 64 or more) of the underlying architecture.</p></li>
|
||||
<li><p>As a consequence, <cite><acronym>MPFR</acronym></cite> uses a
|
||||
base-2 exponent, whereas in <cite><acronym>MPF</acronym></cite>, this
|
||||
is a base-2<sup>32</sup> or base-2<sup>64</sup> exponent, depending on
|
||||
the limb size. For this reason (and other internal ones), the maximum
|
||||
exponent range in <cite><acronym>MPFR</acronym></cite> is different
|
||||
(and smaller, if the exponent is represented by the same type as in
|
||||
<cite><acronym>MPF</acronym></cite>).</p></li>
|
||||
<li><p><cite><acronym>MPFR</acronym></cite> provides an additional rounding
|
||||
mode argument to its functions; furthermore, it is guaranteed that the
|
||||
result of any operation is the nearest possible floating-point value from
|
||||
the exact result (considering the input variables as exact values), taking
|
||||
into account the precision of the destination variable and the rounding
|
||||
mode. <cite><acronym>MPFR</acronym></cite> also says whether the rounded
|
||||
result is above or below the exact result.</p></li>
|
||||
<li><p><cite><acronym>MPFR</acronym></cite> supports much more functions
|
||||
(in particular transcendental functions such as exponentials, logarithms,
|
||||
trigonometric functions and so on) and special values: signed zeros,
|
||||
infinities, not-a-number (NaN).</p></li>
|
||||
</ul></dd>
|
||||
|
||||
<dt id="mpf2mpfr">2. How to convert my program written using
|
||||
<cite><acronym>MPF</acronym></cite> to
|
||||
<cite><acronym>MPFR</acronym></cite>?</dt>
|
||||
|
||||
<dd><p>You need to add <q><code>r</code></q> to the function names, and to
|
||||
specify the rounding mode (<code>MPFR_RNDN</code> for rounding to nearest,
|
||||
<code>MPFR_RNDZ</code> for rounding towards zero, <code>MPFR_RNDU</code>
|
||||
for rounding towards plus infinity, <code>MPFR_RNDD</code> for rounding
|
||||
towards minus infinity). You can also define macros as follows:
|
||||
<code class="block-code">#define mpf_add(a, b, c) mpfr_add(a, b, c, MPFR_RNDN)</code></p>
|
||||
<p>The header file <samp>mpf2mpfr.h</samp> from the
|
||||
<cite><acronym>MPFR</acronym></cite> distribution automatically
|
||||
redefines all <cite><acronym>MPF</acronym></cite> functions in this
|
||||
way, using the default <cite><acronym>MPFR</acronym></cite> rounding
|
||||
mode. Thus you simply need to add the following line in all your files
|
||||
using <cite><acronym>MPF</acronym></cite> functions:
|
||||
<code class="block-code">#include <mpf2mpfr.h></code>
|
||||
just after the <samp>gmp.h</samp> and <samp>mpfr.h</samp>
|
||||
header files. If the program uses <cite><acronym>MPF</acronym></cite>
|
||||
internals (such as direct access to <code>__mpf_struct</code> members),
|
||||
additional changes will be needed.</p></dd>
|
||||
|
||||
<dt id="no_libgmp">3. At configure time, I get the error: <q>libgmp not found or uses a different ABI.</q></dt>
|
||||
|
||||
<dd><p>This test (<samp>checking for __gmpz_init in -lgmp</samp>) comes
|
||||
after the <samp>gmp.h</samp> detection. The failure occurs either because
|
||||
the <cite><acronym>GMP</acronym></cite> library could not be found
|
||||
(as it is not in the provided library search paths) or because the
|
||||
<cite><acronym>GMP</acronym></cite> library that was found does not have
|
||||
the expected <acronym title="Application Binary Interface">ABI</acronym>
|
||||
(<abbr>e.g.</abbr> 32-bit <abbr>vs</abbr> 64-bit). The latter problem can
|
||||
have several causes:</p>
|
||||
<ul>
|
||||
<li>A wrong libgmp library has been picked up. This can occur if you have
|
||||
several <cite><acronym>GMP</acronym></cite> versions installed on the
|
||||
machine and something is wrong with the provided library search paths.</li>
|
||||
<li>Wrong compiler options (<samp>CFLAGS</samp>) were given. In general, the
|
||||
presence or absence of the <samp>-m64</samp> compiler option must match the
|
||||
library <acronym title="Application Binary Interface">ABI</acronym>.</li>
|
||||
<li>A wrong <samp>gmp.h</samp> file has been picked up (if you have several
|
||||
<cite><acronym>GMP</acronym></cite> versions installed). Indeed, by default,
|
||||
<cite><acronym>MPFR</acronym></cite> gets the compiler options from the
|
||||
<samp>gmp.h</samp> file (with <cite><acronym>GMP</acronym></cite> 4.2.3
|
||||
or later); this is needed because <cite><acronym>GMP</acronym></cite> does
|
||||
not necessarily use the default <acronym>ABI</acronym>. The consequence is
|
||||
that if the <samp>gmp.h</samp> file is associated with a library using a
|
||||
different <acronym>ABI</acronym>, the <acronym>ABI</acronym>-related options
|
||||
will be incorrect. Hence the failure.</li>
|
||||
</ul>
|
||||
<p>Note: The <samp>config.log</samp> output gives more information
|
||||
than the error message. In particular, see the output of the test:
|
||||
<samp>checking for CC and CFLAGS in gmp.h</samp>; it should give you
|
||||
the default compiler options (from <samp>gmp.h</samp>).</p>
|
||||
|
||||
<p>See also the answer to the <a href="#undef_ref1">next question</a>.</p></dd>
|
||||
|
||||
<dt id="undef_ref1">4. I get undefined reference to <code>__gmp_get_memory_functions</code>.</dt>
|
||||
|
||||
<dd><p>Note: this was mainly a problem when upgrading from
|
||||
<cite><acronym>GMP</acronym></cite> 4.1.4 to a later version,
|
||||
but information given below may still be useful in other cases,
|
||||
when several <cite><acronym>GMP</acronym></cite> libraries are
|
||||
installed on the same machine.</p>
|
||||
|
||||
<p>If you get such an error, in particular when running
|
||||
<samp>make check</samp>, then this probably means that you are using
|
||||
the header file from <cite><acronym>GMP</acronym></cite> 4.2.x but the
|
||||
<cite><acronym>GMP</acronym></cite> 4.1.4 library. This can happen if
|
||||
several <cite><acronym>GMP</acronym></cite> versions are installed on
|
||||
your machine (<abbr>e.g.</abbr>, one provided by the system in
|
||||
<samp>/usr/{include,lib}</samp> and a new one installed by the owner or
|
||||
administrator of the machine in <samp>/usr/local/{include,lib}</samp>)
|
||||
and your include and library search paths are inconsistent. On various
|
||||
<acronym>GNU</acronym>/Linux machines, this is unfortunately the case
|
||||
by default (<samp>/usr/local/include</samp> is in the default include
|
||||
search path, but <samp>/usr/local/lib</samp> is <em>not</em> in the
|
||||
default library search path). Typical errors are:
|
||||
<samp class="block-code">undefined reference to `__gmp_get_memory_functions'</samp>
|
||||
in <samp>make check</samp>. The best solution is to add
|
||||
<samp>/usr/local/include</samp> to your <var class="env">C_INCLUDE_PATH</var>
|
||||
environment variable and to add <samp>/usr/local/lib</samp> to your
|
||||
<var class="env">LIBRARY_PATH</var> and <var class="env">LD_LIBRARY_PATH</var>
|
||||
environment variables (and/or <var class="env">LD_RUN_PATH</var>).
|
||||
Alternatively, you can use <samp>--with-gmp*</samp> configure options,
|
||||
<abbr>e.g.</abbr> <samp>--with-gmp=/usr/local</samp>, but <strong>this is
|
||||
not guaranteed to work</strong> (in particular with <samp>gcc</samp> and
|
||||
system directories such as <samp>/usr</samp> or <samp>/usr/local</samp>),
|
||||
and other software that uses <cite><acronym>GMP</acronym></cite> and/or
|
||||
<cite><acronym>MPFR</acronym></cite> will need correct paths too;
|
||||
environment variables allow you to set them in a global way.</p>
|
||||
<p>Other information can be given in the <samp>INSTALL</samp> file and
|
||||
<samp>ld</samp> manual. Please look at them for more details. See also
|
||||
the <a href="#undef_ref2">next question</a>.</p></dd>
|
||||
|
||||
<dt id="undef_ref2">5. When I link my program with
|
||||
<cite><acronym>MPFR</acronym></cite>, I get undefined reference
|
||||
to <code>__gmpXXXX</code>.</dt>
|
||||
|
||||
<dd><p>Link your program with <cite><acronym>GMP</acronym></cite>. Assuming
|
||||
that your program is <samp>foo.c</samp>, you should link it using:
|
||||
<samp class="block-code">cc link.c -lmpfr -lgmp</samp>
|
||||
<cite><acronym>MPFR</acronym></cite> library reference (<samp>-lmpfr</samp>)
|
||||
should be before <cite><acronym>GMP</acronym></cite>'s one
|
||||
(<samp>-lgmp</samp>). Another solution is, with <acronym>GNU</acronym>
|
||||
<samp>ld</samp>, to give all the libraries inside a group:
|
||||
<samp class="block-code">gcc link.c -Wl,--start-group libgmp.a libmpfr.a -Wl,--end-group</samp>
|
||||
See <samp>INSTALL</samp> file and <samp>ld</samp> manual for more
|
||||
details.</p>
|
||||
<p>If you used correct link options, but still get an error, this may mean
|
||||
that your include and library search paths are inconsistent. Please see the
|
||||
<a href="#undef_ref1">previous question</a>.</p></dd>
|
||||
|
||||
<dt id="crash_high_prec">6. My program crashes with high precisions.</dt>
|
||||
|
||||
<dd><p>Your stack size limit may be too small; indeed, by default,
|
||||
<cite><acronym>GMP</acronym></cite> 4.1.4 and below allocates all
|
||||
temporary results on the stack, and in very high precisions, this
|
||||
limit may be reached. You can solve this problem in different ways:</p>
|
||||
<ul>
|
||||
<li><p>You can upgrade to <cite><acronym>GMP</acronym></cite> 4.2 (or above),
|
||||
which now makes temporary allocations on the stack only when they are
|
||||
small.</p></li>
|
||||
<li><p>You can increase the stack size limit with the <samp>limit</samp>,
|
||||
<samp>unlimit</samp> or <samp>ulimit</samp> command, depending on your
|
||||
shell. This may fail on some systems, where the maximum stack size cannot
|
||||
be increased above some value.</p></li>
|
||||
<li><p>You can rebuild both <cite><acronym>GMP</acronym></cite> and
|
||||
<cite><acronym>MPFR</acronym></cite> to use another allocation method.</p></li>
|
||||
</ul></dd>
|
||||
|
||||
<dt id="accuracy">7. Though I have increased the precision, the results
|
||||
are not more accurate.</dt>
|
||||
|
||||
<dd><p>The reason may be the use of C floating-point numbers. If you want
|
||||
to store a floating-point constant to a <code>mpfr_t</code>, you should use
|
||||
<code>mpfr_set_str</code> (or one of the <cite><acronym>MPFR</acronym></cite>
|
||||
constant functions, such as <code>mpfr_const_pi</code> for π) instead
|
||||
of <code>mpfr_set_d</code> or <code>mpfr_set_ld</code>. Otherwise the
|
||||
floating-point constant will be first converted into a reduced-precision
|
||||
(<abbr>e.g.</abbr>, 53-bit) binary number before
|
||||
<cite><acronym>MPFR</acronym></cite> can work with it. This is the case
|
||||
in particular for most exact decimal numbers, such as 0.17, which are
|
||||
not exactly representable in binary.</p>
|
||||
<p>Also remember that <cite><acronym>MPFR</acronym></cite> does not track
|
||||
the accuracy of the results: copying a value <var>x</var> to <var>y</var>
|
||||
with <code>mpfr_set (y, x, MPFR_RNDN)</code> where the variable <var>y</var>
|
||||
is more precise than the variable <var>x</var> will not make it more
|
||||
accurate; the (binary) value will remain unchanged.</p></dd>
|
||||
|
||||
<dt id="detect_mpfr">8. How can I detect <cite><acronym>MPFR</acronym></cite>
|
||||
installation using <cite>autoconf</cite> or <cite>pkg-config</cite>?</dt>
|
||||
|
||||
<dd><p>The <cite><acronym>MPFR</acronym></cite> team does not currently
|
||||
recommend any <cite>autoconf</cite> code, but a section will later
|
||||
be added to the <cite><acronym>MPFR</acronym></cite> manual. The
|
||||
<cite><acronym>MPFR</acronym></cite> team does not wish to support
|
||||
<cite>pkg-config</cite> yet.</p></dd>
|
||||
|
||||
<dt id="cite">9. How to cite <cite><acronym>MPFR</acronym></cite> in a
|
||||
scientific publication?</dt>
|
||||
|
||||
<dd><p>To properly cite <cite><acronym>MPFR</acronym></cite> in a scientific
|
||||
publication, please cite the
|
||||
<a href="http://doi.acm.org/10.1145/1236463.1236468"><acronym title="Association for Computing Machinery">ACM</acronym>
|
||||
<acronym title="Transactions on Mathematical Software">TOMS</acronym>
|
||||
paper</a>
|
||||
(<a href="http://toms.acm.org/cgi/TOMSbibget.cgi?Fousse:2007:MMP">BibTeX</a>)
|
||||
and/or the library web page
|
||||
<a href="http://www.mpfr.org/">http://www.mpfr.org</a>. If your publication
|
||||
is related to a particular release of <cite><acronym>MPFR</acronym></cite>,
|
||||
for example if you report timings, please also indicate the release number
|
||||
for future reference.</p></dd>
|
||||
|
||||
<dt id="fpic">10. When I build <cite><acronym>MPFR</acronym></cite>, I get
|
||||
an error asking me to recompile with <samp>-fPIC</samp>.</dt>
|
||||
|
||||
<dd><p>A typical error looks like:</p>
|
||||
<p><tt>/usr/bin/ld: <em>/path/to/</em>libgmp.a(realloc.o): relocation
|
||||
R_X86_64_32 against `.rodata.str1.1' can not be used when making a
|
||||
shared object; recompile with -fPIC<br />
|
||||
<em>/path/to/</em>libgmp.a: could not read symbols: Bad value<br />
|
||||
collect2: ld returned 1 exit status</tt></p>
|
||||
<p>The probable reason is that you tried to build
|
||||
<cite><acronym>MPFR</acronym></cite> with the shared library enabled (this
|
||||
is the default), while only a static <cite><acronym>GMP</acronym></cite>
|
||||
library could be found. To solve this problem, either rebuild and reinstall
|
||||
<cite><acronym>GMP</acronym></cite> without the <samp>--disable-shared</samp>
|
||||
configure option, or configure <cite><acronym>MPFR</acronym></cite> with
|
||||
<samp>--disable-shared</samp>. If you did this and still get the above
|
||||
error, the cause may be conflicting <cite><acronym>GMP</acronym></cite>
|
||||
versions installed on your system; please check that your search path
|
||||
settings are correct.</p>
|
||||
<p>Additional note about the last sentence: Under <acronym>GNU</acronym>/Linux
|
||||
(for instance), the linker takes the first library found in the library search
|
||||
path, whether it is dynamic or static. The default behavior under darwin is
|
||||
different, but <cite><acronym>MPFR</acronym></cite> will change it.</p></dd>
|
||||
<!-- Reference concerning darwin: see MPFR_LD_SEARCH_PATHS_FIRST
|
||||
in MPFR's configure.{ac,in} and acinclude.m4 -->
|
||||
|
||||
</dl>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,422 @@
|
|||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
|
||||
Installing GNU MPFR
|
||||
===================
|
||||
|
||||
Note: In case of problem, please read this INSTALL file carefully before
|
||||
reporting a bug, in particular Section "In case of problem" below. Some
|
||||
problems are due to bad configuration on the user side (not specific to
|
||||
MPFR).
|
||||
|
||||
0. You first need to install GMP. See <http://www.gnu.org/software/gmp/>.
|
||||
MPFR requires GMP version 4.1 or later.
|
||||
|
||||
1. Extract the files from the archive.
|
||||
|
||||
2. It is strongly advised to apply the latest patches (if this has
|
||||
not been done yet), e.g.
|
||||
wget http://www.mpfr.org/mpfr-3.0.1/allpatches
|
||||
patch -N -Z -p1 < allpatches
|
||||
or
|
||||
curl http://www.mpfr.org/mpfr-3.0.1/allpatches | patch -N -Z -p1
|
||||
|
||||
(Those instructions are for the GNU patch command, for example
|
||||
/usr/bin/gpatch on Solaris.)
|
||||
|
||||
3. In the MPFR directory, to detect your system, type:
|
||||
./configure
|
||||
possibly with options (see below, in particular if this step or
|
||||
one of the following fails).
|
||||
Note: paths provided in configure options must always be absolute
|
||||
(relative paths are not supported).
|
||||
|
||||
4. To build the library, type:
|
||||
make
|
||||
|
||||
[optional] if you want to tune MPFR for your specific architecture, see
|
||||
the section "Tuning MPFR" below. Note that for most common architectures,
|
||||
MPFR includes some default tuning parameters which should be near from
|
||||
optimal.
|
||||
|
||||
5. To check the built library (runs the test files), type:
|
||||
make check
|
||||
|
||||
6. To install it (default "/usr/local" | see "--prefix" option), type:
|
||||
make install
|
||||
|
||||
If you installed MPFR (header and library) in directories that are
|
||||
not searched by default by the compiler and/or linking tools, then,
|
||||
like with other libraries, you may need to set up some environment
|
||||
variables such as C_INCLUDE_PATH (to find the header mpfr.h),
|
||||
LIBRARY_PATH (to find the library), and if the shared library has
|
||||
been installed, LD_LIBRARY_PATH (before execution) or LD_RUN_PATH
|
||||
(before linking); this list is not exhaustive and some environment
|
||||
variables may be specific to your system. "make install" gives some
|
||||
instructions; please read them. You can also find more information
|
||||
in the manuals of your compiler and linker. The MPFR FAQ may also
|
||||
give some information.
|
||||
|
||||
Remember that if you have several MPFR (or GMP) versions installed
|
||||
(e.g., one with the system, and one, newer, by you), you will not
|
||||
necessarily get a compilation/linking error if a wrong library is
|
||||
used (e.g., because LD_LIBRARY_PATH has not been set correctly).
|
||||
But unexpected results may occur.
|
||||
|
||||
Under Mac OS X, if the shared library was not installed and you use
|
||||
Apple's linker (this is the default), you will also need to provide
|
||||
the -search_paths_first linker flag ("-Wl,-search_paths_first" when
|
||||
you link via gcc) to make sure that the right library is selected,
|
||||
as by default, Apple's linker selects a shared library preferably,
|
||||
even when it is farther in the library paths. We recall that if a
|
||||
wrong library is selected due to this behavior, unexpected results
|
||||
may occur.
|
||||
|
||||
|
||||
Building the documentation
|
||||
==========================
|
||||
|
||||
To build the documentation in various formats, you may first need to
|
||||
install recent versions of some utilities such as texinfo.
|
||||
|
||||
* Type "make info" to produce the documentation in the info format.
|
||||
|
||||
* Type "make pdf" to produce the documentation in the PDF format.
|
||||
|
||||
* Type "make dvi" to produce the documentation in the DVI format.
|
||||
|
||||
* Type "make ps" to produce the documentation in the Postscript format.
|
||||
|
||||
* Type "make html" to produce the documentation in the HTML format
|
||||
(in several pages); if you want only one output HTML file, then
|
||||
type "makeinfo --html --no-split mpfr.texi" instead.
|
||||
|
||||
|
||||
Building MPFR with internal GMP header files
|
||||
============================================
|
||||
|
||||
MPFR built with internal GMP header files is a bit faster, so you may want
|
||||
to build it with them. Just do this in step 1:
|
||||
|
||||
./configure --with-gmp-build=GMPBUILD
|
||||
|
||||
where GMPBUILD is the GMP build directory. The needed header files are:
|
||||
gmp-impl.h, longlong.h and all the necessary headers to use them.
|
||||
|
||||
As gmp-impl.h and longlong.h are only in the GMP source directory,
|
||||
you first need to copy these files to the build directory if it is
|
||||
different (there may be other workarounds, such as setting $CPPFLAGS
|
||||
to search the GMP source directory).
|
||||
|
||||
Warning: the library obtained in this way may use some internal GMP
|
||||
symbols, and thus dynamically linking your software with a different
|
||||
version of GMP might fail, even though it is declared as compatible
|
||||
by Libtool's versioning system.
|
||||
|
||||
|
||||
Tuning MPFR
|
||||
===========
|
||||
|
||||
For this, you need to build MPFR with a GMP build directory (see above).
|
||||
In the GMP build directory, you also need to go into the "tune" subdirectory
|
||||
and type "make speed". This will build the GMP speed library, which is used
|
||||
by the MPFR tuning mechanism.
|
||||
|
||||
Then go back to the MPFR build directory, and type "make tune". This will
|
||||
build an optimized file "mparam.h" for your specific architecture.
|
||||
|
||||
|
||||
./configure options
|
||||
===================
|
||||
|
||||
--prefix=DIR installs MPFR headers and library in DIR/include and
|
||||
DIR/lib respectively (the default is "/usr/local").
|
||||
|
||||
--with-gmp-include=DIR assumes that DIR contains gmp.h
|
||||
--with-gmp-lib=DIR assumes that DIR contains the GMP library
|
||||
--with-gmp=DIR assumes that DIR is where you have installed GMP.
|
||||
same as --with-gmp-lib=DIR/lib
|
||||
and --with-gmp-include=DIR/include
|
||||
(use either --with-gmp alone or one or both of
|
||||
--with-gmp-lib/--with-gmp-include)
|
||||
Warning! Do not use these options if you have
|
||||
CPPFLAGS and/or LDFLAGS containing a -I or -L
|
||||
option with a directory that contains a GMP
|
||||
header or library file, as these options just
|
||||
add -I and -L options to CPPFLAGS and LDFLAGS
|
||||
*after* the ones that are currently declared,
|
||||
so that DIR will have a lower precedence. Also,
|
||||
this may not work if DIR is a system directory.
|
||||
|
||||
--with-gmp-build=DIR assumes that DIR contains the GMP build directory,
|
||||
and enables the use of GMP internals (see above).
|
||||
Warning! This option and the group of options
|
||||
--with-gmp are mutually exclusive.
|
||||
|
||||
--enable-assert build MPFR with assertions.
|
||||
|
||||
--enable-thread-safe build MPFR as thread safe, using compiler-level
|
||||
Thread Local Storage (TLS). Note: TLS support is
|
||||
roughly tested by configure. If configure detects
|
||||
that TLS does not work (because of the compiler,
|
||||
linker or system libraries), it will output an
|
||||
error message, telling you to build MPFR without
|
||||
thread safe. For instance, though Mac OS X uses
|
||||
GCC, it may not currently support GCC's __thread
|
||||
storage class.
|
||||
|
||||
Note: By default, the configure script tries to set CC/CFLAGS to GMP's
|
||||
ones (this feature needs GMP 4.3.0 or later, or the --with-gmp-build
|
||||
option). However this is not guaranteed to work as the configure script
|
||||
does some compiler tests earlier, and the change may be too late. Also,
|
||||
the values obtained from GMP may be incorrect if GMP has been built
|
||||
on a different machine. In such a case, the user may need to specify
|
||||
CC/CFLAGS as explained below.
|
||||
|
||||
Run "./configure --help" to see the other options (autoconf default options).
|
||||
|
||||
|
||||
In case of problem
|
||||
==================
|
||||
|
||||
First, look for any warning message in the configure output.
|
||||
|
||||
Several documents may help you to solve the problem:
|
||||
* this INSTALL file, in particular information given below;
|
||||
* the FAQ (either the FAQ.html file distributed with MPFR, or the
|
||||
on-line version <http://www.mpfr.org/faq.html>, which may be more
|
||||
up-to-date);
|
||||
* the MPFR web page for this version <http://www.mpfr.org/mpfr-3.0.1/>,
|
||||
which lists bugs found in this version and provides some patches.
|
||||
|
||||
If the "configure" fails, please check that the C compiler and its
|
||||
options are the same as those for the GMP build (specially the ABI).
|
||||
You can see the latter with the following command:
|
||||
|
||||
grep "^CC\|^CFLAGS" GMPBUILD/Makefile
|
||||
|
||||
if the GMP build directory is available. Then type:
|
||||
|
||||
./configure <configure options> CC=<C compiler> CFLAGS="<compiler options>"
|
||||
|
||||
(quotes are needed when there are spaces or other special characters
|
||||
in the CC/CFLAGS value) and continue the install. On some platforms,
|
||||
you should provide further options to match those used by GMP, or set
|
||||
some environment variables. For instance, see the "Notes on AIX/PowerPC"
|
||||
section below.
|
||||
|
||||
Warning! Do NOT use optimization options that can change the semantics
|
||||
of math operations, such as GCC's -ffast-math or Sun CC's -fast.
|
||||
Otherwise conversions from/to double's may be incorrect on infinities,
|
||||
NaN's and signed zeros. Since native FP arithmetic is used in a few
|
||||
places only, such options would not make MPFR faster anyway.
|
||||
|
||||
On some platforms, try with "gmake" (GNU make) instead of "make".
|
||||
Problems have been reported with the Tru64 make.
|
||||
|
||||
If the configure script reports that gmp.h version and libgmp version
|
||||
are different, or if the build was OK, but the tests failed to link
|
||||
with GMP or gave an error like
|
||||
|
||||
undefined reference to `__gmp_get_memory_functions'
|
||||
|
||||
meaning that the GMP library was not found or a wrong GMP library was
|
||||
selected by the linker, then your library search paths are probably
|
||||
not correctly set (some paths are missing or they are specified in an
|
||||
incorrect order).
|
||||
|
||||
Such problems commonly occur under some GNU/Linux machines, where the
|
||||
default header and library search paths may be inconsistent: GCC is
|
||||
configured to search /usr/local/include and /usr/local/lib by default,
|
||||
while the dynamic linker ignores /usr/local/lib. If you have a GMP
|
||||
version installed in /usr (provided by the OS vendor) and a new one
|
||||
installed in /usr/local, then the header of the new GMP version and
|
||||
the library of the old GMP version will be used! The best solution
|
||||
is to make sure that the dynamic linker configuration is consistent
|
||||
with GCC's behavior, for instance by having /usr/local/lib in
|
||||
/etc/ld.so.conf or in some file from /etc/ld.so.conf.d (as Debian
|
||||
did: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=395177). See
|
||||
also http://gcc.gnu.org/ml/gcc-help/2010-01/msg00171.html for more
|
||||
information. Alternatively you can use:
|
||||
* environment variables. This may sometimes be necessary. If DIR
|
||||
is the installation directory of GMP, add DIR/include to your
|
||||
CPATH or C_INCLUDE_PATH (for compilers other than GCC, please
|
||||
check the manual of your compiler), and add DIR/lib to your
|
||||
LIBRARY_PATH and LD_LIBRARY_PATH (and/or LD_RUN_PATH);
|
||||
* --with-gmp* configure options (described above), e.g.
|
||||
--with-gmp=/opt/local (to use /opt/local/include for headers and
|
||||
/opt/local/lib for libraries), but other software that uses GMP
|
||||
and/or MPFR will need correct paths too, and environment variables
|
||||
allow one to set such search paths in a global way.
|
||||
Note about "--with-gmp=/usr/local". This option may appear to
|
||||
solve the above inconsistency problem, but does not work as you
|
||||
expect. Indeed it affects the library search path, in particular,
|
||||
the one used by the dynamic linker (thus adding the missing
|
||||
/usr/local/lib directory as wanted), but since /usr/local/include
|
||||
is a "standard system include directory" for GCC, the include
|
||||
search patch is not changed; this is often not a problem in this
|
||||
particular case because usually, /usr/local/include is already
|
||||
last in the include search patch, but this may fail under some
|
||||
occasions and may trigger obscure errors.
|
||||
|
||||
For instance, under Unix, where paths are separated by a colon:
|
||||
|
||||
* With POSIX sh-compatible shells (e.g. sh, ksh, bash, zsh):
|
||||
export C_INCLUDE_PATH="/usr/local/include:/other/path/include"
|
||||
export LIBRARY_PATH="/usr/local/lib:/other/path/lib"
|
||||
export LD_LIBRARY_PATH="$LIBRARY_PATH"
|
||||
|
||||
* With csh or tcsh:
|
||||
setenv C_INCLUDE_PATH "/usr/local/include:/other/path/include"
|
||||
setenv LIBRARY_PATH "/usr/local/lib:/other/path/lib"
|
||||
setenv LD_LIBRARY_PATH "$LIBRARY_PATH"
|
||||
|
||||
If you can't solve your problem, you should contact us at <mpfr@loria.fr>,
|
||||
indicating the machine and operating system used (uname -a), the compiler
|
||||
and version used (gcc -v if you use gcc), the configure options used if
|
||||
any (including variables such as CC and CFLAGS), the version of GMP and
|
||||
MPFR used, and a description of the problem encountered. Please send us
|
||||
also the log of the "configure" (config.log).
|
||||
|
||||
Note that even if you can build MPFR with a C++ compiler, you can't run
|
||||
the test suite: C and C++ are not the same language! You should use a C
|
||||
compiler instead.
|
||||
|
||||
|
||||
Notes on Mac OS X
|
||||
=================
|
||||
|
||||
If you get an error of the form
|
||||
|
||||
ld: pointer in read-only segment not allowed in slidable image...
|
||||
|
||||
this can mean that the link is done against a static (GMP) library.
|
||||
In such a case, you should configure MPFR with --disable-shared to
|
||||
disable the build of the shared library.
|
||||
|
||||
|
||||
Notes on FreeBSD 4.3
|
||||
====================
|
||||
|
||||
FreeBSD 4.3 is provided with an incorrect <float.h> header file, and
|
||||
MPFR tests related to long double's may fail. If you cannot upgrade
|
||||
the system, you can still use MPFR with FreeBSD 4.3, but you should
|
||||
not use conversions with the long double type.
|
||||
|
||||
|
||||
Notes on AIX/PowerPC
|
||||
====================
|
||||
|
||||
The following has been tested on AIX 5.3 (powerpc-ibm-aix5.3.0.0) with
|
||||
gcc 3.3.2 and GMP 4.2.1.
|
||||
|
||||
If GMP was built with the 64-bit ABI, before building and testing MPFR,
|
||||
you should set the OBJECT_MODE environment variable to 64, e.g., with:
|
||||
|
||||
export OBJECT_MODE=64
|
||||
|
||||
(in a sh-compatible shell). But you should also provide a correct CFLAGS
|
||||
value to the "configure" script: using --with-gmp-build is not sufficient
|
||||
due to the early compiler tests, as gcc will not compile any program if
|
||||
OBJECT_MODE is 64 and the -maix64 option is not provided.
|
||||
|
||||
|
||||
Notes on 32-bit Windows Applications (win32)
|
||||
============================================
|
||||
|
||||
1 - We advise to use MinGW (http://www.mingw.org/), which is simpler and
|
||||
less demanding than Cygwin. Contrary to Cygwin, it also provides native
|
||||
Windows code. The binaries compiled with Cygwin require a dynamic
|
||||
library (cygwin.dll) to work; there is a Cygwin option -mno-cygwin to
|
||||
build native code, but it may require some non-portable tricks.
|
||||
|
||||
2 - If you just want to make a binary with gcc, there is nothing to do:
|
||||
GMP, MPFR and the program compile exactly as under Linux.
|
||||
But if you want to generate a library for MinGW from a Cygwin
|
||||
environment, you may need the -mno-cygwin gcc option (otherwise
|
||||
a typical error is _P_WAIT being undeclared).
|
||||
|
||||
3 - If you want to make libraries to work under another Windows compiler
|
||||
like Visual C / C++, you have two options. Since the unix-like *.a
|
||||
library files are compatible with Windows *.lib files, you can simply
|
||||
rename all *.a libraries to *.lib. The second option is to build
|
||||
MPFR with the Microsoft Visual Studio compiler to produce Windows
|
||||
libraries directly (Visual Studio build projects for MPFR are
|
||||
available at http://fp.gladman.plus.com/computing/gmp4win.htm).
|
||||
|
||||
With gmp-4.1.3, the only remaining problem seems to be the "alloca" calls
|
||||
in GMP. Configuring GMP and MPFR with --enable-alloca=malloc-reentrant
|
||||
should work (if you build MPFR with GMP internal files).
|
||||
|
||||
Or you could add the library
|
||||
"$MINGWIN$/lib/gcc-lib/mingw32/$VERSION$/libgcc.a"
|
||||
to your project: it contains all the extra-functions needed by a program
|
||||
compiled by gcc (division of 64-bit integer, bcopy, alloca...).
|
||||
Of course, include it if and only if your compiler is not gcc.
|
||||
|
||||
4 - On Windows32 / MinGW, if all the tests fail, try to run the test suite
|
||||
with "make check EXEEXT=".
|
||||
|
||||
5 - To avoid using the Microsoft runtime (which might not be conform to ISO C),
|
||||
you can use the MinGW runtime package (which is an integral part of MinGW).
|
||||
For example, with MinGW versions 3.15 and later you can get an
|
||||
ISO-compliant printf() if you compile your application with either
|
||||
'-ansi', '-posix' or '-D__USE_MINGW_ANSI_STDIO'. For example, you can
|
||||
compile and test MPFR with CC="gcc -D__USE_MINGW_ANSI_STDIO".
|
||||
|
||||
For example under Win32, the following problem has been experienced with
|
||||
MPFR 2.4.0 RC1 and the MSVC runtime (msvcrt.dll):
|
||||
|
||||
Error in mpfr_vsprintf (s, "%.*Zi, %R*e, %Lf%n", ...);
|
||||
expected: "00000010610209857723, -1.2345678875e+07, 0.032258"
|
||||
got: "00000010610209857723, -1.2345678875e+07, -0.000000"
|
||||
FAIL: tsprintf.exe
|
||||
|
||||
This error is due to the MSVC runtime not supporting the L length modifier
|
||||
for formatted output (e.g. printf with %Lf). You can check this with the
|
||||
following program:
|
||||
|
||||
#include <stdio.h>
|
||||
int main (void)
|
||||
{
|
||||
long double d = 1. / 31.;
|
||||
printf ("%Lf\n", d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
The expected output is 0.032258.
|
||||
|
||||
Note: The L modifier has been standard for a long time (it was added
|
||||
in ISO C89).
|
||||
|
||||
|
||||
Notes on 64-bit Windows Applications (x64)
|
||||
==========================================
|
||||
|
||||
[See the Notes on 32-bit Windows Applications, which might be relevant here,
|
||||
in particular when running a 64-bit operating system]
|
||||
|
||||
Cygwin and MinGW do not yet offer support for native Windows 64 builds but
|
||||
the 32-bit version of MPFR can be used to build 32-bit applications that
|
||||
will run on 64-bit Windows systems (see above). MPFR can be built as a native
|
||||
64-bit static or DLL library for Windows 64 using the Visual Studio build
|
||||
projects at http://fp.gladman.plus.com/computing/gmp4win.htm.
|
|
@ -0,0 +1,130 @@
|
|||
# Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
# This Makefile.am is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
AUTOMAKE_OPTIONS = gnu ansi2knr
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = tests
|
||||
|
||||
nobase_dist_doc_DATA = AUTHORS BUGS COPYING COPYING.LESSER FAQ.html NEWS TODO \
|
||||
examples/ReadMe examples/divworst.c examples/rndo-add.c examples/sample.c \
|
||||
examples/version.c
|
||||
|
||||
EXTRA_DIST = PATCHES VERSION get_patches.sh round_raw_generic.c gen_inverse.h jyn_asympt.c ieee_floats.h
|
||||
|
||||
include_HEADERS = mpfr.h mpf2mpfr.h
|
||||
|
||||
BUILT_SOURCES = mparam.h
|
||||
|
||||
lib_LTLIBRARIES = libmpfr.la
|
||||
|
||||
libmpfr_la_SOURCES = mpfr.h mpf2mpfr.h mpfr-gmp.h mpfr-impl.h \
|
||||
mpfr-longlong.h mpfr-thread.h exceptions.c extract.c uceil_exp2.c \
|
||||
uceil_log2.c ufloor_log2.c add.c add1.c add_ui.c agm.c clear.c cmp.c \
|
||||
cmp_abs.c cmp_si.c cmp_ui.c comparisons.c div_2exp.c div_2si.c \
|
||||
div_2ui.c div.c div_ui.c dump.c eq.c exp10.c exp2.c exp3.c exp.c \
|
||||
frac.c get_d.c get_exp.c get_str.c init.c inp_str.c isinteger.c \
|
||||
isinf.c isnan.c isnum.c const_log2.c log.c modf.c mul_2exp.c mul_2si.c \
|
||||
mul_2ui.c mul.c mul_ui.c neg.c next.c out_str.c printf.c vasprintf.c \
|
||||
const_pi.c pow.c pow_si.c pow_ui.c print_raw.c print_rnd_mode.c \
|
||||
reldiff.c round_prec.c set.c setmax.c setmin.c set_d.c set_dfl_prec.c \
|
||||
set_exp.c set_rnd.c set_f.c set_prc_raw.c set_prec.c set_q.c set_si.c \
|
||||
set_str.c set_str_raw.c set_ui.c set_z.c sqrt.c sqrt_ui.c sub.c sub1.c \
|
||||
sub_ui.c rint.c ui_div.c ui_sub.c urandom.c urandomb.c get_z_exp.c \
|
||||
swap.c factorial.c cosh.c sinh.c tanh.c sinh_cosh.c acosh.c asinh.c \
|
||||
atanh.c atan.c cmp2.c exp_2.c asin.c const_euler.c cos.c sin.c tan.c \
|
||||
fma.c fms.c hypot.c log1p.c expm1.c log2.c log10.c ui_pow.c \
|
||||
ui_pow_ui.c minmax.c dim.c signbit.c copysign.c setsign.c gmp_op.c \
|
||||
init2.c acos.c sin_cos.c set_nan.c set_inf.c set_zero.c powerof2.c \
|
||||
gamma.c set_ld.c get_ld.c cbrt.c volatile.c fits_s.h fits_sshort.c \
|
||||
fits_sint.c fits_slong.c fits_u.h fits_ushort.c fits_uint.c \
|
||||
fits_ulong.c fits_uintmax.c fits_intmax.c get_si.c get_ui.c zeta.c \
|
||||
cmp_d.c erf.c inits.c inits2.c clears.c sgn.c check.c sub1sp.c \
|
||||
version.c mpn_exp.c mpfr-gmp.c mp_clz_tab.c sum.c add1sp.c \
|
||||
free_cache.c si_op.c cmp_ld.c set_ui_2exp.c set_si_2exp.c set_uj.c \
|
||||
set_sj.c get_sj.c get_uj.c get_z.c iszero.c cache.c sqr.c \
|
||||
int_ceil_log2.c isqrt.c strtofr.c pow_z.c logging.c mulders.c get_f.c \
|
||||
round_p.c erfc.c atan2.c subnormal.c const_catalan.c root.c \
|
||||
gen_inverse.h sec.c csc.c cot.c eint.c sech.c csch.c coth.c \
|
||||
round_near_x.c constant.c abort_prec_max.c stack_interface.c lngamma.c \
|
||||
zeta_ui.c set_d64.c get_d64.c jn.c yn.c rem1.c get_patches.c add_d.c \
|
||||
sub_d.c d_sub.c mul_d.c div_d.c d_div.c li2.c rec_sqrt.c min_prec.c \
|
||||
buildopt.c digamma.c bernoulli.c isregular.c set_flt.c get_flt.c \
|
||||
scale2.c set_z_exp.c ai.c gammaonethird.c
|
||||
|
||||
libmpfr_la_LIBADD = @LIBOBJS@
|
||||
|
||||
# Libtool -version-info CURRENT[:REVISION[:AGE]] for libmpfr.la
|
||||
#
|
||||
# 1. No interfaces changed, only implementations (good):
|
||||
# ==> Increment REVISION.
|
||||
# 2. Interfaces added, none removed (good):
|
||||
# ==> Increment CURRENT, increment AGE, set REVISION to 0.
|
||||
# 3. Interfaces removed or changed (BAD, breaks upward compatibility):
|
||||
# ==> Increment CURRENT, set AGE and REVISION to 0.
|
||||
#
|
||||
# MPFR -version-info
|
||||
# 2.1.x -
|
||||
# 2.2.x 1:x:0
|
||||
# 2.3.x 2:x:1
|
||||
# 2.4.x 3:x:2
|
||||
# 3.0.x 4:x:0
|
||||
libmpfr_la_LDFLAGS = -version-info 4:1:0
|
||||
|
||||
info_TEXINFOS = mpfr.texi
|
||||
|
||||
mpfr_TEXINFOS = fdl.texi
|
||||
|
||||
MAKEINFOFLAGS = --enable-encoding
|
||||
|
||||
# Important note: If for some reason, srcdir is read-only at build time
|
||||
# (and you use objdir != srcdir), then you need to rebuild get_patches.c
|
||||
# (with "make get_patches.c") just after patching the MPFR source. This
|
||||
# should not be a problem in practice, in particular because "make dist"
|
||||
# automatically rebuilds get_patches.c before generating the archives.
|
||||
$(srcdir)/get_patches.c: PATCHES get_patches.sh
|
||||
(cd $(srcdir) && ./get_patches.sh) > $@ || rm -f $@
|
||||
|
||||
# Do not add get_patches.c to CLEANFILES so that this file doesn't
|
||||
# need to be (re)built as long as no patches are applied. Anyway the
|
||||
# update of this file should be regarded as part of the patch process,
|
||||
# and "make clean" shouldn't remove it, just like it doesn't remove
|
||||
# what has been changed by "patch".
|
||||
#CLEANFILES = get_patches.c
|
||||
|
||||
# Tune program
|
||||
EXTRA_PROGRAMS = tuneup speed
|
||||
|
||||
tuneup_SOURCES = tuneup.c
|
||||
tuneup_LDADD = -lspeed libmpfr.la
|
||||
tuneup_LDFLAGS = -static
|
||||
|
||||
speed_SOURCES = speed.c
|
||||
speed_LDADD = -lspeed libmpfr.la
|
||||
speed_LDFLAGS = -static
|
||||
|
||||
tune:
|
||||
$(MAKE) $(AM_MAKEFLAGS) tuneup$(EXEEXT)
|
||||
./tuneup -v
|
||||
$(MAKE) $(AM_MAKEFLAGS) clean
|
||||
$(MAKE) $(AM_MAKEFLAGS) libmpfr.la
|
||||
|
||||
# In a "make dist", check that libtool -version-info value is up-to-date.
|
||||
# But if the VERSION file contains "-dev", this is not checked.
|
||||
# Note: this is a heuristic, to detect some mistakes.
|
||||
dist-hook:
|
||||
grep -q -e -dev $(srcdir)/VERSION || { \
|
||||
mv=`sed -n "s/^\([0-9][0-9]*\)\.\([0-9][0-9]*\)\..*/\1\\\\\\.\2/p" $(srcdir)/VERSION` && \
|
||||
pl=`sed -n "s/^$$mv\.\([0-9][0-9]*\).*/\1/p" $(srcdir)/VERSION` && \
|
||||
printf "mv=%s / pl=%s\n" "$$mv" "$$pl" && \
|
||||
vinfo=`sed -n "s/^# *$$mv\.x *\([0-9][0-9]*\):x:\([0-9][0-9]*\)/\1:$$pl:\2/p" $(srcdir)/Makefile.am` && \
|
||||
printf "vinfo=%s\n" "$$vinfo" && \
|
||||
grep -q -e "-version-info $$vinfo$$" $(srcdir)/Makefile.am; }
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,266 @@
|
|||
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
##############################################################################
|
||||
|
||||
Changes from version 3.0.0 to version 3.0.1:
|
||||
- Bug fixes (see <http://www.mpfr.org/mpfr-3.0.0/#fixed> or ChangeLog file).
|
||||
Note: The mpfr_subnormalize implementation up to MPFR 3.0.0 did not change
|
||||
the flags. In particular, it did not follow the generic rule concerning
|
||||
the inexact flag (and no special behavior was specified). The case of the
|
||||
underflow flag was more a lack of specification.
|
||||
|
||||
Changes from versions 2.4.* to version 3.0.0:
|
||||
- The "boudin aux pommes" release.
|
||||
- MPFR 3.0.0 is binary incompatible with previous versions but (almost)
|
||||
API compatible. More precisely the obsolete functions mpfr_random
|
||||
and mpfr_random2 have been removed, the meaning of the return type
|
||||
of the function mpfr_get_f has changed, and the return type of the
|
||||
function mpfr_get_z is now int instead of void. In practice, this
|
||||
should not break any existing code.
|
||||
- MPFR is now distributed under the GNU Lesser General Public License
|
||||
version 3 or later (LGPL v3+).
|
||||
- Rounding modes GMP_RNDx are now MPFR_RNDx (GMP_RNDx kept for
|
||||
compatibility).
|
||||
- A new rounding mode (MPFR_RNDA) is available to round away from zero.
|
||||
- The rounding mode type is now mpfr_rnd_t (as in previous versions,
|
||||
both mpfr_rnd_t and mp_rnd_t are accepted, but mp_rnd_t may be
|
||||
removed in the future).
|
||||
- The precision type is now mpfr_prec_t (as in previous versions, both
|
||||
mpfr_prec_t and mp_prec_t are accepted, but mp_prec_t may be removed
|
||||
in the future) and it is now signed (it was unsigned in MPFR 2.*, but
|
||||
this was not documented). In practice, this change should not affect
|
||||
existing code that assumed nothing on the precision type.
|
||||
- MPFR now has its own exponent type mpfr_exp_t, which is currently
|
||||
the same as GMP's mp_exp_t.
|
||||
- Functions mpfr_random and mpfr_random2 have been removed.
|
||||
- mpfr_get_f and mpfr_get_z now return a ternary value.
|
||||
- mpfr_strtofr now accepts bases from 37 to 62.
|
||||
- mpfr_custom_get_mantissa was renamed to mpfr_custom_get_significand
|
||||
(mpfr_custom_get_mantissa is still available via a #define).
|
||||
- Functions mpfr_get_si, mpfr_get_ui, mpfr_get_sj, mpfr_get_uj,
|
||||
mpfr_get_z and mpfr_get_z_2exp no longer have cases with undefined
|
||||
behavior; in these cases, the behavior is now specified, and in
|
||||
particular, the erange flag is set.
|
||||
- New functions mpfr_buildopt_tls_p and mpfr_buildopt_decimal_p giving
|
||||
information about options used at MPFR build time.
|
||||
- New function mpfr_regular_p.
|
||||
- New function mpfr_set_zero.
|
||||
- New function mpfr_digamma.
|
||||
- New function mpfr_ai (incomplete, experimental).
|
||||
- New functions mpfr_set_flt and mpfr_get_flt to convert from/to the
|
||||
float type.
|
||||
- New function mpfr_urandom.
|
||||
- New function mpfr_set_z_2exp (companion to mpfr_get_z_2exp, which
|
||||
was renamed from mpfr_get_z_exp in previous versions).
|
||||
- Speed improvement for large precisions in the trigonometric functions
|
||||
(mpfr_sin, mpfr_cos, mpfr_tan, mpfr_sin_cos): speedup of about 2.5
|
||||
for 10^5 digits, of about 5 for 10^6 digits.
|
||||
- Speed improvement for large precisions of the inverse trigonometric
|
||||
functions (arcsin, arccos, arctan): about 2 for 10^3 digits, up to
|
||||
2.7 for 10^6 digits.
|
||||
- Some documentation files are installed in $docdir.
|
||||
- The detection of a GMP build directory (more precisely, the internal
|
||||
header files of GMP) was previously done separately from the use of
|
||||
the --with-gmp-build configure option. This was not consistent with
|
||||
the documentation and with other parts of the configure script. So,
|
||||
as of MPFR 3.0.0, the internal header files of GMP are now used if
|
||||
and only if the --with-gmp-build configure option is given.
|
||||
- The configure script recognizes some extra "long double" formats
|
||||
(double big endian, double little endian, double-double big endian).
|
||||
- MPFR manual: added "API Compatibility" section.
|
||||
- Test coverage: 97.1% lines of code.
|
||||
- Bug fixes.
|
||||
|
||||
Changes from versions 2.3.* to version 2.4.0:
|
||||
- The "andouillette sauce moutarde" release.
|
||||
- MPFR is now a GNU package.
|
||||
- Changes in the behavior of mpfr_strtofr and in its documentation
|
||||
concerning particular cases where the code and the documentation
|
||||
did not match; this change is also present in MPFR 2.3.1.
|
||||
- Behavior of mpfr_check_range changed: if the value is an inexact
|
||||
infinity, the overflow flag is set (in case it was lost); this
|
||||
change is also present in MPFR 2.3.2.
|
||||
- Function mpfr_init_gmp_rand (only defined when building MPFR without
|
||||
the --with-gmp-build configure option) is no longer defined at all.
|
||||
This function was private and not documented, and was used only in
|
||||
the MPFR test suite. User code that calls it is regarded as broken
|
||||
and may fail as a consequence. Running the old test suite against
|
||||
MPFR 2.4.0 may also fail.
|
||||
- New functions:
|
||||
* between a MPFR number and a double: mpfr_add_d, mpfr_sub_d,
|
||||
mpfr_d_sub, mpfr_mul_d, mpfr_div_d, mpfr_d_div,
|
||||
* formatted input/output:
|
||||
mpfr_printf, mpfr_fprintf, mpfr_vprintf, mpfr_vfprintf,
|
||||
mpfr_sprintf, mpfr_snprintf, mpfr_vsprintf, mpfr_vsnprintf,
|
||||
mpfr_asprintf, mpfr_vasprintf.
|
||||
* mpfr_sinh_cosh, mpfr_li2, mpfr_modf, mpfr_fmod, mpfr_rec_sqrt.
|
||||
- Configure test for TLS support.
|
||||
- Get default $CC and $CFLAGS from gmp.h (__GMP_CC / __GMP_CFLAGS,
|
||||
which are available as of GMP 4.2.3).
|
||||
- Documented the fact that mpfr_random and mpfr_random2 will be
|
||||
suppressed in the next release, and that the specification of
|
||||
mpfr_eq may change in the next release (for compatibility with
|
||||
the mpf layer of GMP).
|
||||
- Test coverage: 96.7% lines of code
|
||||
- Bug fixes.
|
||||
|
||||
Changes from versions 2.2.* to version 2.3.0:
|
||||
- The mpfr.info file is now installed in the share subdirectory
|
||||
(as required by the Filesystem Hierarchy Standard); see output
|
||||
of "./configure --help".
|
||||
- The shared library is now enabled by default. If the MPFR build
|
||||
fails on your platform, try the --disable-shared configure option
|
||||
to disable the shared library.
|
||||
- Thread-safe support with Microsoft Visual compiler.
|
||||
- New functions mpfr_j0, mpfr_j1, mpfr_jn, mpfr_y0, mpfr_y1, mpfr_yn,
|
||||
mpfr_lgamma, mpfr_remainder, mpfr_remquo, mpfr_fms, mpfr_signbit,
|
||||
mpfr_setsign, mpfr_copysign, mpfr_get_patches.
|
||||
- Functions mpfr_sin, mpfr_cos and mpfr_sin_cos improved (argument
|
||||
reduction).
|
||||
- More detailed MPFR manual.
|
||||
- Improved tests (make check).
|
||||
- Bug fixes.
|
||||
|
||||
Changes from versions 2.1.* to version 2.2.0:
|
||||
- Bug fixes.
|
||||
- new functions mpfr_set_overflow, mpfr_set_underflow, mpfr_set_inexflag,
|
||||
mpfr_set_erangeflag, mpfr_set_nanflag, mpfr_erfc, mpfr_atan2, mpfr_pow_z,
|
||||
mpfr_subnormalize, mpfr_const_catalan, mpfr_sec, mpfr_csc, mpfr_cot,
|
||||
mpfr_root, mpfr_eint, mpfr_get_f, mpfr_sech, mpfr_csch, mpfr_coth,
|
||||
mpfr_lngamma.
|
||||
- new macro: MPFR_VERSION_STRING
|
||||
- Remove the exported MPFR variables from mpfr.h to mpfr-impl.h.
|
||||
(They were undocumented, so programs which respect the API still work).
|
||||
- Grep CC and CFLAGS from GMP Makefile if possible.
|
||||
- Math functions are faster (both average and worst cases).
|
||||
- Better support for long double.
|
||||
- Shared library of MPFR.
|
||||
- Binary compatible with previous versions if you do not use undocumented
|
||||
features.
|
||||
- Thread safe (if built with --enable-thread-safe).
|
||||
- Logging facility.
|
||||
- Change in the semantics of mpfr_out_str/mpfr_get_str when n_digits=0.
|
||||
- Better locale support.
|
||||
|
||||
Changes from version 2.1.0 to version 2.1.1:
|
||||
- Better way to detect the GMP library.
|
||||
- Bug fixes.
|
||||
|
||||
Changes from version 2.0.3 to version 2.1.0:
|
||||
- Bug fixes.
|
||||
- new functions mpfr_strtofr, mpfr_set_uj, mpfr_set_sj, mpfr_set_ui_2exp,
|
||||
mpfr_set_si_2exp, mpfr_set_sj_2exp, mpfr_set_uj_2exp, mpfr_get_uj,
|
||||
mpfr_get_sj, mpfr_get_z, mpfr_free_str, mpfr_si_sub, mpfr_sub_si,
|
||||
mpfr_mul_si, mpfr_si_div, mpfr_div_si, mpfr_sqr, mpfr_cmp_z, mpfr_cmp_q,
|
||||
mpfr_zero_p, mpfr_free_cache, mpfr_sum, mpfr_get_version,
|
||||
mpfr_get_default_rounding_mode, mpfr_get_emin_min, mpfr_get_emin_max,
|
||||
mpfr_get_emax_min, mpfr_get_emax_max, mpfr_inits, mpfr_inits2, mpfr_clears,
|
||||
mpfr_fits_intmax_p, mpfr_fits_uintmax_p, mpfr_clear_erangeflag,
|
||||
mpfr_erangeflag_p, mpfr_rint_round, mpfr_rint_trunc, mpfr_rint_ceil,
|
||||
mpfr_rint_floor.
|
||||
- new macros MPFR_DECL_INIT, MPFR_VERSION, MPFR_VERSION_NUM,
|
||||
MPFR_VERSION_MAJOR, MPFR_VERSION_MINOR, MPFR_VERSION_PATCHLEVEL.
|
||||
- improved documentation.
|
||||
- improved configure.
|
||||
- improved portability (library and test suite).
|
||||
- It handles correctly non IEEE-754 double.
|
||||
- GMP internal files are not needed to install MPFR.
|
||||
- It is faster with low-precision floating point.
|
||||
- New global flag: ERANGE_FLAG.
|
||||
- Binary incompatible with previous versions, but API compatible.
|
||||
- mpfr_set_str doesn't allow anymore "@NAN@garbagechar" and "@INF@garbagechar",
|
||||
allows base 0 (detection of the base), prefix (0x, 0b), leading whitespace.
|
||||
|
||||
Changes from version 2.0.2 to version 2.0.3:
|
||||
- Bug fixes.
|
||||
- Support GMP as a shared library (not fully tested).
|
||||
|
||||
Changes from version 2.0.1 to version 2.0.2:
|
||||
- many bug fixes and other improvements.
|
||||
- new functions mpfr_prec_round (replaces mpfr_round_prec), mpfr_get_exp,
|
||||
mpfr_set_exp, mpfr_get_ld, mpfr_set_ld, mpfr_get_d_2exp, mpfr_get_si,
|
||||
mpfr_get_ui, mpfr_nextabove, mpfr_nextbelow, mpfr_nexttoward, mpfr_frac,
|
||||
mpfr_fits_*, mpfr_cmp_d, mpfr_cmpabs, mpfr_erf, mpfr_gamma, mpfr_zeta,
|
||||
mpfr_greater_p, mpfr_greaterequal_p, mpfr_less_p, mpfr_lessequal_p,
|
||||
mpfr_lessgreater_p, mpfr_equal_p, mpfr_unordered_p.
|
||||
- removed functions: mpfr_print_binary, mpfr_round_prec (replaced by
|
||||
mpfr_prec_round), mpfr_set_str_raw, mpfr_set_machine_rnd_mode.
|
||||
- function mpfr_isinteger renamed mpfr_integer_p.
|
||||
- return type of some functions changed from void to int, for consistency.
|
||||
- return type of mpfr_set_prec changed from int to void.
|
||||
- new values for exponent range.
|
||||
- rename internal variables.
|
||||
|
||||
Changes from version 2001 to version 2.0.1:
|
||||
- new mathematical functions: acos, acosh, asin, asinh, atan, atanh, cosh,
|
||||
base-2 exponential and logarithm, base-10 logarithm, expm1, factorial,
|
||||
pow, pow_si, pow_ui, sinh, tan, tanh, ui_pow, ui_pow_ui
|
||||
- other new functions: mpfr_const_euler, mpfr_dim, mpfr_fma, mpfr_hypot,
|
||||
mpfr_min, mpfr_max, mpfr_rint, mpfr_set_inf, mpfr_set_nan
|
||||
- new operations with MPZ or MPQ: mpfr_{add,sub,mul,div}_[zq]
|
||||
- new predicates: mpfr_inf_p, mpfr_nan_p, mpfr_number_p, mpfr_isinteger,
|
||||
- add mechanism to set/check exponent range (overflow, underflow), partially
|
||||
implemented in the mpfr functions.
|
||||
- efficiency: mpfr_div is now faster when the divisor has a few limbs
|
||||
- rounding: now mpfr_pow implements exact rounding, and most functions return a
|
||||
ternary value indicating the position of the returned value wrt the exact one
|
||||
(thus the return value is now 'int' instead of 'void')
|
||||
- complete rewrite of the configuration files
|
||||
- mpfr_get_d, mpfr_{add,sub}_one_ulp now get a rounding mode as 2nd argument
|
||||
- some function names did change: mpz_set_fr is now mpfr_get_z_exp,
|
||||
mpfr_print_raw is now mpfr_print_binary.
|
||||
|
||||
Changes from version 1.0 to version 2001:
|
||||
- the default installation does not provide any more access to machine
|
||||
rounding mode, and as a consequence does not compare MPFR results with
|
||||
precision=53 to machine results. Add option -DTEST if you want to have
|
||||
access to machine rounding mode, and to check MPFR results against.
|
||||
- the MPFR files do not need <math.h> any more
|
||||
- the header file <mpfr.h> was split into <mpfr.h> for exported functions
|
||||
and <mpfr-impl.h> for internal functions. The user should not use functions
|
||||
or macros from <mpfr-impl.h>, since those may change in further releases.
|
||||
- <mpfr.h> was modified in order to make easy a C++ interface
|
||||
- MPFR now deals with infinities (+infinity and -infinity) and NaN
|
||||
- the missing function mpfr_swap is now available
|
||||
- mpfr_zeta was removed (was incomplete)
|
||||
- mpfr_init and mpfr_init2 now initialize the corresponding variable to 0
|
||||
(like in other initialization functions from GNU MP)
|
||||
- in case memory allocation fails, an error message is output
|
||||
- several bugs of version 1.0 were fixed
|
||||
|
||||
Changes from version 0.4 to version 1.0:
|
||||
|
||||
- Version 1.0 now uses a standard configure/make installation.
|
||||
- Version 1.0 implements all functions that are available in the MPF class
|
||||
from GMP 3.1 (except mpf_swap) and a header file mpf2mpfr.h is included in
|
||||
the distribution for easy change from MPF to MPFR.
|
||||
- Version 1.0 implements new elementary functions: mpfr_sincos
|
||||
- Some functions and macros have been renamed: mpfr_log2 is now
|
||||
mpfr_const_log2, mpfr_pi is now mpfr_const_pi, SIGN is now MPFR_SIGN.
|
||||
- Version 1.0 uses faster algorithms for mpfr_exp, mpfr_const_pi,
|
||||
mpfr_const_log2. Compare the timings from version 1.0 and version 0.4.
|
||||
- Version 1.0 corrects some bugs of version 0.4.
|
||||
- The precision of MPFR variables is now named mpfr_prec, which makes it
|
||||
easier to change it, to say unsigned long long. Same for the rounding mode
|
||||
which is called mp_rnd_t.
|
||||
|
||||
You'll find other news concerning the GNU MPFR library on the web
|
||||
page <http://www.mpfr.org/>.
|
|
@ -0,0 +1,90 @@
|
|||
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
##############################################################################
|
||||
|
||||
The GNU MPFR distribution contains the following files:
|
||||
(This does not apply to code retrieved by Subversion.)
|
||||
|
||||
AUTHORS - the authors of the library
|
||||
BUGS - bugs in MPFR - please read this file!
|
||||
COPYING - the GNU General Public License, version 3
|
||||
COPYING.LESSER - the GNU Lesser General Public License, version 3
|
||||
ChangeLog - the log of changes
|
||||
FAQ.html - frequently asked questions about MPFR
|
||||
INSTALL - how to install MPFR (see also mpfr.texi)
|
||||
Makefile* - files for building the library
|
||||
NEWS - new features with respect to previous versions
|
||||
PATCHES - empty file (until patches are applied)
|
||||
README - this file
|
||||
TODO - what remains to do (any help is welcome!)
|
||||
VERSION - version of MPFR (next release version if taken by Subversion)
|
||||
ac*.m4 - automatic configuration files
|
||||
ansi2knr.* - convert ANSI C to Kernighan & Ritchie C (source and man page)
|
||||
*.c - source files
|
||||
*.h - header files
|
||||
compile - auxiliary installation file
|
||||
config.* - auxiliary installation files
|
||||
configure* - configuration files
|
||||
depcomp - auxiliary installation file
|
||||
examples/ - directory containing examples
|
||||
fdl.texi - the GNU Free Documentation License
|
||||
get_patches.sh - rebuild get_patches.c when patches have been applied
|
||||
install-sh - installation file
|
||||
ltmain.sh - auxiliary installation file
|
||||
m4/ - directory containing additional configuration files
|
||||
missing - auxiliary installation file
|
||||
mparam_h.in - header file template
|
||||
mpfr.info - info file for MPFR
|
||||
mpfr.texi - texinfo documentation for MPFR (source)
|
||||
tests/ - test directory
|
||||
texinfo.tex - TeX macros to handle mpfr.texi
|
||||
|
||||
According to the special exception to the GNU General Public License,
|
||||
the autotools files compile, config.sub, config.guess, ltmain.sh,
|
||||
m4/libtool.m4 and missing are distributed under the same licence of
|
||||
GNU MPFR.
|
||||
|
||||
|
||||
You can get the latest source code by Subversion at INRIAGForge:
|
||||
|
||||
svn checkout svn://scm.gforge.inria.fr/svn/mpfr/trunk mpfr
|
||||
|
||||
or
|
||||
|
||||
svn checkout https://scm.gforge.inria.fr/svn/mpfr/trunk mpfr
|
||||
|
||||
(the last argument can be any directory name). You can use
|
||||
|
||||
svn ls svn://scm.gforge.inria.fr/svn/mpfr/branches
|
||||
svn ls svn://scm.gforge.inria.fr/svn/mpfr/tags
|
||||
|
||||
to get the list of branches or tags (releases), then checkout a
|
||||
particular branch or tag instead of the trunk. Alternatively, you
|
||||
can now use the "https:" scheme (a.k.a. DAV) instead of "svn:".
|
||||
For more information about Subversion, please see:
|
||||
|
||||
* http://svnbook.red-bean.com/ (the official Subversion book);
|
||||
* http://gcc.gnu.org/wiki/SvnHelp (written for GCC developers,
|
||||
but interesting general information can be found there);
|
||||
* http://subversion.apache.org/faq.html (the Subversion FAQ).
|
||||
|
||||
Subversion users should read the file "README.dev" (provided via
|
||||
SVN only).
|
|
@ -0,0 +1,437 @@
|
|||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
Table of contents:
|
||||
1. Documentation
|
||||
2. Installation
|
||||
3. Changes in existing functions
|
||||
4. New functions to implement
|
||||
5. Efficiency
|
||||
6. Miscellaneous
|
||||
7. Portability
|
||||
|
||||
##############################################################################
|
||||
1. Documentation
|
||||
##############################################################################
|
||||
|
||||
- add a description of the algorithms used + proof of correctness
|
||||
|
||||
##############################################################################
|
||||
2. Installation
|
||||
##############################################################################
|
||||
|
||||
- if we want to distinguish GMP and MPIR, we can check at configure time
|
||||
the following symbols which are only defined in MPIR:
|
||||
|
||||
#define __MPIR_VERSION 0
|
||||
#define __MPIR_VERSION_MINOR 9
|
||||
#define __MPIR_VERSION_PATCHLEVEL 0
|
||||
|
||||
There is also a library symbol mpir_version, which should match VERSION, set
|
||||
by configure, for example 0.9.0.
|
||||
|
||||
##############################################################################
|
||||
3. Changes in existing functions
|
||||
##############################################################################
|
||||
|
||||
- many functions currently taking into account the precision of the *input*
|
||||
variable to set the initial working precison (acosh, asinh, cosh, ...).
|
||||
This is nonsense since the "average" working precision should only depend
|
||||
on the precision of the *output* variable (and maybe on the *value* of
|
||||
the input in case of cancellation).
|
||||
-> remove those dependencies from the input precision.
|
||||
|
||||
- mpfr_get_str should support base up to 62 too.
|
||||
|
||||
- mpfr_can_round:
|
||||
change the meaning of the 2nd argument (err). Currently the error is
|
||||
at most 2^(MPFR_EXP(b)-err), i.e. err is the relative shift wrt the
|
||||
most significant bit of the approximation. I propose that the error
|
||||
is now at most 2^err ulps of the approximation, i.e.
|
||||
2^(MPFR_EXP(b)-MPFR_PREC(b)+err).
|
||||
|
||||
- mpfr_set_q first tries to convert the numerator and the denominator
|
||||
to mpfr_t. But this convertion may fail even if the correctly rounded
|
||||
result is representable. New way to implement:
|
||||
Function q = a/b. nq = PREC(q) na = PREC(a) nb = PREC(b)
|
||||
If na < nb
|
||||
a <- a*2^(nb-na)
|
||||
n <- na-nb+ (HIGH(a,nb) >= b)
|
||||
if (n >= nq)
|
||||
bb <- b*2^(n-nq)
|
||||
a = q*bb+r --> q has exactly n bits.
|
||||
else
|
||||
aa <- a*2^(nq-n)
|
||||
aa = q*b+r --> q has exaclty n bits.
|
||||
If RNDN, takes nq+1 bits. (See also the new division function).
|
||||
|
||||
|
||||
##############################################################################
|
||||
4. New functions to implement
|
||||
##############################################################################
|
||||
|
||||
- implement mpfr_z_sub, mpfr_q_sub, mpfr_z_div, mpfr_q_div?
|
||||
- implement functions for random distributions, see for example
|
||||
http://websympa.loria.fr/wwsympa/arc/mpfr/2010-01/msg00034.html
|
||||
(suggested by Charles Karney <ckarney@Sarnoff.com>, 18 Jan 2010):
|
||||
* a Bernoulli distribution with prob p/q (exact)
|
||||
* a general discrete distribution (i with prob w[i]/sum(w[i]) (Walker
|
||||
algorithm, but make it exact)
|
||||
* a uniform distribution in (a,b)
|
||||
* exponential distribution (mean lambda) (von Neumann's method?)
|
||||
* normal distribution (mean m, s.d. sigma) (ratio method?)
|
||||
- wanted for Magma [John Cannon <john@maths.usyd.edu.au>, Tue, 19 Apr 2005]:
|
||||
HypergeometricU(a,b,s) = 1/gamma(a)*int(exp(-su)*u^(a-1)*(1+u)^(b-a-1),
|
||||
u=0..infinity)
|
||||
JacobiThetaNullK
|
||||
PolylogP, PolylogD, PolylogDold: see http://arxiv.org/abs/math.CA/0702243
|
||||
and the references herein.
|
||||
JBessel(n, x) = BesselJ(n+1/2, x)
|
||||
IncompleteGamma [also wanted by <keith.briggs@bt.com> 4 Feb 2008: Gamma(a,x),
|
||||
gamma(a,x), P(a,x), Q(a,x); see A&S 6.5, ref. [Smith01] in algorithms.bib]
|
||||
KBessel, KBessel2 [2nd kind]
|
||||
JacobiTheta
|
||||
LogIntegral
|
||||
ExponentialIntegralE1
|
||||
E1(z) = int(exp(-t)/t, t=z..infinity), |arg z| < Pi
|
||||
mpfr_eint1: implement E1(x) for x > 0, and Ei(-x) for x < 0
|
||||
E1(NaN) = NaN
|
||||
E1(+Inf) = +0
|
||||
E1(-Inf) = -Inf
|
||||
E1(+0) = +Inf
|
||||
E1(-0) = -Inf
|
||||
DawsonIntegral
|
||||
GammaD(x) = Gamma(x+1/2)
|
||||
- functions defined in the LIA-2 standard
|
||||
+ minimum and maximum (5.2.2): max, min, max_seq, min_seq, mmax_seq
|
||||
and mmin_seq (mpfr_min and mpfr_max correspond to mmin and mmax);
|
||||
+ rounding_rest, floor_rest, ceiling_rest (5.2.4);
|
||||
+ remr (5.2.5): x - round(x/y) y;
|
||||
+ error functions from 5.2.7 (if useful in MPFR);
|
||||
+ power1pm1 (5.3.6.7): (1 + x)^y - 1;
|
||||
+ logbase (5.3.6.12): \log_x(y);
|
||||
+ logbase1p1p (5.3.6.13): \log_{1+x}(1+y);
|
||||
+ rad (5.3.9.1): x - round(x / (2 pi)) 2 pi = remr(x, 2 pi);
|
||||
+ axis_rad (5.3.9.1) if useful in MPFR;
|
||||
+ cycle (5.3.10.1): rad(2 pi x / u) u / (2 pi) = remr(x, u);
|
||||
+ axis_cycle (5.3.10.1) if useful in MPFR;
|
||||
+ sinu, cosu, tanu, cotu, secu, cscu, cossinu, arcsinu, arccosu,
|
||||
arctanu, arccotu, arcsecu, arccscu (5.3.10.{2..14}):
|
||||
sin(x 2 pi / u), etc.;
|
||||
[from which sinpi(x) = sin(Pi*x), ... are trivial to implement, with u=2.]
|
||||
+ arcu (5.3.10.15): arctan2(y,x) u / (2 pi);
|
||||
+ rad_to_cycle, cycle_to_rad, cycle_to_cycle (5.3.11.{1..3}).
|
||||
- From GSL, missing special functions (if useful in MPFR):
|
||||
(cf http://www.gnu.org/software/gsl/manual/gsl-ref.html#Special-Functions)
|
||||
+ The Airy functions Ai(x) and Bi(x) defined by the integral representations:
|
||||
* Ai(x) = (1/\pi) \int_0^\infty \cos((1/3) t^3 + xt) dt
|
||||
* Bi(x) = (1/\pi) \int_0^\infty (e^(-(1/3) t^3) + \sin((1/3) t^3 + xt)) dt
|
||||
* Derivatives of Airy Functions
|
||||
+ The Bessel functions for n integer and n fractional:
|
||||
* Regular Modified Cylindrical Bessel Functions I_n
|
||||
* Irregular Modified Cylindrical Bessel Functions K_n
|
||||
* Regular Spherical Bessel Functions j_n: j_0(x) = \sin(x)/x,
|
||||
j_1(x)= (\sin(x)/x-\cos(x))/x & j_2(x)= ((3/x^2-1)\sin(x)-3\cos(x)/x)/x
|
||||
Note: the "spherical" Bessel functions are solutions of
|
||||
x^2 y'' + 2 x y' + [x^2 - n (n+1)] y = 0 and satisfy
|
||||
j_n(x) = sqrt(Pi/(2x)) J_{n+1/2}(x). They should not be mixed with the
|
||||
classical Bessel Functions, also noted j0, j1, jn, y0, y1, yn in C99
|
||||
and mpfr.
|
||||
Cf http://en.wikipedia.org/wiki/Bessel_function#Spherical_Bessel_functions
|
||||
*Irregular Spherical Bessel Functions y_n: y_0(x) = -\cos(x)/x,
|
||||
y_1(x)= -(\cos(x)/x+\sin(x))/x &
|
||||
y_2(x)= (-3/x^3+1/x)\cos(x)-(3/x^2)\sin(x)
|
||||
* Regular Modified Spherical Bessel Functions i_n:
|
||||
i_l(x) = \sqrt{\pi/(2x)} I_{l+1/2}(x)
|
||||
* Irregular Modified Spherical Bessel Functions:
|
||||
k_l(x) = \sqrt{\pi/(2x)} K_{l+1/2}(x).
|
||||
+ Clausen Function:
|
||||
Cl_2(x) = - \int_0^x dt \log(2 \sin(t/2))
|
||||
Cl_2(\theta) = \Im Li_2(\exp(i \theta)) (dilogarithm).
|
||||
+ Dawson Function: \exp(-x^2) \int_0^x dt \exp(t^2).
|
||||
+ Debye Functions: D_n(x) = n/x^n \int_0^x dt (t^n/(e^t - 1))
|
||||
+ Elliptic Integrals:
|
||||
* Definition of Legendre Forms:
|
||||
F(\phi,k) = \int_0^\phi dt 1/\sqrt((1 - k^2 \sin^2(t)))
|
||||
E(\phi,k) = \int_0^\phi dt \sqrt((1 - k^2 \sin^2(t)))
|
||||
P(\phi,k,n) = \int_0^\phi dt 1/((1 + n \sin^2(t))\sqrt(1 - k^2 \sin^2(t)))
|
||||
* Complete Legendre forms are denoted by
|
||||
K(k) = F(\pi/2, k)
|
||||
E(k) = E(\pi/2, k)
|
||||
* Definition of Carlson Forms
|
||||
RC(x,y) = 1/2 \int_0^\infty dt (t+x)^(-1/2) (t+y)^(-1)
|
||||
RD(x,y,z) = 3/2 \int_0^\infty dt (t+x)^(-1/2) (t+y)^(-1/2) (t+z)^(-3/2)
|
||||
RF(x,y,z) = 1/2 \int_0^\infty dt (t+x)^(-1/2) (t+y)^(-1/2) (t+z)^(-1/2)
|
||||
RJ(x,y,z,p) = 3/2 \int_0^\infty dt
|
||||
(t+x)^(-1/2) (t+y)^(-1/2) (t+z)^(-1/2) (t+p)^(-1)
|
||||
+ Elliptic Functions (Jacobi)
|
||||
+ N-relative exponential:
|
||||
exprel_N(x) = N!/x^N (\exp(x) - \sum_{k=0}^{N-1} x^k/k!)
|
||||
+ exponential integral:
|
||||
E_2(x) := \Re \int_1^\infty dt \exp(-xt)/t^2.
|
||||
Ei_3(x) = \int_0^x dt \exp(-t^3) for x >= 0.
|
||||
Ei(x) := - PV(\int_{-x}^\infty dt \exp(-t)/t)
|
||||
+ Hyperbolic/Trigonometric Integrals
|
||||
Shi(x) = \int_0^x dt \sinh(t)/t
|
||||
Chi(x) := Re[ \gamma_E + \log(x) + \int_0^x dt (\cosh[t]-1)/t]
|
||||
Si(x) = \int_0^x dt \sin(t)/t
|
||||
Ci(x) = -\int_x^\infty dt \cos(t)/t for x > 0
|
||||
AtanInt(x) = \int_0^x dt \arctan(t)/t
|
||||
[ \gamma_E is the Euler constant ]
|
||||
+ Fermi-Dirac Function:
|
||||
F_j(x) := (1/r\Gamma(j+1)) \int_0^\infty dt (t^j / (\exp(t-x) + 1))
|
||||
+ Pochhammer symbol (a)_x := \Gamma(a + x)/\Gamma(a) : see [Smith01] in
|
||||
algorithms.bib
|
||||
logarithm of the Pochhammer symbol
|
||||
+ Gegenbauer Functions
|
||||
+ Laguerre Functions
|
||||
+ Eta Function: \eta(s) = (1-2^{1-s}) \zeta(s)
|
||||
Hurwitz zeta function: \zeta(s,q) = \sum_0^\infty (k+q)^{-s}.
|
||||
+ Lambert W Functions, W(x) are defined to be solutions of the equation:
|
||||
W(x) \exp(W(x)) = x.
|
||||
This function has multiple branches for x < 0 (2 funcs W0(x) and Wm1(x))
|
||||
+ Trigamma Function psi'(x).
|
||||
and Polygamma Function: psi^{(m)}(x) for m >= 0, x > 0.
|
||||
|
||||
- from gnumeric (www.gnome.org/projects/gnumeric/doc/function-reference.html):
|
||||
- beta
|
||||
- betaln
|
||||
- degrees
|
||||
- radians
|
||||
- sqrtpi
|
||||
|
||||
- mpfr_frexp(mpfr_t rop, mpfr_exp_t *n, mpfr_t op, mpfr_rnd_t rnd) suggested
|
||||
by Steve Kargl <sgk@troutmask.apl.washington.edu> Sun, 7 Aug 2005
|
||||
- mpfr_inp_raw, mpfr_out_raw (cf mail "Serialization of mpfr_t" from Alexey
|
||||
and answer from Granlund on mpfr list, May 2007)
|
||||
- [maybe useful for SAGE] implement companion frac_* functions to the rint_*
|
||||
functions. For example mpfr_frac_floor(x) = x - floor(x). (The current
|
||||
mpfr_frac function corresponds to mpfr_rint_trunc.)
|
||||
- scaled erfc (http://websympa.loria.fr/wwsympa/arc/mpfr/2009-05/msg00054.html)
|
||||
- asec, acsc, acot, asech, acsch and acoth (mail from Björn Terelius on mpfr
|
||||
list, 18 June 2009)
|
||||
|
||||
##############################################################################
|
||||
5. Efficiency
|
||||
##############################################################################
|
||||
|
||||
- compute exp by using the series for cosh or sinh, which has half the terms
|
||||
(see Exercise 4.11 from Modern Computer Arithmetic, version 0.3)
|
||||
The same method can be used for log, using the series for atanh, i.e.,
|
||||
atanh(x) = 1/2*log((1+x)/(1-x)).
|
||||
- improve mpfr_gamma (see http://code.google.com/p/fastfunlib/). A possible
|
||||
idea is to implement a fast algorithm for the argument reconstruction
|
||||
gamma(x+k). One could also use the series for 1/gamma(x), see for example
|
||||
http://dlmf.nist.gov/5/7/ or formula (36) from
|
||||
http://mathworld.wolfram.com/GammaFunction.html
|
||||
- fix regression with mpfr_mpz_root (from Keith Briggs, 5 July 2006), for
|
||||
example on 3Ghz P4 with gmp-4.2, x=12.345:
|
||||
prec=50000 k=2 k=3 k=10 k=100
|
||||
mpz_root 0.036 0.072 0.476 7.628
|
||||
mpfr_mpz_root 0.004 0.004 0.036 12.20
|
||||
See also mail from Carl Witty on mpfr list, 09 Oct 2007.
|
||||
- implement Mulders algorithm for squaring and division
|
||||
- for sparse input (say x=1 with 2 bits), mpfr_exp is not faster than for
|
||||
full precision when precision <= MPFR_EXP_THRESHOLD. The reason is
|
||||
that argument reduction kills sparsity. Maybe avoid argument reduction
|
||||
for sparse input?
|
||||
- speed up const_euler for large precision [for x=1.1, prec=16610, it takes
|
||||
75% of the total time of eint(x)!]
|
||||
- speed up mpfr_atan for large arguments (to speed up mpc_log)
|
||||
[from Mark Watkins on Fri, 18 Mar 2005]
|
||||
Also mpfr_atan(x) seems slower (by a factor of 2) for x near from 1.
|
||||
Example on a Athlon for 10^5 bits: x=1.1 takes 3s, whereas 2.1 takes 1.8s.
|
||||
The current implementation does not give monotonous timing for the following:
|
||||
mpfr_random (x); for (i = 0; i < k; i++) mpfr_atan (y, x, MPFR_RNDN);
|
||||
for precision 300 and k=1000, we get 1070ms, and 500ms only for p=400!
|
||||
- improve mpfr_sin on values like ~pi (do not compute sin from cos, because
|
||||
of the cancellation). For instance, reduce the input modulo pi/2 in
|
||||
[-pi/4,pi/4], and define auxiliary functions for which the argument is
|
||||
assumed to be already reduced (so that the sin function can avoid
|
||||
unnecessary computations by calling the auxiliary cos function instead of
|
||||
the full cos function). This will require a native code for sin, for
|
||||
example using the reduction sin(3x)=3sin(x)-4sin(x)^3.
|
||||
See http://websympa.loria.fr/wwsympa/arc/mpfr/2007-08/msg00001.html and
|
||||
the following messages.
|
||||
- improve generic.c to work for number of terms <> 2^k
|
||||
- rewrite mpfr_greater_p... as native code.
|
||||
- inline mpfr_neg? Problems with NAN flags:
|
||||
#define mpfr_neg(_d,_x,_r) \
|
||||
(__builtin_constant_p ((_d)==(_x)) && (_d)==(_x) ? \
|
||||
((_d)->_mpfr_sign = -(_d)->_mpfr_sign, 0) : \
|
||||
mpfr_neg ((_d), (_x), (_r))) */
|
||||
|
||||
- mpf_t uses a scheme where the number of limbs actually present can
|
||||
be less than the selected precision, thereby allowing low precision
|
||||
values (for instance small integers) to be stored and manipulated in
|
||||
an mpf_t efficiently.
|
||||
|
||||
Perhaps mpfr should get something similar, especially if looking to
|
||||
replace mpf with mpfr, though it'd be a major change. Alternately
|
||||
perhaps those mpfr routines like mpfr_mul where optimizations are
|
||||
possible through stripping low zero bits or limbs could check for
|
||||
that (this would be less efficient but easier).
|
||||
|
||||
- try the idea of the paper "Reduced Cancellation in the Evaluation of Entire
|
||||
Functions and Applications to the Error Function" by W. Gawronski, J. Mueller
|
||||
and M. Reinhard, to be published in SIAM Journal on Numerical Analysis: to
|
||||
avoid cancellation in say erfc(x) for x large, they compute the Taylor
|
||||
expansion of erfc(x)*exp(x^2/2) instead (which has less cancellation),
|
||||
and then divide by exp(x^2/2) (which is simpler to compute).
|
||||
|
||||
- replace the *_THRESHOLD macros by global (TLS) variables that can be
|
||||
changed at run time (via a function, like other variables)? One benefit
|
||||
is that users could use a single MPFR binary on several machines (e.g.,
|
||||
a library provided by binary packages or shared via NFS) with different
|
||||
thresholds. On the default values, this would be a bit less efficient
|
||||
than the current code, but this isn't probably noticeable (this should
|
||||
be tested). Something like:
|
||||
long *mpfr_tune_get(void) to get the current values (the first value
|
||||
is the size of the array).
|
||||
int mpfr_tune_set(long *array) to set the tune values.
|
||||
int mpfr_tune_run(long level) to find the best values (the support
|
||||
for this feature is optional, this can also be done with an
|
||||
external function).
|
||||
|
||||
- better distinguish different processors (for example Opteron and Core 2)
|
||||
and use corresponding default tuning parameters (as in GMP). This could be
|
||||
done in configure.in to avoid hacking config.guess, for example define
|
||||
MPFR_HAVE_CORE2.
|
||||
Note (VL): the effect on cross-compilation (that can be a processor
|
||||
with the same architecture, e.g. compilation on a Core 2 for an
|
||||
Opteron) is not clear. The choice should be consistent with the
|
||||
build target (e.g. -march or -mtune value with gcc).
|
||||
Also choose better default values. For instance, the default value of
|
||||
MPFR_MUL_THRESHOLD is 40, while the best values that have been found
|
||||
are between 11 and 19 for 32 bits and between 4 and 10 for 64 bits!
|
||||
|
||||
- during the Many Digits competition, we noticed that (our implantation of)
|
||||
Mulders short product was slower than a full product for large sizes.
|
||||
This should be precisely analyzed and fixed if needed.
|
||||
|
||||
##############################################################################
|
||||
6. Miscellaneous
|
||||
##############################################################################
|
||||
|
||||
- Once the double inclusion of mpfr.h is fully supported, add tstdint
|
||||
to check_PROGRAMS in the tests/Makefile.am file.
|
||||
|
||||
- [suggested by Tobias Burnus <burnus(at)net-b.de> and
|
||||
Asher Langton <langton(at)gcc.gnu.org>, Wed, 01 Aug 2007]
|
||||
support quiet and signaling NaNs in mpfr:
|
||||
* functions to set/test a quiet/signaling NaN: mpfr_set_snan, mpfr_snan_p,
|
||||
mpfr_set_qnan, mpfr_qnan_p
|
||||
* correctly convert to/from double (if encoding of s/qNaN is fixed in 754R)
|
||||
|
||||
- check again coverage: on July 27, Patrick Pelissier reports that the
|
||||
following files are not tested at 100%: add1.c, atan.c, atan2.c,
|
||||
cache.c, cmp2.c, const_catalan.c, const_euler.c, const_log2.c, cos.c,
|
||||
gen_inverse.h, div_ui.c, eint.c, exp3.c, exp_2.c, expm1.c, fma.c, fms.c,
|
||||
lngamma.c, gamma.c, get_d.c, get_f.c, get_ld.c, get_str.c, get_z.c,
|
||||
inp_str.c, jn.c, jyn_asympt.c, lngamma.c, mpfr-gmp.c, mul.c, mul_ui.c,
|
||||
mulders.c, out_str.c, pow.c, print_raw.c, rint.c, root.c, round_near_x.c,
|
||||
round_raw_generic.c, set_d.c, set_ld.c, set_q.c, set_uj.c, set_z.c, sin.c,
|
||||
sin_cos.c, sinh.c, sqr.c, stack_interface.c, sub1.c, sub1sp.c, subnormal.c,
|
||||
uceil_exp2.c, uceil_log2.c, ui_pow_ui.c, urandomb.c, yn.c, zeta.c, zeta_ui.c.
|
||||
|
||||
- check the constants mpfr_set_emin (-16382-63) and mpfr_set_emax (16383) in
|
||||
get_ld.c and the other constants, and provide a testcase for large and
|
||||
small numbers.
|
||||
|
||||
- from Kevin Ryde <user42@zip.com.au>:
|
||||
Also for pi.c, a pre-calculated compiled-in pi to a few thousand
|
||||
digits would be good value I think. After all, say 10000 bits using
|
||||
1250 bytes would still be small compared to the code size!
|
||||
Store pi in round to zero mode (to recover other modes).
|
||||
|
||||
- add a new rounding mode: round to nearest, with ties away from zero
|
||||
(this is roundTiesToAway in 754-2008, could be used by mpfr_round)
|
||||
- add a new roundind mode: round to odd. If the result is not exactly
|
||||
representable, then round to the odd mantissa. This rounding
|
||||
has the nice property that for k > 1, if:
|
||||
y = round(x, p+k, TO_ODD)
|
||||
z = round(y, p, TO_NEAREST_EVEN), then
|
||||
z = round(x, p, TO_NEAREST_EVEN)
|
||||
so it avoids the double-rounding problem.
|
||||
|
||||
- add tests of the ternary value for constants
|
||||
|
||||
- When doing Extensive Check (--enable-assert=full), since all the
|
||||
functions use a similar use of MACROS (ZivLoop, ROUND_P), it should
|
||||
be possible to do such a scheme:
|
||||
For the first call to ROUND_P when we can round.
|
||||
Mark it as such and save the approximated rounding value in
|
||||
a temporary variable.
|
||||
Then after, if the mark is set, check if:
|
||||
- we still can round.
|
||||
- The rounded value is the same.
|
||||
It should be a complement to tgeneric tests.
|
||||
|
||||
- add a new exception "division by zero" (IEEE-754 terminology) / "infinitary"
|
||||
(LIA-2 terminology). In IEEE 754R (2006 February 14 8:00):
|
||||
"The division by zero exception shall be signaled iff an exact
|
||||
infinite result is defined for an operation on finite operands.
|
||||
[such as a pole or logarithmic singularity.] In particular, the
|
||||
division by zero exception shall be signaled if the divisor is
|
||||
zero and the dividend is a finite nonzero number."
|
||||
|
||||
- in div.c, try to find a case for which cy != 0 after the line
|
||||
cy = mpn_sub_1 (sp + k, sp + k, qsize, cy);
|
||||
(which should be added to the tests), e.g. by having {vp, k} = 0, or
|
||||
prove that this cannot happen.
|
||||
|
||||
- add a configure test for --enable-logging to ignore the option if
|
||||
it cannot be supported. Modify the "configure --help" description
|
||||
to say "on systems that support it".
|
||||
|
||||
- allow generic tests to run with a restricted exponent range.
|
||||
|
||||
- add generic bad cases for functions that don't have an inverse
|
||||
function that is implemented (use a single Newton iteration).
|
||||
|
||||
- add bad cases for the internal error bound (by using a dichotomy
|
||||
between a bad case for the correct rounding and some input value
|
||||
with fewer Ziv iterations?).
|
||||
|
||||
- add an option to use a 32-bit exponent type (int) on LP64 machines,
|
||||
mainly for developers, in order to be able to test the case where the
|
||||
extended exponent range is the same as the default exponent range, on
|
||||
such platforms.
|
||||
|
||||
- test underflow/overflow detection of various functions (in particular
|
||||
mpfr_exp) in reduced exponent ranges, including ranges that do not
|
||||
contain 0.
|
||||
|
||||
|
||||
##############################################################################
|
||||
7. Portability
|
||||
##############################################################################
|
||||
|
||||
- support the decimal64 function without requiring --with-gmp-build
|
||||
|
||||
- [Kevin about texp.c long strings]
|
||||
For strings longer than c99 guarantees, it might be cleaner to
|
||||
introduce a "tests_strdupcat" or something to concatenate literal
|
||||
strings into newly allocated memory. I thought I'd done that in a
|
||||
couple of places already. Arrays of chars are not much fun.
|
||||
|
||||
- use http://gcc.gnu.org/viewcvs/trunk/config/stdint.m4 for mpfr-gmp.h
|
||||
|
||||
- rename configure.in to configure.ac
|
|
@ -0,0 +1 @@
|
|||
3.0.1
|
|
@ -0,0 +1,32 @@
|
|||
/* mpfr_abort_prec_max -- Abort due to maximal precision overflow.
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
void mpfr_abort_prec_max (void)
|
||||
{
|
||||
fprintf (stderr, "MPFR: Maximal precision overflow\n");
|
||||
abort ();
|
||||
}
|
||||
|
|
@ -0,0 +1,851 @@
|
|||
dnl MPFR specific autoconf macros
|
||||
|
||||
dnl Copyright 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
dnl Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
dnl
|
||||
dnl This file is part of the GNU MPFR Library.
|
||||
dnl
|
||||
dnl The GNU MPFR Library is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU Lesser General Public License as published
|
||||
dnl by the Free Software Foundation; either version 3 of the License, or (at
|
||||
dnl your option) any later version.
|
||||
dnl
|
||||
dnl The GNU MPFR Library is distributed in the hope that it will be useful, but
|
||||
dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
dnl License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU Lesser General Public License
|
||||
dnl along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
dnl http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
dnl 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
dnl autoconf 2.60 is necessary because of the use of AC_PROG_SED.
|
||||
dnl The following line allows the autoconf wrapper (when installed)
|
||||
dnl to work as expected.
|
||||
dnl If you change the required version, please update README.dev too!
|
||||
AC_PREREQ(2.60)
|
||||
|
||||
dnl ------------------------------------------------------------
|
||||
dnl You must put in MPFR_CONFIGS everything which configure MPFR
|
||||
dnl except:
|
||||
dnl -everything dealing with CC and CFLAGS in particular the ABI
|
||||
dnl but the IEEE-754 specific flags must be set here.
|
||||
dnl -GMP's linkage.
|
||||
dnl -Libtool stuff.
|
||||
dnl -Handling of special arguments of MPFR's configure.
|
||||
AC_DEFUN([MPFR_CONFIGS],
|
||||
[
|
||||
AC_REQUIRE([AC_OBJEXT])
|
||||
AC_REQUIRE([MPFR_CHECK_LIBM])
|
||||
AC_REQUIRE([AC_HEADER_TIME])
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
|
||||
AC_CHECK_HEADER([limits.h],, AC_MSG_ERROR([limits.h not found]))
|
||||
AC_CHECK_HEADER([float.h],, AC_MSG_ERROR([float.h not found]))
|
||||
AC_CHECK_HEADER([string.h],, AC_MSG_ERROR([string.h not found]))
|
||||
|
||||
dnl Check for locales
|
||||
AC_CHECK_HEADERS([locale.h])
|
||||
|
||||
dnl Check for wide characters (wchar_t and wint_t)
|
||||
AC_CHECK_HEADERS([wchar.h])
|
||||
|
||||
dnl Check for stdargs
|
||||
AC_CHECK_HEADER([stdarg.h],[AC_DEFINE([HAVE_STDARG],1,[Define if stdarg])],
|
||||
[AC_CHECK_HEADER([varargs.h],,
|
||||
AC_MSG_ERROR([stdarg.h or varargs.h not found]))])
|
||||
|
||||
dnl sys/fpu.h - MIPS specific
|
||||
AC_CHECK_HEADERS([sys/time.h sys/fpu.h])
|
||||
|
||||
dnl Check how to get `alloca'
|
||||
AC_FUNC_ALLOCA
|
||||
|
||||
dnl SIZE_MAX macro
|
||||
gl_SIZE_MAX
|
||||
|
||||
dnl va_copy macro
|
||||
AC_MSG_CHECKING([how to copy va_list])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdarg.h>
|
||||
]], [[
|
||||
va_list ap1, ap2;
|
||||
va_copy(ap1, ap2);
|
||||
]])], [
|
||||
AC_MSG_RESULT([va_copy])
|
||||
AC_DEFINE(HAVE_VA_COPY)
|
||||
], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdarg.h>
|
||||
]], [[
|
||||
va_list ap1, ap2;
|
||||
__va_copy(ap1, ap2);
|
||||
]])], [AC_DEFINE([HAVE___VA_COPY]) AC_MSG_RESULT([__va_copy])],
|
||||
[AC_MSG_RESULT([memcpy])])])
|
||||
|
||||
dnl FIXME: The functions memmove, memset and strtol are really needed by
|
||||
dnl MPFR, but if they are implemented as macros, this is also OK (in our
|
||||
dnl case). So, we do not return an error, but their tests are currently
|
||||
dnl useless.
|
||||
dnl gettimeofday is not defined for MinGW
|
||||
AC_CHECK_FUNCS([memmove memset setlocale strtol gettimeofday])
|
||||
|
||||
dnl Check for IEEE-754 switches on Alpha
|
||||
case $host in
|
||||
alpha*-*-*)
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
AC_CACHE_CHECK([for IEEE-754 switches], mpfr_cv_ieee_switches, [
|
||||
if test -n "$GCC"; then
|
||||
mpfr_cv_ieee_switches="-mfp-rounding-mode=d -mieee-with-inexact"
|
||||
else
|
||||
mpfr_cv_ieee_switches="-fprm d -ieee_with_inexact"
|
||||
fi
|
||||
CFLAGS="$CFLAGS $mpfr_cv_ieee_switches"
|
||||
AC_TRY_COMPILE(,,, mpfr_cv_ieee_switches="none")
|
||||
])
|
||||
if test "$mpfr_cv_ieee_switches" = "none"; then
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
else
|
||||
CFLAGS="$saved_CFLAGS $mpfr_cv_ieee_switches"
|
||||
fi
|
||||
esac
|
||||
|
||||
dnl check for long long
|
||||
AC_CHECK_TYPE([long long int],
|
||||
AC_DEFINE(HAVE_LONG_LONG, 1, [Define if compiler supports long long]),,)
|
||||
|
||||
dnl intmax_t is C99
|
||||
AC_CHECK_TYPES([intmax_t])
|
||||
if test "$ac_cv_type_intmax_t" = yes; then
|
||||
AC_CACHE_CHECK([for working INTMAX_MAX], mpfr_cv_have_intmax_max, [
|
||||
AC_TRY_COMPILE([#include <stdint.h>], [intmax_t x = INTMAX_MAX;],
|
||||
mpfr_cv_have_intmax_max=yes, mpfr_cv_have_intmax_max=no)
|
||||
])
|
||||
if test "$mpfr_cv_have_intmax_max" = "yes"; then
|
||||
AC_DEFINE(MPFR_HAVE_INTMAX_MAX,1,[Define if you have a working INTMAX_MAX.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_TYPE( [union fpc_csr],
|
||||
AC_DEFINE(HAVE_FPC_CSR,1,[Define if union fpc_csr is available]), ,
|
||||
[
|
||||
#if HAVE_SYS_FPU_H
|
||||
# include <sys/fpu.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
dnl Check for fesetround
|
||||
AC_CACHE_CHECK([for fesetround], mpfr_cv_have_fesetround, [
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS="$LIBS $MPFR_LIBM"
|
||||
AC_TRY_LINK([#include <fenv.h>], [fesetround(FE_TONEAREST);],
|
||||
mpfr_cv_have_fesetround=yes, mpfr_cv_have_fesetround=no)
|
||||
LIBS="$saved_LIBS"
|
||||
])
|
||||
if test "$mpfr_cv_have_fesetround" = "yes"; then
|
||||
AC_DEFINE(MPFR_HAVE_FESETROUND,1,[Define if you have the `fesetround' function via the <fenv.h> header file.])
|
||||
fi
|
||||
|
||||
dnl Check for gcc float-conversion bug; if need be, -ffloat-store is used to
|
||||
dnl force the conversion to the destination type when a value is stored to
|
||||
dnl a variable (see ISO C99 standard 5.1.2.3#13, 6.3.1.5#2, 6.3.1.8#2). This
|
||||
dnl is important concerning the exponent range. Note that this doesn't solve
|
||||
dnl the double-rounding problem.
|
||||
if test -n "$GCC"; then
|
||||
AC_CACHE_CHECK([for gcc float-conversion bug], mpfr_cv_gcc_floatconv_bug, [
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS="$LIBS $MPFR_LIBM"
|
||||
AC_TRY_RUN([
|
||||
#include <float.h>
|
||||
#ifdef MPFR_HAVE_FESETROUND
|
||||
#include <fenv.h>
|
||||
#endif
|
||||
static double get_max (void);
|
||||
int main() {
|
||||
double x = 0.5;
|
||||
double y;
|
||||
int i;
|
||||
for (i = 1; i <= 11; i++)
|
||||
x *= x;
|
||||
if (x != 0)
|
||||
return 1;
|
||||
#ifdef MPFR_HAVE_FESETROUND
|
||||
/* Useful test for the G4 PowerPC */
|
||||
fesetround(FE_TOWARDZERO);
|
||||
x = y = get_max ();
|
||||
x *= 2.0;
|
||||
if (x != y)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
static double get_max (void) { static volatile double d = DBL_MAX; return d; }
|
||||
], [mpfr_cv_gcc_floatconv_bug="no"],
|
||||
[mpfr_cv_gcc_floatconv_bug="yes, use -ffloat-store"],
|
||||
[mpfr_cv_gcc_floatconv_bug="cannot test, use -ffloat-store"])
|
||||
LIBS="$saved_LIBS"
|
||||
])
|
||||
if test "$mpfr_cv_gcc_floatconv_bug" != "no"; then
|
||||
CFLAGS="$CFLAGS -ffloat-store"
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Check if denormalized numbers are supported
|
||||
AC_CACHE_CHECK([for denormalized numbers], mpfr_cv_have_denorms, [
|
||||
AC_TRY_RUN([
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
int main() {
|
||||
double x = 2.22507385850720138309e-308;
|
||||
fprintf (stderr, "%e\n", x / 2.0);
|
||||
return 2.0 * (x / 2.0) != x;
|
||||
}
|
||||
], mpfr_cv_have_denorms=yes, mpfr_cv_have_denorms=no, mpfr_cv_have_denorms=no)
|
||||
])
|
||||
if test "$mpfr_cv_have_denorms" = "yes"; then
|
||||
AC_DEFINE(HAVE_DENORMS,1,[Define if denormalized floats work.])
|
||||
fi
|
||||
|
||||
dnl Check whether NAN != NAN (as required by the IEEE-754 standard,
|
||||
dnl but not by the ISO C standard). For instance, this is false with
|
||||
dnl MIPSpro 7.3.1.3m under IRIX64. By default, assume this is true.
|
||||
AC_CACHE_CHECK([if NAN == NAN], mpfr_cv_nanisnan, [
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#ifndef NAN
|
||||
# define NAN (0.0/0.0)
|
||||
#endif
|
||||
int main() {
|
||||
double d;
|
||||
d = NAN;
|
||||
return d != d;
|
||||
}
|
||||
], [mpfr_cv_nanisnan="yes"],
|
||||
[mpfr_cv_nanisnan="no"],
|
||||
[mpfr_cv_nanisnan="cannot test, assume no"])
|
||||
])
|
||||
if test "$mpfr_cv_nanisnan" = "yes"; then
|
||||
AC_DEFINE(MPFR_NANISNAN,1,[Define if NAN == NAN.])
|
||||
AC_MSG_WARN([The test NAN != NAN is false. The probable reason is that])
|
||||
AC_MSG_WARN([your compiler optimizes floating-point expressions in an])
|
||||
AC_MSG_WARN([unsafe way because some option, such as -ffast-math or])
|
||||
AC_MSG_WARN([-fast (depending on the compiler), has been used. You])
|
||||
AC_MSG_WARN([should NOT use such an option, otherwise MPFR functions])
|
||||
AC_MSG_WARN([such as mpfr_get_d and mpfr_set_d may return incorrect])
|
||||
AC_MSG_WARN([results on special FP numbers (e.g. NaN or signed zeros).])
|
||||
AC_MSG_WARN([If you did not use such an option, please send us a bug])
|
||||
AC_MSG_WARN([report so that we can try to find a workaround for your])
|
||||
AC_MSG_WARN([platform and/or document the behavior.])
|
||||
fi
|
||||
|
||||
dnl Check if the chars '0' to '9' are consecutive values
|
||||
AC_MSG_CHECKING([if charset has consecutive values])
|
||||
AC_RUN_IFELSE(AC_LANG_PROGRAM([[
|
||||
char *number = "0123456789";
|
||||
char *lower = "abcdefghijklmnopqrstuvwxyz";
|
||||
char *upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
]],[[
|
||||
int i;
|
||||
unsigned char *p;
|
||||
for (p = (unsigned char*) number, i = 0; i < 9; i++)
|
||||
if ( (*p)+1 != *(p+1) ) return 1;
|
||||
for (p = (unsigned char*) lower, i = 0; i < 25; i++)
|
||||
if ( (*p)+1 != *(p+1) ) return 1;
|
||||
for (p = (unsigned char*) upper, i = 0; i < 25; i++)
|
||||
if ( (*p)+1 != *(p+1) ) return 1;
|
||||
]]), [AC_MSG_RESULT(yes)],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_DEFINE(MPFR_NO_CONSECUTIVE_CHARSET,1,[Charset is not consecutive])
|
||||
], [AC_MSG_RESULT(can not test)])
|
||||
|
||||
dnl Must be checked with the LIBM
|
||||
dnl but we don't want to add the LIBM to MPFR dependency.
|
||||
dnl Can't use AC_CHECK_FUNCS since the function may be in LIBM but
|
||||
dnl not exported in math.h
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS="$LIBS $MPFR_LIBM"
|
||||
dnl AC_CHECK_FUNCS([round trunc floor ceil nearbyint])
|
||||
AC_MSG_CHECKING(for math/round)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <math.h>
|
||||
int f (double (*func)(double)) { return 0;}
|
||||
]], [[
|
||||
double a = 17.42;
|
||||
a = f (round);
|
||||
return 0;
|
||||
]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_ROUND, 1,[Have ISO-C99 round function])
|
||||
],[AC_MSG_RESULT(no)])
|
||||
|
||||
AC_MSG_CHECKING(for math/trunc)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <math.h>
|
||||
int f (double (*func)(double)) { return 0;}
|
||||
]], [[
|
||||
double a = 17.42;
|
||||
a = f(trunc);
|
||||
return 0;
|
||||
]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_TRUNC, 1,[Have ISO-C99 trunc function])
|
||||
],[AC_MSG_RESULT(no)])
|
||||
|
||||
AC_MSG_CHECKING(for math/floor)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <math.h>
|
||||
int f (double (*func)(double)) { return 0;}
|
||||
]], [[
|
||||
double a = 17.42;
|
||||
a = f(floor);
|
||||
return 0;
|
||||
]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_FLOOR, 1,[Have ISO-C99 floor function])
|
||||
],[AC_MSG_RESULT(no)])
|
||||
|
||||
AC_MSG_CHECKING(for math/ceil)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <math.h>
|
||||
int f (double (*func)(double)) { return 0;}
|
||||
]], [[
|
||||
double a = 17.42;
|
||||
a = f(ceil);
|
||||
return 0;
|
||||
]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_CEIL, 1,[Have ISO-C99 ceil function])
|
||||
],[AC_MSG_RESULT(no)])
|
||||
|
||||
AC_MSG_CHECKING(for math/rint)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <math.h>
|
||||
int f (double (*func)(double)) { return 0;}
|
||||
]], [[
|
||||
double a = 17.42;
|
||||
a = f(nearbyint);
|
||||
return 0;
|
||||
]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_NEARBYINT, 1,[Have ISO-C99 rint function])
|
||||
],[AC_MSG_RESULT(no)])
|
||||
|
||||
LIBS="$saved_LIBS"
|
||||
|
||||
dnl Now try to check the long double format
|
||||
MPFR_C_LONG_DOUBLE_FORMAT
|
||||
|
||||
dnl Check if thread-local variables are supported.
|
||||
dnl At least two problems can occur in practice:
|
||||
dnl 1. The compilation fails, e.g. because the compiler doesn't know
|
||||
dnl about the __thread keyword.
|
||||
dnl 2. The compilation succeeds, but the system doesn't support TLS or
|
||||
dnl there is some ld configuration problem. One of the effects can
|
||||
dnl be that thread-local variables always evaluate to 0. So, it is
|
||||
dnl important to run the test below.
|
||||
if test "$enable_thread_safe" = yes; then
|
||||
AC_CACHE_CHECK([for TLS support], mpfr_cv_working_tls, [
|
||||
saved_CPPFLAGS="$CPPFLAGS"
|
||||
# The -I$srcdir is necessary when objdir is different from srcdir.
|
||||
CPPFLAGS="$CPPFLAGS -I$srcdir"
|
||||
AC_RUN_IFELSE([
|
||||
#define MPFR_USE_THREAD_SAFE 1
|
||||
#include "mpfr-thread.h"
|
||||
MPFR_THREAD_ATTR int x = 17;
|
||||
int main() {
|
||||
return x != 17;
|
||||
}
|
||||
], [mpfr_cv_working_tls="yes"],
|
||||
[AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([please configure with --disable-thread-safe])],
|
||||
[mpfr_cv_working_tls="cannot test, assume yes"])
|
||||
CPPFLAGS="$saved_CPPFLAGS"
|
||||
])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl MPFR_C_LONG_DOUBLE_FORMAT
|
||||
dnl -------------------------
|
||||
dnl Determine the format of a long double.
|
||||
dnl
|
||||
dnl The object file is grepped, so as to work when cross compiling. A
|
||||
dnl start and end sequence is included to avoid false matches, and
|
||||
dnl allowance is made for the desired data crossing an "od -b" line
|
||||
dnl boundary. The test number is a small integer so it should appear
|
||||
dnl exactly, no rounding or truncation etc.
|
||||
dnl
|
||||
dnl "od -b" is supported even by Unix V7, and the awk script used doesn't
|
||||
dnl have functions or anything, so even an "old" awk should suffice.
|
||||
dnl
|
||||
dnl The 10-byte IEEE extended format is generally padded to either 12 or 16
|
||||
dnl bytes for alignment purposes. The SVR4 i386 ABI is 12 bytes, or i386
|
||||
dnl gcc -m128bit-long-double selects 16 bytes. IA-64 is 16 bytes in LP64
|
||||
dnl mode, or 12 bytes in ILP32 mode. The first 10 bytes is the relevant
|
||||
dnl part in all cases (big and little endian).
|
||||
dnl
|
||||
dnl Enhancements:
|
||||
dnl
|
||||
dnl Could match more formats, but no need to worry until there's code
|
||||
dnl wanting to use them.
|
||||
dnl
|
||||
dnl Don't want to duplicate the double matching from GMP_C_DOUBLE_FORMAT,
|
||||
dnl perhaps we should merge with that macro, to match data formats
|
||||
dnl irrespective of the C type in question. Or perhaps just let the code
|
||||
dnl use DOUBLE macros when sizeof(double)==sizeof(long double).
|
||||
|
||||
AC_DEFUN([MPFR_C_LONG_DOUBLE_FORMAT],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([AC_PROG_AWK])
|
||||
AC_REQUIRE([AC_OBJEXT])
|
||||
AC_CHECK_TYPES([long double])
|
||||
AC_CACHE_CHECK([format of `long double' floating point],
|
||||
mpfr_cv_c_long_double_format,
|
||||
[mpfr_cv_c_long_double_format=unknown
|
||||
if test "$ac_cv_type_long_double" != yes; then
|
||||
mpfr_cv_c_long_double_format="not available"
|
||||
else
|
||||
cat >conftest.c <<\EOF
|
||||
[
|
||||
/* "before" is 16 bytes to ensure there's no padding between it and "x".
|
||||
We're not expecting any "long double" bigger than 16 bytes or with
|
||||
alignment requirements stricter than 16 bytes. */
|
||||
struct {
|
||||
char before[16];
|
||||
long double x;
|
||||
char after[8];
|
||||
} foo = {
|
||||
{ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\001', '\043', '\105', '\147', '\211', '\253', '\315', '\357' },
|
||||
-123456789.0,
|
||||
{ '\376', '\334', '\272', '\230', '\166', '\124', '\062', '\020' }
|
||||
};
|
||||
]
|
||||
EOF
|
||||
mpfr_compile="$CC $CFLAGS $CPPFLAGS -c conftest.c >&AC_FD_CC 2>&1"
|
||||
if AC_TRY_EVAL(mpfr_compile); then
|
||||
cat >conftest.awk <<\EOF
|
||||
[
|
||||
BEGIN {
|
||||
found = 0
|
||||
}
|
||||
|
||||
# got[] holds a sliding window of bytes read the input. got[0] is the most
|
||||
# recent byte read, and got[31] the oldest byte read, so when looking to
|
||||
# match some data the indices are "reversed".
|
||||
#
|
||||
{
|
||||
for (f = 2; f <= NF; f++)
|
||||
{
|
||||
# new byte, shift others up
|
||||
for (i = 31; i >= 0; i--)
|
||||
got[i+1] = got[i];
|
||||
got[0] = $f;
|
||||
|
||||
# end sequence
|
||||
if (got[7] != "376") continue
|
||||
if (got[6] != "334") continue
|
||||
if (got[5] != "272") continue
|
||||
if (got[4] != "230") continue
|
||||
if (got[3] != "166") continue
|
||||
if (got[2] != "124") continue
|
||||
if (got[1] != "062") continue
|
||||
if (got[0] != "020") continue
|
||||
|
||||
# start sequence, with 8-byte body
|
||||
if (got[23] == "001" && \
|
||||
got[22] == "043" && \
|
||||
got[21] == "105" && \
|
||||
got[20] == "147" && \
|
||||
got[19] == "211" && \
|
||||
got[18] == "253" && \
|
||||
got[17] == "315" && \
|
||||
got[16] == "357")
|
||||
{
|
||||
saw = " (" got[15] \
|
||||
" " got[14] \
|
||||
" " got[13] \
|
||||
" " got[12] \
|
||||
" " got[11] \
|
||||
" " got[10] \
|
||||
" " got[9] \
|
||||
" " got[8] ")"
|
||||
|
||||
if (got[15] == "301" && \
|
||||
got[14] == "235" && \
|
||||
got[13] == "157" && \
|
||||
got[12] == "064" && \
|
||||
got[11] == "124" && \
|
||||
got[10] == "000" && \
|
||||
got[9] == "000" && \
|
||||
got[8] == "000")
|
||||
{
|
||||
print "IEEE double, big endian"
|
||||
found = 1
|
||||
exit
|
||||
}
|
||||
|
||||
if (got[15] == "000" && \
|
||||
got[14] == "000" && \
|
||||
got[13] == "000" && \
|
||||
got[12] == "124" && \
|
||||
got[11] == "064" && \
|
||||
got[10] == "157" && \
|
||||
got[9] == "235" && \
|
||||
got[8] == "301")
|
||||
{
|
||||
print "IEEE double, little endian"
|
||||
found = 1
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
# start sequence, with 12-byte body
|
||||
if (got[27] == "001" && \
|
||||
got[26] == "043" && \
|
||||
got[25] == "105" && \
|
||||
got[24] == "147" && \
|
||||
got[23] == "211" && \
|
||||
got[22] == "253" && \
|
||||
got[21] == "315" && \
|
||||
got[20] == "357")
|
||||
{
|
||||
saw = " (" got[19] \
|
||||
" " got[18] \
|
||||
" " got[17] \
|
||||
" " got[16] \
|
||||
" " got[15] \
|
||||
" " got[14] \
|
||||
" " got[13] \
|
||||
" " got[12] \
|
||||
" " got[11] \
|
||||
" " got[10] \
|
||||
" " got[9] \
|
||||
" " got[8] ")"
|
||||
|
||||
if (got[19] == "000" && \
|
||||
got[18] == "000" && \
|
||||
got[17] == "000" && \
|
||||
got[16] == "000" && \
|
||||
got[15] == "240" && \
|
||||
got[14] == "242" && \
|
||||
got[13] == "171" && \
|
||||
got[12] == "353" && \
|
||||
got[11] == "031" && \
|
||||
got[10] == "300")
|
||||
{
|
||||
print "IEEE extended, little endian"
|
||||
found = 1
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
# start sequence, with 16-byte body
|
||||
if (got[31] == "001" && \
|
||||
got[30] == "043" && \
|
||||
got[29] == "105" && \
|
||||
got[28] == "147" && \
|
||||
got[27] == "211" && \
|
||||
got[26] == "253" && \
|
||||
got[25] == "315" && \
|
||||
got[24] == "357")
|
||||
{
|
||||
saw = " (" got[23] \
|
||||
" " got[22] \
|
||||
" " got[21] \
|
||||
" " got[20] \
|
||||
" " got[19] \
|
||||
" " got[18] \
|
||||
" " got[17] \
|
||||
" " got[16] \
|
||||
" " got[15] \
|
||||
" " got[14] \
|
||||
" " got[13] \
|
||||
" " got[12] \
|
||||
" " got[11] \
|
||||
" " got[10] \
|
||||
" " got[9] \
|
||||
" " got[8] ")"
|
||||
|
||||
if (got[23] == "000" && \
|
||||
got[22] == "000" && \
|
||||
got[21] == "000" && \
|
||||
got[20] == "000" && \
|
||||
got[19] == "240" && \
|
||||
got[18] == "242" && \
|
||||
got[17] == "171" && \
|
||||
got[16] == "353" && \
|
||||
got[15] == "031" && \
|
||||
got[14] == "300")
|
||||
{
|
||||
print "IEEE extended, little endian"
|
||||
found = 1
|
||||
exit
|
||||
}
|
||||
|
||||
if (got[23] == "300" && \
|
||||
got[22] == "031" && \
|
||||
got[21] == "326" && \
|
||||
got[20] == "363" && \
|
||||
got[19] == "105" && \
|
||||
got[18] == "100" && \
|
||||
got[17] == "000" && \
|
||||
got[16] == "000" && \
|
||||
got[15] == "000" && \
|
||||
got[14] == "000" && \
|
||||
got[13] == "000" && \
|
||||
got[12] == "000" && \
|
||||
got[11] == "000" && \
|
||||
got[10] == "000" && \
|
||||
got[9] == "000" && \
|
||||
got[8] == "000")
|
||||
{
|
||||
print "IEEE quad, big endian"
|
||||
found = 1
|
||||
exit
|
||||
}
|
||||
|
||||
if (got[23] == "000" && \
|
||||
got[22] == "000" && \
|
||||
got[21] == "000" && \
|
||||
got[20] == "000" && \
|
||||
got[19] == "000" && \
|
||||
got[18] == "000" && \
|
||||
got[17] == "000" && \
|
||||
got[16] == "000" && \
|
||||
got[15] == "000" && \
|
||||
got[14] == "000" && \
|
||||
got[13] == "100" && \
|
||||
got[12] == "105" && \
|
||||
got[11] == "363" && \
|
||||
got[10] == "326" && \
|
||||
got[9] == "031" && \
|
||||
got[8] == "300")
|
||||
{
|
||||
print "IEEE quad, little endian"
|
||||
found = 1
|
||||
exit
|
||||
}
|
||||
|
||||
if (got[23] == "301" && \
|
||||
got[22] == "235" && \
|
||||
got[21] == "157" && \
|
||||
got[20] == "064" && \
|
||||
got[19] == "124" && \
|
||||
got[18] == "000" && \
|
||||
got[17] == "000" && \
|
||||
got[16] == "000" && \
|
||||
got[15] == "000" && \
|
||||
got[14] == "000" && \
|
||||
got[13] == "000" && \
|
||||
got[12] == "000" && \
|
||||
got[11] == "000" && \
|
||||
got[10] == "000" && \
|
||||
got[9] == "000" && \
|
||||
got[8] == "000")
|
||||
{
|
||||
print "possibly double-double, big endian"
|
||||
found = 1
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if (! found)
|
||||
print "unknown", saw
|
||||
}
|
||||
]
|
||||
EOF
|
||||
mpfr_cv_c_long_double_format=`od -b conftest.$OBJEXT | $AWK -f conftest.awk`
|
||||
case $mpfr_cv_c_long_double_format in
|
||||
unknown*)
|
||||
echo "cannot match anything, conftest.$OBJEXT contains" >&AC_FD_CC
|
||||
od -b conftest.$OBJEXT >&AC_FD_CC
|
||||
;;
|
||||
esac
|
||||
else
|
||||
AC_MSG_WARN([oops, cannot compile test program])
|
||||
fi
|
||||
fi
|
||||
rm -f conftest*
|
||||
])
|
||||
|
||||
AH_VERBATIM([HAVE_LDOUBLE],
|
||||
[/* Define one of the following to 1 for the format of a `long double'.
|
||||
If your format is not among these choices, or you don't know what it is,
|
||||
then leave all undefined.
|
||||
IEEE_EXT is the 10-byte IEEE extended precision format.
|
||||
IEEE_QUAD is the 16-byte IEEE quadruple precision format.
|
||||
LITTLE or BIG is the endianness. */
|
||||
#undef HAVE_LDOUBLE_IEEE_EXT_LITTLE
|
||||
#undef HAVE_LDOUBLE_IEEE_QUAD_BIG])
|
||||
|
||||
case $mpfr_cv_c_long_double_format in
|
||||
"IEEE extended, little endian")
|
||||
AC_DEFINE(HAVE_LDOUBLE_IEEE_EXT_LITTLE, 1)
|
||||
;;
|
||||
"IEEE quad, big endian")
|
||||
AC_DEFINE(HAVE_LDOUBLE_IEEE_QUAD_BIG, 1)
|
||||
;;
|
||||
"IEEE quad, little endian")
|
||||
AC_DEFINE(HAVE_LDOUBLE_IEEE_QUAD_LITTLE, 1)
|
||||
;;
|
||||
"possibly double-double, big endian")
|
||||
AC_MSG_WARN([This format is known on GCC/PowerPC platforms,])
|
||||
AC_MSG_WARN([but due to GCC PR26374, we can't test further.])
|
||||
AC_MSG_WARN([You can safely ignore this warning, though.])
|
||||
# Since we are not sure, we do not want to define a macro.
|
||||
;;
|
||||
unknown* | "not available")
|
||||
;;
|
||||
*)
|
||||
AC_MSG_WARN([oops, unrecognised float format: $mpfr_cv_c_long_double_format])
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
|
||||
dnl MPFR_CHECK_LIBM
|
||||
dnl ---------------
|
||||
dnl Determine a math library -lm to use.
|
||||
|
||||
AC_DEFUN([MPFR_CHECK_LIBM],
|
||||
[AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_SUBST(MPFR_LIBM,'')
|
||||
case $host in
|
||||
*-*-beos* | *-*-cygwin* | *-*-pw32*)
|
||||
# According to libtool AC CHECK LIBM, these systems don't have libm
|
||||
;;
|
||||
*-*-solaris*)
|
||||
# On Solaris the math functions new in C99 are in -lm9x.
|
||||
# FIXME: Do we need -lm9x as well as -lm, or just instead of?
|
||||
AC_CHECK_LIB(m9x, main, MPFR_LIBM="-lm9x")
|
||||
AC_CHECK_LIB(m, main, MPFR_LIBM="$MPFR_LIBM -lm")
|
||||
;;
|
||||
*-ncr-sysv4.3*)
|
||||
# FIXME: What does -lmw mean? Libtool AC CHECK LIBM does it this way.
|
||||
AC_CHECK_LIB(mw, _mwvalidcheckl, MPFR_LIBM="-lmw")
|
||||
AC_CHECK_LIB(m, main, MPFR_LIBM="$MPFR_LIBM -lm")
|
||||
;;
|
||||
*)
|
||||
AC_CHECK_LIB(m, main, MPFR_LIBM="-lm")
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
|
||||
dnl MPFR_LD_SEARCH_PATHS_FIRST
|
||||
dnl --------------------------
|
||||
|
||||
AC_DEFUN([MPFR_LD_SEARCH_PATHS_FIRST],
|
||||
[case "$LD $LDFLAGS" in
|
||||
*-Wl,-search_paths_first*) ;;
|
||||
*) AC_MSG_CHECKING([if the compiler understands -Wl,-search_paths_first])
|
||||
saved_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="-Wl,-search_paths_first $LDFLAGS"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
|
||||
[AC_MSG_RESULT(yes)],
|
||||
[AC_MSG_RESULT(no)]
|
||||
LDFLAGS="$saved_LDFLAGS")
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
|
||||
dnl GMP_C_ATTRIBUTE_MODE
|
||||
dnl --------------------
|
||||
dnl Introduced in gcc 2.2, but perhaps not in all Apple derived versions.
|
||||
dnl Needed for mpfr-longlong.h; this is currently necessary for s390.
|
||||
dnl
|
||||
dnl TODO: Replace this with a cleaner type size detection, as this
|
||||
dnl solution only works with gcc and assumes CHAR_BIT == 8. Probably use
|
||||
dnl <stdint.h>, and <http://gcc.gnu.org/viewcvs/trunk/config/stdint.m4>
|
||||
dnl as a fallback.
|
||||
|
||||
AC_DEFUN([GMP_C_ATTRIBUTE_MODE],
|
||||
[AC_CACHE_CHECK([whether gcc __attribute__ ((mode (XX))) works],
|
||||
gmp_cv_c_attribute_mode,
|
||||
[AC_TRY_COMPILE([typedef int SItype __attribute__ ((mode (SI)));], ,
|
||||
gmp_cv_c_attribute_mode=yes, gmp_cv_c_attribute_mode=no)
|
||||
])
|
||||
if test $gmp_cv_c_attribute_mode = yes; then
|
||||
AC_DEFINE(HAVE_ATTRIBUTE_MODE, 1,
|
||||
[Define to 1 if the compiler accepts gcc style __attribute__ ((mode (XX)))])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl MPFR_FUNC_GMP_PRINTF_SPEC
|
||||
dnl ------------------------------------
|
||||
dnl MPFR_FUNC_GMP_PRINTF_SPEC(spec, type, [includes], [if-true], [if-false])
|
||||
dnl Check if gmp_sprintf supports the conversion specification 'spec'
|
||||
dnl with type 'type'.
|
||||
dnl Expand 'if-true' if printf supports 'spec', 'if-false' otherwise.
|
||||
|
||||
AC_DEFUN([MPFR_FUNC_GMP_PRINTF_SPEC],[
|
||||
AC_MSG_CHECKING(if gmp_printf supports "%$1")
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdio.h>
|
||||
$3
|
||||
#include <gmp.h>
|
||||
]], [[
|
||||
char s[256];
|
||||
$2 a = 17;
|
||||
|
||||
if (gmp_sprintf (s, "(%0.0$1)(%d)", a, 42) == -1) return 1;
|
||||
return (strcmp (s, "(17)(42)") != 0);
|
||||
]])],
|
||||
[AC_MSG_RESULT(yes)
|
||||
$4],
|
||||
[AC_MSG_RESULT(no)
|
||||
$5])
|
||||
])
|
||||
|
||||
|
||||
dnl MPFR_CHECK_PRINTF_SPEC
|
||||
dnl ----------------------
|
||||
dnl Check if gmp_printf supports some optional length modifiers.
|
||||
dnl Defined symbols are negative to shorten the gcc command line.
|
||||
|
||||
AC_DEFUN([MPFR_CHECK_PRINTF_SPEC], [
|
||||
AC_REQUIRE([MPFR_CONFIGS])dnl
|
||||
if test "$ac_cv_type_intmax_t" = yes; then
|
||||
MPFR_FUNC_GMP_PRINTF_SPEC([jd], [intmax_t], [
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
],,
|
||||
[AC_DEFINE([NPRINTF_J], 1, [gmp_printf cannot read intmax_t])])
|
||||
fi
|
||||
|
||||
MPFR_FUNC_GMP_PRINTF_SPEC([hhd], [char], [
|
||||
#include <gmp.h>
|
||||
],,
|
||||
[AC_DEFINE([NPRINTF_HH], 1, [gmp_printf cannot use 'hh' length modifier])])
|
||||
|
||||
MPFR_FUNC_GMP_PRINTF_SPEC([lld], [long long int], [
|
||||
#include <gmp.h>
|
||||
],,
|
||||
[AC_DEFINE([NPRINTF_LL], 1, [gmp_printf cannot read long long int])])
|
||||
|
||||
MPFR_FUNC_GMP_PRINTF_SPEC([Lf], [long double], [
|
||||
#include <gmp.h>
|
||||
],,
|
||||
[AC_DEFINE([NPRINTF_L], 1, [gmp_printf cannot read long double])])
|
||||
|
||||
MPFR_FUNC_GMP_PRINTF_SPEC([td], [ptrdiff_t], [
|
||||
#if defined (__cplusplus)
|
||||
#include <cstddef>
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#include "gmp.h"
|
||||
],,
|
||||
[AC_DEFINE([NPRINTF_T], 1, [gmp_printf cannot read ptrdiff_t])])
|
||||
])
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,144 @@
|
|||
/* mpfr_acos -- arc-cosinus of a floating-point number
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library, and was contributed by Mathieu Dutour.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_acos (mpfr_ptr acos, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t xp, arcc, tmp;
|
||||
mpfr_exp_t supplement;
|
||||
mpfr_prec_t prec;
|
||||
int sign, compared, inexact;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("acos[%#R]=%R inexact=%d", acos, acos, inexact));
|
||||
|
||||
/* Singular cases */
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
|
||||
{
|
||||
MPFR_SET_NAN (acos);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else /* necessarily x=0 */
|
||||
{
|
||||
MPFR_ASSERTD(MPFR_IS_ZERO(x));
|
||||
/* acos(0)=Pi/2 */
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
inexact = mpfr_const_pi (acos, rnd_mode);
|
||||
mpfr_div_2ui (acos, acos, 1, rnd_mode); /* exact */
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (acos, inexact, rnd_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set x_p=|x| */
|
||||
sign = MPFR_SIGN (x);
|
||||
mpfr_init2 (xp, MPFR_PREC (x));
|
||||
mpfr_abs (xp, x, MPFR_RNDN); /* Exact */
|
||||
|
||||
compared = mpfr_cmp_ui (xp, 1);
|
||||
|
||||
if (MPFR_UNLIKELY (compared >= 0))
|
||||
{
|
||||
mpfr_clear (xp);
|
||||
if (compared > 0) /* acos(x) = NaN for x > 1 */
|
||||
{
|
||||
MPFR_SET_NAN(acos);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MPFR_IS_POS_SIGN (sign)) /* acos(+1) = 0 */
|
||||
return mpfr_set_ui (acos, 0, rnd_mode);
|
||||
else /* acos(-1) = Pi */
|
||||
return mpfr_const_pi (acos, rnd_mode);
|
||||
}
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* Compute the supplement */
|
||||
mpfr_ui_sub (xp, 1, xp, MPFR_RNDD);
|
||||
if (MPFR_IS_POS_SIGN (sign))
|
||||
supplement = 2 - 2 * MPFR_GET_EXP (xp);
|
||||
else
|
||||
supplement = 2 - MPFR_GET_EXP (xp);
|
||||
mpfr_clear (xp);
|
||||
|
||||
prec = MPFR_PREC (acos);
|
||||
prec += MPFR_INT_CEIL_LOG2(prec) + 10 + supplement;
|
||||
|
||||
/* VL: The following change concerning prec comes from r3145
|
||||
"Optimize mpfr_acos by choosing a better initial precision."
|
||||
but it doesn't seem to be correct and leads to problems (assertion
|
||||
failure or very important inefficiency) with tiny arguments.
|
||||
Therefore, I've disabled it. */
|
||||
/* If x ~ 2^-N, acos(x) ~ PI/2 - x - x^3/6
|
||||
If Prec < 2*N, we can't round since x^3/6 won't be counted. */
|
||||
#if 0
|
||||
if (MPFR_PREC (acos) >= MPFR_PREC (x) && MPFR_GET_EXP (x) < 0)
|
||||
{
|
||||
mpfr_uexp_t pmin = (mpfr_uexp_t) (-2 * MPFR_GET_EXP (x)) + 5;
|
||||
MPFR_ASSERTN (pmin <= MPFR_PREC_MAX);
|
||||
if (prec < pmin)
|
||||
prec = pmin;
|
||||
}
|
||||
#endif
|
||||
|
||||
mpfr_init2 (tmp, prec);
|
||||
mpfr_init2 (arcc, prec);
|
||||
|
||||
MPFR_ZIV_INIT (loop, prec);
|
||||
for (;;)
|
||||
{
|
||||
/* acos(x) = Pi/2 - asin(x) = Pi/2 - atan(x/sqrt(1-x^2)) */
|
||||
mpfr_sqr (tmp, x, MPFR_RNDN);
|
||||
mpfr_ui_sub (tmp, 1, tmp, MPFR_RNDN);
|
||||
mpfr_sqrt (tmp, tmp, MPFR_RNDN);
|
||||
mpfr_div (tmp, x, tmp, MPFR_RNDN);
|
||||
mpfr_atan (arcc, tmp, MPFR_RNDN);
|
||||
mpfr_const_pi (tmp, MPFR_RNDN);
|
||||
mpfr_div_2ui (tmp, tmp, 1, MPFR_RNDN);
|
||||
mpfr_sub (arcc, tmp, arcc, MPFR_RNDN);
|
||||
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (arcc, prec - supplement,
|
||||
MPFR_PREC (acos), rnd_mode)))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, prec);
|
||||
mpfr_set_prec (tmp, prec);
|
||||
mpfr_set_prec (arcc, prec);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inexact = mpfr_set (acos, arcc, rnd_mode);
|
||||
mpfr_clear (tmp);
|
||||
mpfr_clear (arcc);
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (acos, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/* mpfr_acosh -- inverse hyperbolic cosine
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* The computation of acosh is done by *
|
||||
* acosh= ln(x + sqrt(x^2-1)) */
|
||||
|
||||
int
|
||||
mpfr_acosh (mpfr_ptr y, mpfr_srcptr x , mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
int inexact;
|
||||
int comp;
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
/* Deal with special cases */
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
/* Nan, or zero or -Inf */
|
||||
if (MPFR_IS_INF (x) && MPFR_IS_POS (x))
|
||||
{
|
||||
MPFR_SET_INF (y);
|
||||
MPFR_SET_POS (y);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
else /* Nan, or zero or -Inf */
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
}
|
||||
comp = mpfr_cmp_ui (x, 1);
|
||||
if (MPFR_UNLIKELY (comp < 0))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_UNLIKELY (comp == 0))
|
||||
{
|
||||
MPFR_SET_ZERO (y); /* acosh(1) = 0 */
|
||||
MPFR_SET_POS (y);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* General case */
|
||||
{
|
||||
/* Declaration of the intermediary variables */
|
||||
mpfr_t t;
|
||||
/* Declaration of the size variables */
|
||||
mpfr_prec_t Ny = MPFR_PREC(y); /* Precision of output variable */
|
||||
mpfr_prec_t Nt; /* Precision of the intermediary variable */
|
||||
mpfr_exp_t err, exp_te, d; /* Precision of error */
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
/* compute the precision of intermediary variable */
|
||||
/* the optimal number of bits : see algorithms.tex */
|
||||
Nt = Ny + 4 + MPFR_INT_CEIL_LOG2 (Ny);
|
||||
|
||||
/* initialization of intermediary variables */
|
||||
mpfr_init2 (t, Nt);
|
||||
|
||||
/* First computation of acosh */
|
||||
MPFR_ZIV_INIT (loop, Nt);
|
||||
for (;;)
|
||||
{
|
||||
MPFR_BLOCK_DECL (flags);
|
||||
|
||||
/* compute acosh */
|
||||
MPFR_BLOCK (flags, mpfr_mul (t, x, x, MPFR_RNDD)); /* x^2 */
|
||||
if (MPFR_OVERFLOW (flags))
|
||||
{
|
||||
mpfr_t ln2;
|
||||
mpfr_prec_t pln2;
|
||||
|
||||
/* As x is very large and the precision is not too large, we
|
||||
assume that we obtain the same result by evaluating ln(2x).
|
||||
We need to compute ln(x) + ln(2) as 2x can overflow. TODO:
|
||||
write a proof and add an MPFR_ASSERTN. */
|
||||
mpfr_log (t, x, MPFR_RNDN); /* err(log) < 1/2 ulp(t) */
|
||||
pln2 = Nt - MPFR_PREC_MIN < MPFR_GET_EXP (t) ?
|
||||
MPFR_PREC_MIN : Nt - MPFR_GET_EXP (t);
|
||||
mpfr_init2 (ln2, pln2);
|
||||
mpfr_const_log2 (ln2, MPFR_RNDN); /* err(ln2) < 1/2 ulp(t) */
|
||||
mpfr_add (t, t, ln2, MPFR_RNDN); /* err <= 3/2 ulp(t) */
|
||||
mpfr_clear (ln2);
|
||||
err = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
exp_te = MPFR_GET_EXP (t);
|
||||
mpfr_sub_ui (t, t, 1, MPFR_RNDD); /* x^2-1 */
|
||||
if (MPFR_UNLIKELY (MPFR_IS_ZERO (t)))
|
||||
{
|
||||
/* This means that x is very close to 1: x = 1 + t with
|
||||
t < 2^(-Nt). We have: acosh(x) = sqrt(2t) (1 - eps(t))
|
||||
with 0 < eps(t) < t / 12. */
|
||||
mpfr_sub_ui (t, x, 1, MPFR_RNDD); /* t = x - 1 */
|
||||
mpfr_mul_2ui (t, t, 1, MPFR_RNDN); /* 2t */
|
||||
mpfr_sqrt (t, t, MPFR_RNDN); /* sqrt(2t) */
|
||||
err = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
d = exp_te - MPFR_GET_EXP (t);
|
||||
mpfr_sqrt (t, t, MPFR_RNDN); /* sqrt(x^2-1) */
|
||||
mpfr_add (t, t, x, MPFR_RNDN); /* sqrt(x^2-1)+x */
|
||||
mpfr_log (t, t, MPFR_RNDN); /* ln(sqrt(x^2-1)+x) */
|
||||
|
||||
/* error estimate -- see algorithms.tex */
|
||||
err = 3 + MAX (1, d) - MPFR_GET_EXP (t);
|
||||
/* error is bounded by 1/2 + 2^err <= 2^(max(0,1+err)) */
|
||||
err = MAX (0, 1 + err);
|
||||
}
|
||||
}
|
||||
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (t, Nt - err, Ny, rnd_mode)))
|
||||
break;
|
||||
|
||||
/* reactualisation of the precision */
|
||||
MPFR_ZIV_NEXT (loop, Nt);
|
||||
mpfr_set_prec (t, Nt);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inexact = mpfr_set (y, t, rnd_mode);
|
||||
|
||||
mpfr_clear (t);
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/* mpfr_add -- add two floating-point numbers
|
||||
|
||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_add (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
MPFR_LOG_FUNC (("b[%#R]=%R c[%#R]=%R rnd=%d", b, b, c, c, rnd_mode),
|
||||
("a[%#R]=%R", a, a));
|
||||
|
||||
if (MPFR_ARE_SINGULAR(b,c))
|
||||
{
|
||||
if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c))
|
||||
{
|
||||
MPFR_SET_NAN(a);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
/* neither b nor c is NaN here */
|
||||
else if (MPFR_IS_INF(b))
|
||||
{
|
||||
if (!MPFR_IS_INF(c) || MPFR_SIGN(b) == MPFR_SIGN(c))
|
||||
{
|
||||
MPFR_SET_INF(a);
|
||||
MPFR_SET_SAME_SIGN(a, b);
|
||||
MPFR_RET(0); /* exact */
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_SET_NAN(a);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
}
|
||||
else if (MPFR_IS_INF(c))
|
||||
{
|
||||
MPFR_SET_INF(a);
|
||||
MPFR_SET_SAME_SIGN(a, c);
|
||||
MPFR_RET(0); /* exact */
|
||||
}
|
||||
/* now either b or c is zero */
|
||||
else if (MPFR_IS_ZERO(b))
|
||||
{
|
||||
if (MPFR_IS_ZERO(c))
|
||||
{
|
||||
/* for round away, we take the same convention for 0 + 0
|
||||
as for round to zero or to nearest: it always gives +0,
|
||||
except (-0) + (-0) = -0. */
|
||||
MPFR_SET_SIGN(a,
|
||||
(rnd_mode != MPFR_RNDD ?
|
||||
((MPFR_IS_NEG(b) && MPFR_IS_NEG(c)) ? -1 : 1) :
|
||||
((MPFR_IS_POS(b) && MPFR_IS_POS(c)) ? 1 : -1)));
|
||||
MPFR_SET_ZERO(a);
|
||||
MPFR_RET(0); /* 0 + 0 is exact */
|
||||
}
|
||||
return mpfr_set (a, c, rnd_mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_ASSERTD(MPFR_IS_ZERO(c));
|
||||
return mpfr_set (a, b, rnd_mode);
|
||||
}
|
||||
}
|
||||
|
||||
MPFR_ASSERTD(MPFR_IS_PURE_FP(b) && MPFR_IS_PURE_FP(c));
|
||||
|
||||
if (MPFR_UNLIKELY(MPFR_SIGN(b) != MPFR_SIGN(c)))
|
||||
{ /* signs differ, it's a subtraction */
|
||||
if (MPFR_LIKELY(MPFR_PREC(a) == MPFR_PREC(b)
|
||||
&& MPFR_PREC(b) == MPFR_PREC(c)))
|
||||
return mpfr_sub1sp(a,b,c,rnd_mode);
|
||||
else
|
||||
return mpfr_sub1(a, b, c, rnd_mode);
|
||||
}
|
||||
else
|
||||
{ /* signs are equal, it's an addition */
|
||||
if (MPFR_LIKELY(MPFR_PREC(a) == MPFR_PREC(b)
|
||||
&& MPFR_PREC(b) == MPFR_PREC(c)))
|
||||
if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c))
|
||||
return mpfr_add1sp(a, c, b, rnd_mode);
|
||||
else
|
||||
return mpfr_add1sp(a, b, c, rnd_mode);
|
||||
else
|
||||
if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c))
|
||||
return mpfr_add1(a, c, b, rnd_mode);
|
||||
else
|
||||
return mpfr_add1(a, b, c, rnd_mode);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,535 @@
|
|||
/* mpfr_add1 -- internal function to perform a "real" addition
|
||||
|
||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* compute sign(b) * (|b| + |c|), assuming b and c have same sign,
|
||||
and are not NaN, Inf, nor zero. */
|
||||
int
|
||||
mpfr_add1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mp_limb_t *ap, *bp, *cp;
|
||||
mpfr_prec_t aq, bq, cq, aq2;
|
||||
mp_size_t an, bn, cn;
|
||||
mpfr_exp_t difw, exp;
|
||||
int sh, rb, fb, inex;
|
||||
mpfr_uexp_t diff_exp;
|
||||
MPFR_TMP_DECL(marker);
|
||||
|
||||
MPFR_ASSERTD(MPFR_IS_PURE_FP(b) && MPFR_IS_PURE_FP(c));
|
||||
|
||||
MPFR_TMP_MARK(marker);
|
||||
|
||||
aq = MPFR_PREC(a);
|
||||
bq = MPFR_PREC(b);
|
||||
cq = MPFR_PREC(c);
|
||||
|
||||
an = (aq-1)/GMP_NUMB_BITS+1; /* number of limbs of a */
|
||||
aq2 = (mpfr_prec_t) an * GMP_NUMB_BITS;
|
||||
sh = aq2 - aq; /* non-significant bits in low limb */
|
||||
|
||||
bn = (bq-1)/GMP_NUMB_BITS+1; /* number of limbs of b */
|
||||
cn = (cq-1)/GMP_NUMB_BITS+1; /* number of limbs of c */
|
||||
|
||||
ap = MPFR_MANT(a);
|
||||
bp = MPFR_MANT(b);
|
||||
cp = MPFR_MANT(c);
|
||||
|
||||
if (MPFR_UNLIKELY(ap == bp))
|
||||
{
|
||||
bp = (mpfr_limb_ptr) MPFR_TMP_ALLOC (bn * BYTES_PER_MP_LIMB);
|
||||
MPN_COPY (bp, ap, bn);
|
||||
if (ap == cp)
|
||||
{ cp = bp; }
|
||||
}
|
||||
else if (MPFR_UNLIKELY(ap == cp))
|
||||
{
|
||||
cp = (mpfr_limb_ptr) MPFR_TMP_ALLOC (cn * BYTES_PER_MP_LIMB);
|
||||
MPN_COPY(cp, ap, cn);
|
||||
}
|
||||
|
||||
exp = MPFR_GET_EXP (b);
|
||||
MPFR_SET_SAME_SIGN(a, b);
|
||||
MPFR_UPDATE2_RND_MODE(rnd_mode, MPFR_SIGN(b));
|
||||
/* now rnd_mode is either MPFR_RNDN, MPFR_RNDZ or MPFR_RNDA */
|
||||
diff_exp = (mpfr_uexp_t) exp - MPFR_GET_EXP(c);
|
||||
|
||||
/*
|
||||
* 1. Compute the significant part A', the non-significant bits of A
|
||||
* are taken into account.
|
||||
*
|
||||
* 2. Perform the rounding. At each iteration, we remember:
|
||||
* _ r = rounding bit
|
||||
* _ f = following bits (same value)
|
||||
* where the result has the form: [number A]rfff...fff + a remaining
|
||||
* value in the interval [0,2) ulp. We consider the most significant
|
||||
* bits of the remaining value to update the result; a possible carry
|
||||
* is immediately taken into account and A is updated accordingly. As
|
||||
* soon as the bits f don't have the same value, A can be rounded.
|
||||
* Variables:
|
||||
* _ rb = rounding bit (0 or 1).
|
||||
* _ fb = following bits (0 or 1), then sticky bit.
|
||||
* If fb == 0, the only thing that can change is the sticky bit.
|
||||
*/
|
||||
|
||||
rb = fb = -1; /* means: not initialized */
|
||||
|
||||
if (MPFR_UNLIKELY(aq2 <= diff_exp))
|
||||
{ /* c does not overlap with a' */
|
||||
if (MPFR_UNLIKELY(an > bn))
|
||||
{ /* a has more limbs than b */
|
||||
/* copy b to the most significant limbs of a */
|
||||
MPN_COPY(ap + (an - bn), bp, bn);
|
||||
/* zero the least significant limbs of a */
|
||||
MPN_ZERO(ap, an - bn);
|
||||
}
|
||||
else /* an <= bn */
|
||||
{
|
||||
/* copy the most significant limbs of b to a */
|
||||
MPN_COPY(ap, bp + (bn - an), an);
|
||||
}
|
||||
}
|
||||
else /* aq2 > diff_exp */
|
||||
{ /* c overlaps with a' */
|
||||
mp_limb_t *a2p;
|
||||
mp_limb_t cc;
|
||||
mpfr_prec_t dif;
|
||||
mp_size_t difn, k;
|
||||
int shift;
|
||||
|
||||
/* copy c (shifted) into a */
|
||||
|
||||
dif = aq2 - diff_exp;
|
||||
/* dif is the number of bits of c which overlap with a' */
|
||||
|
||||
difn = (dif-1)/GMP_NUMB_BITS + 1;
|
||||
/* only the highest difn limbs from c have to be considered */
|
||||
if (MPFR_UNLIKELY(difn > cn))
|
||||
{
|
||||
/* c doesn't have enough limbs; take into account the virtual
|
||||
zero limbs now by zeroing the least significant limbs of a' */
|
||||
MPFR_ASSERTD(difn - cn <= an);
|
||||
MPN_ZERO(ap, difn - cn);
|
||||
difn = cn;
|
||||
}
|
||||
k = diff_exp / GMP_NUMB_BITS;
|
||||
|
||||
/* zero the most significant k limbs of a */
|
||||
a2p = ap + (an - k);
|
||||
MPN_ZERO(a2p, k);
|
||||
|
||||
shift = diff_exp % GMP_NUMB_BITS;
|
||||
|
||||
if (MPFR_LIKELY(shift))
|
||||
{
|
||||
MPFR_ASSERTD(a2p - difn >= ap);
|
||||
cc = mpn_rshift(a2p - difn, cp + (cn - difn), difn, shift);
|
||||
if (MPFR_UNLIKELY(a2p - difn > ap))
|
||||
*(a2p - difn - 1) = cc;
|
||||
}
|
||||
else
|
||||
MPN_COPY(a2p - difn, cp + (cn - difn), difn);
|
||||
|
||||
/* add b to a */
|
||||
cc = MPFR_UNLIKELY(an > bn)
|
||||
? mpn_add_n(ap + (an - bn), ap + (an - bn), bp, bn)
|
||||
: mpn_add_n(ap, ap, bp + (bn - an), an);
|
||||
|
||||
if (MPFR_UNLIKELY(cc)) /* carry */
|
||||
{
|
||||
if (MPFR_UNLIKELY(exp == __gmpfr_emax))
|
||||
{
|
||||
inex = mpfr_overflow (a, rnd_mode, MPFR_SIGN(a));
|
||||
goto end_of_add;
|
||||
}
|
||||
exp++;
|
||||
rb = (ap[0] >> sh) & 1; /* LSB(a) --> rounding bit after the shift */
|
||||
if (MPFR_LIKELY(sh))
|
||||
{
|
||||
mp_limb_t mask, bb;
|
||||
|
||||
mask = MPFR_LIMB_MASK (sh);
|
||||
bb = ap[0] & mask;
|
||||
ap[0] &= (~mask) << 1;
|
||||
if (bb == 0)
|
||||
fb = 0;
|
||||
else if (bb == mask)
|
||||
fb = 1;
|
||||
}
|
||||
mpn_rshift(ap, ap, an, 1);
|
||||
ap[an-1] += MPFR_LIMB_HIGHBIT;
|
||||
if (sh && fb < 0)
|
||||
goto rounding;
|
||||
} /* cc */
|
||||
} /* aq2 > diff_exp */
|
||||
|
||||
/* non-significant bits of a */
|
||||
if (MPFR_LIKELY(rb < 0 && sh))
|
||||
{
|
||||
mp_limb_t mask, bb;
|
||||
|
||||
mask = MPFR_LIMB_MASK (sh);
|
||||
bb = ap[0] & mask;
|
||||
ap[0] &= ~mask;
|
||||
rb = bb >> (sh - 1);
|
||||
if (MPFR_LIKELY(sh > 1))
|
||||
{
|
||||
mask >>= 1;
|
||||
bb &= mask;
|
||||
if (bb == 0)
|
||||
fb = 0;
|
||||
else if (bb == mask)
|
||||
fb = 1;
|
||||
else
|
||||
goto rounding;
|
||||
}
|
||||
}
|
||||
|
||||
/* determine rounding and sticky bits (and possible carry) */
|
||||
|
||||
difw = (mpfr_exp_t) an - (mpfr_exp_t) (diff_exp / GMP_NUMB_BITS);
|
||||
/* difw is the number of limbs from b (regarded as having an infinite
|
||||
precision) that have already been combined with c; -n if the next
|
||||
n limbs from b won't be combined with c. */
|
||||
|
||||
if (MPFR_UNLIKELY(bn > an))
|
||||
{ /* there are still limbs from b that haven't been taken into account */
|
||||
mp_size_t bk;
|
||||
|
||||
if (fb == 0 && difw <= 0)
|
||||
{
|
||||
fb = 1; /* c hasn't been taken into account ==> sticky bit != 0 */
|
||||
goto rounding;
|
||||
}
|
||||
|
||||
bk = bn - an; /* index of lowest considered limb from b, > 0 */
|
||||
while (difw < 0)
|
||||
{ /* ulp(next limb from b) > msb(c) */
|
||||
mp_limb_t bb;
|
||||
|
||||
bb = bp[--bk];
|
||||
|
||||
MPFR_ASSERTD(fb != 0);
|
||||
if (fb > 0)
|
||||
{
|
||||
if (bb != MP_LIMB_T_MAX)
|
||||
{
|
||||
fb = 1; /* c hasn't been taken into account
|
||||
==> sticky bit != 0 */
|
||||
goto rounding;
|
||||
}
|
||||
}
|
||||
else /* fb not initialized yet */
|
||||
{
|
||||
if (rb < 0) /* rb not initialized yet */
|
||||
{
|
||||
rb = bb >> (GMP_NUMB_BITS - 1);
|
||||
bb |= MPFR_LIMB_HIGHBIT;
|
||||
}
|
||||
fb = 1;
|
||||
if (bb != MP_LIMB_T_MAX)
|
||||
goto rounding;
|
||||
}
|
||||
|
||||
if (bk == 0)
|
||||
{ /* b has entirely been read */
|
||||
fb = 1; /* c hasn't been taken into account
|
||||
==> sticky bit != 0 */
|
||||
goto rounding;
|
||||
}
|
||||
|
||||
difw++;
|
||||
} /* while */
|
||||
MPFR_ASSERTD(bk > 0 && difw >= 0);
|
||||
|
||||
if (difw <= cn)
|
||||
{
|
||||
mp_size_t ck;
|
||||
mp_limb_t cprev;
|
||||
int difs;
|
||||
|
||||
ck = cn - difw;
|
||||
difs = diff_exp % GMP_NUMB_BITS;
|
||||
|
||||
if (difs == 0 && ck == 0)
|
||||
goto c_read;
|
||||
|
||||
cprev = ck == cn ? 0 : cp[ck];
|
||||
|
||||
if (fb < 0)
|
||||
{
|
||||
mp_limb_t bb, cc;
|
||||
|
||||
if (difs)
|
||||
{
|
||||
cc = cprev << (GMP_NUMB_BITS - difs);
|
||||
if (--ck >= 0)
|
||||
{
|
||||
cprev = cp[ck];
|
||||
cc += cprev >> difs;
|
||||
}
|
||||
}
|
||||
else
|
||||
cc = cp[--ck];
|
||||
|
||||
bb = bp[--bk] + cc;
|
||||
|
||||
if (bb < cc /* carry */
|
||||
&& (rb < 0 || (rb ^= 1) == 0)
|
||||
&& mpn_add_1(ap, ap, an, MPFR_LIMB_ONE << sh))
|
||||
{
|
||||
if (exp == __gmpfr_emax)
|
||||
{
|
||||
inex = mpfr_overflow (a, rnd_mode, MPFR_SIGN(a));
|
||||
goto end_of_add;
|
||||
}
|
||||
exp++;
|
||||
ap[an-1] = MPFR_LIMB_HIGHBIT;
|
||||
rb = 0;
|
||||
}
|
||||
|
||||
if (rb < 0) /* rb not initialized yet */
|
||||
{
|
||||
rb = bb >> (GMP_NUMB_BITS - 1);
|
||||
bb <<= 1;
|
||||
bb |= bb >> (GMP_NUMB_BITS - 1);
|
||||
}
|
||||
|
||||
fb = bb != 0;
|
||||
if (fb && bb != MP_LIMB_T_MAX)
|
||||
goto rounding;
|
||||
} /* fb < 0 */
|
||||
|
||||
while (bk > 0)
|
||||
{
|
||||
mp_limb_t bb, cc;
|
||||
|
||||
if (difs)
|
||||
{
|
||||
if (ck < 0)
|
||||
goto c_read;
|
||||
cc = cprev << (GMP_NUMB_BITS - difs);
|
||||
if (--ck >= 0)
|
||||
{
|
||||
cprev = cp[ck];
|
||||
cc += cprev >> difs;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ck == 0)
|
||||
goto c_read;
|
||||
cc = cp[--ck];
|
||||
}
|
||||
|
||||
bb = bp[--bk] + cc;
|
||||
if (bb < cc) /* carry */
|
||||
{
|
||||
fb ^= 1;
|
||||
if (fb)
|
||||
goto rounding;
|
||||
rb ^= 1;
|
||||
if (rb == 0 && mpn_add_1(ap, ap, an, MPFR_LIMB_ONE << sh))
|
||||
{
|
||||
if (MPFR_UNLIKELY(exp == __gmpfr_emax))
|
||||
{
|
||||
inex = mpfr_overflow (a, rnd_mode, MPFR_SIGN(a));
|
||||
goto end_of_add;
|
||||
}
|
||||
exp++;
|
||||
ap[an-1] = MPFR_LIMB_HIGHBIT;
|
||||
}
|
||||
} /* bb < cc */
|
||||
|
||||
if (!fb && bb != 0)
|
||||
{
|
||||
fb = 1;
|
||||
goto rounding;
|
||||
}
|
||||
if (fb && bb != MP_LIMB_T_MAX)
|
||||
goto rounding;
|
||||
} /* while */
|
||||
|
||||
/* b has entirely been read */
|
||||
|
||||
if (fb || ck < 0)
|
||||
goto rounding;
|
||||
if (difs && cprev << (GMP_NUMB_BITS - difs))
|
||||
{
|
||||
fb = 1;
|
||||
goto rounding;
|
||||
}
|
||||
while (ck)
|
||||
{
|
||||
if (cp[--ck])
|
||||
{
|
||||
fb = 1;
|
||||
goto rounding;
|
||||
}
|
||||
} /* while */
|
||||
} /* difw <= cn */
|
||||
else
|
||||
{ /* c has entirely been read */
|
||||
c_read:
|
||||
if (fb < 0) /* fb not initialized yet */
|
||||
{
|
||||
mp_limb_t bb;
|
||||
|
||||
MPFR_ASSERTD(bk > 0);
|
||||
bb = bp[--bk];
|
||||
if (rb < 0) /* rb not initialized yet */
|
||||
{
|
||||
rb = bb >> (GMP_NUMB_BITS - 1);
|
||||
bb &= ~MPFR_LIMB_HIGHBIT;
|
||||
}
|
||||
fb = bb != 0;
|
||||
} /* fb < 0 */
|
||||
if (fb)
|
||||
goto rounding;
|
||||
while (bk)
|
||||
{
|
||||
if (bp[--bk])
|
||||
{
|
||||
fb = 1;
|
||||
goto rounding;
|
||||
}
|
||||
} /* while */
|
||||
} /* difw > cn */
|
||||
} /* bn > an */
|
||||
else if (fb != 1) /* if fb == 1, the sticky bit is 1 (no possible carry) */
|
||||
{ /* b has entirely been read */
|
||||
if (difw > cn)
|
||||
{ /* c has entirely been read */
|
||||
if (rb < 0)
|
||||
rb = 0;
|
||||
fb = 0;
|
||||
}
|
||||
else if (diff_exp > aq2)
|
||||
{ /* b is followed by at least a zero bit, then by c */
|
||||
if (rb < 0)
|
||||
rb = 0;
|
||||
fb = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mp_size_t ck;
|
||||
int difs;
|
||||
|
||||
MPFR_ASSERTD(difw >= 0 && cn >= difw);
|
||||
ck = cn - difw;
|
||||
difs = diff_exp % GMP_NUMB_BITS;
|
||||
|
||||
if (difs == 0 && ck == 0)
|
||||
{ /* c has entirely been read */
|
||||
if (rb < 0)
|
||||
rb = 0;
|
||||
fb = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mp_limb_t cc;
|
||||
|
||||
cc = difs ? (MPFR_ASSERTD(ck < cn),
|
||||
cp[ck] << (GMP_NUMB_BITS - difs)) : cp[--ck];
|
||||
if (rb < 0)
|
||||
{
|
||||
rb = cc >> (GMP_NUMB_BITS - 1);
|
||||
cc &= ~MPFR_LIMB_HIGHBIT;
|
||||
}
|
||||
while (cc == 0)
|
||||
{
|
||||
if (ck == 0)
|
||||
{
|
||||
fb = 0;
|
||||
goto rounding;
|
||||
}
|
||||
cc = cp[--ck];
|
||||
} /* while */
|
||||
fb = 1;
|
||||
}
|
||||
}
|
||||
} /* fb != 1 */
|
||||
|
||||
rounding:
|
||||
/* rnd_mode should be one of MPFR_RNDN, MPFR_RNDZ or MPFR_RNDA */
|
||||
if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
|
||||
{
|
||||
if (fb == 0)
|
||||
{
|
||||
if (rb == 0)
|
||||
{
|
||||
inex = 0;
|
||||
goto set_exponent;
|
||||
}
|
||||
/* round to even */
|
||||
if (ap[0] & (MPFR_LIMB_ONE << sh))
|
||||
goto rndn_away;
|
||||
else
|
||||
goto rndn_zero;
|
||||
}
|
||||
if (rb == 0)
|
||||
{
|
||||
rndn_zero:
|
||||
inex = MPFR_IS_NEG(a) ? 1 : -1;
|
||||
goto set_exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
rndn_away:
|
||||
inex = MPFR_IS_POS(a) ? 1 : -1;
|
||||
goto add_one_ulp;
|
||||
}
|
||||
}
|
||||
else if (rnd_mode == MPFR_RNDZ)
|
||||
{
|
||||
inex = rb || fb ? (MPFR_IS_NEG(a) ? 1 : -1) : 0;
|
||||
goto set_exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_ASSERTN (rnd_mode == MPFR_RNDA);
|
||||
inex = rb || fb ? (MPFR_IS_POS(a) ? 1 : -1) : 0;
|
||||
if (inex)
|
||||
goto add_one_ulp;
|
||||
else
|
||||
goto set_exponent;
|
||||
}
|
||||
|
||||
add_one_ulp: /* add one unit in last place to a */
|
||||
if (MPFR_UNLIKELY(mpn_add_1 (ap, ap, an, MPFR_LIMB_ONE << sh)))
|
||||
{
|
||||
if (MPFR_UNLIKELY(exp == __gmpfr_emax))
|
||||
{
|
||||
inex = mpfr_overflow (a, rnd_mode, MPFR_SIGN(a));
|
||||
goto end_of_add;
|
||||
}
|
||||
exp++;
|
||||
ap[an-1] = MPFR_LIMB_HIGHBIT;
|
||||
}
|
||||
|
||||
set_exponent:
|
||||
MPFR_SET_EXP (a, exp);
|
||||
|
||||
end_of_add:
|
||||
MPFR_TMP_FREE(marker);
|
||||
MPFR_RET (inex);
|
||||
}
|
|
@ -0,0 +1,384 @@
|
|||
/* mpfr_add1sp -- internal function to perform a "real" addition
|
||||
All the op must have the same precision
|
||||
|
||||
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* Check if we have to check the result of mpfr_add1sp with mpfr_add1 */
|
||||
#ifdef WANT_ASSERT
|
||||
# if WANT_ASSERT >= 2
|
||||
|
||||
int mpfr_add1sp2 (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t);
|
||||
int mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t tmpa, tmpb, tmpc;
|
||||
int inexb, inexc, inexact, inexact2;
|
||||
|
||||
mpfr_init2 (tmpa, MPFR_PREC (a));
|
||||
mpfr_init2 (tmpb, MPFR_PREC (b));
|
||||
mpfr_init2 (tmpc, MPFR_PREC (c));
|
||||
|
||||
inexb = mpfr_set (tmpb, b, MPFR_RNDN);
|
||||
MPFR_ASSERTN (inexb == 0);
|
||||
|
||||
inexc = mpfr_set (tmpc, c, MPFR_RNDN);
|
||||
MPFR_ASSERTN (inexc == 0);
|
||||
|
||||
inexact2 = mpfr_add1 (tmpa, tmpb, tmpc, rnd_mode);
|
||||
inexact = mpfr_add1sp2 (a, b, c, rnd_mode);
|
||||
|
||||
if (mpfr_cmp (tmpa, a) || inexact != inexact2)
|
||||
{
|
||||
fprintf (stderr, "add1 & add1sp return different values for %s\n"
|
||||
"Prec_a = %lu, Prec_b = %lu, Prec_c = %lu\nB = ",
|
||||
mpfr_print_rnd_mode (rnd_mode),
|
||||
MPFR_PREC (a), MPFR_PREC (b), MPFR_PREC (c));
|
||||
mpfr_fprint_binary (stderr, tmpb);
|
||||
fprintf (stderr, "\nC = ");
|
||||
mpfr_fprint_binary (stderr, tmpc);
|
||||
fprintf (stderr, "\n\nadd1 : ");
|
||||
mpfr_fprint_binary (stderr, tmpa);
|
||||
fprintf (stderr, "\nadd1sp: ");
|
||||
mpfr_fprint_binary (stderr, a);
|
||||
fprintf (stderr, "\nInexact sp = %d | Inexact = %d\n",
|
||||
inexact, inexact2);
|
||||
MPFR_ASSERTN (0);
|
||||
}
|
||||
mpfr_clears (tmpa, tmpb, tmpc, (mpfr_ptr) 0);
|
||||
return inexact;
|
||||
}
|
||||
# define mpfr_add1sp mpfr_add1sp2
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Debugging support */
|
||||
#ifdef DEBUG
|
||||
# undef DEBUG
|
||||
# define DEBUG(x) (x)
|
||||
#else
|
||||
# define DEBUG(x) /**/
|
||||
#endif
|
||||
|
||||
/* compute sign(b) * (|b| + |c|)
|
||||
Returns 0 iff result is exact,
|
||||
a negative value when the result is less than the exact value,
|
||||
a positive value otherwise. */
|
||||
int
|
||||
mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_uexp_t d;
|
||||
mpfr_prec_t p;
|
||||
unsigned int sh;
|
||||
mp_size_t n;
|
||||
mp_limb_t *ap, *cp;
|
||||
mpfr_exp_t bx;
|
||||
mp_limb_t limb;
|
||||
int inexact;
|
||||
MPFR_TMP_DECL(marker);
|
||||
|
||||
MPFR_TMP_MARK(marker);
|
||||
|
||||
MPFR_ASSERTD(MPFR_PREC(a) == MPFR_PREC(b) && MPFR_PREC(b) == MPFR_PREC(c));
|
||||
MPFR_ASSERTD(MPFR_IS_PURE_FP(b) && MPFR_IS_PURE_FP(c));
|
||||
MPFR_ASSERTD(MPFR_GET_EXP(b) >= MPFR_GET_EXP(c));
|
||||
|
||||
/* Read prec and num of limbs */
|
||||
p = MPFR_PREC(b);
|
||||
n = (p+GMP_NUMB_BITS-1)/GMP_NUMB_BITS;
|
||||
MPFR_UNSIGNED_MINUS_MODULO(sh, p);
|
||||
bx = MPFR_GET_EXP(b);
|
||||
d = (mpfr_uexp_t) (bx - MPFR_GET_EXP(c));
|
||||
|
||||
DEBUG (printf ("New add1sp with diff=%lu\n", (unsigned long) d));
|
||||
|
||||
if (MPFR_UNLIKELY(d == 0))
|
||||
{
|
||||
/* d==0 */
|
||||
DEBUG( mpfr_print_mant_binary("C= ", MPFR_MANT(c), p) );
|
||||
DEBUG( mpfr_print_mant_binary("B= ", MPFR_MANT(b), p) );
|
||||
bx++; /* exp + 1 */
|
||||
ap = MPFR_MANT(a);
|
||||
limb = mpn_add_n(ap, MPFR_MANT(b), MPFR_MANT(c), n);
|
||||
DEBUG( mpfr_print_mant_binary("A= ", ap, p) );
|
||||
MPFR_ASSERTD(limb != 0); /* There must be a carry */
|
||||
limb = ap[0]; /* Get LSB (In fact, LSW) */
|
||||
mpn_rshift(ap, ap, n, 1); /* Shift mantissa A */
|
||||
ap[n-1] |= MPFR_LIMB_HIGHBIT; /* Set MSB */
|
||||
ap[0] &= ~MPFR_LIMB_MASK(sh); /* Clear LSB bit */
|
||||
if (MPFR_LIKELY((limb&(MPFR_LIMB_ONE<<sh)) == 0)) /* Check exact case */
|
||||
{ inexact = 0; goto set_exponent; }
|
||||
/* Zero: Truncate
|
||||
Nearest: Even Rule => truncate or add 1
|
||||
Away: Add 1 */
|
||||
if (MPFR_LIKELY(rnd_mode==MPFR_RNDN))
|
||||
{
|
||||
if (MPFR_LIKELY((ap[0]&(MPFR_LIMB_ONE<<sh))==0))
|
||||
{ inexact = -1; goto set_exponent; }
|
||||
else
|
||||
goto add_one_ulp;
|
||||
}
|
||||
MPFR_UPDATE_RND_MODE(rnd_mode, MPFR_IS_NEG(b));
|
||||
if (rnd_mode==MPFR_RNDZ)
|
||||
{ inexact = -1; goto set_exponent; }
|
||||
else
|
||||
goto add_one_ulp;
|
||||
}
|
||||
else if (MPFR_UNLIKELY (d >= p))
|
||||
{
|
||||
if (MPFR_LIKELY (d > p))
|
||||
{
|
||||
/* d > p : Copy B in A */
|
||||
/* Away: Add 1
|
||||
Nearest: Trunc
|
||||
Zero: Trunc */
|
||||
if (MPFR_LIKELY (rnd_mode==MPFR_RNDN
|
||||
|| MPFR_IS_LIKE_RNDZ (rnd_mode, MPFR_IS_NEG (b))))
|
||||
{
|
||||
copy_set_exponent:
|
||||
ap = MPFR_MANT (a);
|
||||
MPN_COPY (ap, MPFR_MANT(b), n);
|
||||
inexact = -1;
|
||||
goto set_exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_add_one_ulp:
|
||||
ap = MPFR_MANT(a);
|
||||
MPN_COPY (ap, MPFR_MANT(b), n);
|
||||
goto add_one_ulp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* d==p : Copy B in A */
|
||||
/* Away: Add 1
|
||||
Nearest: Even Rule if C is a power of 2, else Add 1
|
||||
Zero: Trunc */
|
||||
if (MPFR_LIKELY(rnd_mode==MPFR_RNDN))
|
||||
{
|
||||
/* Check if C was a power of 2 */
|
||||
cp = MPFR_MANT(c);
|
||||
if (MPFR_UNLIKELY(cp[n-1] == MPFR_LIMB_HIGHBIT))
|
||||
{
|
||||
mp_size_t k = n-1;
|
||||
do {
|
||||
k--;
|
||||
} while (k>=0 && cp[k]==0);
|
||||
if (MPFR_UNLIKELY(k<0))
|
||||
/* Power of 2: Even rule */
|
||||
if ((MPFR_MANT (b)[0]&(MPFR_LIMB_ONE<<sh))==0)
|
||||
goto copy_set_exponent;
|
||||
}
|
||||
/* Not a Power of 2 */
|
||||
goto copy_add_one_ulp;
|
||||
}
|
||||
else if (MPFR_IS_LIKE_RNDZ (rnd_mode, MPFR_IS_NEG (b)))
|
||||
goto copy_set_exponent;
|
||||
else
|
||||
goto copy_add_one_ulp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mp_limb_t mask;
|
||||
mp_limb_t bcp, bcp1; /* Cp and C'p+1 */
|
||||
|
||||
/* General case: 1 <= d < p */
|
||||
cp = (mp_limb_t*) MPFR_TMP_ALLOC(n * BYTES_PER_MP_LIMB);
|
||||
|
||||
/* Shift c in temporary allocated place */
|
||||
{
|
||||
mpfr_uexp_t dm;
|
||||
mp_size_t m;
|
||||
|
||||
dm = d % GMP_NUMB_BITS;
|
||||
m = d / GMP_NUMB_BITS;
|
||||
if (MPFR_UNLIKELY(dm == 0))
|
||||
{
|
||||
/* dm = 0 and m > 0: Just copy */
|
||||
MPFR_ASSERTD(m!=0);
|
||||
MPN_COPY(cp, MPFR_MANT(c)+m, n-m);
|
||||
MPN_ZERO(cp+n-m, m);
|
||||
}
|
||||
else if (MPFR_LIKELY(m == 0))
|
||||
{
|
||||
/* dm >=1 and m == 0: just shift */
|
||||
MPFR_ASSERTD(dm >= 1);
|
||||
mpn_rshift(cp, MPFR_MANT(c), n, dm);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* dm > 0 and m > 0: shift and zero */
|
||||
mpn_rshift(cp, MPFR_MANT(c)+m, n-m, dm);
|
||||
MPN_ZERO(cp+n-m, m);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG( mpfr_print_mant_binary("Before", MPFR_MANT(c), p) );
|
||||
DEBUG( mpfr_print_mant_binary("B= ", MPFR_MANT(b), p) );
|
||||
DEBUG( mpfr_print_mant_binary("After ", cp, p) );
|
||||
|
||||
/* Compute bcp=Cp and bcp1=C'p+1 */
|
||||
if (MPFR_LIKELY (sh > 0))
|
||||
{
|
||||
/* Try to compute them from C' rather than C */
|
||||
bcp = (cp[0] & (MPFR_LIMB_ONE<<(sh-1))) ;
|
||||
if (MPFR_LIKELY(cp[0]&MPFR_LIMB_MASK(sh-1)))
|
||||
bcp1 = 1;
|
||||
else
|
||||
{
|
||||
/* We can't compute C'p+1 from C'. Compute it from C */
|
||||
/* Start from bit x=p-d+sh in mantissa C
|
||||
(+sh since we have already looked sh bits in C'!) */
|
||||
mpfr_prec_t x = p-d+sh-1;
|
||||
if (MPFR_LIKELY(x>p))
|
||||
/* We are already looked at all the bits of c, so C'p+1 = 0*/
|
||||
bcp1 = 0;
|
||||
else
|
||||
{
|
||||
mp_limb_t *tp = MPFR_MANT(c);
|
||||
mp_size_t kx = n-1 - (x / GMP_NUMB_BITS);
|
||||
mpfr_prec_t sx = GMP_NUMB_BITS-1-(x%GMP_NUMB_BITS);
|
||||
DEBUG (printf ("(First) x=%lu Kx=%ld Sx=%lu\n",
|
||||
(unsigned long) x, (long) kx,
|
||||
(unsigned long) sx));
|
||||
/* Looks at the last bits of limb kx (if sx=0 does nothing)*/
|
||||
if (tp[kx] & MPFR_LIMB_MASK(sx))
|
||||
bcp1 = 1;
|
||||
else
|
||||
{
|
||||
/*kx += (sx==0);*/
|
||||
/*If sx==0, tp[kx] hasn't been checked*/
|
||||
do {
|
||||
kx--;
|
||||
} while (kx>=0 && tp[kx]==0);
|
||||
bcp1 = (kx >= 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* sh == 0 */
|
||||
{
|
||||
/* Compute Cp and C'p+1 from C with sh=0 */
|
||||
mp_limb_t *tp = MPFR_MANT(c);
|
||||
/* Start from bit x=p-d in mantissa C */
|
||||
mpfr_prec_t x = p-d;
|
||||
mp_size_t kx = n-1 - (x / GMP_NUMB_BITS);
|
||||
mpfr_prec_t sx = GMP_NUMB_BITS-1-(x%GMP_NUMB_BITS);
|
||||
MPFR_ASSERTD(p >= d);
|
||||
bcp = tp[kx] & (MPFR_LIMB_ONE<<sx);
|
||||
/* Looks at the last bits of limb kx (If sx=0, does nothing)*/
|
||||
if (tp[kx]&MPFR_LIMB_MASK(sx))
|
||||
bcp1 = 1;
|
||||
else
|
||||
{
|
||||
do {
|
||||
kx--;
|
||||
} while (kx>=0 && tp[kx]==0);
|
||||
bcp1 = (kx>=0);
|
||||
}
|
||||
}
|
||||
DEBUG (printf("sh=%u Cp=%lu C'p+1=%lu\n", sh,
|
||||
(unsigned long) bcp, (unsigned long) bcp1));
|
||||
|
||||
/* Clean shifted C' */
|
||||
mask = ~MPFR_LIMB_MASK(sh);
|
||||
cp[0] &= mask;
|
||||
|
||||
/* Add the mantissa c from b in a */
|
||||
ap = MPFR_MANT(a);
|
||||
limb = mpn_add_n (ap, MPFR_MANT(b), cp, n);
|
||||
DEBUG( mpfr_print_mant_binary("Add= ", ap, p) );
|
||||
|
||||
/* Check for overflow */
|
||||
if (MPFR_UNLIKELY (limb))
|
||||
{
|
||||
limb = ap[0] & (MPFR_LIMB_ONE<<sh); /* Get LSB */
|
||||
mpn_rshift (ap, ap, n, 1); /* Shift mantissa*/
|
||||
bx++; /* Fix exponent */
|
||||
ap[n-1] |= MPFR_LIMB_HIGHBIT; /* Set MSB */
|
||||
ap[0] &= mask; /* Clear LSB bit */
|
||||
bcp1 |= bcp; /* Recompute C'p+1 */
|
||||
bcp = limb; /* Recompute Cp */
|
||||
DEBUG (printf ("(Overflow) Cp=%lu C'p+1=%lu\n",
|
||||
(unsigned long) bcp, (unsigned long) bcp1));
|
||||
DEBUG (mpfr_print_mant_binary ("Add= ", ap, p));
|
||||
}
|
||||
|
||||
/* Round:
|
||||
Zero: Truncate but could be exact.
|
||||
Away: Add 1 if Cp or C'p+1 !=0
|
||||
Nearest: Truncate but could be exact if Cp==0
|
||||
Add 1 if C'p+1 !=0,
|
||||
Even rule else */
|
||||
if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
|
||||
{
|
||||
if (MPFR_LIKELY(bcp == 0))
|
||||
{ inexact = MPFR_LIKELY(bcp1) ? -1 : 0; goto set_exponent; }
|
||||
else if (MPFR_UNLIKELY(bcp1==0) && (ap[0]&(MPFR_LIMB_ONE<<sh))==0)
|
||||
{ inexact = -1; goto set_exponent; }
|
||||
else
|
||||
goto add_one_ulp;
|
||||
}
|
||||
MPFR_UPDATE_RND_MODE(rnd_mode, MPFR_IS_NEG(b));
|
||||
if (rnd_mode == MPFR_RNDZ)
|
||||
{
|
||||
inexact = MPFR_LIKELY(bcp || bcp1) ? -1 : 0;
|
||||
goto set_exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MPFR_UNLIKELY(bcp==0 && bcp1==0))
|
||||
{ inexact = 0; goto set_exponent; }
|
||||
else
|
||||
goto add_one_ulp;
|
||||
}
|
||||
}
|
||||
MPFR_ASSERTN(0);
|
||||
|
||||
add_one_ulp:
|
||||
/* add one unit in last place to a */
|
||||
DEBUG( printf("AddOneUlp\n") );
|
||||
if (MPFR_UNLIKELY( mpn_add_1(ap, ap, n, MPFR_LIMB_ONE<<sh) ))
|
||||
{
|
||||
/* Case 100000x0 = 0x1111x1 + 1*/
|
||||
DEBUG( printf("Pow of 2\n") );
|
||||
bx++;
|
||||
ap[n-1] = MPFR_LIMB_HIGHBIT;
|
||||
}
|
||||
inexact = 1;
|
||||
|
||||
set_exponent:
|
||||
if (MPFR_UNLIKELY(bx > __gmpfr_emax)) /* Check for overflow */
|
||||
{
|
||||
DEBUG( printf("Overflow\n") );
|
||||
MPFR_TMP_FREE(marker);
|
||||
MPFR_SET_SAME_SIGN(a,b);
|
||||
return mpfr_overflow(a, rnd_mode, MPFR_SIGN(a));
|
||||
}
|
||||
MPFR_SET_EXP (a, bx);
|
||||
MPFR_SET_SAME_SIGN(a,b);
|
||||
|
||||
MPFR_TMP_FREE(marker);
|
||||
MPFR_RET (inexact * MPFR_INT_SIGN (a));
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* mpfr_add_d -- add a multiple precision floating-point number
|
||||
to a machine double precision float
|
||||
|
||||
Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_add_d (mpfr_ptr a, mpfr_srcptr b, double c, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
mpfr_t d;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_LOG_FUNC (("b[%#R]=%R c=%.20g rnd=%d", b, b, c, rnd_mode),
|
||||
("a[%#R]=%R", a, a));
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
mpfr_init2 (d, IEEE_DBL_MANT_DIG);
|
||||
inexact = mpfr_set_d (d, c, rnd_mode);
|
||||
MPFR_ASSERTN (inexact == 0);
|
||||
|
||||
mpfr_clear_flags ();
|
||||
inexact = mpfr_add (a, b, d, rnd_mode);
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
|
||||
|
||||
mpfr_clear (d);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (a, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* mpfr_add_ui -- add a floating-point number with a machine integer
|
||||
|
||||
Copyright 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_add_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
if (MPFR_LIKELY(u != 0) ) /* if u=0, do nothing */
|
||||
{
|
||||
mpfr_t uu;
|
||||
mp_limb_t up[1];
|
||||
unsigned long cnt;
|
||||
int inex;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_TMP_INIT1 (up, uu, GMP_NUMB_BITS);
|
||||
MPFR_ASSERTD (u == (mp_limb_t) u);
|
||||
count_leading_zeros(cnt, (mp_limb_t) u);
|
||||
up[0] = (mp_limb_t) u << cnt;
|
||||
|
||||
/* Optimization note: Exponent save/restore operations may be
|
||||
removed if mpfr_add works even when uu is out-of-range. */
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
MPFR_SET_EXP (uu, GMP_NUMB_BITS - cnt);
|
||||
inex = mpfr_add(y, x, uu, rnd_mode);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range(y, inex, rnd_mode);
|
||||
}
|
||||
else
|
||||
/* (unsigned long) 0 is assumed to be a real 0 (unsigned) */
|
||||
return mpfr_set (y, x, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,314 @@
|
|||
/* mpfr_agm -- arithmetic-geometric mean of two floating-point numbers
|
||||
|
||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* agm(x,y) is between x and y, so we don't need to save exponent range */
|
||||
int
|
||||
mpfr_agm (mpfr_ptr r, mpfr_srcptr op2, mpfr_srcptr op1, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int compare, inexact;
|
||||
mp_size_t s;
|
||||
mpfr_prec_t p, q;
|
||||
mp_limb_t *up, *vp, *ufp, *vfp;
|
||||
mpfr_t u, v, uf, vf, sc1, sc2;
|
||||
mpfr_exp_t scaleop = 0, scaleit;
|
||||
unsigned long n; /* number of iterations */
|
||||
MPFR_ZIV_DECL (loop);
|
||||
MPFR_TMP_DECL(marker);
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_LOG_FUNC (("op2[%#R]=%R op1[%#R]=%R rnd=%d", op2,op2,op1,op1,rnd_mode),
|
||||
("r[%#R]=%R inexact=%d", r, r, inexact));
|
||||
|
||||
/* Deal with special values */
|
||||
if (MPFR_ARE_SINGULAR (op1, op2))
|
||||
{
|
||||
/* If a or b is NaN, the result is NaN */
|
||||
if (MPFR_IS_NAN(op1) || MPFR_IS_NAN(op2))
|
||||
{
|
||||
MPFR_SET_NAN(r);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
/* now one of a or b is Inf or 0 */
|
||||
/* If a and b is +Inf, the result is +Inf.
|
||||
Otherwise if a or b is -Inf or 0, the result is NaN */
|
||||
else if (MPFR_IS_INF(op1) || MPFR_IS_INF(op2))
|
||||
{
|
||||
if (MPFR_IS_STRICTPOS(op1) && MPFR_IS_STRICTPOS(op2))
|
||||
{
|
||||
MPFR_SET_INF(r);
|
||||
MPFR_SET_SAME_SIGN(r, op1);
|
||||
MPFR_RET(0); /* exact */
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_SET_NAN(r);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
}
|
||||
else /* a and b are neither NaN nor Inf, and one is zero */
|
||||
{ /* If a or b is 0, the result is +0 since a sqrt is positive */
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (op1) || MPFR_IS_ZERO (op2));
|
||||
MPFR_SET_POS (r);
|
||||
MPFR_SET_ZERO (r);
|
||||
MPFR_RET (0); /* exact */
|
||||
}
|
||||
}
|
||||
|
||||
/* If a or b is negative (excluding -Infinity), the result is NaN */
|
||||
if (MPFR_UNLIKELY(MPFR_IS_NEG(op1) || MPFR_IS_NEG(op2)))
|
||||
{
|
||||
MPFR_SET_NAN(r);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
|
||||
/* Precision of the following calculus */
|
||||
q = MPFR_PREC(r);
|
||||
p = q + MPFR_INT_CEIL_LOG2(q) + 15;
|
||||
MPFR_ASSERTD (p >= 7); /* see algorithms.tex */
|
||||
s = (p - 1) / GMP_NUMB_BITS + 1;
|
||||
|
||||
/* b (op2) and a (op1) are the 2 operands but we want b >= a */
|
||||
compare = mpfr_cmp (op1, op2);
|
||||
if (MPFR_UNLIKELY( compare == 0 ))
|
||||
{
|
||||
mpfr_set (r, op1, rnd_mode);
|
||||
MPFR_RET (0); /* exact */
|
||||
}
|
||||
else if (compare > 0)
|
||||
{
|
||||
mpfr_srcptr t = op1;
|
||||
op1 = op2;
|
||||
op2 = t;
|
||||
}
|
||||
|
||||
/* Now b (=op2) > a (=op1) */
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
MPFR_TMP_MARK(marker);
|
||||
|
||||
/* Main loop */
|
||||
MPFR_ZIV_INIT (loop, p);
|
||||
for (;;)
|
||||
{
|
||||
mpfr_prec_t eq;
|
||||
unsigned long err = 0; /* must be set to 0 at each Ziv iteration */
|
||||
MPFR_BLOCK_DECL (flags);
|
||||
|
||||
/* Init temporary vars */
|
||||
MPFR_TMP_INIT (up, u, p, s);
|
||||
MPFR_TMP_INIT (vp, v, p, s);
|
||||
MPFR_TMP_INIT (ufp, uf, p, s);
|
||||
MPFR_TMP_INIT (vfp, vf, p, s);
|
||||
|
||||
/* Calculus of un and vn */
|
||||
retry:
|
||||
MPFR_BLOCK (flags,
|
||||
mpfr_mul (u, op1, op2, MPFR_RNDN);
|
||||
/* mpfr_mul(...): faster since PREC(op) < PREC(u) */
|
||||
mpfr_add (v, op1, op2, MPFR_RNDN);
|
||||
/* mpfr_add with !=prec is still good */);
|
||||
if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags) || MPFR_UNDERFLOW (flags)))
|
||||
{
|
||||
mpfr_exp_t e1 , e2;
|
||||
|
||||
MPFR_ASSERTN (scaleop == 0);
|
||||
e1 = MPFR_GET_EXP (op1);
|
||||
e2 = MPFR_GET_EXP (op2);
|
||||
|
||||
/* Let's determine scaleop to avoid an overflow/underflow. */
|
||||
if (MPFR_OVERFLOW (flags))
|
||||
{
|
||||
/* Let's recall that emin <= e1 <= e2 <= emax.
|
||||
There has been an overflow. Thus e2 >= emax/2.
|
||||
If the mpfr_mul overflowed, then e1 + e2 > emax.
|
||||
If the mpfr_add overflowed, then e2 = emax.
|
||||
We want: (e1 + scale) + (e2 + scale) <= emax,
|
||||
i.e. scale <= (emax - e1 - e2) / 2. Let's take
|
||||
scale = min(floor((emax - e1 - e2) / 2), -1).
|
||||
This is OK, as:
|
||||
1. emin <= scale <= -1.
|
||||
2. e1 + scale >= emin. Indeed:
|
||||
* If e1 + e2 > emax, then
|
||||
e1 + scale >= e1 + (emax - e1 - e2) / 2 - 1
|
||||
>= (emax + e1 - emax) / 2 - 1
|
||||
>= e1 / 2 - 1 >= emin.
|
||||
* Otherwise, mpfr_mul didn't overflow, therefore
|
||||
mpfr_add overflowed and e2 = emax, so that
|
||||
e1 > emin (see restriction below).
|
||||
e1 + scale > emin - 1, thus e1 + scale >= emin.
|
||||
3. e2 + scale <= emax, since scale < 0. */
|
||||
if (e1 + e2 > __gmpfr_emax)
|
||||
{
|
||||
scaleop = - (((e1 + e2) - __gmpfr_emax + 1) / 2);
|
||||
MPFR_ASSERTN (scaleop < 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The addition necessarily overflowed. */
|
||||
MPFR_ASSERTN (e2 == __gmpfr_emax);
|
||||
/* The case where e1 = emin and e2 = emax is not supported
|
||||
here. This would mean that the precision of e2 would be
|
||||
huge (and possibly not supported in practice anyway). */
|
||||
MPFR_ASSERTN (e1 > __gmpfr_emin);
|
||||
scaleop = -1;
|
||||
}
|
||||
|
||||
}
|
||||
else /* underflow only (in the multiplication) */
|
||||
{
|
||||
/* We have e1 + e2 <= emin (so, e1 <= e2 <= 0).
|
||||
We want: (e1 + scale) + (e2 + scale) >= emin + 1,
|
||||
i.e. scale >= (emin + 1 - e1 - e2) / 2. let's take
|
||||
scale = ceil((emin + 1 - e1 - e2) / 2). This is OK, as:
|
||||
1. 1 <= scale <= emax.
|
||||
2. e1 + scale >= emin + 1 >= emin.
|
||||
3. e2 + scale <= scale <= emax. */
|
||||
MPFR_ASSERTN (e1 <= e2 && e2 <= 0);
|
||||
scaleop = (__gmpfr_emin + 2 - e1 - e2) / 2;
|
||||
MPFR_ASSERTN (scaleop > 0);
|
||||
}
|
||||
|
||||
MPFR_ALIAS (sc1, op1, MPFR_SIGN (op1), e1 + scaleop);
|
||||
MPFR_ALIAS (sc2, op2, MPFR_SIGN (op2), e2 + scaleop);
|
||||
op1 = sc1;
|
||||
op2 = sc2;
|
||||
MPFR_LOG_MSG (("Exception in pre-iteration, scale = %"
|
||||
MPFR_EXP_FSPEC "d\n", scaleop));
|
||||
goto retry;
|
||||
}
|
||||
|
||||
mpfr_clear_flags ();
|
||||
mpfr_sqrt (u, u, MPFR_RNDN);
|
||||
mpfr_div_2ui (v, v, 1, MPFR_RNDN);
|
||||
|
||||
scaleit = 0;
|
||||
n = 1;
|
||||
while (mpfr_cmp2 (u, v, &eq) != 0 && eq <= p - 2)
|
||||
{
|
||||
MPFR_BLOCK_DECL (flags2);
|
||||
|
||||
MPFR_LOG_MSG (("Iteration n = %lu\n", n));
|
||||
|
||||
retry2:
|
||||
mpfr_add (vf, u, v, MPFR_RNDN); /* No overflow? */
|
||||
mpfr_div_2ui (vf, vf, 1, MPFR_RNDN);
|
||||
/* See proof in algorithms.tex */
|
||||
if (4*eq > p)
|
||||
{
|
||||
mpfr_t w;
|
||||
MPFR_BLOCK_DECL (flags3);
|
||||
|
||||
MPFR_LOG_MSG (("4*eq > p\n", 0));
|
||||
|
||||
/* vf = V(k) */
|
||||
mpfr_init2 (w, (p + 1) / 2);
|
||||
MPFR_BLOCK
|
||||
(flags3,
|
||||
mpfr_sub (w, v, u, MPFR_RNDN); /* e = V(k-1)-U(k-1) */
|
||||
mpfr_sqr (w, w, MPFR_RNDN); /* e = e^2 */
|
||||
mpfr_div_2ui (w, w, 4, MPFR_RNDN); /* e*= (1/2)^2*1/4 */
|
||||
mpfr_div (w, w, vf, MPFR_RNDN); /* 1/4*e^2/V(k) */
|
||||
);
|
||||
if (MPFR_LIKELY (! MPFR_UNDERFLOW (flags3)))
|
||||
{
|
||||
mpfr_sub (v, vf, w, MPFR_RNDN);
|
||||
err = MPFR_GET_EXP (vf) - MPFR_GET_EXP (v); /* 0 or 1 */
|
||||
mpfr_clear (w);
|
||||
break;
|
||||
}
|
||||
/* There has been an underflow because of the cancellation
|
||||
between V(k-1) and U(k-1). Let's use the conventional
|
||||
method. */
|
||||
MPFR_LOG_MSG (("4*eq > p -> underflow\n", 0));
|
||||
mpfr_clear (w);
|
||||
mpfr_clear_underflow ();
|
||||
}
|
||||
/* U(k) increases, so that U.V can overflow (but not underflow). */
|
||||
MPFR_BLOCK (flags2, mpfr_mul (uf, u, v, MPFR_RNDN););
|
||||
if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags2)))
|
||||
{
|
||||
mpfr_exp_t scale2;
|
||||
|
||||
scale2 = - (((MPFR_GET_EXP (u) + MPFR_GET_EXP (v))
|
||||
- __gmpfr_emax + 1) / 2);
|
||||
MPFR_EXP (u) += scale2;
|
||||
MPFR_EXP (v) += scale2;
|
||||
scaleit += scale2;
|
||||
MPFR_LOG_MSG (("Overflow in iteration n = %lu, scaleit = %"
|
||||
MPFR_EXP_FSPEC "d (%" MPFR_EXP_FSPEC "d)\n",
|
||||
n, scaleit, scale2));
|
||||
mpfr_clear_overflow ();
|
||||
goto retry2;
|
||||
}
|
||||
mpfr_sqrt (u, uf, MPFR_RNDN);
|
||||
mpfr_swap (v, vf);
|
||||
n ++;
|
||||
}
|
||||
|
||||
MPFR_LOG_MSG (("End of iterations (n = %lu)\n", n));
|
||||
|
||||
/* the error on v is bounded by (18n+51) ulps, or twice if there
|
||||
was an exponent loss in the final subtraction */
|
||||
err += MPFR_INT_CEIL_LOG2(18 * n + 51); /* 18n+51 should not overflow
|
||||
since n is about log(p) */
|
||||
/* we should have n+2 <= 2^(p/4) [see algorithms.tex] */
|
||||
if (MPFR_LIKELY (MPFR_INT_CEIL_LOG2(n + 2) <= p / 4 &&
|
||||
MPFR_CAN_ROUND (v, p - err, q, rnd_mode)))
|
||||
break; /* Stop the loop */
|
||||
|
||||
/* Next iteration */
|
||||
MPFR_ZIV_NEXT (loop, p);
|
||||
s = (p - 1) / GMP_NUMB_BITS + 1;
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
if (MPFR_UNLIKELY ((__gmpfr_flags & (MPFR_FLAGS_ALL ^ MPFR_FLAGS_INEXACT))
|
||||
!= 0))
|
||||
{
|
||||
MPFR_ASSERTN (! mpfr_overflow_p ()); /* since mpfr_clear_flags */
|
||||
MPFR_ASSERTN (! mpfr_underflow_p ()); /* since mpfr_clear_flags */
|
||||
MPFR_ASSERTN (! mpfr_nanflag_p ()); /* since mpfr_clear_flags */
|
||||
}
|
||||
|
||||
/* Setting of the result */
|
||||
inexact = mpfr_set (r, v, rnd_mode);
|
||||
MPFR_EXP (r) -= scaleop + scaleit;
|
||||
|
||||
/* Let's clean */
|
||||
MPFR_TMP_FREE(marker);
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
/* From the definition of the AGM, underflow and overflow
|
||||
are not possible. */
|
||||
return mpfr_check_range (r, inexact, rnd_mode);
|
||||
/* agm(u,v) can be exact for u, v rational only for u=v.
|
||||
Proof (due to Nicolas Brisebarre): it suffices to consider
|
||||
u=1 and v<1. Then 1/AGM(1,v) = 2F1(1/2,1/2,1;1-v^2),
|
||||
and a theorem due to G.V. Chudnovsky states that for x a
|
||||
non-zero algebraic number with |x|<1, then
|
||||
2F1(1/2,1/2,1;x) and 2F1(-1/2,1/2,1;x) are algebraically
|
||||
independent over Q. */
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/* mpfr_ai -- Airy function Ai
|
||||
|
||||
Copyright 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
#define MPFR_SMALL_PRECISION 32
|
||||
|
||||
|
||||
/* Reminder and notations:
|
||||
-----------------------
|
||||
|
||||
Ai is the solution of:
|
||||
/ y'' - x*y = 0
|
||||
{ Ai(0) = 1/ ( 9^(1/3)*Gamma(2/3) )
|
||||
\ Ai'(0) = -1/ ( 3^(1/3)*Gamma(1/3) )
|
||||
|
||||
Series development:
|
||||
Ai(x) = sum (a_i*x^i)
|
||||
= sum (t_i)
|
||||
|
||||
Recurrences:
|
||||
a_(i+3) = a_i / ((i+2)*(i+3))
|
||||
t_(i+3) = t_i * x^3 / ((i+2)*(i+3))
|
||||
|
||||
Values:
|
||||
a_0 = Ai(0) ~ 0.355
|
||||
a_1 = Ai'(0) ~ -0.259
|
||||
*/
|
||||
|
||||
|
||||
/* Airy function Ai evaluated by the most naive algorithm */
|
||||
int
|
||||
mpfr_ai (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd)
|
||||
{
|
||||
MPFR_ZIV_DECL (loop);
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
mpfr_prec_t wprec; /* working precision */
|
||||
mpfr_prec_t prec; /* target precision */
|
||||
mpfr_prec_t err; /* used to estimate the evaluation error */
|
||||
mpfr_prec_t correct_bits; /* estimates the number of correct bits*/
|
||||
unsigned long int k;
|
||||
unsigned long int cond; /* condition number of the series */
|
||||
unsigned long int assumed_exponent; /* used as a lowerbound of |EXP(Ai(x))| */
|
||||
int r;
|
||||
mpfr_t s; /* used to store the partial sum */
|
||||
mpfr_t ti, tip1; /* used to store successive values of t_i */
|
||||
mpfr_t x3; /* used to store x^3 */
|
||||
mpfr_t tmp_sp, tmp2_sp; /* small precision variables */
|
||||
unsigned long int x3u; /* used to store ceil(x^3) */
|
||||
mpfr_t temp1, temp2;
|
||||
int test1, test2;
|
||||
|
||||
/* Logging */
|
||||
MPFR_LOG_FUNC ( ("x[%#R]=%R rnd=%d", x, x, rnd), ("y[%#R]=%R", y, y) );
|
||||
|
||||
/* Special cases */
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF (x))
|
||||
return mpfr_set_ui (y, 0, rnd);
|
||||
}
|
||||
|
||||
/* FIXME: handle the case x == 0 (and in a consistent way for +0 and -0) */
|
||||
|
||||
/* Save current exponents range */
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* FIXME: underflow for large values of |x| ? */
|
||||
|
||||
|
||||
/* Set initial precision */
|
||||
/* If we compute sum(i=0, N-1, t_i), the relative error is bounded by */
|
||||
/* 2*(4N)*2^(1-wprec)*C(|x|)/Ai(x) */
|
||||
/* where C(|x|) = 1 if 0<=x<=1 */
|
||||
/* and C(|x|) = (1/2)*x^(-1/4)*exp(2/3 x^(3/2)) if x >= 1 */
|
||||
|
||||
/* A priori, we do not know N, so we estimate it to ~ prec */
|
||||
/* If 0<=x<=1, we estimate Ai(x) ~ 1/8 */
|
||||
/* if 1<=x, we estimate Ai(x) ~ (1/4)*x^(-1/4)*exp(-2/3 * x^(3/2)) */
|
||||
/* if x<=0, ????? */
|
||||
|
||||
/* We begin with 11 guard bits */
|
||||
prec = MPFR_PREC (y)+11;
|
||||
MPFR_ZIV_INIT (loop, prec);
|
||||
|
||||
/* The working precision is heuristically chosen in order to obtain */
|
||||
/* approximately prec correct bits in the sum. To sum up: the sum */
|
||||
/* is stopped when the *exact* sum gives ~ prec correct bit. And */
|
||||
/* when it is stopped, the accuracy of the computed sum, with respect*/
|
||||
/* to the exact one should be ~prec bits. */
|
||||
mpfr_init2 (tmp_sp, MPFR_SMALL_PRECISION);
|
||||
mpfr_init2 (tmp2_sp, MPFR_SMALL_PRECISION);
|
||||
mpfr_abs (tmp_sp, x, MPFR_RNDU);
|
||||
mpfr_pow_ui (tmp_sp, tmp_sp, 3, MPFR_RNDU);
|
||||
mpfr_sqrt (tmp_sp, tmp_sp, MPFR_RNDU); /* tmp_sp ~ x^3/2 */
|
||||
|
||||
/* 0.96179669392597567 >~ 2/3 * log2(e). See algorithms.tex */
|
||||
mpfr_set_str(tmp2_sp, "0.96179669392597567", 10, MPFR_RNDU);
|
||||
mpfr_mul (tmp2_sp, tmp_sp, tmp2_sp, MPFR_RNDU);
|
||||
|
||||
/* cond represents the number of lost bits in the evaluation of the sum */
|
||||
if ( (MPFR_IS_ZERO(x)) || (MPFR_GET_EXP (x) <= 0) )
|
||||
cond = 0;
|
||||
else
|
||||
cond = mpfr_get_ui (tmp2_sp, MPFR_RNDU) - (MPFR_GET_EXP (x)-1)/4 - 1;
|
||||
|
||||
/* The variable assumed_exponent is used to store the maximal assumed */
|
||||
/* exponent of Ai(x). More precisely, we assume that |Ai(x)| will be */
|
||||
/* greater than 2^{-assumed_exponent}. */
|
||||
if (MPFR_IS_ZERO(x))
|
||||
assumed_exponent = 2;
|
||||
else
|
||||
{
|
||||
if (MPFR_IS_POS (x))
|
||||
{
|
||||
if (MPFR_GET_EXP (x) <= 0)
|
||||
assumed_exponent = 3;
|
||||
else
|
||||
assumed_exponent = (2 + (MPFR_GET_EXP (x)/4 + 1)
|
||||
+ mpfr_get_ui (tmp2_sp, MPFR_RNDU));
|
||||
}
|
||||
/* We do not know Ai (x) yet */
|
||||
/* We cover the case when EXP (Ai (x))>=-10 */
|
||||
else
|
||||
assumed_exponent = 10;
|
||||
}
|
||||
|
||||
wprec = prec + MPFR_INT_CEIL_LOG2 (prec) + 5 + cond + assumed_exponent;
|
||||
|
||||
mpfr_init (ti);
|
||||
mpfr_init (tip1);
|
||||
mpfr_init (temp1);
|
||||
mpfr_init (temp2);
|
||||
mpfr_init (x3);
|
||||
mpfr_init (s);
|
||||
|
||||
/* ZIV loop */
|
||||
for (;;)
|
||||
{
|
||||
MPFR_LOG_MSG (("Working precision: %Pu\n", wprec));
|
||||
mpfr_set_prec (ti, wprec);
|
||||
mpfr_set_prec (tip1, wprec);
|
||||
mpfr_set_prec (x3, wprec);
|
||||
mpfr_set_prec (s, wprec);
|
||||
|
||||
mpfr_sqr (x3, x, MPFR_RNDU);
|
||||
mpfr_mul (x3, x3, x, (MPFR_IS_POS (x)?MPFR_RNDU:MPFR_RNDD)); /* x3=x^3 */
|
||||
if (MPFR_IS_NEG (x))
|
||||
MPFR_CHANGE_SIGN (x3);
|
||||
x3u = mpfr_get_ui (x3, MPFR_RNDU); /* x3u >= ceil(x^3) */
|
||||
if (MPFR_IS_NEG (x))
|
||||
MPFR_CHANGE_SIGN (x3);
|
||||
|
||||
mpfr_gamma_one_and_two_third (temp1, temp2, wprec);
|
||||
mpfr_set_ui (ti, 9, MPFR_RNDN);
|
||||
mpfr_cbrt (ti, ti, MPFR_RNDN);
|
||||
mpfr_mul (ti, ti, temp2, MPFR_RNDN);
|
||||
mpfr_ui_div (ti, 1, ti , MPFR_RNDN); /* ti = 1/( Gamma (2/3)*9^(1/3) ) */
|
||||
|
||||
mpfr_set_ui (tip1, 3, MPFR_RNDN);
|
||||
mpfr_cbrt (tip1, tip1, MPFR_RNDN);
|
||||
mpfr_mul (tip1, tip1, temp1, MPFR_RNDN);
|
||||
mpfr_neg (tip1, tip1, MPFR_RNDN);
|
||||
mpfr_div (tip1, x, tip1, MPFR_RNDN); /* tip1 = -x/(Gamma (1/3)*3^(1/3)) */
|
||||
|
||||
mpfr_add (s, ti, tip1, MPFR_RNDN);
|
||||
|
||||
|
||||
/* Evaluation of the series */
|
||||
k = 2;
|
||||
for (;;)
|
||||
{
|
||||
mpfr_mul (ti, ti, x3, MPFR_RNDN);
|
||||
mpfr_mul (tip1, tip1, x3, MPFR_RNDN);
|
||||
|
||||
mpfr_div_ui2 (ti, ti, k, (k+1), MPFR_RNDN);
|
||||
mpfr_div_ui2 (tip1, tip1, (k+1), (k+2), MPFR_RNDN);
|
||||
|
||||
k += 3;
|
||||
mpfr_add (s, s, ti, MPFR_RNDN);
|
||||
mpfr_add (s, s, tip1, MPFR_RNDN);
|
||||
|
||||
/* FIXME: if s==0 */
|
||||
test1 = MPFR_IS_ZERO (ti)
|
||||
|| (MPFR_GET_EXP (ti) + (mpfr_exp_t)prec + 3 <= MPFR_GET_EXP (s));
|
||||
test2 = MPFR_IS_ZERO (tip1)
|
||||
|| (MPFR_GET_EXP (tip1) + (mpfr_exp_t)prec + 3 <= MPFR_GET_EXP (s));
|
||||
|
||||
if ( test1 && test2 && (x3u <= k*(k+1)/2) )
|
||||
break; /* FIXME: if k*(k+1) overflows */
|
||||
}
|
||||
|
||||
MPFR_LOG_MSG (("Truncation rank: %lu\n", k));
|
||||
|
||||
err = 4 + MPFR_INT_CEIL_LOG2 (k) + cond - MPFR_GET_EXP (s);
|
||||
|
||||
/* err is the number of bits lost due to the evaluation error */
|
||||
/* wprec-(prec+1): number of bits lost due to the approximation error */
|
||||
MPFR_LOG_MSG (("Roundoff error: %Pu\n", err));
|
||||
MPFR_LOG_MSG (("Approxim error: %Pu\n", wprec-prec-1));
|
||||
|
||||
if (wprec < err+1)
|
||||
correct_bits=0;
|
||||
else
|
||||
{
|
||||
if (wprec < err+prec+1)
|
||||
correct_bits = wprec - err - 1;
|
||||
else
|
||||
correct_bits = prec;
|
||||
}
|
||||
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (s, correct_bits, MPFR_PREC (y), rnd)))
|
||||
break;
|
||||
|
||||
if (correct_bits == 0)
|
||||
{
|
||||
assumed_exponent *= 2;
|
||||
MPFR_LOG_MSG (("Not a single bit correct (assumed_exponent=%lu)\n",
|
||||
assumed_exponent));
|
||||
wprec = prec + 5 + MPFR_INT_CEIL_LOG2 (k) + cond + assumed_exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (correct_bits < prec)
|
||||
{ /* The precision was badly chosen */
|
||||
MPFR_LOG_MSG (("Bad assumption on the exponent of Ai(x)", 0));
|
||||
MPFR_LOG_MSG ((" (E=%ld)\n", (long) MPFR_GET_EXP (s)));
|
||||
wprec = prec + err + 1;
|
||||
}
|
||||
else
|
||||
{ /* We are really in a bad case of the TMD */
|
||||
MPFR_ZIV_NEXT (loop, prec);
|
||||
|
||||
/* We update wprec */
|
||||
/* We assume that K will not be multiplied by more than 4 */
|
||||
wprec = prec + (MPFR_INT_CEIL_LOG2 (k)+2) + 5 + cond
|
||||
- MPFR_GET_EXP (s);
|
||||
}
|
||||
}
|
||||
|
||||
} /* End of ZIV loop */
|
||||
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
r = mpfr_set (y, s, rnd);
|
||||
|
||||
mpfr_clear (ti);
|
||||
mpfr_clear (tip1);
|
||||
mpfr_clear (temp1);
|
||||
mpfr_clear (temp2);
|
||||
mpfr_clear (x3);
|
||||
mpfr_clear (s);
|
||||
mpfr_clear (tmp_sp);
|
||||
mpfr_clear (tmp2_sp);
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, r, rnd);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
.TH ANSI2KNR 1 "19 Jan 1996"
|
||||
.SH NAME
|
||||
ansi2knr \- convert ANSI C to Kernighan & Ritchie C
|
||||
.SH SYNOPSIS
|
||||
.I ansi2knr
|
||||
[--varargs] input_file [output_file]
|
||||
.SH DESCRIPTION
|
||||
If no output_file is supplied, output goes to stdout.
|
||||
.br
|
||||
There are no error messages.
|
||||
.sp
|
||||
.I ansi2knr
|
||||
recognizes function definitions by seeing a non-keyword identifier at the left
|
||||
margin, followed by a left parenthesis, with a right parenthesis as the last
|
||||
character on the line, and with a left brace as the first token on the
|
||||
following line (ignoring possible intervening comments). It will recognize a
|
||||
multi-line header provided that no intervening line ends with a left or right
|
||||
brace or a semicolon. These algorithms ignore whitespace and comments, except
|
||||
that the function name must be the first thing on the line.
|
||||
.sp
|
||||
The following constructs will confuse it:
|
||||
.br
|
||||
- Any other construct that starts at the left margin and follows the
|
||||
above syntax (such as a macro or function call).
|
||||
.br
|
||||
- Some macros that tinker with the syntax of the function header.
|
||||
.sp
|
||||
The --varargs switch is obsolete, and is recognized only for
|
||||
backwards compatibility. The present version of
|
||||
.I ansi2knr
|
||||
will always attempt to convert a ... argument to va_alist and va_dcl.
|
||||
.SH AUTHOR
|
||||
L. Peter Deutsch <ghost@aladdin.com> wrote the original ansi2knr and
|
||||
continues to maintain the current version; most of the code in the current
|
||||
version is his work. ansi2knr also includes contributions by Francois
|
||||
Pinard <pinard@iro.umontreal.ca> and Jim Avera <jima@netcom.com>.
|
|
@ -0,0 +1,739 @@
|
|||
/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. */
|
||||
|
||||
/*$Id: ansi2knr.c,v 1.1.1.1 2011/06/20 05:53:13 mrg Exp $*/
|
||||
/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
|
||||
|
||||
/*
|
||||
ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone for the
|
||||
consequences of using it or for whether it serves any particular purpose or
|
||||
works at all, unless he says so in writing. Refer to the GNU General Public
|
||||
License (the "GPL") for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute ansi2knr,
|
||||
but only under the conditions described in the GPL. A copy of this license
|
||||
is supposed to have been given to you along with ansi2knr so you can know
|
||||
your rights and responsibilities. It should be in a file named COPYLEFT,
|
||||
or, if there is no file named COPYLEFT, a file named COPYING. Among other
|
||||
things, the copyright notice and this notice must be preserved on all
|
||||
copies.
|
||||
|
||||
We explicitly state here what we believe is already implied by the GPL: if
|
||||
the ansi2knr program is distributed as a separate set of sources and a
|
||||
separate executable file which are aggregated on a storage medium together
|
||||
with another program, this in itself does not bring the other program under
|
||||
the GPL, nor does the mere fact that such a program or the procedures for
|
||||
constructing it invoke the ansi2knr executable bring any other part of the
|
||||
program under the GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]
|
||||
* --filename provides the file name for the #line directive in the output,
|
||||
* overriding input_file (if present).
|
||||
* If no input_file is supplied, input is read from stdin.
|
||||
* If no output_file is supplied, output goes to stdout.
|
||||
* There are no error messages.
|
||||
*
|
||||
* ansi2knr recognizes function definitions by seeing a non-keyword
|
||||
* identifier at the left margin, followed by a left parenthesis, with a
|
||||
* right parenthesis as the last character on the line, and with a left
|
||||
* brace as the first token on the following line (ignoring possible
|
||||
* intervening comments and/or preprocessor directives), except that a line
|
||||
* consisting of only
|
||||
* identifier1(identifier2)
|
||||
* will not be considered a function definition unless identifier2 is
|
||||
* the word "void", and a line consisting of
|
||||
* identifier1(identifier2, <<arbitrary>>)
|
||||
* will not be considered a function definition.
|
||||
* ansi2knr will recognize a multi-line header provided that no intervening
|
||||
* line ends with a left or right brace or a semicolon. These algorithms
|
||||
* ignore whitespace, comments, and preprocessor directives, except that
|
||||
* the function name must be the first thing on the line. The following
|
||||
* constructs will confuse it:
|
||||
* - Any other construct that starts at the left margin and
|
||||
* follows the above syntax (such as a macro or function call).
|
||||
* - Some macros that tinker with the syntax of function headers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The original and principal author of ansi2knr is L. Peter Deutsch
|
||||
* <ghost@aladdin.com>. Other authors are noted in the change history
|
||||
* that follows (in reverse chronological order):
|
||||
|
||||
lpd 2000-04-12 backs out Eggert's changes because of bugs:
|
||||
- concatlits didn't declare the type of its bufend argument;
|
||||
- concatlits didn't recognize when it was inside a comment;
|
||||
- scanstring could scan backward past the beginning of the string; when
|
||||
- the check for \ + newline in scanstring was unnecessary.
|
||||
|
||||
2000-03-05 Paul Eggert <eggert@twinsun.com>
|
||||
|
||||
Add support for concatenated string literals.
|
||||
* ansi2knr.c (concatlits): New decl.
|
||||
(main): Invoke concatlits to concatenate string literals.
|
||||
(scanstring): Handle backslash-newline correctly. Work with
|
||||
character constants. Fix bug when scanning backwards through
|
||||
backslash-quote. Check for unterminated strings.
|
||||
(convert1): Parse character constants, too.
|
||||
(appendline, concatlits): New functions.
|
||||
* ansi2knr.1: Document this.
|
||||
|
||||
lpd 1999-08-17 added code to allow preprocessor directives
|
||||
wherever comments are allowed
|
||||
lpd 1999-04-12 added minor fixes from Pavel Roskin
|
||||
<pavel_roskin@geocities.com> for clean compilation with
|
||||
gcc -W -Wall
|
||||
lpd 1999-03-22 added hack to recognize lines consisting of
|
||||
identifier1(identifier2, xxx) as *not* being procedures
|
||||
lpd 1999-02-03 made indentation of preprocessor commands consistent
|
||||
lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
|
||||
endless loop; quoted strings within an argument list
|
||||
confused the parser
|
||||
lpd 1999-01-24 added a check for write errors on the output,
|
||||
suggested by Jim Meyering <meyering@ascend.com>
|
||||
lpd 1998-11-09 added further hack to recognize identifier(void)
|
||||
as being a procedure
|
||||
lpd 1998-10-23 added hack to recognize lines consisting of
|
||||
identifier1(identifier2) as *not* being procedures
|
||||
lpd 1997-12-08 made input_file optional; only closes input and/or
|
||||
output file if not stdin or stdout respectively; prints
|
||||
usage message on stderr rather than stdout; adds
|
||||
--filename switch (changes suggested by
|
||||
<ceder@lysator.liu.se>)
|
||||
lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
|
||||
compilers that don't understand void, as suggested by
|
||||
Tom Lane
|
||||
lpd 1996-01-15 changed to require that the first non-comment token
|
||||
on the line following a function header be a left brace,
|
||||
to reduce sensitivity to macros, as suggested by Tom Lane
|
||||
<tgl@sss.pgh.pa.us>
|
||||
lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
|
||||
undefined preprocessor symbols as 0; changed all #ifdefs
|
||||
for configuration symbols to #ifs
|
||||
lpd 1995-04-05 changed copyright notice to make it clear that
|
||||
including ansi2knr in a program does not bring the entire
|
||||
program under the GPL
|
||||
lpd 1994-12-18 added conditionals for systems where ctype macros
|
||||
don't handle 8-bit characters properly, suggested by
|
||||
Francois Pinard <pinard@iro.umontreal.ca>;
|
||||
removed --varargs switch (this is now the default)
|
||||
lpd 1994-10-10 removed CONFIG_BROKETS conditional
|
||||
lpd 1994-07-16 added some conditionals to help GNU `configure',
|
||||
suggested by Francois Pinard <pinard@iro.umontreal.ca>;
|
||||
properly erase prototype args in function parameters,
|
||||
contributed by Jim Avera <jima@netcom.com>;
|
||||
correct error in writeblanks (it shouldn't erase EOLs)
|
||||
lpd 1989-xx-xx original version
|
||||
*/
|
||||
|
||||
/* Most of the conditionals here are to make ansi2knr work with */
|
||||
/* or without the GNU configure machinery. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
|
||||
/*
|
||||
For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
|
||||
This will define HAVE_CONFIG_H and so, activate the following lines.
|
||||
*/
|
||||
|
||||
# if STDC_HEADERS || HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# else
|
||||
# include <strings.h>
|
||||
# endif
|
||||
|
||||
#else /* not HAVE_CONFIG_H */
|
||||
|
||||
/* Otherwise do it the hard way */
|
||||
|
||||
# ifdef BSD
|
||||
# include <strings.h>
|
||||
# else
|
||||
# ifdef VMS
|
||||
extern int strlen(), strncmp();
|
||||
# else
|
||||
# include <string.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* not HAVE_CONFIG_H */
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
/*
|
||||
malloc and free should be declared in stdlib.h,
|
||||
but if you've got a K&R compiler, they probably aren't.
|
||||
*/
|
||||
# ifdef MSDOS
|
||||
# include <malloc.h>
|
||||
# else
|
||||
# ifdef VMS
|
||||
extern char *malloc();
|
||||
extern void free();
|
||||
# else
|
||||
extern char *malloc();
|
||||
extern int free();
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Define NULL (for *very* old compilers). */
|
||||
#ifndef NULL
|
||||
# define NULL (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The ctype macros don't always handle 8-bit characters correctly.
|
||||
* Compensate for this here.
|
||||
*/
|
||||
#ifdef isascii
|
||||
# undef HAVE_ISASCII /* just in case */
|
||||
# define HAVE_ISASCII 1
|
||||
#else
|
||||
#endif
|
||||
#if STDC_HEADERS || !HAVE_ISASCII
|
||||
# define is_ascii(c) 1
|
||||
#else
|
||||
# define is_ascii(c) isascii(c)
|
||||
#endif
|
||||
|
||||
#define is_space(c) (is_ascii(c) && isspace(c))
|
||||
#define is_alpha(c) (is_ascii(c) && isalpha(c))
|
||||
#define is_alnum(c) (is_ascii(c) && isalnum(c))
|
||||
|
||||
/* Scanning macros */
|
||||
#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
|
||||
#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
|
||||
|
||||
/* Forward references */
|
||||
char *ppdirforward();
|
||||
char *ppdirbackward();
|
||||
char *skipspace();
|
||||
char *scanstring();
|
||||
int writeblanks();
|
||||
int test1();
|
||||
int convert1();
|
||||
|
||||
/* The main program */
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{ FILE *in = stdin;
|
||||
FILE *out = stdout;
|
||||
char *filename = 0;
|
||||
char *program_name = argv[0];
|
||||
char *output_name = 0;
|
||||
#define bufsize 5000 /* arbitrary size */
|
||||
char *buf;
|
||||
char *line;
|
||||
char *more;
|
||||
char *usage =
|
||||
"Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
|
||||
/*
|
||||
* In previous versions, ansi2knr recognized a --varargs switch.
|
||||
* If this switch was supplied, ansi2knr would attempt to convert
|
||||
* a ... argument to va_alist and va_dcl; if this switch was not
|
||||
* supplied, ansi2knr would simply drop any such arguments.
|
||||
* Now, ansi2knr always does this conversion, and we only
|
||||
* check for this switch for backward compatibility.
|
||||
*/
|
||||
int convert_varargs = 1;
|
||||
int output_error;
|
||||
|
||||
while ( argc > 1 && argv[1][0] == '-' ) {
|
||||
if ( !strcmp(argv[1], "--varargs") ) {
|
||||
convert_varargs = 1;
|
||||
argc--;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
|
||||
filename = argv[2];
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
|
||||
argv[1]);
|
||||
fprintf(stderr, usage);
|
||||
exit(1);
|
||||
}
|
||||
switch ( argc )
|
||||
{
|
||||
default:
|
||||
fprintf(stderr, usage);
|
||||
exit(0);
|
||||
case 3:
|
||||
output_name = argv[2];
|
||||
out = fopen(output_name, "w");
|
||||
if ( out == NULL ) {
|
||||
fprintf(stderr, "%s: Cannot open output file %s\n",
|
||||
program_name, output_name);
|
||||
exit(1);
|
||||
}
|
||||
/* falls through */
|
||||
case 2:
|
||||
in = fopen(argv[1], "r");
|
||||
if ( in == NULL ) {
|
||||
fprintf(stderr, "%s: Cannot open input file %s\n",
|
||||
program_name, argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
if ( filename == 0 )
|
||||
filename = argv[1];
|
||||
/* falls through */
|
||||
case 1:
|
||||
break;
|
||||
}
|
||||
if ( filename )
|
||||
fprintf(out, "#line 1 \"%s\"\n", filename);
|
||||
buf = malloc(bufsize);
|
||||
if ( buf == NULL )
|
||||
{
|
||||
fprintf(stderr, "Unable to allocate read buffer!\n");
|
||||
exit(1);
|
||||
}
|
||||
line = buf;
|
||||
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
|
||||
{
|
||||
test: line += strlen(line);
|
||||
switch ( test1(buf) )
|
||||
{
|
||||
case 2: /* a function header */
|
||||
convert1(buf, out, 1, convert_varargs);
|
||||
break;
|
||||
case 1: /* a function */
|
||||
/* Check for a { at the start of the next line. */
|
||||
more = ++line;
|
||||
f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
|
||||
goto wl;
|
||||
if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
|
||||
goto wl;
|
||||
switch ( *skipspace(ppdirforward(more), 1) )
|
||||
{
|
||||
case '{':
|
||||
/* Definitely a function header. */
|
||||
convert1(buf, out, 0, convert_varargs);
|
||||
fputs(more, out);
|
||||
break;
|
||||
case 0:
|
||||
/* The next line was blank or a comment: */
|
||||
/* keep scanning for a non-comment. */
|
||||
line += strlen(line);
|
||||
goto f;
|
||||
default:
|
||||
/* buf isn't a function header, but */
|
||||
/* more might be. */
|
||||
fputs(buf, out);
|
||||
strcpy(buf, more);
|
||||
line = buf;
|
||||
goto test;
|
||||
}
|
||||
break;
|
||||
case -1: /* maybe the start of a function */
|
||||
if ( line != buf + (bufsize - 1) ) /* overflow check */
|
||||
continue;
|
||||
/* falls through */
|
||||
default: /* not a function */
|
||||
wl: fputs(buf, out);
|
||||
break;
|
||||
}
|
||||
line = buf;
|
||||
}
|
||||
if ( line != buf )
|
||||
fputs(buf, out);
|
||||
free(buf);
|
||||
if ( output_name ) {
|
||||
output_error = ferror(out);
|
||||
output_error |= fclose(out);
|
||||
} else { /* out == stdout */
|
||||
fflush(out);
|
||||
output_error = ferror(out);
|
||||
}
|
||||
if ( output_error ) {
|
||||
fprintf(stderr, "%s: error writing to %s\n", program_name,
|
||||
(output_name ? output_name : "stdout"));
|
||||
exit(1);
|
||||
}
|
||||
if ( in != stdin )
|
||||
fclose(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip forward or backward over one or more preprocessor directives.
|
||||
*/
|
||||
char *
|
||||
ppdirforward(p)
|
||||
char *p;
|
||||
{
|
||||
for (; *p == '#'; ++p) {
|
||||
for (; *p != '\r' && *p != '\n'; ++p)
|
||||
if (*p == 0)
|
||||
return p;
|
||||
if (*p == '\r' && p[1] == '\n')
|
||||
++p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
char *
|
||||
ppdirbackward(p, limit)
|
||||
char *p;
|
||||
char *limit;
|
||||
{
|
||||
char *np = p;
|
||||
|
||||
for (;; p = --np) {
|
||||
if (*np == '\n' && np[-1] == '\r')
|
||||
--np;
|
||||
for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
|
||||
if (np[-1] == 0)
|
||||
return np;
|
||||
if (*np != '#')
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over whitespace, comments, and preprocessor directives,
|
||||
* in either direction.
|
||||
*/
|
||||
char *
|
||||
skipspace(p, dir)
|
||||
char *p;
|
||||
int dir; /* 1 for forward, -1 for backward */
|
||||
{
|
||||
for ( ; ; ) {
|
||||
while ( is_space(*p) )
|
||||
p += dir;
|
||||
if ( !(*p == '/' && p[dir] == '*') )
|
||||
break;
|
||||
p += dir; p += dir;
|
||||
while ( !(*p == '*' && p[dir] == '/') ) {
|
||||
if ( *p == 0 )
|
||||
return p; /* multi-line comment?? */
|
||||
p += dir;
|
||||
}
|
||||
p += dir; p += dir;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Scan over a quoted string, in either direction. */
|
||||
char *
|
||||
scanstring(p, dir)
|
||||
char *p;
|
||||
int dir;
|
||||
{
|
||||
for (p += dir; ; p += dir)
|
||||
if (*p == '"' && p[-dir] != '\\')
|
||||
return p + dir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write blanks over part of a string.
|
||||
* Don't overwrite end-of-line characters.
|
||||
*/
|
||||
int
|
||||
writeblanks(start, end)
|
||||
char *start;
|
||||
char *end;
|
||||
{ char *p;
|
||||
for ( p = start; p < end; p++ )
|
||||
if ( *p != '\r' && *p != '\n' )
|
||||
*p = ' ';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether the string in buf is a function definition.
|
||||
* The string may contain and/or end with a newline.
|
||||
* Return as follows:
|
||||
* 0 - definitely not a function definition;
|
||||
* 1 - definitely a function definition;
|
||||
* 2 - definitely a function prototype (NOT USED);
|
||||
* -1 - may be the beginning of a function definition,
|
||||
* append another line and look again.
|
||||
* The reason we don't attempt to convert function prototypes is that
|
||||
* Ghostscript's declaration-generating macros look too much like
|
||||
* prototypes, and confuse the algorithms.
|
||||
*/
|
||||
int
|
||||
test1(buf)
|
||||
char *buf;
|
||||
{ char *p = buf;
|
||||
char *bend;
|
||||
char *endfn;
|
||||
int contin;
|
||||
|
||||
if ( !isidfirstchar(*p) )
|
||||
return 0; /* no name at left margin */
|
||||
bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
|
||||
switch ( *bend )
|
||||
{
|
||||
case ';': contin = 0 /*2*/; break;
|
||||
case ')': contin = 1; break;
|
||||
case '{': return 0; /* not a function */
|
||||
case '}': return 0; /* not a function */
|
||||
default: contin = -1;
|
||||
}
|
||||
while ( isidchar(*p) )
|
||||
p++;
|
||||
endfn = p;
|
||||
p = skipspace(p, 1);
|
||||
if ( *p++ != '(' )
|
||||
return 0; /* not a function */
|
||||
p = skipspace(p, 1);
|
||||
if ( *p == ')' )
|
||||
return 0; /* no parameters */
|
||||
/* Check that the apparent function name isn't a keyword. */
|
||||
/* We only need to check for keywords that could be followed */
|
||||
/* by a left parenthesis (which, unfortunately, is most of them). */
|
||||
{ static char *words[] =
|
||||
{ "asm", "auto", "case", "char", "const", "double",
|
||||
"extern", "float", "for", "if", "int", "long",
|
||||
"register", "return", "short", "signed", "sizeof",
|
||||
"static", "switch", "typedef", "unsigned",
|
||||
"void", "volatile", "while", 0
|
||||
};
|
||||
char **key = words;
|
||||
char *kp;
|
||||
unsigned len = endfn - buf;
|
||||
|
||||
while ( (kp = *key) != 0 )
|
||||
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
|
||||
return 0; /* name is a keyword */
|
||||
key++;
|
||||
}
|
||||
}
|
||||
{
|
||||
char *id = p;
|
||||
int len;
|
||||
/*
|
||||
* Check for identifier1(identifier2) and not
|
||||
* identifier1(void), or identifier1(identifier2, xxxx).
|
||||
*/
|
||||
|
||||
while ( isidchar(*p) )
|
||||
p++;
|
||||
len = p - id;
|
||||
p = skipspace(p, 1);
|
||||
if (*p == ',' ||
|
||||
(*p == ')' && (len != 4 || strncmp(id, "void", 4)))
|
||||
)
|
||||
return 0; /* not a function */
|
||||
}
|
||||
/*
|
||||
* If the last significant character was a ), we need to count
|
||||
* parentheses, because it might be part of a formal parameter
|
||||
* that is a procedure.
|
||||
*/
|
||||
if (contin > 0) {
|
||||
int level = 0;
|
||||
|
||||
for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
|
||||
level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
|
||||
if (level > 0)
|
||||
contin = -1;
|
||||
}
|
||||
return contin;
|
||||
}
|
||||
|
||||
/* Convert a recognized function definition or header to K&R syntax. */
|
||||
int
|
||||
convert1(buf, out, header, convert_varargs)
|
||||
char *buf;
|
||||
FILE *out;
|
||||
int header; /* Boolean */
|
||||
int convert_varargs; /* Boolean */
|
||||
{ char *endfn;
|
||||
char *p;
|
||||
/*
|
||||
* The breaks table contains pointers to the beginning and end
|
||||
* of each argument.
|
||||
*/
|
||||
char **breaks;
|
||||
unsigned num_breaks = 2; /* for testing */
|
||||
char **btop;
|
||||
char **bp;
|
||||
char **ap;
|
||||
char *vararg = 0;
|
||||
|
||||
/* Pre-ANSI implementations don't agree on whether strchr */
|
||||
/* is called strchr or index, so we open-code it here. */
|
||||
for ( endfn = buf; *(endfn++) != '('; )
|
||||
;
|
||||
top: p = endfn;
|
||||
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
|
||||
if ( breaks == NULL )
|
||||
{ /* Couldn't allocate break table, give up */
|
||||
fprintf(stderr, "Unable to allocate break table!\n");
|
||||
fputs(buf, out);
|
||||
return -1;
|
||||
}
|
||||
btop = breaks + num_breaks * 2 - 2;
|
||||
bp = breaks;
|
||||
/* Parse the argument list */
|
||||
do
|
||||
{ int level = 0;
|
||||
char *lp = NULL;
|
||||
char *rp = NULL;
|
||||
char *end = NULL;
|
||||
|
||||
if ( bp >= btop )
|
||||
{ /* Filled up break table. */
|
||||
/* Allocate a bigger one and start over. */
|
||||
free((char *)breaks);
|
||||
num_breaks <<= 1;
|
||||
goto top;
|
||||
}
|
||||
*bp++ = p;
|
||||
/* Find the end of the argument */
|
||||
for ( ; end == NULL; p++ )
|
||||
{ switch(*p)
|
||||
{
|
||||
case ',':
|
||||
if ( !level ) end = p;
|
||||
break;
|
||||
case '(':
|
||||
if ( !level ) lp = p;
|
||||
level++;
|
||||
break;
|
||||
case ')':
|
||||
if ( --level < 0 ) end = p;
|
||||
else rp = p;
|
||||
break;
|
||||
case '/':
|
||||
if (p[1] == '*')
|
||||
p = skipspace(p, 1) - 1;
|
||||
break;
|
||||
case '"':
|
||||
p = scanstring(p, 1) - 1;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
/* Erase any embedded prototype parameters. */
|
||||
if ( lp && rp )
|
||||
writeblanks(lp + 1, rp);
|
||||
p--; /* back up over terminator */
|
||||
/* Find the name being declared. */
|
||||
/* This is complicated because of procedure and */
|
||||
/* array modifiers. */
|
||||
for ( ; ; )
|
||||
{ p = skipspace(p - 1, -1);
|
||||
switch ( *p )
|
||||
{
|
||||
case ']': /* skip array dimension(s) */
|
||||
case ')': /* skip procedure args OR name */
|
||||
{ int level = 1;
|
||||
while ( level )
|
||||
switch ( *--p )
|
||||
{
|
||||
case ']': case ')':
|
||||
level++;
|
||||
break;
|
||||
case '[': case '(':
|
||||
level--;
|
||||
break;
|
||||
case '/':
|
||||
if (p > buf && p[-1] == '*')
|
||||
p = skipspace(p, -1) + 1;
|
||||
break;
|
||||
case '"':
|
||||
p = scanstring(p, -1) + 1;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
|
||||
{ /* We found the name being declared */
|
||||
while ( !isidfirstchar(*p) )
|
||||
p = skipspace(p, 1) + 1;
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
|
||||
{ if ( convert_varargs )
|
||||
{ *bp++ = "va_alist";
|
||||
vararg = p-2;
|
||||
}
|
||||
else
|
||||
{ p++;
|
||||
if ( bp == breaks + 1 ) /* sole argument */
|
||||
writeblanks(breaks[0], p);
|
||||
else
|
||||
writeblanks(bp[-1] - 1, p);
|
||||
bp--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ while ( isidchar(*p) ) p--;
|
||||
*bp++ = p+1;
|
||||
}
|
||||
p = end;
|
||||
}
|
||||
while ( *p++ == ',' );
|
||||
*bp = p;
|
||||
/* Make a special check for 'void' arglist */
|
||||
if ( bp == breaks+2 )
|
||||
{ p = skipspace(breaks[0], 1);
|
||||
if ( !strncmp(p, "void", 4) )
|
||||
{ p = skipspace(p+4, 1);
|
||||
if ( p == breaks[2] - 1 )
|
||||
{ bp = breaks; /* yup, pretend arglist is empty */
|
||||
writeblanks(breaks[0], p + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Put out the function name and left parenthesis. */
|
||||
p = buf;
|
||||
while ( p != endfn ) putc(*p, out), p++;
|
||||
/* Put out the declaration. */
|
||||
if ( header )
|
||||
{ fputs(");", out);
|
||||
for ( p = breaks[0]; *p; p++ )
|
||||
if ( *p == '\r' || *p == '\n' )
|
||||
putc(*p, out);
|
||||
}
|
||||
else
|
||||
{ for ( ap = breaks+1; ap < bp; ap += 2 )
|
||||
{ p = *ap;
|
||||
while ( isidchar(*p) )
|
||||
putc(*p, out), p++;
|
||||
if ( ap < bp - 1 )
|
||||
fputs(", ", out);
|
||||
}
|
||||
fputs(") ", out);
|
||||
/* Put out the argument declarations */
|
||||
for ( ap = breaks+2; ap <= bp; ap += 2 )
|
||||
(*ap)[-1] = ';';
|
||||
if ( vararg != 0 )
|
||||
{ *vararg = 0;
|
||||
fputs(breaks[0], out); /* any prior args */
|
||||
fputs("va_dcl", out); /* the final arg */
|
||||
fputs(bp[0], out);
|
||||
}
|
||||
else
|
||||
fputs(breaks[0], out);
|
||||
}
|
||||
free((char *)breaks);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/* mpfr_asin -- arc-sinus of a floating-point number
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library, and was contributed by Mathieu Dutour.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_asin (mpfr_ptr asin, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t xp;
|
||||
int compared, inexact;
|
||||
mpfr_prec_t prec;
|
||||
mpfr_exp_t xp_exp;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("asin[%#R]=%R inexact=%d", asin, asin, inexact));
|
||||
|
||||
/* Special cases */
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
|
||||
{
|
||||
MPFR_SET_NAN (asin);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else /* x = 0 */
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (x));
|
||||
MPFR_SET_ZERO (asin);
|
||||
MPFR_SET_SAME_SIGN (asin, x);
|
||||
MPFR_RET (0); /* exact result */
|
||||
}
|
||||
}
|
||||
|
||||
/* asin(x) = x + x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */
|
||||
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (asin, x, -2 * MPFR_GET_EXP (x), 2, 1,
|
||||
rnd_mode, {});
|
||||
|
||||
/* Set x_p=|x| (x is a normal number) */
|
||||
mpfr_init2 (xp, MPFR_PREC (x));
|
||||
inexact = mpfr_abs (xp, x, MPFR_RNDN);
|
||||
MPFR_ASSERTD (inexact == 0);
|
||||
|
||||
compared = mpfr_cmp_ui (xp, 1);
|
||||
|
||||
if (MPFR_UNLIKELY (compared >= 0))
|
||||
{
|
||||
mpfr_clear (xp);
|
||||
if (compared > 0) /* asin(x) = NaN for |x| > 1 */
|
||||
{
|
||||
MPFR_SET_NAN (asin);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else /* x = 1 or x = -1 */
|
||||
{
|
||||
if (MPFR_IS_POS (x)) /* asin(+1) = Pi/2 */
|
||||
inexact = mpfr_const_pi (asin, rnd_mode);
|
||||
else /* asin(-1) = -Pi/2 */
|
||||
{
|
||||
inexact = -mpfr_const_pi (asin, MPFR_INVERT_RND(rnd_mode));
|
||||
MPFR_CHANGE_SIGN (asin);
|
||||
}
|
||||
mpfr_div_2ui (asin, asin, 1, rnd_mode); /* May underflow */
|
||||
return inexact;
|
||||
}
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* Compute exponent of 1 - ABS(x) */
|
||||
mpfr_ui_sub (xp, 1, xp, MPFR_RNDD);
|
||||
MPFR_ASSERTD (MPFR_GET_EXP (xp) <= 0);
|
||||
MPFR_ASSERTD (MPFR_GET_EXP (x) <= 0);
|
||||
xp_exp = 2 - MPFR_GET_EXP (xp);
|
||||
|
||||
/* Set up initial prec */
|
||||
prec = MPFR_PREC (asin) + 10 + xp_exp;
|
||||
|
||||
/* use asin(x) = atan(x/sqrt(1-x^2)) */
|
||||
MPFR_ZIV_INIT (loop, prec);
|
||||
for (;;)
|
||||
{
|
||||
mpfr_set_prec (xp, prec);
|
||||
mpfr_sqr (xp, x, MPFR_RNDN);
|
||||
mpfr_ui_sub (xp, 1, xp, MPFR_RNDN);
|
||||
mpfr_sqrt (xp, xp, MPFR_RNDN);
|
||||
mpfr_div (xp, x, xp, MPFR_RNDN);
|
||||
mpfr_atan (xp, xp, MPFR_RNDN);
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (xp, prec - xp_exp,
|
||||
MPFR_PREC (asin), rnd_mode)))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, prec);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
inexact = mpfr_set (asin, xp, rnd_mode);
|
||||
|
||||
mpfr_clear (xp);
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (asin, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/* mpfr_asinh -- inverse hyperbolic sine
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* The computation of asinh is done by *
|
||||
* asinh = ln(x + sqrt(x^2 + 1)) */
|
||||
|
||||
int
|
||||
mpfr_asinh (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
int signx, neg;
|
||||
mpfr_prec_t Ny, Nt;
|
||||
mpfr_t t; /* auxiliary variables */
|
||||
mpfr_exp_t err;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF (x))
|
||||
{
|
||||
MPFR_SET_INF (y);
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
else /* x is necessarily 0 */
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (x));
|
||||
MPFR_SET_ZERO (y); /* asinh(0) = 0 */
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* asinh(x) = x - x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */
|
||||
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -2 * MPFR_GET_EXP (x), 2, 0,
|
||||
rnd_mode, {});
|
||||
|
||||
Ny = MPFR_PREC (y); /* Precision of output variable */
|
||||
|
||||
signx = MPFR_SIGN (x);
|
||||
neg = MPFR_IS_NEG (x);
|
||||
|
||||
/* General case */
|
||||
|
||||
/* compute the precision of intermediary variable */
|
||||
/* the optimal number of bits : see algorithms.tex */
|
||||
Nt = Ny + 4 + MPFR_INT_CEIL_LOG2 (Ny);
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* initialize intermediary variables */
|
||||
mpfr_init2 (t, Nt);
|
||||
|
||||
/* First computation of asinh */
|
||||
MPFR_ZIV_INIT (loop, Nt);
|
||||
for (;;)
|
||||
{
|
||||
/* compute asinh */
|
||||
mpfr_mul (t, x, x, MPFR_RNDD); /* x^2 */
|
||||
mpfr_add_ui (t, t, 1, MPFR_RNDD); /* x^2+1 */
|
||||
mpfr_sqrt (t, t, MPFR_RNDN); /* sqrt(x^2+1) */
|
||||
(neg ? mpfr_sub : mpfr_add) (t, t, x, MPFR_RNDN); /* sqrt(x^2+1)+x */
|
||||
mpfr_log (t, t, MPFR_RNDN); /* ln(sqrt(x^2+1)+x)*/
|
||||
|
||||
if (MPFR_LIKELY (MPFR_IS_PURE_FP (t)))
|
||||
{
|
||||
/* error estimate -- see algorithms.tex */
|
||||
err = Nt - (MAX (4 - MPFR_GET_EXP (t), 0) + 1);
|
||||
if (MPFR_LIKELY (MPFR_IS_ZERO (t)
|
||||
|| MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* actualisation of the precision */
|
||||
MPFR_ZIV_NEXT (loop, Nt);
|
||||
mpfr_set_prec (t, Nt);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inexact = mpfr_set4 (y, t, rnd_mode, signx);
|
||||
|
||||
mpfr_clear (t);
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,435 @@
|
|||
/* mpfr_atan -- arc-tangent of a floating-point number
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library, and was contributed by Mathieu Dutour.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* If x = p/2^r, put in y an approximation of atan(x)/x using 2^m terms
|
||||
for the series expansion, with an error of at most 1 ulp.
|
||||
Assumes |x| < 1.
|
||||
|
||||
If X=x^2, we want 1 - X/3 + X^2/5 - ... + (-1)^k*X^k/(2k+1) + ...
|
||||
|
||||
Assume p is non-zero.
|
||||
|
||||
When we sum terms up to x^k/(2k+1), the denominator Q[0] is
|
||||
3*5*7*...*(2k+1) ~ (2k/e)^k.
|
||||
*/
|
||||
static void
|
||||
mpfr_atan_aux (mpfr_ptr y, mpz_ptr p, long r, int m, mpz_t *tab)
|
||||
{
|
||||
mpz_t *S, *Q, *ptoj;
|
||||
unsigned long n, i, k, j, l;
|
||||
mpfr_exp_t diff, expo;
|
||||
int im, done;
|
||||
mpfr_prec_t mult, *accu, *log2_nb_terms;
|
||||
mpfr_prec_t precy = MPFR_PREC(y);
|
||||
|
||||
MPFR_ASSERTD(mpz_cmp_ui (p, 0) != 0);
|
||||
|
||||
accu = (mpfr_prec_t*) (*__gmp_allocate_func) ((2 * m + 2) * sizeof (mpfr_prec_t));
|
||||
log2_nb_terms = accu + m + 1;
|
||||
|
||||
/* Set Tables */
|
||||
S = tab; /* S */
|
||||
ptoj = S + 1*(m+1); /* p^2^j Precomputed table */
|
||||
Q = S + 2*(m+1); /* Product of Odd integer table */
|
||||
|
||||
/* From p to p^2, and r to 2r */
|
||||
mpz_mul (p, p, p);
|
||||
MPFR_ASSERTD (2 * r > r);
|
||||
r = 2 * r;
|
||||
|
||||
/* Normalize p */
|
||||
n = mpz_scan1 (p, 0);
|
||||
mpz_tdiv_q_2exp (p, p, n); /* exact */
|
||||
MPFR_ASSERTD (r > n);
|
||||
r -= n;
|
||||
/* since |p/2^r| < 1, and p is a non-zero integer, necessarily r > 0 */
|
||||
|
||||
MPFR_ASSERTD (mpz_sgn (p) > 0);
|
||||
MPFR_ASSERTD (m > 0);
|
||||
|
||||
/* check if p=1 (special case) */
|
||||
l = 0;
|
||||
/*
|
||||
We compute by binary splitting, with X = x^2 = p/2^r:
|
||||
P(a,b) = p if a+1=b, P(a,c)*P(c,b) otherwise
|
||||
Q(a,b) = (2a+1)*2^r if a+1=b [except Q(0,1)=1], Q(a,c)*Q(c,b) otherwise
|
||||
S(a,b) = p*(2a+1) if a+1=b, Q(c,b)*S(a,c)+Q(a,c)*P(a,c)*S(c,b) otherwise
|
||||
Then atan(x)/x ~ S(0,i)/Q(0,i) for i so that (p/2^r)^i/i is small enough.
|
||||
The factor 2^(r*(b-a)) in Q(a,b) is implicit, thus we have to take it
|
||||
into account when we compute with Q.
|
||||
*/
|
||||
accu[0] = 0; /* accu[k] = Mult[0] + ... + Mult[k], where Mult[j] is the
|
||||
number of bits of the corresponding term S[j]/Q[j] */
|
||||
if (mpz_cmp_ui (p, 1) != 0)
|
||||
{
|
||||
/* p <> 1: precompute ptoj table */
|
||||
mpz_set (ptoj[0], p);
|
||||
for (im = 1 ; im <= m ; im ++)
|
||||
mpz_mul (ptoj[im], ptoj[im - 1], ptoj[im - 1]);
|
||||
/* main loop */
|
||||
n = 1UL << m;
|
||||
/* the ith term being X^i/(2i+1) with X=p/2^r, we can stop when
|
||||
p^i/2^(r*i) < 2^(-precy), i.e. r*i > precy + log2(p^i) */
|
||||
for (i = k = done = 0; (i < n) && (done == 0); i += 2, k ++)
|
||||
{
|
||||
/* initialize both S[k],Q[k] and S[k+1],Q[k+1] */
|
||||
mpz_set_ui (Q[k+1], 2 * i + 3); /* Q(i+1,i+2) */
|
||||
mpz_mul_ui (S[k+1], p, 2 * i + 1); /* S(i+1,i+2) */
|
||||
mpz_mul_2exp (S[k], Q[k+1], r);
|
||||
mpz_sub (S[k], S[k], S[k+1]); /* S(i,i+2) */
|
||||
mpz_mul_ui (Q[k], Q[k+1], 2 * i + 1); /* Q(i,i+2) */
|
||||
log2_nb_terms[k] = 1; /* S[k]/Q[k] corresponds to 2 terms */
|
||||
for (j = (i + 2) >> 1, l = 1; (j & 1) == 0; l ++, j >>= 1, k --)
|
||||
{
|
||||
/* invariant: S[k-1]/Q[k-1] and S[k]/Q[k] correspond
|
||||
to 2^l terms each. We combine them into S[k-1]/Q[k-1] */
|
||||
MPFR_ASSERTD (k > 0);
|
||||
mpz_mul (S[k], S[k], Q[k-1]);
|
||||
mpz_mul (S[k], S[k], ptoj[l]);
|
||||
mpz_mul (S[k-1], S[k-1], Q[k]);
|
||||
mpz_mul_2exp (S[k-1], S[k-1], r << l);
|
||||
mpz_add (S[k-1], S[k-1], S[k]);
|
||||
mpz_mul (Q[k-1], Q[k-1], Q[k]);
|
||||
log2_nb_terms[k-1] = l + 1;
|
||||
/* now S[k-1]/Q[k-1] corresponds to 2^(l+1) terms */
|
||||
MPFR_MPZ_SIZEINBASE2(mult, ptoj[l+1]);
|
||||
/* FIXME: precompute bits(ptoj[l+1]) outside the loop? */
|
||||
mult = (r << (l + 1)) - mult - 1;
|
||||
accu[k-1] = (k == 1) ? mult : accu[k-2] + mult;
|
||||
if (accu[k-1] > precy)
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* special case p=1: the ith term being X^i/(2i+1) with X=1/2^r,
|
||||
we can stop when r*i > precy i.e. i > precy/r */
|
||||
{
|
||||
n = 1UL << m;
|
||||
for (i = k = 0; (i < n) && (i <= precy / r); i += 2, k ++)
|
||||
{
|
||||
mpz_set_ui (Q[k + 1], 2 * i + 3);
|
||||
mpz_mul_2exp (S[k], Q[k+1], r);
|
||||
mpz_sub_ui (S[k], S[k], 1 + 2 * i);
|
||||
mpz_mul_ui (Q[k], Q[k + 1], 1 + 2 * i);
|
||||
log2_nb_terms[k] = 1; /* S[k]/Q[k] corresponds to 2 terms */
|
||||
for (j = (i + 2) >> 1, l = 1; (j & 1) == 0; l++, j >>= 1, k --)
|
||||
{
|
||||
MPFR_ASSERTD (k > 0);
|
||||
mpz_mul (S[k], S[k], Q[k-1]);
|
||||
mpz_mul (S[k-1], S[k-1], Q[k]);
|
||||
mpz_mul_2exp (S[k-1], S[k-1], r << l);
|
||||
mpz_add (S[k-1], S[k-1], S[k]);
|
||||
mpz_mul (Q[k-1], Q[k-1], Q[k]);
|
||||
log2_nb_terms[k-1] = l + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* we need to combine S[0]/Q[0]...S[k-1]/Q[k-1] */
|
||||
l = 0; /* number of terms accumulated in S[k]/Q[k] */
|
||||
while (k > 1)
|
||||
{
|
||||
k --;
|
||||
/* combine S[k-1]/Q[k-1] and S[k]/Q[k] */
|
||||
j = log2_nb_terms[k-1];
|
||||
mpz_mul (S[k], S[k], Q[k-1]);
|
||||
if (mpz_cmp_ui (p, 1) != 0)
|
||||
mpz_mul (S[k], S[k], ptoj[j]);
|
||||
mpz_mul (S[k-1], S[k-1], Q[k]);
|
||||
l += 1 << log2_nb_terms[k];
|
||||
mpz_mul_2exp (S[k-1], S[k-1], r * l);
|
||||
mpz_add (S[k-1], S[k-1], S[k]);
|
||||
mpz_mul (Q[k-1], Q[k-1], Q[k]);
|
||||
}
|
||||
(*__gmp_free_func) (accu, (2 * m + 2) * sizeof (mpfr_prec_t));
|
||||
|
||||
MPFR_MPZ_SIZEINBASE2 (diff, S[0]);
|
||||
diff -= 2 * precy;
|
||||
expo = diff;
|
||||
if (diff >= 0)
|
||||
mpz_tdiv_q_2exp (S[0], S[0], diff);
|
||||
else
|
||||
mpz_mul_2exp (S[0], S[0], -diff);
|
||||
|
||||
MPFR_MPZ_SIZEINBASE2 (diff, Q[0]);
|
||||
diff -= precy;
|
||||
expo -= diff;
|
||||
if (diff >= 0)
|
||||
mpz_tdiv_q_2exp (Q[0], Q[0], diff);
|
||||
else
|
||||
mpz_mul_2exp (Q[0], Q[0], -diff);
|
||||
|
||||
mpz_tdiv_q (S[0], S[0], Q[0]);
|
||||
mpfr_set_z (y, S[0], MPFR_RNDD);
|
||||
MPFR_SET_EXP (y, MPFR_EXP(y) + expo - r * (i - 1));
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_atan (mpfr_ptr atan, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t xp, arctgt, sk, tmp, tmp2;
|
||||
mpz_t ukz;
|
||||
mpz_t *tabz;
|
||||
mpfr_exp_t exptol;
|
||||
mpfr_prec_t prec, realprec, est_lost, lost;
|
||||
unsigned long twopoweri, log2p, red;
|
||||
int comparaison, inexact;
|
||||
int i, n0, oldn0;
|
||||
MPFR_GROUP_DECL (group);
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("atan[%#R]=%R inexact=%d", atan, atan, inexact));
|
||||
|
||||
/* Singular cases */
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x))
|
||||
{
|
||||
MPFR_SET_NAN (atan);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF (x))
|
||||
{
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
if (MPFR_IS_POS (x)) /* arctan(+inf) = Pi/2 */
|
||||
inexact = mpfr_const_pi (atan, rnd_mode);
|
||||
else /* arctan(-inf) = -Pi/2 */
|
||||
{
|
||||
inexact = -mpfr_const_pi (atan,
|
||||
MPFR_INVERT_RND (rnd_mode));
|
||||
MPFR_CHANGE_SIGN (atan);
|
||||
}
|
||||
mpfr_div_2ui (atan, atan, 1, rnd_mode); /* exact (no exceptions) */
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (atan, inexact, rnd_mode);
|
||||
}
|
||||
else /* x is necessarily 0 */
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (x));
|
||||
MPFR_SET_ZERO (atan);
|
||||
MPFR_SET_SAME_SIGN (atan, x);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* atan(x) = x - x^3/3 + x^5/5...
|
||||
so the error is < 2^(3*EXP(x)-1)
|
||||
so `EXP(x)-(3*EXP(x)-1)` = -2*EXP(x)+1 */
|
||||
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (atan, x, -2 * MPFR_GET_EXP (x), 1, 0,
|
||||
rnd_mode, {});
|
||||
|
||||
/* Set x_p=|x| */
|
||||
MPFR_TMP_INIT_ABS (xp, x);
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* Other simple case arctan(-+1)=-+pi/4 */
|
||||
comparaison = mpfr_cmp_ui (xp, 1);
|
||||
if (MPFR_UNLIKELY (comparaison == 0))
|
||||
{
|
||||
int neg = MPFR_IS_NEG (x);
|
||||
inexact = mpfr_const_pi (atan, MPFR_IS_POS (x) ? rnd_mode
|
||||
: MPFR_INVERT_RND (rnd_mode));
|
||||
if (neg)
|
||||
{
|
||||
inexact = -inexact;
|
||||
MPFR_CHANGE_SIGN (atan);
|
||||
}
|
||||
mpfr_div_2ui (atan, atan, 2, rnd_mode); /* exact (no exceptions) */
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (atan, inexact, rnd_mode);
|
||||
}
|
||||
|
||||
realprec = MPFR_PREC (atan) + MPFR_INT_CEIL_LOG2 (MPFR_PREC (atan)) + 4;
|
||||
prec = realprec + GMP_NUMB_BITS;
|
||||
|
||||
/* Initialisation */
|
||||
mpz_init (ukz);
|
||||
MPFR_GROUP_INIT_4 (group, prec, sk, tmp, tmp2, arctgt);
|
||||
oldn0 = 0;
|
||||
tabz = (mpz_t *) 0;
|
||||
|
||||
MPFR_ZIV_INIT (loop, prec);
|
||||
for (;;)
|
||||
{
|
||||
/* First, if |x| < 1, we need to have more prec to be able to round (sup)
|
||||
n0 = ceil(log(prec_requested + 2 + 1+ln(2.4)/ln(2))/log(2)) */
|
||||
mpfr_prec_t sup;
|
||||
sup = MPFR_GET_EXP (xp) < 0 ? 2 - MPFR_GET_EXP (xp) : 1; /* sup >= 1 */
|
||||
|
||||
n0 = MPFR_INT_CEIL_LOG2 ((realprec + sup) + 3);
|
||||
/* since realprec >= 4, n0 >= ceil(log2(8)) >= 3, thus 3*n0 > 2 */
|
||||
prec = (realprec + sup) + 1 + MPFR_INT_CEIL_LOG2 (3*n0-2);
|
||||
|
||||
/* the number of lost bits due to argument reduction is
|
||||
9 - 2 * EXP(sk), which we estimate by 9 + 2*ceil(log2(p))
|
||||
since we manage that sk < 1/p */
|
||||
if (MPFR_PREC (atan) > 100)
|
||||
{
|
||||
log2p = MPFR_INT_CEIL_LOG2(prec) / 2 - 3;
|
||||
est_lost = 9 + 2 * log2p;
|
||||
prec += est_lost;
|
||||
}
|
||||
else
|
||||
log2p = est_lost = 0; /* don't reduce the argument */
|
||||
|
||||
/* Initialisation */
|
||||
MPFR_GROUP_REPREC_4 (group, prec, sk, tmp, tmp2, arctgt);
|
||||
if (MPFR_LIKELY (oldn0 == 0))
|
||||
{
|
||||
oldn0 = 3 * (n0 + 1);
|
||||
tabz = (mpz_t *) (*__gmp_allocate_func) (oldn0 * sizeof (mpz_t));
|
||||
for (i = 0; i < oldn0; i++)
|
||||
mpz_init (tabz[i]);
|
||||
}
|
||||
else if (MPFR_UNLIKELY (oldn0 < 3 * (n0 + 1)))
|
||||
{
|
||||
tabz = (mpz_t *) (*__gmp_reallocate_func)
|
||||
(tabz, oldn0 * sizeof (mpz_t), 3 * (n0 + 1)*sizeof (mpz_t));
|
||||
for (i = oldn0; i < 3 * (n0 + 1); i++)
|
||||
mpz_init (tabz[i]);
|
||||
oldn0 = 3 * (n0 + 1);
|
||||
}
|
||||
|
||||
/* The mpfr_ui_div below mustn't underflow. This is guaranteed by
|
||||
MPFR_SAVE_EXPO_MARK, but let's check that for maintainability. */
|
||||
MPFR_ASSERTD (__gmpfr_emax <= 1 - __gmpfr_emin);
|
||||
|
||||
if (comparaison > 0) /* use atan(xp) = Pi/2 - atan(1/xp) */
|
||||
mpfr_ui_div (sk, 1, xp, MPFR_RNDN);
|
||||
else
|
||||
mpfr_set (sk, xp, MPFR_RNDN);
|
||||
|
||||
/* now 0 < sk <= 1 */
|
||||
|
||||
/* Argument reduction: atan(x) = 2 atan((sqrt(1+x^2)-1)/x).
|
||||
We want |sk| < k/sqrt(p) where p is the target precision. */
|
||||
lost = 0;
|
||||
for (red = 0; MPFR_GET_EXP(sk) > - (mpfr_exp_t) log2p; red ++)
|
||||
{
|
||||
lost = 9 - 2 * MPFR_EXP(sk);
|
||||
mpfr_mul (tmp, sk, sk, MPFR_RNDN);
|
||||
mpfr_add_ui (tmp, tmp, 1, MPFR_RNDN);
|
||||
mpfr_sqrt (tmp, tmp, MPFR_RNDN);
|
||||
mpfr_sub_ui (tmp, tmp, 1, MPFR_RNDN);
|
||||
if (red == 0 && comparaison > 0)
|
||||
/* use xp = 1/sk */
|
||||
mpfr_mul (sk, tmp, xp, MPFR_RNDN);
|
||||
else
|
||||
mpfr_div (sk, tmp, sk, MPFR_RNDN);
|
||||
}
|
||||
|
||||
/* we started from x0 = 1/|x| if |x| > 1, and |x| otherwise, thus
|
||||
we had x0 = min(|x|, 1/|x|) <= 1, and applied 'red' times the
|
||||
argument reduction x -> (sqrt(1+x^2)-1)/x, which keeps 0 < x < 1,
|
||||
thus 0 < sk <= 1, and sk=1 can occur only if red=0 */
|
||||
|
||||
/* If sk=1, then if |x| < 1, we have 1 - 2^(-prec-1) <= |x| < 1,
|
||||
or if |x| > 1, we have 1 - 2^(-prec-1) <= 1/|x| < 1, thus in all
|
||||
cases ||x| - 1| <= 2^(-prec), from which it follows
|
||||
|atan|x| - Pi/4| <= 2^(-prec), given the Taylor expansion
|
||||
atan(1+x) = Pi/4 + x/2 - x^2/4 + ...
|
||||
Since Pi/4 = 0.785..., the error is at most one ulp.
|
||||
*/
|
||||
if (MPFR_UNLIKELY(mpfr_cmp_ui (sk, 1) == 0))
|
||||
{
|
||||
mpfr_const_pi (arctgt, MPFR_RNDN); /* 1/2 ulp extra error */
|
||||
mpfr_div_2ui (arctgt, arctgt, 2, MPFR_RNDN); /* exact */
|
||||
realprec = prec - 2;
|
||||
goto can_round;
|
||||
}
|
||||
|
||||
/* Assignation */
|
||||
MPFR_SET_ZERO (arctgt);
|
||||
twopoweri = 1 << 0;
|
||||
MPFR_ASSERTD (n0 >= 4);
|
||||
for (i = 0 ; i < n0; i++)
|
||||
{
|
||||
if (MPFR_UNLIKELY (MPFR_IS_ZERO (sk)))
|
||||
break;
|
||||
/* Calculation of trunc(tmp) --> mpz */
|
||||
mpfr_mul_2ui (tmp, sk, twopoweri, MPFR_RNDN);
|
||||
mpfr_trunc (tmp, tmp);
|
||||
if (!MPFR_IS_ZERO (tmp))
|
||||
{
|
||||
/* tmp = ukz*2^exptol */
|
||||
exptol = mpfr_get_z_2exp (ukz, tmp);
|
||||
/* since the s_k are decreasing (see algorithms.tex),
|
||||
and s_0 = min(|x|, 1/|x|) < 1, we have sk < 1,
|
||||
thus exptol < 0 */
|
||||
MPFR_ASSERTD (exptol < 0);
|
||||
mpz_tdiv_q_2exp (ukz, ukz, (unsigned long int) (-exptol));
|
||||
/* since tmp is a non-zero integer, and tmp = ukzold*2^exptol,
|
||||
we now have ukz = tmp, thus ukz is non-zero */
|
||||
/* Calculation of arctan(Ak) */
|
||||
mpfr_set_z (tmp, ukz, MPFR_RNDN);
|
||||
mpfr_div_2ui (tmp, tmp, twopoweri, MPFR_RNDN);
|
||||
mpfr_atan_aux (tmp2, ukz, twopoweri, n0 - i, tabz);
|
||||
mpfr_mul (tmp2, tmp2, tmp, MPFR_RNDN);
|
||||
/* Addition */
|
||||
mpfr_add (arctgt, arctgt, tmp2, MPFR_RNDN);
|
||||
/* Next iteration */
|
||||
mpfr_sub (tmp2, sk, tmp, MPFR_RNDN);
|
||||
mpfr_mul (sk, sk, tmp, MPFR_RNDN);
|
||||
mpfr_add_ui (sk, sk, 1, MPFR_RNDN);
|
||||
mpfr_div (sk, tmp2, sk, MPFR_RNDN);
|
||||
}
|
||||
twopoweri <<= 1;
|
||||
}
|
||||
/* Add last step (Arctan(sk) ~= sk */
|
||||
mpfr_add (arctgt, arctgt, sk, MPFR_RNDN);
|
||||
|
||||
/* argument reduction */
|
||||
mpfr_mul_2exp (arctgt, arctgt, red, MPFR_RNDN);
|
||||
|
||||
if (comparaison > 0)
|
||||
{ /* atan(x) = Pi/2-atan(1/x) for x > 0 */
|
||||
mpfr_const_pi (tmp, MPFR_RNDN);
|
||||
mpfr_div_2ui (tmp, tmp, 1, MPFR_RNDN);
|
||||
mpfr_sub (arctgt, tmp, arctgt, MPFR_RNDN);
|
||||
}
|
||||
MPFR_SET_POS (arctgt);
|
||||
|
||||
can_round:
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (arctgt, realprec + est_lost - lost,
|
||||
MPFR_PREC (atan), rnd_mode)))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, realprec);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inexact = mpfr_set4 (atan, arctgt, rnd_mode, MPFR_SIGN (x));
|
||||
|
||||
for (i = 0 ; i < oldn0 ; i++)
|
||||
mpz_clear (tabz[i]);
|
||||
mpz_clear (ukz);
|
||||
(*__gmp_free_func) (tabz, oldn0 * sizeof (mpz_t));
|
||||
MPFR_GROUP_CLEAR (group);
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (arctgt, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
/* mpfr_atan2 -- arc-tan 2 of a floating-point number
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library, and was contributed by Mathieu Dutour.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
static int
|
||||
pi_div_2ui (mpfr_ptr dest, int i, int neg, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
if (neg) /* -PI/2^i */
|
||||
{
|
||||
inexact = - mpfr_const_pi (dest, MPFR_INVERT_RND (rnd_mode));
|
||||
MPFR_CHANGE_SIGN (dest);
|
||||
}
|
||||
else /* PI/2^i */
|
||||
{
|
||||
inexact = mpfr_const_pi (dest, rnd_mode);
|
||||
}
|
||||
mpfr_div_2ui (dest, dest, i, rnd_mode); /* exact */
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (dest, inexact, rnd_mode);
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_atan2 (mpfr_ptr dest, mpfr_srcptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t tmp, pi;
|
||||
int inexact;
|
||||
mpfr_prec_t prec;
|
||||
mpfr_exp_t e;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
MPFR_LOG_FUNC (("y[%#R]=%R x[%#R]=%R rnd=%d", y, y, x, x, rnd_mode),
|
||||
("atan[%#R]=%R inexact=%d", dest, dest, inexact));
|
||||
|
||||
/* Special cases */
|
||||
if (MPFR_ARE_SINGULAR (x, y))
|
||||
{
|
||||
/* atan2(0, 0) does not raise the "invalid" floating-point
|
||||
exception, nor does atan2(y, 0) raise the "divide-by-zero"
|
||||
floating-point exception.
|
||||
-- atan2(±0, -0) returns ±pi.313)
|
||||
-- atan2(±0, +0) returns ±0.
|
||||
-- atan2(±0, x) returns ±pi, for x < 0.
|
||||
-- atan2(±0, x) returns ±0, for x > 0.
|
||||
-- atan2(y, ±0) returns -pi/2 for y < 0.
|
||||
-- atan2(y, ±0) returns pi/2 for y > 0.
|
||||
-- atan2(±oo, -oo) returns ±3pi/4.
|
||||
-- atan2(±oo, +oo) returns ±pi/4.
|
||||
-- atan2(±oo, x) returns ±pi/2, for finite x.
|
||||
-- atan2(±y, -oo) returns ±pi, for finite y > 0.
|
||||
-- atan2(±y, +oo) returns ±0, for finite y > 0.
|
||||
*/
|
||||
if (MPFR_IS_NAN (x) || MPFR_IS_NAN (y))
|
||||
{
|
||||
MPFR_SET_NAN (dest);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
if (MPFR_IS_ZERO (y))
|
||||
{
|
||||
if (MPFR_IS_NEG (x)) /* +/- PI */
|
||||
{
|
||||
set_pi:
|
||||
if (MPFR_IS_NEG (y))
|
||||
{
|
||||
inexact = mpfr_const_pi (dest, MPFR_INVERT_RND (rnd_mode));
|
||||
MPFR_CHANGE_SIGN (dest);
|
||||
return -inexact;
|
||||
}
|
||||
else
|
||||
return mpfr_const_pi (dest, rnd_mode);
|
||||
}
|
||||
else /* +/- 0 */
|
||||
{
|
||||
set_zero:
|
||||
MPFR_SET_ZERO (dest);
|
||||
MPFR_SET_SAME_SIGN (dest, y);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (MPFR_IS_ZERO (x))
|
||||
{
|
||||
return pi_div_2ui (dest, 1, MPFR_IS_NEG (y), rnd_mode);
|
||||
}
|
||||
if (MPFR_IS_INF (y))
|
||||
{
|
||||
if (!MPFR_IS_INF (x)) /* +/- PI/2 */
|
||||
return pi_div_2ui (dest, 1, MPFR_IS_NEG (y), rnd_mode);
|
||||
else if (MPFR_IS_POS (x)) /* +/- PI/4 */
|
||||
return pi_div_2ui (dest, 2, MPFR_IS_NEG (y), rnd_mode);
|
||||
else /* +/- 3*PI/4: Ugly since we have to round properly */
|
||||
{
|
||||
mpfr_t tmp2;
|
||||
MPFR_ZIV_DECL (loop2);
|
||||
mpfr_prec_t prec2 = MPFR_PREC (dest) + 10;
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
mpfr_init2 (tmp2, prec2);
|
||||
MPFR_ZIV_INIT (loop2, prec2);
|
||||
for (;;)
|
||||
{
|
||||
mpfr_const_pi (tmp2, MPFR_RNDN);
|
||||
mpfr_mul_ui (tmp2, tmp2, 3, MPFR_RNDN); /* Error <= 2 */
|
||||
mpfr_div_2ui (tmp2, tmp2, 2, MPFR_RNDN);
|
||||
if (mpfr_round_p (MPFR_MANT (tmp2), MPFR_LIMB_SIZE (tmp2),
|
||||
MPFR_PREC (tmp2) - 2,
|
||||
MPFR_PREC (dest) + (rnd_mode == MPFR_RNDN)))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop2, prec2);
|
||||
mpfr_set_prec (tmp2, prec2);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop2);
|
||||
if (MPFR_IS_NEG (y))
|
||||
MPFR_CHANGE_SIGN (tmp2);
|
||||
inexact = mpfr_set (dest, tmp2, rnd_mode);
|
||||
mpfr_clear (tmp2);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (dest, inexact, rnd_mode);
|
||||
}
|
||||
}
|
||||
MPFR_ASSERTD (MPFR_IS_INF (x));
|
||||
if (MPFR_IS_NEG (x))
|
||||
goto set_pi;
|
||||
else
|
||||
goto set_zero;
|
||||
}
|
||||
|
||||
/* When x=1, atan2(y,x) = atan(y). FIXME: more generally, if x is a power
|
||||
of two, we could call directly atan(y/x) since y/x is exact. */
|
||||
if (mpfr_cmp_ui (x, 1) == 0)
|
||||
return mpfr_atan (dest, y, rnd_mode);
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* Set up initial prec */
|
||||
prec = MPFR_PREC (dest) + 3 + MPFR_INT_CEIL_LOG2 (MPFR_PREC (dest));
|
||||
mpfr_init2 (tmp, prec);
|
||||
|
||||
MPFR_ZIV_INIT (loop, prec);
|
||||
if (MPFR_IS_POS (x))
|
||||
/* use atan2(y,x) = atan(y/x) */
|
||||
for (;;)
|
||||
{
|
||||
int div_inex;
|
||||
MPFR_BLOCK_DECL (flags);
|
||||
|
||||
MPFR_BLOCK (flags, div_inex = mpfr_div (tmp, y, x, MPFR_RNDN));
|
||||
if (div_inex == 0)
|
||||
{
|
||||
/* Result is exact. */
|
||||
inexact = mpfr_atan (dest, tmp, rnd_mode);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Error <= ulp (tmp) except in case of underflow or overflow. */
|
||||
|
||||
/* If the division underflowed, since |atan(z)/z| < 1, we have
|
||||
an underflow. */
|
||||
if (MPFR_UNDERFLOW (flags))
|
||||
{
|
||||
int sign;
|
||||
|
||||
/* In the case MPFR_RNDN with 2^(emin-2) < |y/x| < 2^(emin-1):
|
||||
The smallest significand value S > 1 of |y/x| is:
|
||||
* 1 / (1 - 2^(-px)) if py <= px,
|
||||
* (1 - 2^(-px) + 2^(-py)) / (1 - 2^(-px)) if py >= px.
|
||||
Therefore S - 1 > 2^(-pz), where pz = max(px,py). We have:
|
||||
atan(|y/x|) > atan(z), where z = 2^(emin-2) * (1 + 2^(-pz)).
|
||||
> z - z^3 / 3.
|
||||
> 2^(emin-2) * (1 + 2^(-pz) - 2^(2 emin - 5))
|
||||
Assuming pz <= -2 emin + 5, we can round away from zero
|
||||
(this is what mpfr_underflow always does on MPFR_RNDN).
|
||||
In the case MPFR_RNDN with |y/x| <= 2^(emin-2), we round
|
||||
toward zero, as |atan(z)/z| < 1. */
|
||||
MPFR_ASSERTN (MPFR_PREC_MAX <=
|
||||
2 * (mpfr_uexp_t) - MPFR_EMIN_MIN + 5);
|
||||
if (rnd_mode == MPFR_RNDN && MPFR_IS_ZERO (tmp))
|
||||
rnd_mode = MPFR_RNDZ;
|
||||
sign = MPFR_SIGN (tmp);
|
||||
mpfr_clear (tmp);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_underflow (dest, rnd_mode, sign);
|
||||
}
|
||||
|
||||
mpfr_atan (tmp, tmp, MPFR_RNDN); /* Error <= 2*ulp (tmp) since
|
||||
abs(D(arctan)) <= 1 */
|
||||
/* TODO: check that the error bound is correct in case of overflow. */
|
||||
/* FIXME: Error <= ulp(tmp) ? */
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - 2, MPFR_PREC (dest),
|
||||
rnd_mode)))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, prec);
|
||||
mpfr_set_prec (tmp, prec);
|
||||
}
|
||||
else /* x < 0 */
|
||||
/* Use sign(y)*(PI - atan (|y/x|)) */
|
||||
{
|
||||
mpfr_init2 (pi, prec);
|
||||
for (;;)
|
||||
{
|
||||
mpfr_div (tmp, y, x, MPFR_RNDN); /* Error <= ulp (tmp) */
|
||||
/* If tmp is 0, we have |y/x| <= 2^(-emin-2), thus
|
||||
atan|y/x| < 2^(-emin-2). */
|
||||
MPFR_SET_POS (tmp); /* no error */
|
||||
mpfr_atan (tmp, tmp, MPFR_RNDN); /* Error <= 2*ulp (tmp) since
|
||||
abs(D(arctan)) <= 1 */
|
||||
mpfr_const_pi (pi, MPFR_RNDN); /* Error <= ulp(pi) /2 */
|
||||
e = MPFR_NOTZERO(tmp) ? MPFR_GET_EXP (tmp) : __gmpfr_emin - 1;
|
||||
mpfr_sub (tmp, pi, tmp, MPFR_RNDN); /* see above */
|
||||
if (MPFR_IS_NEG (y))
|
||||
MPFR_CHANGE_SIGN (tmp);
|
||||
/* Error(tmp) <= (1/2+2^(EXP(pi)-EXP(tmp)-1)+2^(e-EXP(tmp)+1))*ulp
|
||||
<= 2^(MAX (MAX (EXP(PI)-EXP(tmp)-1, e-EXP(tmp)+1),
|
||||
-1)+2)*ulp(tmp) */
|
||||
e = MAX (MAX (MPFR_GET_EXP (pi)-MPFR_GET_EXP (tmp) - 1,
|
||||
e - MPFR_GET_EXP (tmp) + 1), -1) + 2;
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - e, MPFR_PREC (dest),
|
||||
rnd_mode)))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, prec);
|
||||
mpfr_set_prec (tmp, prec);
|
||||
mpfr_set_prec (pi, prec);
|
||||
}
|
||||
mpfr_clear (pi);
|
||||
}
|
||||
inexact = mpfr_set (dest, tmp, rnd_mode);
|
||||
|
||||
end:
|
||||
MPFR_ZIV_FREE (loop);
|
||||
mpfr_clear (tmp);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (dest, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/* mpfr_atanh -- Inverse Hyperbolic Tangente
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* The computation of atanh is done by
|
||||
atanh= 1/2*ln(x+1)-1/2*ln(1-x) */
|
||||
|
||||
int
|
||||
mpfr_atanh (mpfr_ptr y, mpfr_srcptr xt , mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
mpfr_t x, t, te;
|
||||
mpfr_prec_t Nx, Ny, Nt;
|
||||
mpfr_exp_t err;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", xt, xt, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
/* Special cases */
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (xt)))
|
||||
{
|
||||
/* atanh(NaN) = NaN, and atanh(+/-Inf) = NaN since tanh gives a result
|
||||
between -1 and 1 */
|
||||
if (MPFR_IS_NAN (xt) || MPFR_IS_INF (xt))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else /* necessarily xt is 0 */
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (xt));
|
||||
MPFR_SET_ZERO (y); /* atanh(0) = 0 */
|
||||
MPFR_SET_SAME_SIGN (y,xt);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* atanh (x) = NaN as soon as |x| > 1, and arctanh(+/-1) = +/-Inf */
|
||||
if (MPFR_UNLIKELY (MPFR_EXP (xt) > 0))
|
||||
{
|
||||
if (MPFR_EXP (xt) == 1 && mpfr_powerof2_raw (xt))
|
||||
{
|
||||
MPFR_SET_INF (y);
|
||||
MPFR_SET_SAME_SIGN (y, xt);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
|
||||
/* atanh(x) = x + x^3/3 + ... so the error is < 2^(3*EXP(x)-1) */
|
||||
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, xt, -2 * MPFR_GET_EXP (xt), 1, 1,
|
||||
rnd_mode, {});
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* Compute initial precision */
|
||||
Nx = MPFR_PREC (xt);
|
||||
MPFR_TMP_INIT_ABS (x, xt);
|
||||
Ny = MPFR_PREC (y);
|
||||
Nt = MAX (Nx, Ny);
|
||||
/* the optimal number of bits : see algorithms.ps */
|
||||
Nt = Nt + MPFR_INT_CEIL_LOG2 (Nt) + 4;
|
||||
|
||||
/* initialise of intermediary variable */
|
||||
mpfr_init2 (t, Nt);
|
||||
mpfr_init2 (te, Nt);
|
||||
|
||||
/* First computation of cosh */
|
||||
MPFR_ZIV_INIT (loop, Nt);
|
||||
for (;;)
|
||||
{
|
||||
/* compute atanh */
|
||||
mpfr_ui_sub (te, 1, x, MPFR_RNDU); /* (1-xt)*/
|
||||
mpfr_add_ui (t, x, 1, MPFR_RNDD); /* (xt+1)*/
|
||||
mpfr_div (t, t, te, MPFR_RNDN); /* (1+xt)/(1-xt)*/
|
||||
mpfr_log (t, t, MPFR_RNDN); /* ln((1+xt)/(1-xt))*/
|
||||
mpfr_div_2ui (t, t, 1, MPFR_RNDN); /* (1/2)*ln((1+xt)/(1-xt))*/
|
||||
|
||||
/* error estimate: see algorithms.tex */
|
||||
/* FIXME: this does not correspond to the value in algorithms.tex!!! */
|
||||
/* err=Nt-__gmpfr_ceil_log2(1+5*pow(2,1-MPFR_EXP(t)));*/
|
||||
err = Nt - (MAX (4 - MPFR_GET_EXP (t), 0) + 1);
|
||||
|
||||
if (MPFR_LIKELY (MPFR_IS_ZERO (t)
|
||||
|| MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
|
||||
break;
|
||||
|
||||
/* reactualisation of the precision */
|
||||
MPFR_ZIV_NEXT (loop, Nt);
|
||||
mpfr_set_prec (t, Nt);
|
||||
mpfr_set_prec (te, Nt);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inexact = mpfr_set4 (y, t, rnd_mode, MPFR_SIGN (xt));
|
||||
|
||||
mpfr_clear(t);
|
||||
mpfr_clear(te);
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/* bernoulli -- internal function to compute Bernoulli numbers.
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* assuming b[0]...b[2(n-1)] are computed, computes and stores B[2n]*(2n+1)!
|
||||
|
||||
t/(exp(t)-1) = sum(B[j]*t^j/j!, j=0..infinity)
|
||||
thus t = (exp(t)-1) * sum(B[j]*t^j/j!, n=0..infinity).
|
||||
Taking the coefficient of degree n+1 > 1, we get:
|
||||
0 = sum(1/(n+1-k)!*B[k]/k!, k=0..n)
|
||||
which gives:
|
||||
B[n] = -sum(binomial(n+1,k)*B[k], k=0..n-1)/(n+1).
|
||||
|
||||
Let C[n] = B[n]*(n+1)!.
|
||||
Then C[n] = -sum(binomial(n+1,k)*C[k]*n!/(k+1)!, k=0..n-1),
|
||||
which proves that the C[n] are integers.
|
||||
*/
|
||||
mpz_t*
|
||||
mpfr_bernoulli_internal (mpz_t *b, unsigned long n)
|
||||
{
|
||||
if (n == 0)
|
||||
{
|
||||
b = (mpz_t *) (*__gmp_allocate_func) (sizeof (mpz_t));
|
||||
mpz_init_set_ui (b[0], 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mpz_t t;
|
||||
unsigned long k;
|
||||
|
||||
b = (mpz_t *) (*__gmp_reallocate_func)
|
||||
(b, n * sizeof (mpz_t), (n + 1) * sizeof (mpz_t));
|
||||
mpz_init (b[n]);
|
||||
/* b[n] = -sum(binomial(2n+1,2k)*C[k]*(2n)!/(2k+1)!, k=0..n-1) */
|
||||
mpz_init_set_ui (t, 2 * n + 1);
|
||||
mpz_mul_ui (t, t, 2 * n - 1);
|
||||
mpz_mul_ui (t, t, 2 * n);
|
||||
mpz_mul_ui (t, t, n);
|
||||
mpz_fdiv_q_ui (t, t, 3); /* exact: t=binomial(2*n+1,2*k)*(2*n)!/(2*k+1)!
|
||||
for k=n-1 */
|
||||
mpz_mul (b[n], t, b[n-1]);
|
||||
for (k = n - 1; k-- > 0;)
|
||||
{
|
||||
mpz_mul_ui (t, t, 2 * k + 1);
|
||||
mpz_mul_ui (t, t, 2 * k + 2);
|
||||
mpz_mul_ui (t, t, 2 * k + 2);
|
||||
mpz_mul_ui (t, t, 2 * k + 3);
|
||||
mpz_fdiv_q_ui (t, t, 2 * (n - k) + 1);
|
||||
mpz_fdiv_q_ui (t, t, 2 * (n - k));
|
||||
mpz_addmul (b[n], t, b[k]);
|
||||
}
|
||||
/* take into account C[1] */
|
||||
mpz_mul_ui (t, t, 2 * n + 1);
|
||||
mpz_fdiv_q_2exp (t, t, 1);
|
||||
mpz_sub (b[n], b[n], t);
|
||||
mpz_neg (b[n], b[n]);
|
||||
mpz_clear (t);
|
||||
}
|
||||
return b;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* buildopt.c -- functions giving information about options used during the
|
||||
mpfr library compilation
|
||||
|
||||
Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_buildopt_tls_p (void)
|
||||
{
|
||||
#ifdef MPFR_USE_THREAD_SAFE
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_buildopt_decimal_p (void)
|
||||
{
|
||||
#ifdef MPFR_WANT_DECIMAL_FLOATS
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/* mpfr_cache -- cache interface for multiple-precision constants in MPFR.
|
||||
|
||||
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
#if 0 /* this function is not used/documented/tested so far, it could be
|
||||
useful if some user wants to add a new constant to mpfr, and
|
||||
implement a cache mechanism for that constant */
|
||||
void
|
||||
mpfr_init_cache (mpfr_cache_t cache, int (*func)(mpfr_ptr, mpfr_rnd_t))
|
||||
{
|
||||
MPFR_PREC (cache->x) = 0; /* Invalid prec to detect that the cache is not
|
||||
valid. Maybe add a flag? */
|
||||
cache->func = func;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
mpfr_clear_cache (mpfr_cache_t cache)
|
||||
{
|
||||
if (MPFR_PREC (cache->x) != 0)
|
||||
mpfr_clear (cache->x);
|
||||
MPFR_PREC (cache->x) = 0;
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_cache (mpfr_ptr dest, mpfr_cache_t cache, mpfr_rnd_t rnd)
|
||||
{
|
||||
mpfr_prec_t prec = MPFR_PREC (dest);
|
||||
mpfr_prec_t pold = MPFR_PREC (cache->x);
|
||||
int inexact, sign;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
if (MPFR_UNLIKELY (prec > pold))
|
||||
{
|
||||
/* No previous result in the cache or the precision of the
|
||||
previous result is not sufficient. */
|
||||
|
||||
if (MPFR_UNLIKELY (pold == 0)) /* No previous result. */
|
||||
mpfr_init2 (cache->x, prec);
|
||||
|
||||
/* Update the cache. */
|
||||
pold = prec;
|
||||
/* no need to keep the previous value */
|
||||
mpfr_set_prec (cache->x, pold);
|
||||
cache->inexact = (*cache->func) (cache->x, MPFR_RNDN);
|
||||
}
|
||||
|
||||
/* now pold >= prec is the precision of cache->x */
|
||||
|
||||
/* First, check if the cache has the exact value (unlikely).
|
||||
Else the exact value is between (assuming x=cache->x > 0):
|
||||
x and x+ulp(x) if cache->inexact < 0,
|
||||
x-ulp(x) and x if cache->inexact > 0,
|
||||
and abs(x-exact) <= ulp(x)/2. */
|
||||
|
||||
/* we assume all cached constants are positive */
|
||||
MPFR_ASSERTN (MPFR_IS_POS (cache->x)); /* TODO... */
|
||||
sign = MPFR_SIGN (cache->x);
|
||||
MPFR_SET_EXP (dest, MPFR_GET_EXP (cache->x));
|
||||
MPFR_SET_SIGN (dest, sign);
|
||||
|
||||
/* round cache->x from precision pold down to precision prec */
|
||||
MPFR_RNDRAW_GEN (inexact, dest,
|
||||
MPFR_MANT (cache->x), pold, rnd, sign,
|
||||
if (MPFR_UNLIKELY (cache->inexact == 0))
|
||||
{
|
||||
if ((_sp[0] & _ulp) == 0)
|
||||
{
|
||||
inexact = -sign;
|
||||
goto trunc_doit;
|
||||
}
|
||||
else
|
||||
goto addoneulp;
|
||||
}
|
||||
else if (cache->inexact < 0)
|
||||
goto addoneulp;
|
||||
else /* cache->inexact > 0 */
|
||||
{
|
||||
inexact = -sign;
|
||||
goto trunc_doit;
|
||||
},
|
||||
if (MPFR_UNLIKELY (++MPFR_EXP (dest) > __gmpfr_emax))
|
||||
mpfr_overflow (dest, rnd, sign);
|
||||
);
|
||||
|
||||
if (MPFR_LIKELY (cache->inexact != 0))
|
||||
{
|
||||
switch (rnd)
|
||||
{
|
||||
case MPFR_RNDZ:
|
||||
case MPFR_RNDD:
|
||||
if (MPFR_UNLIKELY (inexact == 0))
|
||||
{
|
||||
inexact = cache->inexact;
|
||||
if (inexact > 0)
|
||||
{
|
||||
mpfr_nextbelow (dest);
|
||||
inexact = -inexact;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MPFR_RNDU:
|
||||
case MPFR_RNDA:
|
||||
if (MPFR_UNLIKELY (inexact == 0))
|
||||
{
|
||||
inexact = cache->inexact;
|
||||
if (inexact < 0)
|
||||
{
|
||||
mpfr_nextabove (dest);
|
||||
inexact = -inexact;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: /* MPFR_RNDN */
|
||||
if (MPFR_UNLIKELY(inexact == 0))
|
||||
inexact = cache->inexact;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (dest, inexact, rnd);
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/* mpfr_cbrt -- cube root function.
|
||||
|
||||
Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* The computation of y = x^(1/3) is done as follows:
|
||||
|
||||
Let x = sign * m * 2^(3*e) where m is an integer
|
||||
|
||||
with 2^(3n-3) <= m < 2^(3n) where n = PREC(y)
|
||||
|
||||
and m = s^3 + r where 0 <= r and m < (s+1)^3
|
||||
|
||||
we want that s has n bits i.e. s >= 2^(n-1), or m >= 2^(3n-3)
|
||||
i.e. m must have at least 3n-2 bits
|
||||
|
||||
then x^(1/3) = s * 2^e if r=0
|
||||
x^(1/3) = (s+1) * 2^e if round up
|
||||
x^(1/3) = (s-1) * 2^e if round down
|
||||
x^(1/3) = s * 2^e if nearest and r < 3/2*s^2+3/4*s+1/8
|
||||
(s+1) * 2^e otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
mpfr_cbrt (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpz_t m;
|
||||
mpfr_exp_t e, r, sh;
|
||||
mpfr_prec_t n, size_m, tmp;
|
||||
int inexact, negative;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
/* special values */
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF (x))
|
||||
{
|
||||
MPFR_SET_INF (y);
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
/* case 0: cbrt(+/- 0) = +/- 0 */
|
||||
else /* x is necessarily 0 */
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (x));
|
||||
MPFR_SET_ZERO (y);
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* General case */
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
mpz_init (m);
|
||||
|
||||
e = mpfr_get_z_2exp (m, x); /* x = m * 2^e */
|
||||
if ((negative = MPFR_IS_NEG(x)))
|
||||
mpz_neg (m, m);
|
||||
r = e % 3;
|
||||
if (r < 0)
|
||||
r += 3;
|
||||
/* x = (m*2^r) * 2^(e-r) = (m*2^r) * 2^(3*q) */
|
||||
|
||||
MPFR_MPZ_SIZEINBASE2 (size_m, m);
|
||||
n = MPFR_PREC (y) + (rnd_mode == MPFR_RNDN);
|
||||
|
||||
/* we want 3*n-2 <= size_m + 3*sh + r <= 3*n
|
||||
i.e. 3*sh + size_m + r <= 3*n */
|
||||
sh = (3 * (mpfr_exp_t) n - (mpfr_exp_t) size_m - r) / 3;
|
||||
sh = 3 * sh + r;
|
||||
if (sh >= 0)
|
||||
{
|
||||
mpz_mul_2exp (m, m, sh);
|
||||
e = e - sh;
|
||||
}
|
||||
else if (r > 0)
|
||||
{
|
||||
mpz_mul_2exp (m, m, r);
|
||||
e = e - r;
|
||||
}
|
||||
|
||||
/* invariant: x = m*2^e, with e divisible by 3 */
|
||||
|
||||
/* we reuse the variable m to store the cube root, since it is not needed
|
||||
any more: we just need to know if the root is exact */
|
||||
inexact = mpz_root (m, m, 3) == 0;
|
||||
|
||||
MPFR_MPZ_SIZEINBASE2 (tmp, m);
|
||||
sh = tmp - n;
|
||||
if (sh > 0) /* we have to flush to 0 the last sh bits from m */
|
||||
{
|
||||
inexact = inexact || ((mpfr_exp_t) mpz_scan1 (m, 0) < sh);
|
||||
mpz_fdiv_q_2exp (m, m, sh);
|
||||
e += 3 * sh;
|
||||
}
|
||||
|
||||
if (inexact)
|
||||
{
|
||||
if (negative)
|
||||
rnd_mode = MPFR_INVERT_RND (rnd_mode);
|
||||
if (rnd_mode == MPFR_RNDU || rnd_mode == MPFR_RNDA
|
||||
|| (rnd_mode == MPFR_RNDN && mpz_tstbit (m, 0)))
|
||||
inexact = 1, mpz_add_ui (m, m, 1);
|
||||
else
|
||||
inexact = -1;
|
||||
}
|
||||
|
||||
/* either inexact is not zero, and the conversion is exact, i.e. inexact
|
||||
is not changed; or inexact=0, and inexact is set only when
|
||||
rnd_mode=MPFR_RNDN and bit (n+1) from m is 1 */
|
||||
inexact += mpfr_set_z (y, m, MPFR_RNDN);
|
||||
MPFR_SET_EXP (y, MPFR_GET_EXP (y) + e / 3);
|
||||
|
||||
if (negative)
|
||||
{
|
||||
MPFR_CHANGE_SIGN (y);
|
||||
inexact = -inexact;
|
||||
}
|
||||
|
||||
mpz_clear (m);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/* mpfr_check -- Check if a floating-point number has not been corrupted.
|
||||
|
||||
Copyright 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/*
|
||||
* Check if x is a valid mpfr_t initializes by mpfr_init
|
||||
* Returns 0 if isn't valid
|
||||
*/
|
||||
int
|
||||
mpfr_check (mpfr_srcptr x)
|
||||
{
|
||||
mp_size_t s, i;
|
||||
mp_limb_t tmp;
|
||||
volatile mp_limb_t *xm;
|
||||
int rw;
|
||||
|
||||
/* Check Sign */
|
||||
if (MPFR_SIGN(x) != MPFR_SIGN_POS && MPFR_SIGN(x) != MPFR_SIGN_NEG)
|
||||
return 0;
|
||||
/* Check Precision */
|
||||
if ( (MPFR_PREC(x) < MPFR_PREC_MIN) || (MPFR_PREC(x) > MPFR_PREC_MAX))
|
||||
return 0;
|
||||
/* Check Mantissa */
|
||||
xm = MPFR_MANT(x);
|
||||
if (!xm)
|
||||
return 0;
|
||||
/* Check size of mantissa */
|
||||
s = MPFR_GET_ALLOC_SIZE(x);
|
||||
if (s<=0 || s > MP_SIZE_T_MAX ||
|
||||
MPFR_PREC(x) > ((mpfr_prec_t)s*GMP_NUMB_BITS))
|
||||
return 0;
|
||||
/* Acces all the mp_limb of the mantissa: may do a seg fault */
|
||||
for(i = 0 ; i < s ; i++)
|
||||
tmp = xm[i];
|
||||
/* Check if it isn't singular*/
|
||||
if (MPFR_IS_PURE_FP(x))
|
||||
{
|
||||
/* Check first mp_limb of mantissa (Must start with a 1 bit) */
|
||||
if ( ((xm[MPFR_LIMB_SIZE(x)-1])>>(GMP_NUMB_BITS-1)) == 0)
|
||||
return 0;
|
||||
/* Check last mp_limb of mantissa */
|
||||
rw = (MPFR_PREC(x) % GMP_NUMB_BITS);
|
||||
if (rw != 0)
|
||||
{
|
||||
tmp = MPFR_LIMB_MASK (GMP_NUMB_BITS - rw);
|
||||
if ((xm[0] & tmp) != 0)
|
||||
return 0;
|
||||
}
|
||||
/* Check exponent range */
|
||||
if ((MPFR_EXP (x) < __gmpfr_emin) || (MPFR_EXP (x) > __gmpfr_emax))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Singular value is zero, inf or nan */
|
||||
MPFR_ASSERTD(MPFR_IS_ZERO(x) || MPFR_IS_NAN(x) || MPFR_IS_INF(x));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/* mpfr_clear -- free the memory space allocated for a floating-point number
|
||||
|
||||
Copyright 1999, 2000, 2001, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
void
|
||||
mpfr_clear (mpfr_ptr m)
|
||||
{
|
||||
(*__gmp_free_func) (MPFR_GET_REAL_PTR (m),
|
||||
MPFR_MALLOC_SIZE (MPFR_GET_ALLOC_SIZE (m)));
|
||||
MPFR_MANT (m) = (mp_limb_t *) 0;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/* mpfr_clears -- free the memory space allocated for several
|
||||
floating-point numbers
|
||||
|
||||
Copyright 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#undef HAVE_STDARG
|
||||
#include "config.h" /* for a build within gmp */
|
||||
#endif
|
||||
|
||||
#if HAVE_STDARG
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
void
|
||||
#if HAVE_STDARG
|
||||
mpfr_clears (mpfr_ptr x, ...)
|
||||
#else
|
||||
mpfr_clears (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
#if HAVE_STDARG
|
||||
va_start (arg, x);
|
||||
#else
|
||||
mpfr_ptr x;
|
||||
va_start(arg);
|
||||
x = va_arg (arg, mpfr_ptr);
|
||||
#endif
|
||||
|
||||
while (x != 0)
|
||||
{
|
||||
mpfr_clear (x);
|
||||
x = (mpfr_ptr) va_arg (arg, mpfr_ptr);
|
||||
}
|
||||
va_end (arg);
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/* mpfr_cmp -- compare two floating-point numbers
|
||||
|
||||
Copyright 1999, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* returns 0 iff b = sign(s) * c
|
||||
a positive value iff b > sign(s) * c
|
||||
a negative value iff b < sign(s) * c
|
||||
returns 0 and sets erange flag if b and/or c is NaN.
|
||||
*/
|
||||
|
||||
int
|
||||
mpfr_cmp3 (mpfr_srcptr b, mpfr_srcptr c, int s)
|
||||
{
|
||||
mpfr_exp_t be, ce;
|
||||
mp_size_t bn, cn;
|
||||
mp_limb_t *bp, *cp;
|
||||
|
||||
s = MPFR_MULT_SIGN( s , MPFR_SIGN(c) );
|
||||
|
||||
if (MPFR_ARE_SINGULAR(b, c))
|
||||
{
|
||||
if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c))
|
||||
{
|
||||
MPFR_SET_ERANGE ();
|
||||
return 0;
|
||||
}
|
||||
else if (MPFR_IS_INF(b))
|
||||
{
|
||||
if (MPFR_IS_INF(c) && s == MPFR_SIGN(b) )
|
||||
return 0;
|
||||
else
|
||||
return MPFR_SIGN(b);
|
||||
}
|
||||
else if (MPFR_IS_INF(c))
|
||||
return -s;
|
||||
else if (MPFR_IS_ZERO(b))
|
||||
return MPFR_IS_ZERO(c) ? 0 : -s;
|
||||
else /* necessarily c=0 */
|
||||
return MPFR_SIGN(b);
|
||||
}
|
||||
/* b and c are real numbers */
|
||||
if (s != MPFR_SIGN(b))
|
||||
return MPFR_SIGN(b);
|
||||
|
||||
/* now signs are equal */
|
||||
|
||||
be = MPFR_GET_EXP (b);
|
||||
ce = MPFR_GET_EXP (c);
|
||||
if (be > ce)
|
||||
return s;
|
||||
if (be < ce)
|
||||
return -s;
|
||||
|
||||
/* both signs and exponents are equal */
|
||||
|
||||
bn = (MPFR_PREC(b)-1)/GMP_NUMB_BITS;
|
||||
cn = (MPFR_PREC(c)-1)/GMP_NUMB_BITS;
|
||||
|
||||
bp = MPFR_MANT(b);
|
||||
cp = MPFR_MANT(c);
|
||||
|
||||
for ( ; bn >= 0 && cn >= 0; bn--, cn--)
|
||||
{
|
||||
if (bp[bn] > cp[cn])
|
||||
return s;
|
||||
if (bp[bn] < cp[cn])
|
||||
return -s;
|
||||
}
|
||||
for ( ; bn >= 0; bn--)
|
||||
if (bp[bn])
|
||||
return s;
|
||||
for ( ; cn >= 0; cn--)
|
||||
if (cp[cn])
|
||||
return -s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef mpfr_cmp
|
||||
int
|
||||
mpfr_cmp (mpfr_srcptr b, mpfr_srcptr c)
|
||||
{
|
||||
return mpfr_cmp3 (b, c, 1);
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
/* mpfr_cmp2 -- exponent shift when subtracting two numbers.
|
||||
|
||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* If |b| != |c|, puts the number of canceled bits when one subtracts |c|
|
||||
from |b| in *cancel. Returns the sign of the difference.
|
||||
|
||||
Assumes neither of b or c is NaN, +/- infinity, or +/- 0.
|
||||
|
||||
In other terms, if |b| != |c|, mpfr_cmp2 (b, c) returns
|
||||
EXP(max(|b|,|c|)) - EXP(|b| - |c|).
|
||||
*/
|
||||
|
||||
int
|
||||
mpfr_cmp2 (mpfr_srcptr b, mpfr_srcptr c, mpfr_prec_t *cancel)
|
||||
{
|
||||
mp_limb_t *bp, *cp, bb, cc = 0, lastc = 0, dif, high_dif = 0;
|
||||
mp_size_t bn, cn;
|
||||
mpfr_uexp_t diff_exp;
|
||||
mpfr_prec_t res = 0;
|
||||
int sign;
|
||||
|
||||
/* b=c should not happen, since cmp2 is called only from agm
|
||||
(with different variables), and from sub1 (if same b=c, then
|
||||
sub1sp would be called instead */
|
||||
MPFR_ASSERTD (b != c);
|
||||
|
||||
/* the cases b=0 or c=0 are also treated apart in agm and sub
|
||||
(which calls sub1) */
|
||||
MPFR_ASSERTD (MPFR_IS_PURE_FP(b));
|
||||
MPFR_ASSERTD (MPFR_IS_PURE_FP(c));
|
||||
|
||||
if (MPFR_GET_EXP (b) >= MPFR_GET_EXP (c))
|
||||
{
|
||||
sign = 1;
|
||||
diff_exp = (mpfr_uexp_t) MPFR_GET_EXP (b) - MPFR_GET_EXP (c);
|
||||
|
||||
bp = MPFR_MANT(b);
|
||||
cp = MPFR_MANT(c);
|
||||
|
||||
bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
|
||||
cn = (MPFR_PREC(c) - 1) / GMP_NUMB_BITS; /* # of limbs of c minus 1 */
|
||||
|
||||
if (MPFR_UNLIKELY( diff_exp == 0 ))
|
||||
{
|
||||
while (bn >= 0 && cn >= 0 && bp[bn] == cp[cn])
|
||||
{
|
||||
bn--;
|
||||
cn--;
|
||||
res += GMP_NUMB_BITS;
|
||||
}
|
||||
|
||||
if (MPFR_UNLIKELY (bn < 0))
|
||||
{
|
||||
if (MPFR_LIKELY (cn < 0)) /* b = c */
|
||||
return 0;
|
||||
|
||||
bp = cp;
|
||||
bn = cn;
|
||||
cn = -1;
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
if (MPFR_UNLIKELY (cn < 0))
|
||||
/* c discards exactly the upper part of b */
|
||||
{
|
||||
unsigned int z;
|
||||
|
||||
MPFR_ASSERTD (bn >= 0);
|
||||
|
||||
while (bp[bn] == 0)
|
||||
{
|
||||
if (--bn < 0) /* b = c */
|
||||
return 0;
|
||||
res += GMP_NUMB_BITS;
|
||||
}
|
||||
|
||||
count_leading_zeros(z, bp[bn]); /* bp[bn] <> 0 */
|
||||
*cancel = res + z;
|
||||
return sign;
|
||||
}
|
||||
|
||||
MPFR_ASSERTD (bn >= 0);
|
||||
MPFR_ASSERTD (cn >= 0);
|
||||
MPFR_ASSERTD (bp[bn] != cp[cn]);
|
||||
if (bp[bn] < cp[cn])
|
||||
{
|
||||
mp_limb_t *tp;
|
||||
mp_size_t tn;
|
||||
|
||||
tp = bp; bp = cp; cp = tp;
|
||||
tn = bn; bn = cn; cn = tn;
|
||||
sign = -1;
|
||||
}
|
||||
}
|
||||
} /* MPFR_EXP(b) >= MPFR_EXP(c) */
|
||||
else /* MPFR_EXP(b) < MPFR_EXP(c) */
|
||||
{
|
||||
sign = -1;
|
||||
diff_exp = (mpfr_uexp_t) MPFR_GET_EXP (c) - MPFR_GET_EXP (b);
|
||||
|
||||
bp = MPFR_MANT(c);
|
||||
cp = MPFR_MANT(b);
|
||||
|
||||
bn = (MPFR_PREC(c) - 1) / GMP_NUMB_BITS;
|
||||
cn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
|
||||
}
|
||||
|
||||
/* now we have removed the identical upper limbs of b and c
|
||||
(can happen only when diff_exp = 0), and after the possible
|
||||
swap, we have |b| > |c|: bp[bn] > cc, bn >= 0, cn >= 0,
|
||||
diff_exp = EXP(b) - EXP(c).
|
||||
*/
|
||||
|
||||
if (MPFR_LIKELY (diff_exp < GMP_NUMB_BITS))
|
||||
{
|
||||
cc = cp[cn] >> diff_exp;
|
||||
/* warning: a shift by GMP_NUMB_BITS may give wrong results */
|
||||
if (diff_exp)
|
||||
lastc = cp[cn] << (GMP_NUMB_BITS - diff_exp);
|
||||
cn--;
|
||||
}
|
||||
else
|
||||
diff_exp -= GMP_NUMB_BITS; /* cc = 0 */
|
||||
|
||||
dif = bp[bn--] - cc; /* necessarily dif >= 1 */
|
||||
MPFR_ASSERTD(dif >= 1);
|
||||
|
||||
/* now high_dif = 0, dif >= 1, lastc is the neglected part of cp[cn+1] */
|
||||
|
||||
while (MPFR_UNLIKELY ((cn >= 0 || lastc != 0)
|
||||
&& (high_dif == 0) && (dif == 1)))
|
||||
{ /* dif=1 implies diff_exp = 0 or 1 */
|
||||
bb = (bn >= 0) ? bp[bn] : 0;
|
||||
cc = lastc;
|
||||
if (cn >= 0)
|
||||
{
|
||||
if (diff_exp == 0)
|
||||
{
|
||||
cc += cp[cn];
|
||||
}
|
||||
else /* diff_exp = 1 */
|
||||
{
|
||||
cc += cp[cn] >> 1;
|
||||
lastc = cp[cn] << (GMP_NUMB_BITS - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
lastc = 0;
|
||||
high_dif = 1 - mpn_sub_n (&dif, &bb, &cc, 1);
|
||||
bn--;
|
||||
cn--;
|
||||
res += GMP_NUMB_BITS;
|
||||
}
|
||||
|
||||
/* (cn<0 and lastc=0) or (high_dif,dif)<>(0,1) */
|
||||
|
||||
if (MPFR_UNLIKELY (high_dif != 0)) /* high_dif == 1 */
|
||||
{
|
||||
res--;
|
||||
if (dif != 0)
|
||||
{
|
||||
*cancel = res;
|
||||
return sign;
|
||||
}
|
||||
}
|
||||
else /* high_dif == 0 */
|
||||
{
|
||||
unsigned int z;
|
||||
|
||||
count_leading_zeros(z, dif); /* dif > 1 here */
|
||||
res += z;
|
||||
if (MPFR_LIKELY(dif != (MPFR_LIMB_ONE << (GMP_NUMB_BITS - z - 1))))
|
||||
{ /* dif is not a power of two */
|
||||
*cancel = res;
|
||||
return sign;
|
||||
}
|
||||
}
|
||||
|
||||
/* now result is res + (low(b) < low(c)) */
|
||||
while (MPFR_UNLIKELY (bn >= 0 && (cn >= 0 || lastc != 0)))
|
||||
{
|
||||
if (diff_exp >= GMP_NUMB_BITS)
|
||||
diff_exp -= GMP_NUMB_BITS;
|
||||
else
|
||||
{
|
||||
cc = lastc;
|
||||
if (cn >= 0)
|
||||
{
|
||||
cc += cp[cn] >> diff_exp;
|
||||
if (diff_exp != 0)
|
||||
lastc = cp[cn] << (GMP_NUMB_BITS - diff_exp);
|
||||
}
|
||||
else
|
||||
lastc = 0;
|
||||
cn--;
|
||||
}
|
||||
if (bp[bn] != cc)
|
||||
{
|
||||
*cancel = res + (bp[bn] < cc);
|
||||
return sign;
|
||||
}
|
||||
bn--;
|
||||
}
|
||||
|
||||
if (bn < 0)
|
||||
{
|
||||
if (lastc != 0)
|
||||
res++;
|
||||
else
|
||||
{
|
||||
while (cn >= 0 && cp[cn] == 0)
|
||||
cn--;
|
||||
if (cn >= 0)
|
||||
res++;
|
||||
}
|
||||
}
|
||||
|
||||
*cancel = res;
|
||||
return sign;
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/* mpfr_cmpabs -- compare the absolute values of two FP numbers
|
||||
|
||||
Copyright 1999, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* Return a positive value if abs(b) > abs(c), 0 if abs(b) = abs(c), and
|
||||
a negative value if abs(b) < abs(c). Neither b nor c may be NaN. */
|
||||
|
||||
int
|
||||
mpfr_cmpabs (mpfr_srcptr b, mpfr_srcptr c)
|
||||
{
|
||||
mpfr_exp_t be, ce;
|
||||
mp_size_t bn, cn;
|
||||
mp_limb_t *bp, *cp;
|
||||
|
||||
if (MPFR_ARE_SINGULAR (b, c))
|
||||
{
|
||||
if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c))
|
||||
{
|
||||
MPFR_SET_ERANGE ();
|
||||
return 0;
|
||||
}
|
||||
else if (MPFR_IS_INF (b))
|
||||
return ! MPFR_IS_INF (c);
|
||||
else if (MPFR_IS_INF (c))
|
||||
return -1;
|
||||
else if (MPFR_IS_ZERO (c))
|
||||
return ! MPFR_IS_ZERO (b);
|
||||
else /* b == 0 */
|
||||
return -1;
|
||||
}
|
||||
|
||||
MPFR_ASSERTD (MPFR_IS_PURE_FP (b));
|
||||
MPFR_ASSERTD (MPFR_IS_PURE_FP (c));
|
||||
|
||||
/* Now that we know that b and c are pure FP numbers (i.e. they have
|
||||
a meaningful exponent), we use MPFR_EXP instead of MPFR_GET_EXP to
|
||||
allow exponents outside the current exponent range. For instance,
|
||||
this is useful for mpfr_pow, which compares values to __gmpfr_one.
|
||||
This is for internal use only! For compatibility with other MPFR
|
||||
versions, the user must still provide values that are representable
|
||||
in the current exponent range. */
|
||||
be = MPFR_EXP (b);
|
||||
ce = MPFR_EXP (c);
|
||||
if (be > ce)
|
||||
return 1;
|
||||
if (be < ce)
|
||||
return -1;
|
||||
|
||||
/* exponents are equal */
|
||||
|
||||
bn = MPFR_LIMB_SIZE(b)-1;
|
||||
cn = MPFR_LIMB_SIZE(c)-1;
|
||||
|
||||
bp = MPFR_MANT(b);
|
||||
cp = MPFR_MANT(c);
|
||||
|
||||
for ( ; bn >= 0 && cn >= 0; bn--, cn--)
|
||||
{
|
||||
if (bp[bn] > cp[cn])
|
||||
return 1;
|
||||
if (bp[bn] < cp[cn])
|
||||
return -1;
|
||||
}
|
||||
|
||||
for ( ; bn >= 0; bn--)
|
||||
if (bp[bn])
|
||||
return 1;
|
||||
|
||||
for ( ; cn >= 0; cn--)
|
||||
if (cp[cn])
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* mpfr_cmp_d -- compare a floating-point number with a double
|
||||
|
||||
Copyright 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_cmp_d (mpfr_srcptr b, double d)
|
||||
{
|
||||
mpfr_t tmp;
|
||||
int res;
|
||||
|
||||
mpfr_init2 (tmp, IEEE_DBL_MANT_DIG);
|
||||
res = mpfr_set_d (tmp, d, MPFR_RNDN);
|
||||
MPFR_ASSERTD (res == 0);
|
||||
res = mpfr_cmp (b, tmp);
|
||||
mpfr_clear (tmp);
|
||||
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* mpfr_cmp_d -- compare a floating-point number with a long double
|
||||
|
||||
Copyright 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_cmp_ld (mpfr_srcptr b, long double d)
|
||||
{
|
||||
mpfr_t tmp;
|
||||
int res;
|
||||
|
||||
mpfr_init2 (tmp, MPFR_LDBL_MANT_DIG);
|
||||
res = mpfr_set_ld (tmp, d, MPFR_RNDN);
|
||||
MPFR_ASSERTD (res == 0);
|
||||
res = mpfr_cmp (b, tmp);
|
||||
mpfr_clear (tmp);
|
||||
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/* mpfr_cmp_si_2exp -- compare a floating-point number with a signed
|
||||
machine integer multiplied by a power of 2
|
||||
|
||||
Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* returns a positive value if b > i*2^f,
|
||||
a negative value if b < i*2^f,
|
||||
zero if b = i*2^f.
|
||||
b must not be NaN.
|
||||
*/
|
||||
|
||||
int
|
||||
mpfr_cmp_si_2exp (mpfr_srcptr b, long int i, mpfr_exp_t f)
|
||||
{
|
||||
int si;
|
||||
|
||||
si = i < 0 ? -1 : 1; /* sign of i */
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (b)))
|
||||
{
|
||||
if (MPFR_IS_INF(b))
|
||||
return MPFR_INT_SIGN(b);
|
||||
else if (MPFR_IS_ZERO(b))
|
||||
return i != 0 ? -si : 0;
|
||||
/* NAN */
|
||||
MPFR_SET_ERANGE ();
|
||||
return 0;
|
||||
}
|
||||
else if (MPFR_SIGN(b) != si || i == 0)
|
||||
return MPFR_INT_SIGN (b);
|
||||
else /* b and i are of same sign si */
|
||||
{
|
||||
mpfr_exp_t e;
|
||||
unsigned long ai;
|
||||
int k;
|
||||
mp_size_t bn;
|
||||
mp_limb_t c, *bp;
|
||||
|
||||
ai = SAFE_ABS(unsigned long, i);
|
||||
|
||||
/* ai must be representable in a mp_limb_t */
|
||||
MPFR_ASSERTN(ai == (mp_limb_t) ai);
|
||||
|
||||
e = MPFR_GET_EXP (b); /* 2^(e-1) <= b < 2^e */
|
||||
if (e <= f)
|
||||
return -si;
|
||||
if (f < MPFR_EMAX_MAX - GMP_NUMB_BITS &&
|
||||
e > f + GMP_NUMB_BITS)
|
||||
return si;
|
||||
|
||||
/* now f < e <= f + GMP_NUMB_BITS */
|
||||
c = (mp_limb_t) ai;
|
||||
count_leading_zeros(k, c);
|
||||
if ((int) (e - f) > GMP_NUMB_BITS - k)
|
||||
return si;
|
||||
if ((int) (e - f) < GMP_NUMB_BITS - k)
|
||||
return -si;
|
||||
|
||||
/* now b and i*2^f have the same exponent */
|
||||
c <<= k;
|
||||
bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
|
||||
bp = MPFR_MANT(b);
|
||||
if (bp[bn] > c)
|
||||
return si;
|
||||
if (bp[bn] < c)
|
||||
return -si;
|
||||
|
||||
/* most significant limbs agree, check remaining limbs from b */
|
||||
while (bn > 0)
|
||||
if (bp[--bn])
|
||||
return si;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#undef mpfr_cmp_si
|
||||
int
|
||||
mpfr_cmp_si (mpfr_srcptr b, long int i)
|
||||
{
|
||||
return mpfr_cmp_si_2exp (b, i, 0);
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/* mpfr_cmp_ui_2exp -- compare a floating-point number with an unsigned
|
||||
machine integer multiplied by a power of 2
|
||||
|
||||
Copyright 1999, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* returns a positive value if b > i*2^f,
|
||||
a negative value if b < i*2^f,
|
||||
zero if b = i*2^f.
|
||||
b must not be NaN
|
||||
*/
|
||||
|
||||
int
|
||||
mpfr_cmp_ui_2exp (mpfr_srcptr b, unsigned long int i, mpfr_exp_t f)
|
||||
{
|
||||
if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(b) ))
|
||||
{
|
||||
if (MPFR_IS_NAN (b))
|
||||
{
|
||||
MPFR_SET_ERANGE ();
|
||||
return 0;
|
||||
}
|
||||
else if (MPFR_IS_INF(b))
|
||||
return MPFR_INT_SIGN (b);
|
||||
else /* since b cannot be NaN, b=0 here */
|
||||
return i != 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
if (MPFR_IS_NEG (b))
|
||||
return -1;
|
||||
/* now b > 0 */
|
||||
else if (MPFR_UNLIKELY(i == 0))
|
||||
return 1;
|
||||
else /* b > 0, i > 0 */
|
||||
{
|
||||
mpfr_exp_t e;
|
||||
int k;
|
||||
mp_size_t bn;
|
||||
mp_limb_t c, *bp;
|
||||
|
||||
/* i must be representable in a mp_limb_t */
|
||||
MPFR_ASSERTN(i == (mp_limb_t) i);
|
||||
|
||||
e = MPFR_GET_EXP (b); /* 2^(e-1) <= b < 2^e */
|
||||
if (e <= f)
|
||||
return -1;
|
||||
if (f < MPFR_EMAX_MAX - GMP_NUMB_BITS &&
|
||||
e > f + GMP_NUMB_BITS)
|
||||
return 1;
|
||||
|
||||
/* now f < e <= f + GMP_NUMB_BITS */
|
||||
c = (mp_limb_t) i;
|
||||
count_leading_zeros(k, c);
|
||||
if ((int) (e - f) > GMP_NUMB_BITS - k)
|
||||
return 1;
|
||||
if ((int) (e - f) < GMP_NUMB_BITS - k)
|
||||
return -1;
|
||||
|
||||
/* now b and i*2^f have the same exponent */
|
||||
c <<= k;
|
||||
bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
|
||||
bp = MPFR_MANT(b);
|
||||
if (bp[bn] > c)
|
||||
return 1;
|
||||
if (bp[bn] < c)
|
||||
return -1;
|
||||
|
||||
/* most significant limbs agree, check remaining limbs from b */
|
||||
while (bn > 0)
|
||||
if (bp[--bn] != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#undef mpfr_cmp_ui
|
||||
int
|
||||
mpfr_cmp_ui (mpfr_srcptr b, unsigned long int i)
|
||||
{
|
||||
return mpfr_cmp_ui_2exp (b, i, 0);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/* comparison predicates
|
||||
|
||||
Copyright 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* Note: these functions currently use mpfr_cmp; they could have their
|
||||
own code to be faster. */
|
||||
|
||||
/* = < > unordered
|
||||
* mpfr_greater_p 0 0 1 0
|
||||
* mpfr_greaterequal_p 1 0 1 0
|
||||
* mpfr_less_p 0 1 0 0
|
||||
* mpfr_lessequal_p 1 1 0 0
|
||||
* mpfr_lessgreater_p 0 1 1 0
|
||||
* mpfr_equal_p 1 0 0 0
|
||||
* mpfr_unordered_p 0 0 0 1
|
||||
*/
|
||||
|
||||
int
|
||||
mpfr_greater_p (mpfr_srcptr x, mpfr_srcptr y)
|
||||
{
|
||||
return MPFR_IS_NAN(x) || MPFR_IS_NAN(y) ? 0 : (mpfr_cmp (x, y) > 0);
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_greaterequal_p (mpfr_srcptr x, mpfr_srcptr y)
|
||||
{
|
||||
return MPFR_IS_NAN(x) || MPFR_IS_NAN(y) ? 0 : (mpfr_cmp (x, y) >= 0);
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_less_p (mpfr_srcptr x, mpfr_srcptr y)
|
||||
{
|
||||
return MPFR_IS_NAN(x) || MPFR_IS_NAN(y) ? 0 : (mpfr_cmp (x, y) < 0);
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_lessequal_p (mpfr_srcptr x, mpfr_srcptr y)
|
||||
{
|
||||
return MPFR_IS_NAN(x) || MPFR_IS_NAN(y) ? 0 : (mpfr_cmp (x, y) <= 0);
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_lessgreater_p (mpfr_srcptr x, mpfr_srcptr y)
|
||||
{
|
||||
return MPFR_IS_NAN(x) || MPFR_IS_NAN(y) ? 0 : (mpfr_cmp (x, y) != 0);
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_equal_p (mpfr_srcptr x, mpfr_srcptr y)
|
||||
{
|
||||
return MPFR_IS_NAN(x) || MPFR_IS_NAN(y) ? 0 : (mpfr_cmp (x, y) == 0);
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_unordered_p (mpfr_srcptr x, mpfr_srcptr y)
|
||||
{
|
||||
return MPFR_IS_NAN(x) || MPFR_IS_NAN(y);
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand `-c -o'.
|
||||
|
||||
scriptversion=2009-10-06.20; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software
|
||||
# Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can 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, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand `-c -o'.
|
||||
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file `INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
eat=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as `compile cc -o foo foo.c'.
|
||||
# So we strip `-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no `-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# `.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use `[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,495 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_COPYRIGHT([
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
])
|
||||
|
||||
dnl Add check-news when it checks for more than 15 lines
|
||||
AC_INIT([MPFR],[3.0.1])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11 no-define dist-bzip2 dist-xz dist-zip])
|
||||
AM_MAINTAINER_MODE(enable)
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
dnl FIXME: The AC_ARG_ENABLE(decimal-float...) part does things too
|
||||
dnl early, even when this option is not used. In particular, it must
|
||||
dnl be put after AC_PROG_CC; another problem is that the GMP CFLAGS
|
||||
dnl and CC check may modify the compiler.
|
||||
|
||||
test_CFLAGS=${CFLAGS+set}
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
dnl To use a separate config header.
|
||||
dnl There is still some problem with GMP's HAVE_CONFIG
|
||||
dnl AC_CONFIG_HEADERS([mpfrconf.h:mpfrconf.in])
|
||||
|
||||
dnl Extra arguments to configure
|
||||
unset gmp_lib_path GMP_CFLAGS GMP_CC
|
||||
AC_ARG_WITH(gmp_include,
|
||||
[ --with-gmp-include=DIR GMP include directory ],
|
||||
CPPFLAGS="$CPPFLAGS -I$withval")
|
||||
AC_ARG_WITH(gmp_lib,
|
||||
[ --with-gmp-lib=DIR GMP lib directory ], [
|
||||
LDFLAGS="$LDFLAGS -L$withval"
|
||||
gmp_lib_path="$withval"
|
||||
])
|
||||
AC_ARG_WITH(gmp,
|
||||
[ --with-gmp=DIR GMP install directory ], [
|
||||
if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
|
||||
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
gmp_lib_path="$withval/lib"
|
||||
else
|
||||
AC_MSG_FAILURE([Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.])
|
||||
fi
|
||||
])
|
||||
|
||||
AC_ARG_WITH(gmp_build,
|
||||
[ --with-gmp-build=DIR GMP build directory (please read INSTALL file)],
|
||||
[
|
||||
if test -z "$gmp_lib_path" && test -z "$with_gmp_include" ; then
|
||||
CPPFLAGS="$CPPFLAGS -I$withval -I$withval/tune"
|
||||
LDFLAGS="$LDFLAGS -L$withval -L$withval/.libs -L$withval/tune/"
|
||||
gmp_lib_path="$withval$PATH_SEPARATOR$withval/.libs$PATH_SEPARATOR$withval/tune"
|
||||
if test -r $withval/Makefile ; then
|
||||
GMP_CFLAGS=`grep -w "CFLAGS =" $withval/Makefile | sed 's/CFLAGS = //'`
|
||||
GMP_CC=`grep -w "CC =" $withval/Makefile | sed 's/CC = //'`
|
||||
fi
|
||||
use_gmp_build=yes
|
||||
else
|
||||
AC_MSG_FAILURE([Do not use --with-gmp-build and other --with-gmp options simultaneously.])
|
||||
fi
|
||||
])
|
||||
|
||||
AC_ARG_WITH(mulhigh_size,
|
||||
[ --with-mulhigh-size=NUM internal threshold table for mulhigh],
|
||||
AC_DEFINE_UNQUOTED([MPFR_MULHIGH_SIZE],$withval, [Mulhigh size]))
|
||||
|
||||
AC_ARG_ENABLE(assert,
|
||||
[ --enable-assert enable ASSERT checking [[default=no]]],
|
||||
[ case $enableval in
|
||||
yes) AC_DEFINE([WANT_ASSERT],1,[Want assertion]) ;;
|
||||
no) ;;
|
||||
full) AC_DEFINE([WANT_ASSERT],2,[Want assertion]) ;;
|
||||
*) AC_MSG_ERROR([bad value for --enable-assert: yes, no or full]) ;;
|
||||
esac])
|
||||
AC_ARG_ENABLE(logging,
|
||||
[ --enable-logging enable MPFR logging (the system must support it)
|
||||
[[default=no]]],
|
||||
[ disable_gcc_format_warning=yes
|
||||
case $enableval in
|
||||
yes) AC_DEFINE([MPFR_USE_LOGGING],1,[Log what MPFR does]) ;;
|
||||
no) ;;
|
||||
*) AC_MSG_ERROR([bad value for --enable-logging: yes or no]) ;;
|
||||
esac])
|
||||
AC_ARG_ENABLE(thread-safe,
|
||||
[ --enable-thread-safe build MPFR as thread safe (the system must support
|
||||
it) [[default=no]]],
|
||||
[ case $enableval in
|
||||
yes) AC_DEFINE([MPFR_USE_THREAD_SAFE],1,[Build MPFR as thread safe]) ;;
|
||||
no) ;;
|
||||
*) AC_MSG_ERROR([bad value for --enable-thread-safe: yes or no]) ;;
|
||||
esac])
|
||||
AC_ARG_ENABLE(warnings,
|
||||
[ --enable-warnings allow MPFR to output warnings to stderr [[default=no]]],
|
||||
[ case $enableval in
|
||||
yes) AC_DEFINE([MPFR_USE_WARNINGS],1,[Allow MPFR to output warnings to stderr]) ;;
|
||||
no) ;;
|
||||
*) AC_MSG_ERROR([bad value for --enable-warnings: yes or no]) ;;
|
||||
esac])
|
||||
|
||||
AC_ARG_ENABLE(tests-timeout,
|
||||
[ --enable-tests-timeout=NUM enable timeout (NUM seconds) for test programs
|
||||
(NUM <= 9999) [[default=no]]; if enabled, env variable
|
||||
$MPFR_TESTS_TIMEOUT overrides NUM (0: no timeout).],
|
||||
[ case $enableval in
|
||||
no) ;;
|
||||
yes) AC_DEFINE([MPFR_TESTS_TIMEOUT], 0, [timeout limit]) ;;
|
||||
[[0-9]]|[[0-9]][[0-9]]|[[0-9]][[0-9]][[0-9]]|[[0-9]][[0-9]][[0-9]][[0-9]])
|
||||
AC_DEFINE_UNQUOTED([MPFR_TESTS_TIMEOUT], $enableval, [timeout limit]) ;;
|
||||
*) AC_MSG_ERROR([bad value for --enable-tests-timeout]) ;;
|
||||
esac])
|
||||
|
||||
|
||||
dnl
|
||||
dnl Setup CC and CFLAGS
|
||||
dnl
|
||||
|
||||
dnl Check if user request its CC and CFLAGS
|
||||
if test -n "$CFLAGS" || test -n "$CC" ; then
|
||||
user_redefine_cc=yes
|
||||
fi
|
||||
dnl Autoconf detection
|
||||
AC_PROG_EGREP
|
||||
AC_PROG_SED
|
||||
|
||||
dnl ********************************************************************
|
||||
dnl Check for CC and CFLAGS in gmp.h
|
||||
|
||||
if test -z "$user_redefine_cc" && test "$cross_compiling" != yes ; then
|
||||
|
||||
dnl We need to guess the C preprocessor instead of using AC_PROG_CPP,
|
||||
dnl since AC_PROG_CPP implies AC_PROG_CC, which chooses a compiler
|
||||
dnl (before we have the chance to get it from gmp.h) and does some
|
||||
dnl checking related to this compiler (such as dependency tracking
|
||||
dnl options); if the compiler changes due to __GMP_CC in gmp.h, one
|
||||
dnl would have incorrect settings.
|
||||
dnl FIXME: Move this in aclocal ?
|
||||
if test -z "$GMP_CC$GMP_CFLAGS" ; then
|
||||
AC_MSG_CHECKING(for CC and CFLAGS in gmp.h)
|
||||
GMP_CC=__GMP_CC
|
||||
GMP_CFLAGS=__GMP_CFLAGS
|
||||
for cpp in /lib/cpp gcc cc c99
|
||||
do
|
||||
test $cpp = /lib/cpp || cpp="$cpp -E"
|
||||
echo foo > conftest.c
|
||||
if $cpp $CPPFLAGS conftest.c > /dev/null 2> /dev/null ; then
|
||||
# Get CC
|
||||
echo "#include \"gmp.h\"" > conftest.c
|
||||
echo "MPFR_OPTION __GMP_CC" >> conftest.c
|
||||
GMP_CC=`$cpp $CPPFLAGS conftest.c 2> /dev/null | $EGREP MPFR_OPTION | $SED -e 's/MPFR_OPTION //g' | $SED -e 's/"//g'`
|
||||
# Get CFLAGS
|
||||
echo "#include \"gmp.h\"" > conftest.c
|
||||
echo "MPFR_OPTION __GMP_CFLAGS" >> conftest.c
|
||||
GMP_CFLAGS=`$cpp $CPPFLAGS conftest.c 2> /dev/null | $EGREP MPFR_OPTION | $SED -e 's/MPFR_OPTION //g'| $SED -e 's/"//g'`
|
||||
break
|
||||
fi
|
||||
done
|
||||
rm -f conftest*
|
||||
if test "x$GMP_CC" = "x__GMP_CC" || test "x$GMP_CFLAGS" = "x__GMP_CFLAGS" ; then
|
||||
AC_MSG_RESULT(no)
|
||||
GMP_CFLAGS=
|
||||
GMP_CC=
|
||||
else
|
||||
AC_MSG_RESULT(yes [CC=$GMP_CC CFLAGS=$GMP_CFLAGS])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl But these variables may be invalid, so we must check them first.
|
||||
dnl Note: we do not use AC_RUN_IFELSE, as it implies AC_PROG_CC.
|
||||
if test -n "$GMP_CC$GMP_CFLAGS" ; then
|
||||
AC_MSG_CHECKING(for CC=$GMP_CC and CFLAGS=$GMP_CFLAGS)
|
||||
echo "int main (void) { return 0; }" > conftest.c
|
||||
if $GMP_CC $GMP_CFLAGS -o conftest conftest.c 2> /dev/null ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
CFLAGS=$GMP_CFLAGS
|
||||
CC=$GMP_CC
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
dnl ********************************************************************
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_LANG(C)
|
||||
|
||||
AC_ARG_ENABLE(decimal-float,
|
||||
[ --enable-decimal-float build conversion functions from/to decimal floats
|
||||
[[default=no]]],
|
||||
[ case $enableval in
|
||||
yes) AC_DEFINE([MPFR_WANT_DECIMAL_FLOATS],1,
|
||||
[Build decimal float functions])
|
||||
AC_MSG_CHECKING(if compiler knows _Decimal64)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[_Decimal64 x;]])],
|
||||
[AC_MSG_RESULT(yes)
|
||||
if test "$use_gmp_build" != yes ; then
|
||||
AC_MSG_ERROR([decimal float support requires --with-gmp-build])
|
||||
fi
|
||||
AC_MSG_CHECKING(if _GMP_IEEE_FLOATS is defined)
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
||||
#include "gmp.h"
|
||||
#include "gmp-impl.h"
|
||||
#ifndef _GMP_IEEE_FLOATS
|
||||
#error "_GMP_IEEE_FLOATS is not defined"
|
||||
#endif]])],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([decimal float support requires _GMP_IEEE_FLOATS])])
|
||||
],
|
||||
[AC_MSG_ERROR([Compiler doesn't know _Decimal64; try GCC >= 4.2, configured with --enable-decimal-float]
|
||||
)])
|
||||
AC_MSG_CHECKING(decimal float format)
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdlib.h>
|
||||
]], [[
|
||||
union { double d; _Decimal64 d64; } y;
|
||||
y.d64 = 1234567890123456.0dd;
|
||||
return y.d == 0.14894469406741037E-123 ? 0 :
|
||||
y.d == 0.59075095508629822E-68 ? 1 : 2;
|
||||
]])], [AC_MSG_RESULT(DPD)
|
||||
AC_DEFINE([DPD_FORMAT],1,[])],
|
||||
[if test "$?" != 1 ; then
|
||||
AC_MSG_FAILURE(neither DPD nor BID)
|
||||
fi
|
||||
AC_MSG_RESULT(BID)],
|
||||
[AC_MSG_RESULT(assuming DPD)
|
||||
AC_DEFINE([DPD_FORMAT],1,[])])
|
||||
;;
|
||||
no) ;;
|
||||
*) AC_MSG_ERROR([bad value for --enable-decimal-float: yes or no]) ;;
|
||||
esac])
|
||||
|
||||
dnl Check if compiler is ICC, and if such a case, disable GCC
|
||||
dnl And add some specific flags.
|
||||
dnl Don't add Warnings Flags (Otherwise you'll get more than 20000 warnings).
|
||||
dnl Add -long_double flags? Don't use -pc64 !
|
||||
dnl Notes (VL):
|
||||
dnl * With icc 10.1 20080212 on itanium, the __ICC macro is not defined,
|
||||
dnl even when the -icc option is used (contrary to what is documented
|
||||
dnl on the icc man page).
|
||||
dnl * When ICC is correctly detected (__ICC macro defined), unsetting
|
||||
dnl the GCC variable confuses libtool. See:
|
||||
dnl http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=485421
|
||||
dnl * If need be, the gcc predefined macros __GNUC_* can be disabled
|
||||
dnl thanks to the -no-gcc option.
|
||||
AC_MSG_CHECKING(for ICC)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#if !defined(__ICC)
|
||||
# error "ICC Not Found"
|
||||
error
|
||||
#endif
|
||||
]], [[]])],[
|
||||
AC_MSG_RESULT(yes)
|
||||
CFLAGS="-fp_port -mp -wd1572 -wd265 -wd186 -wd239 $CFLAGS"
|
||||
],[AC_MSG_RESULT(no)])
|
||||
|
||||
dnl If compiler is gcc, then use some specific flags.
|
||||
dnl But don't touch user other flags.
|
||||
if test "$test_CFLAGS" != set && test -n "$GCC"; then
|
||||
CFLAGS="-Wall -Wmissing-prototypes -Wpointer-arith $CFLAGS"
|
||||
if test -n "$disable_gcc_format_warning" ; then
|
||||
CFLAGS="$CFLAGS -Wno-format"
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_PROG_CC_C_O
|
||||
AM_C_PROTOTYPES
|
||||
|
||||
case $host in
|
||||
*-apple-darwin*)
|
||||
dnl This allows to take the first GMP library in the library paths,
|
||||
dnl whether it is dynamic or static. This behavior is more sensible,
|
||||
dnl in particular because it is the only way to link with a version
|
||||
dnl only available in static form when another version is available
|
||||
dnl in dynamic, and also for consistency, because the compiler will
|
||||
dnl take the first gmp.h found in the include paths (so, we need to
|
||||
dnl take a library that corresponds to this header file). This is a
|
||||
dnl common problem with darwin.
|
||||
MPFR_LD_SEARCH_PATHS_FIRST ;;
|
||||
esac
|
||||
|
||||
AC_C_CONST
|
||||
AC_C_VOLATILE
|
||||
MPFR_CONFIGS
|
||||
|
||||
dnl
|
||||
dnl Setup GMP detection
|
||||
dnl
|
||||
|
||||
dnl Check GMP Header
|
||||
AC_MSG_CHECKING(for gmp.h)
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
||||
#include "gmp.h"
|
||||
]])],[AC_MSG_RESULT(yes)],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([gmp.h can't be found, or is unusable.])
|
||||
])
|
||||
|
||||
dnl Configs for Windows DLLs.
|
||||
dnl libtool requires "-no-undefined" for win32 dll
|
||||
dnl It also disables the tests involving the linking with LIBGMP if DLL
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
case $host in
|
||||
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
|
||||
AC_MSG_CHECKING(for DLL/static GMP)
|
||||
if test "$enable_shared" = yes; then
|
||||
LDFLAGS="$LDFLAGS -no-undefined"
|
||||
dont_link_with_gmp="yes"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include "gmp.h"
|
||||
#if !__GMP_LIBGMP_DLL
|
||||
# error "Dead man"
|
||||
error
|
||||
#endif
|
||||
]], [[]])],[AC_MSG_RESULT(DLL)],[
|
||||
AC_MSG_RESULT(static)
|
||||
AC_MSG_ERROR([gmp.h isn't a DLL: use --enable-static --disable-shared]) ])
|
||||
else
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include "gmp.h"
|
||||
#if __GMP_LIBGMP_DLL
|
||||
# error "Dead man"
|
||||
error
|
||||
#endif
|
||||
]], [[]])],[AC_MSG_RESULT(static)],[
|
||||
AC_MSG_RESULT(DLL)
|
||||
AC_MSG_ERROR([gmp.h is a DLL: use --disable-static --enable-shared]) ])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
dnl Finally set up LibTool
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
|
||||
dnl
|
||||
dnl For mpfr-longlong.h - TODO: should be replaced (see acinclude.m4).
|
||||
dnl
|
||||
|
||||
GMP_C_ATTRIBUTE_MODE
|
||||
|
||||
|
||||
dnl
|
||||
dnl Setup GMP detection (continued)
|
||||
dnl
|
||||
|
||||
AC_MSG_CHECKING(for recent GMP)
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
||||
#include "gmp.h"
|
||||
#if (__GNU_MP_VERSION*100+__GNU_MP_VERSION_MINOR*10 < 410)
|
||||
# error "min GMP version is 4.1.0"
|
||||
error
|
||||
#endif
|
||||
]])],[AC_MSG_RESULT(yes)],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([GMP 4.1.0 min required])
|
||||
])
|
||||
|
||||
dnl Check if we can use internal header files of GMP (only --with-gmp-build)
|
||||
if test "$use_gmp_build" = yes ; then
|
||||
AC_MSG_CHECKING(for gmp internal files)
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
|
||||
#include "gmp.h"
|
||||
#include "gmp-impl.h"
|
||||
#include "longlong.h"
|
||||
]])],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([MPFR_HAVE_GMP_IMPL],1,[Use GMP Internal Files])
|
||||
],[
|
||||
AC_MSG_ERROR([header files gmp-impl.h and longlong.h not found])
|
||||
])
|
||||
fi
|
||||
|
||||
dnl Check for valid GMP_NUMB_BITS and BYTES_PER_MP_LIMB
|
||||
dnl This test doesn't need to link with libgmp (at least it shouldn't).
|
||||
if test "$use_gmp_build" = yes ; then
|
||||
AC_MSG_CHECKING(for valid GMP_NUMB_BITS)
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <limits.h>
|
||||
#include "gmp.h"
|
||||
#include "gmp-impl.h"
|
||||
]], [[
|
||||
return GMP_NUMB_BITS == BYTES_PER_MP_LIMB * CHAR_BIT
|
||||
&& sizeof(mp_limb_t) == BYTES_PER_MP_LIMB ? 0 : 1;
|
||||
]])], [AC_MSG_RESULT(yes)], [
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([GMP_NUMB_BITS is incorrect.
|
||||
You probably need to change some of the GMP or MPFR compile options.])],
|
||||
[AC_MSG_RESULT([can't test])])
|
||||
fi
|
||||
|
||||
|
||||
dnl We really need to link using libtool. But it is impossible with the current
|
||||
dnl libtool.
|
||||
dnl The practical problems appear only under MS Windows since the library name
|
||||
dnl is libgmp-3 (due to libtool versionning). The best solution
|
||||
dnl is to believe it works under MS-Windows.
|
||||
if test "$dont_link_with_gmp" = yes ; then
|
||||
LIBS="-lgmp $LIBS"
|
||||
else
|
||||
|
||||
dnl Check if we can link with GMP
|
||||
AC_CHECK_LIB(gmp, __gmpz_init, [LIBS="-lgmp $LIBS"],
|
||||
[AC_MSG_ERROR(libgmp not found or uses a different ABI.
|
||||
Please read the INSTALL file -- see "In case of problem".)])
|
||||
|
||||
dnl Check for corresponding 'gmp.h' and libgmp.a
|
||||
AC_MSG_CHECKING(if gmp.h version and libgmp version are the same)
|
||||
dnl We do not set LD_LIBRARY_PATH, as it is not possible to set it just
|
||||
dnl before the test program is run, and we do not want to affect other
|
||||
dnl programs (such as the compiler), because the behavior could be
|
||||
dnl incorrect and even have security implications.
|
||||
saved_LD_RUN_PATH="$LD_RUN_PATH"
|
||||
LD_RUN_PATH="${LD_RUN_PATH:+$LD_RUN_PATH$PATH_SEPARATOR}$gmp_lib_path"
|
||||
export LD_RUN_PATH
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "gmp.h"
|
||||
]], [[
|
||||
char buffer[100];
|
||||
sprintf (buffer, "%d.%d.%d", __GNU_MP_VERSION, __GNU_MP_VERSION_MINOR,
|
||||
__GNU_MP_VERSION_PATCHLEVEL);
|
||||
printf ("(%s/%s) ", buffer, gmp_version);
|
||||
if (strcmp (buffer, gmp_version) == 0)
|
||||
return 0;
|
||||
if (__GNU_MP_VERSION_PATCHLEVEL != 0)
|
||||
return 1;
|
||||
sprintf (buffer, "%d.%d", __GNU_MP_VERSION, __GNU_MP_VERSION_MINOR);
|
||||
return (strcmp (buffer, gmp_version) != 0) ? 1 : 0;
|
||||
]])],
|
||||
[AC_MSG_RESULT(yes)
|
||||
MPFR_CHECK_PRINTF_SPEC],
|
||||
[AC_MSG_RESULT(no)
|
||||
AC_MSG_WARN(['gmp.h' and 'libgmp' seems to have different versions or])
|
||||
AC_MSG_WARN([we cannot run a program linked with GMP (if you cannot])
|
||||
AC_MSG_WARN([see the version numbers above). A cause may be different])
|
||||
AC_MSG_WARN([GMP versions with different ABI's.])
|
||||
AC_MSG_WARN([However since we can't use 'libtool' inside the configure,])
|
||||
AC_MSG_WARN([we can't be sure. See 'config.log' for details.])
|
||||
],AC_MSG_RESULT([can not test])
|
||||
)
|
||||
LD_RUN_PATH="$saved_LD_RUN_PATH"
|
||||
|
||||
dnl End of tests which need to link with GMP.
|
||||
fi
|
||||
|
||||
dnl Remove also many MACROS (AC_DEFINE) which are unused by MPFR
|
||||
dnl and polluate (and slow down because libtool has to parse them) the build.
|
||||
if test -f confdefs.h; then
|
||||
sed '/#define PACKAGE_/d' <confdefs.h >confdefs.tmp
|
||||
sed '/#define HAVE_STRING/d' <confdefs.tmp >confdefs.h
|
||||
sed '/#define HAVE_ALLOCA /d' <confdefs.h >confdefs.tmp
|
||||
sed '/#define HAVE_DLFCN_H/d' <confdefs.tmp >confdefs.h
|
||||
sed '/#define HAVE_MEM/d' <confdefs.h >confdefs.tmp
|
||||
sed '/#define STDC_HEADERS/d' <confdefs.tmp >confdefs.h
|
||||
sed '/#define HAVE_STRTOL/d' <confdefs.h >confdefs.tmp
|
||||
sed '/#define HAVE_STDLIB_H/d' <confdefs.tmp >confdefs.h
|
||||
sed '/#define HAVE_UNISTD_H/d' <confdefs.h >confdefs.tmp
|
||||
sed '/#define HAVE_STDC_HEADERS/d' <confdefs.tmp >confdefs.h
|
||||
sed '/#define HAVE_LONG_DOUBLE/d' <confdefs.h >confdefs.tmp
|
||||
sed '/#define HAVE_SYS_STAT_H/d' <confdefs.tmp >confdefs.h
|
||||
sed '/#define HAVE_SYS_TYPES_H/d' <confdefs.h >confdefs.tmp
|
||||
sed '/#define PROTOTYPES/d' <confdefs.tmp >confdefs.h
|
||||
sed '/#define __PROTOTYPES/d' <confdefs.h >confdefs.tmp
|
||||
|
||||
mv confdefs.tmp confdefs.h
|
||||
fi
|
||||
|
||||
dnl Output
|
||||
AC_CONFIG_FILES([Makefile tests/Makefile mparam.h:mparam_h.in])
|
||||
AC_OUTPUT
|
||||
|
||||
dnl NEWS README AUTHORS Changelog
|
|
@ -0,0 +1,152 @@
|
|||
/* mpfr_const_catalan -- compute Catalan's constant.
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* Declare the cache */
|
||||
MPFR_DECL_INIT_CACHE(__gmpfr_cache_const_catalan, mpfr_const_catalan_internal);
|
||||
|
||||
/* Set User Interface */
|
||||
#undef mpfr_const_catalan
|
||||
int
|
||||
mpfr_const_catalan (mpfr_ptr x, mpfr_rnd_t rnd_mode) {
|
||||
return mpfr_cache (x, __gmpfr_cache_const_catalan, rnd_mode);
|
||||
}
|
||||
|
||||
/* return T, Q such that T/Q = sum(k!^2/(2k)!/(2k+1)^2, k=n1..n2-1) */
|
||||
static void
|
||||
S (mpz_t T, mpz_t P, mpz_t Q, unsigned long n1, unsigned long n2)
|
||||
{
|
||||
if (n2 == n1 + 1)
|
||||
{
|
||||
if (n1 == 0)
|
||||
{
|
||||
mpz_set_ui (P, 1);
|
||||
mpz_set_ui (Q, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mpz_set_ui (P, 2 * n1 - 1);
|
||||
mpz_mul_ui (P, P, n1);
|
||||
mpz_ui_pow_ui (Q, 2 * n1 + 1, 2);
|
||||
mpz_mul_2exp (Q, Q, 1);
|
||||
}
|
||||
mpz_set (T, P);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long m = (n1 + n2) / 2;
|
||||
mpz_t T2, P2, Q2;
|
||||
S (T, P, Q, n1, m);
|
||||
mpz_init (T2);
|
||||
mpz_init (P2);
|
||||
mpz_init (Q2);
|
||||
S (T2, P2, Q2, m, n2);
|
||||
mpz_mul (T, T, Q2);
|
||||
mpz_mul (T2, T2, P);
|
||||
mpz_add (T, T, T2);
|
||||
mpz_mul (P, P, P2);
|
||||
mpz_mul (Q, Q, Q2);
|
||||
mpz_clear (T2);
|
||||
mpz_clear (P2);
|
||||
mpz_clear (Q2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't need to save/restore exponent range: the cache does it.
|
||||
Catalan's constant is G = sum((-1)^k/(2*k+1)^2, k=0..infinity).
|
||||
We compute it using formula (31) of Victor Adamchik's page
|
||||
"33 representations for Catalan's constant"
|
||||
http://www-2.cs.cmu.edu/~adamchik/articles/catalan/catalan.htm
|
||||
|
||||
G = Pi/8*log(2+sqrt(3)) + 3/8*sum(k!^2/(2k)!/(2k+1)^2,k=0..infinity)
|
||||
*/
|
||||
int
|
||||
mpfr_const_catalan_internal (mpfr_ptr g, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t x, y, z;
|
||||
mpz_t T, P, Q;
|
||||
mpfr_prec_t pg, p;
|
||||
int inex;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
MPFR_GROUP_DECL (group);
|
||||
|
||||
MPFR_LOG_FUNC (("rnd_mode=%d", rnd_mode), ("g[%#R]=%R inex=%d", g, g, inex));
|
||||
|
||||
/* Here are the WC (max prec = 100.000.000)
|
||||
Once we have found a chain of 11, we only look for bigger chain.
|
||||
Found 3 '1' at 0
|
||||
Found 5 '1' at 9
|
||||
Found 6 '0' at 34
|
||||
Found 9 '1' at 176
|
||||
Found 11 '1' at 705
|
||||
Found 12 '0' at 913
|
||||
Found 14 '1' at 12762
|
||||
Found 15 '1' at 152561
|
||||
Found 16 '0' at 171725
|
||||
Found 18 '0' at 525355
|
||||
Found 20 '0' at 529245
|
||||
Found 21 '1' at 6390133
|
||||
Found 22 '0' at 7806417
|
||||
Found 25 '1' at 11936239
|
||||
Found 27 '1' at 51752950
|
||||
*/
|
||||
pg = MPFR_PREC (g);
|
||||
p = pg + MPFR_INT_CEIL_LOG2 (pg) + 7;
|
||||
|
||||
MPFR_GROUP_INIT_3 (group, p, x, y, z);
|
||||
mpz_init (T);
|
||||
mpz_init (P);
|
||||
mpz_init (Q);
|
||||
|
||||
MPFR_ZIV_INIT (loop, p);
|
||||
for (;;) {
|
||||
mpfr_sqrt_ui (x, 3, MPFR_RNDU);
|
||||
mpfr_add_ui (x, x, 2, MPFR_RNDU);
|
||||
mpfr_log (x, x, MPFR_RNDU);
|
||||
mpfr_const_pi (y, MPFR_RNDU);
|
||||
mpfr_mul (x, x, y, MPFR_RNDN);
|
||||
S (T, P, Q, 0, (p - 1) / 2);
|
||||
mpz_mul_ui (T, T, 3);
|
||||
mpfr_set_z (y, T, MPFR_RNDU);
|
||||
mpfr_set_z (z, Q, MPFR_RNDD);
|
||||
mpfr_div (y, y, z, MPFR_RNDN);
|
||||
mpfr_add (x, x, y, MPFR_RNDN);
|
||||
mpfr_div_2ui (x, x, 3, MPFR_RNDN);
|
||||
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (x, p - 5, pg, rnd_mode)))
|
||||
break;
|
||||
|
||||
MPFR_ZIV_NEXT (loop, p);
|
||||
MPFR_GROUP_REPREC_3 (group, p, x, y, z);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
inex = mpfr_set (g, x, rnd_mode);
|
||||
|
||||
MPFR_GROUP_CLEAR (group);
|
||||
mpz_clear (T);
|
||||
mpz_clear (P);
|
||||
mpz_clear (Q);
|
||||
|
||||
return inex;
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
/* mpfr_const_euler -- Euler's constant
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* Declare the cache */
|
||||
MPFR_DECL_INIT_CACHE(__gmpfr_cache_const_euler, mpfr_const_euler_internal);
|
||||
|
||||
/* Set User Interface */
|
||||
#undef mpfr_const_euler
|
||||
int
|
||||
mpfr_const_euler (mpfr_ptr x, mpfr_rnd_t rnd_mode) {
|
||||
return mpfr_cache (x, __gmpfr_cache_const_euler, rnd_mode);
|
||||
}
|
||||
|
||||
|
||||
static void mpfr_const_euler_S2 (mpfr_ptr, unsigned long);
|
||||
static void mpfr_const_euler_R (mpfr_ptr, unsigned long);
|
||||
|
||||
int
|
||||
mpfr_const_euler_internal (mpfr_t x, mpfr_rnd_t rnd)
|
||||
{
|
||||
mpfr_prec_t prec = MPFR_PREC(x), m, log2m;
|
||||
mpfr_t y, z;
|
||||
unsigned long n;
|
||||
int inexact;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
log2m = MPFR_INT_CEIL_LOG2 (prec);
|
||||
m = prec + 2 * log2m + 23;
|
||||
|
||||
mpfr_init2 (y, m);
|
||||
mpfr_init2 (z, m);
|
||||
|
||||
MPFR_ZIV_INIT (loop, m);
|
||||
for (;;)
|
||||
{
|
||||
mpfr_exp_t exp_S, err;
|
||||
/* since prec >= 1, we have m >= 24 here, which ensures n >= 9 below */
|
||||
n = 1 + (unsigned long) ((double) m * LOG2 / 2.0);
|
||||
MPFR_ASSERTD (n >= 9);
|
||||
mpfr_const_euler_S2 (y, n); /* error <= 3 ulps */
|
||||
exp_S = MPFR_EXP(y);
|
||||
mpfr_set_ui (z, n, MPFR_RNDN);
|
||||
mpfr_log (z, z, MPFR_RNDD); /* error <= 1 ulp */
|
||||
mpfr_sub (y, y, z, MPFR_RNDN); /* S'(n) - log(n) */
|
||||
/* the error is less than 1/2 + 3*2^(exp_S-EXP(y)) + 2^(EXP(z)-EXP(y))
|
||||
<= 1/2 + 2^(exp_S+2-EXP(y)) + 2^(EXP(z)-EXP(y))
|
||||
<= 1/2 + 2^(1+MAX(exp_S+2,EXP(z))-EXP(y)) */
|
||||
err = 1 + MAX(exp_S + 2, MPFR_EXP(z)) - MPFR_EXP(y);
|
||||
err = (err >= -1) ? err + 1 : 0; /* error <= 2^err ulp(y) */
|
||||
exp_S = MPFR_EXP(y);
|
||||
mpfr_const_euler_R (z, n); /* err <= ulp(1/2) = 2^(-m) */
|
||||
mpfr_sub (y, y, z, MPFR_RNDN);
|
||||
/* err <= 1/2 ulp(y) + 2^(-m) + 2^(err + exp_S - EXP(y)) ulp(y).
|
||||
Since the result is between 0.5 and 1, ulp(y) = 2^(-m).
|
||||
So we get 3/2*ulp(y) + 2^(err + exp_S - EXP(y)) ulp(y).
|
||||
3/2 + 2^e <= 2^(e+1) for e>=1, and <= 2^2 otherwise */
|
||||
err = err + exp_S - MPFR_EXP(y);
|
||||
err = (err >= 1) ? err + 1 : 2;
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (y, m - err, prec, rnd)))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, m);
|
||||
mpfr_set_prec (y, m);
|
||||
mpfr_set_prec (z, m);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inexact = mpfr_set (x, y, rnd);
|
||||
|
||||
mpfr_clear (y);
|
||||
mpfr_clear (z);
|
||||
|
||||
return inexact; /* always inexact */
|
||||
}
|
||||
|
||||
static void
|
||||
mpfr_const_euler_S2_aux (mpz_t P, mpz_t Q, mpz_t T, unsigned long n,
|
||||
unsigned long a, unsigned long b, int need_P)
|
||||
{
|
||||
if (a + 1 == b)
|
||||
{
|
||||
mpz_set_ui (P, n);
|
||||
if (a > 1)
|
||||
mpz_mul_si (P, P, 1 - (long) a);
|
||||
mpz_set (T, P);
|
||||
mpz_set_ui (Q, a);
|
||||
mpz_mul_ui (Q, Q, a);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long c = (a + b) / 2;
|
||||
mpz_t P2, Q2, T2;
|
||||
mpfr_const_euler_S2_aux (P, Q, T, n, a, c, 1);
|
||||
mpz_init (P2);
|
||||
mpz_init (Q2);
|
||||
mpz_init (T2);
|
||||
mpfr_const_euler_S2_aux (P2, Q2, T2, n, c, b, 1);
|
||||
mpz_mul (T, T, Q2);
|
||||
mpz_mul (T2, T2, P);
|
||||
mpz_add (T, T, T2);
|
||||
if (need_P)
|
||||
mpz_mul (P, P, P2);
|
||||
mpz_mul (Q, Q, Q2);
|
||||
mpz_clear (P2);
|
||||
mpz_clear (Q2);
|
||||
mpz_clear (T2);
|
||||
/* divide by 2 if possible */
|
||||
{
|
||||
unsigned long v2;
|
||||
v2 = mpz_scan1 (P, 0);
|
||||
c = mpz_scan1 (Q, 0);
|
||||
if (c < v2)
|
||||
v2 = c;
|
||||
c = mpz_scan1 (T, 0);
|
||||
if (c < v2)
|
||||
v2 = c;
|
||||
if (v2)
|
||||
{
|
||||
mpz_tdiv_q_2exp (P, P, v2);
|
||||
mpz_tdiv_q_2exp (Q, Q, v2);
|
||||
mpz_tdiv_q_2exp (T, T, v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* computes S(n) = sum(n^k*(-1)^(k-1)/k!/k, k=1..ceil(4.319136566 * n))
|
||||
using binary splitting.
|
||||
We have S(n) = sum(f(k), k=1..N) with N=ceil(4.319136566 * n)
|
||||
and f(k) = n^k*(-1)*(k-1)/k!/k,
|
||||
thus f(k)/f(k-1) = -n*(k-1)/k^2
|
||||
*/
|
||||
static void
|
||||
mpfr_const_euler_S2 (mpfr_t x, unsigned long n)
|
||||
{
|
||||
mpz_t P, Q, T;
|
||||
unsigned long N = (unsigned long) (ALPHA * (double) n + 1.0);
|
||||
mpz_init (P);
|
||||
mpz_init (Q);
|
||||
mpz_init (T);
|
||||
mpfr_const_euler_S2_aux (P, Q, T, n, 1, N + 1, 0);
|
||||
mpfr_set_z (x, T, MPFR_RNDN);
|
||||
mpfr_div_z (x, x, Q, MPFR_RNDN);
|
||||
mpz_clear (P);
|
||||
mpz_clear (Q);
|
||||
mpz_clear (T);
|
||||
}
|
||||
|
||||
/* computes R(n) = exp(-n)/n * sum(k!/(-n)^k, k=0..n-2)
|
||||
with error at most 4*ulp(x). Assumes n>=2.
|
||||
Since x <= exp(-n)/n <= 1/8, then 4*ulp(x) <= ulp(1).
|
||||
*/
|
||||
static void
|
||||
mpfr_const_euler_R (mpfr_t x, unsigned long n)
|
||||
{
|
||||
unsigned long k, m;
|
||||
mpz_t a, s;
|
||||
mpfr_t y;
|
||||
|
||||
MPFR_ASSERTN (n >= 2); /* ensures sum(k!/(-n)^k, k=0..n-2) >= 2/3 */
|
||||
|
||||
/* as we multiply the sum by exp(-n), we need only PREC(x) - n/LOG2 bits */
|
||||
m = MPFR_PREC(x) - (unsigned long) ((double) n / LOG2);
|
||||
|
||||
mpz_init_set_ui (a, 1);
|
||||
mpz_mul_2exp (a, a, m);
|
||||
mpz_init_set (s, a);
|
||||
|
||||
for (k = 1; k <= n; k++)
|
||||
{
|
||||
mpz_mul_ui (a, a, k);
|
||||
mpz_fdiv_q_ui (a, a, n);
|
||||
/* the error e(k) on a is e(k) <= 1 + k/n*e(k-1) with e(0)=0,
|
||||
i.e. e(k) <= k */
|
||||
if (k % 2)
|
||||
mpz_sub (s, s, a);
|
||||
else
|
||||
mpz_add (s, s, a);
|
||||
}
|
||||
/* the error on s is at most 1+2+...+n = n*(n+1)/2 */
|
||||
mpz_fdiv_q_ui (s, s, n); /* err <= 1 + (n+1)/2 */
|
||||
MPFR_ASSERTN (MPFR_PREC(x) >= mpz_sizeinbase(s, 2));
|
||||
mpfr_set_z (x, s, MPFR_RNDD); /* exact */
|
||||
mpfr_div_2ui (x, x, m, MPFR_RNDD);
|
||||
/* now x = 1/n * sum(k!/(-n)^k, k=0..n-2) <= 1/n */
|
||||
/* err(x) <= (n+1)/2^m <= (n+1)*exp(n)/2^PREC(x) */
|
||||
|
||||
mpfr_init2 (y, m);
|
||||
mpfr_set_si (y, -(long)n, MPFR_RNDD); /* assumed exact */
|
||||
mpfr_exp (y, y, MPFR_RNDD); /* err <= ulp(y) <= exp(-n)*2^(1-m) */
|
||||
mpfr_mul (x, x, y, MPFR_RNDD);
|
||||
/* err <= ulp(x) + (n + 1 + 2/n) / 2^prec(x)
|
||||
<= ulp(x) + (n + 1 + 2/n) ulp(x)/x since x*2^(-prec(x)) < ulp(x)
|
||||
<= ulp(x) + (n + 1 + 2/n) 3/(2n) ulp(x) since x >= 2/3*n for n >= 2
|
||||
<= 4 * ulp(x) for n >= 2 */
|
||||
mpfr_clear (y);
|
||||
|
||||
mpz_clear (a);
|
||||
mpz_clear (s);
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/* mpfr_const_log2 -- compute natural logarithm of 2
|
||||
|
||||
Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* Declare the cache */
|
||||
MPFR_DECL_INIT_CACHE(__gmpfr_cache_const_log2, mpfr_const_log2_internal);
|
||||
|
||||
/* Set User interface */
|
||||
#undef mpfr_const_log2
|
||||
int
|
||||
mpfr_const_log2 (mpfr_ptr x, mpfr_rnd_t rnd_mode) {
|
||||
return mpfr_cache (x, __gmpfr_cache_const_log2, rnd_mode);
|
||||
}
|
||||
|
||||
/* Auxiliary function: Compute the terms from n1 to n2 (excluded)
|
||||
3/4*sum((-1)^n*n!^2/2^n/(2*n+1)!, n = n1..n2-1).
|
||||
Numerator is T[0], denominator is Q[0],
|
||||
Compute P[0] only when need_P is non-zero.
|
||||
Need 1+ceil(log(n2-n1)/log(2)) cells in T[],P[],Q[].
|
||||
*/
|
||||
static void
|
||||
S (mpz_t *T, mpz_t *P, mpz_t *Q, unsigned long n1, unsigned long n2, int need_P)
|
||||
{
|
||||
if (n2 == n1 + 1)
|
||||
{
|
||||
if (n1 == 0)
|
||||
mpz_set_ui (P[0], 3);
|
||||
else
|
||||
{
|
||||
mpz_set_ui (P[0], n1);
|
||||
mpz_neg (P[0], P[0]);
|
||||
}
|
||||
if (n1 <= (ULONG_MAX / 4 - 1) / 2)
|
||||
mpz_set_ui (Q[0], 4 * (2 * n1 + 1));
|
||||
else /* to avoid overflow in 4 * (2 * n1 + 1) */
|
||||
{
|
||||
mpz_set_ui (Q[0], n1);
|
||||
mpz_mul_2exp (Q[0], Q[0], 1);
|
||||
mpz_add_ui (Q[0], Q[0], 1);
|
||||
mpz_mul_2exp (Q[0], Q[0], 2);
|
||||
}
|
||||
mpz_set (T[0], P[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long m = (n1 / 2) + (n2 / 2) + (n1 & 1UL & n2);
|
||||
unsigned long v, w;
|
||||
|
||||
S (T, P, Q, n1, m, 1);
|
||||
S (T + 1, P + 1, Q + 1, m, n2, need_P);
|
||||
mpz_mul (T[0], T[0], Q[1]);
|
||||
mpz_mul (T[1], T[1], P[0]);
|
||||
mpz_add (T[0], T[0], T[1]);
|
||||
if (need_P)
|
||||
mpz_mul (P[0], P[0], P[1]);
|
||||
mpz_mul (Q[0], Q[0], Q[1]);
|
||||
|
||||
/* remove common trailing zeroes if any */
|
||||
v = mpz_scan1 (T[0], 0);
|
||||
if (v > 0)
|
||||
{
|
||||
w = mpz_scan1 (Q[0], 0);
|
||||
if (w < v)
|
||||
v = w;
|
||||
if (need_P)
|
||||
{
|
||||
w = mpz_scan1 (P[0], 0);
|
||||
if (w < v)
|
||||
v = w;
|
||||
}
|
||||
/* now v = min(val(T), val(Q), val(P)) */
|
||||
if (v > 0)
|
||||
{
|
||||
mpz_fdiv_q_2exp (T[0], T[0], v);
|
||||
mpz_fdiv_q_2exp (Q[0], Q[0], v);
|
||||
if (need_P)
|
||||
mpz_fdiv_q_2exp (P[0], P[0], v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't need to save / restore exponent range: the cache does it */
|
||||
int
|
||||
mpfr_const_log2_internal (mpfr_ptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
unsigned long n = MPFR_PREC (x);
|
||||
mpfr_prec_t w; /* working precision */
|
||||
unsigned long N;
|
||||
mpz_t *T, *P, *Q;
|
||||
mpfr_t t, q;
|
||||
int inexact;
|
||||
int ok = 1; /* ensures that the 1st try will give correct rounding */
|
||||
unsigned long lgN, i;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
MPFR_LOG_FUNC (("rnd_mode=%d", rnd_mode), ("x[%#R]=%R inex=%d",x,x,inexact));
|
||||
|
||||
mpfr_init2 (t, MPFR_PREC_MIN);
|
||||
mpfr_init2 (q, MPFR_PREC_MIN);
|
||||
|
||||
if (n < 1253)
|
||||
w = n + 10; /* ensures correct rounding for the four rounding modes,
|
||||
together with N = w / 3 + 1 (see below). */
|
||||
else if (n < 2571)
|
||||
w = n + 11; /* idem */
|
||||
else if (n < 3983)
|
||||
w = n + 12;
|
||||
else if (n < 4854)
|
||||
w = n + 13;
|
||||
else if (n < 26248)
|
||||
w = n + 14;
|
||||
else
|
||||
{
|
||||
w = n + 15;
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
MPFR_ZIV_INIT (loop, w);
|
||||
for (;;)
|
||||
{
|
||||
N = w / 3 + 1; /* Warning: do not change that (even increasing N!)
|
||||
without checking correct rounding in the above
|
||||
ranges for n. */
|
||||
|
||||
/* the following are needed for error analysis (see algorithms.tex) */
|
||||
MPFR_ASSERTD(w >= 3 && N >= 2);
|
||||
|
||||
lgN = MPFR_INT_CEIL_LOG2 (N) + 1;
|
||||
T = (mpz_t *) (*__gmp_allocate_func) (3 * lgN * sizeof (mpz_t));
|
||||
P = T + lgN;
|
||||
Q = T + 2*lgN;
|
||||
for (i = 0; i < lgN; i++)
|
||||
{
|
||||
mpz_init (T[i]);
|
||||
mpz_init (P[i]);
|
||||
mpz_init (Q[i]);
|
||||
}
|
||||
|
||||
S (T, P, Q, 0, N, 0);
|
||||
|
||||
mpfr_set_prec (t, w);
|
||||
mpfr_set_prec (q, w);
|
||||
|
||||
mpfr_set_z (t, T[0], MPFR_RNDN);
|
||||
mpfr_set_z (q, Q[0], MPFR_RNDN);
|
||||
mpfr_div (t, t, q, MPFR_RNDN);
|
||||
|
||||
for (i = 0; i < lgN; i++)
|
||||
{
|
||||
mpz_clear (T[i]);
|
||||
mpz_clear (P[i]);
|
||||
mpz_clear (Q[i]);
|
||||
}
|
||||
(*__gmp_free_func) (T, 3 * lgN * sizeof (mpz_t));
|
||||
|
||||
if (MPFR_LIKELY (ok != 0
|
||||
|| mpfr_can_round (t, w - 2, MPFR_RNDN, rnd_mode, n)))
|
||||
break;
|
||||
|
||||
MPFR_ZIV_NEXT (loop, w);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inexact = mpfr_set (x, t, rnd_mode);
|
||||
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (q);
|
||||
|
||||
return inexact;
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/* mpfr_const_pi -- compute Pi
|
||||
|
||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* Declare the cache */
|
||||
MPFR_DECL_INIT_CACHE(__gmpfr_cache_const_pi, mpfr_const_pi_internal);
|
||||
|
||||
/* Set User Interface */
|
||||
#undef mpfr_const_pi
|
||||
int
|
||||
mpfr_const_pi (mpfr_ptr x, mpfr_rnd_t rnd_mode) {
|
||||
return mpfr_cache (x, __gmpfr_cache_const_pi, rnd_mode);
|
||||
}
|
||||
|
||||
/* Don't need to save/restore exponent range: the cache does it */
|
||||
int
|
||||
mpfr_const_pi_internal (mpfr_ptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t a, A, B, D, S;
|
||||
mpfr_prec_t px, p, cancel, k, kmax;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
int inex;
|
||||
|
||||
MPFR_LOG_FUNC (("rnd_mode=%d", rnd_mode), ("x[%#R]=%R inex=%d", x, x, inex));
|
||||
|
||||
px = MPFR_PREC (x);
|
||||
|
||||
/* we need 9*2^kmax - 4 >= px+2*kmax+8 */
|
||||
for (kmax = 2; ((px + 2 * kmax + 12) / 9) >> kmax; kmax ++);
|
||||
|
||||
p = px + 3 * kmax + 14; /* guarantees no recomputation for px <= 10000 */
|
||||
|
||||
mpfr_init2 (a, p);
|
||||
mpfr_init2 (A, p);
|
||||
mpfr_init2 (B, p);
|
||||
mpfr_init2 (D, p);
|
||||
mpfr_init2 (S, p);
|
||||
|
||||
MPFR_ZIV_INIT (loop, p);
|
||||
for (;;) {
|
||||
mpfr_set_ui (a, 1, MPFR_RNDN); /* a = 1 */
|
||||
mpfr_set_ui (A, 1, MPFR_RNDN); /* A = a^2 = 1 */
|
||||
mpfr_set_ui_2exp (B, 1, -1, MPFR_RNDN); /* B = b^2 = 1/2 */
|
||||
mpfr_set_ui_2exp (D, 1, -2, MPFR_RNDN); /* D = 1/4 */
|
||||
|
||||
#define b B
|
||||
#define ap a
|
||||
#define Ap A
|
||||
#define Bp B
|
||||
for (k = 0, cancel = 0; ; k++)
|
||||
{
|
||||
/* invariant: 1/2 <= B <= A <= a < 1 */
|
||||
mpfr_add (S, A, B, MPFR_RNDN); /* 1 <= S <= 2 */
|
||||
mpfr_div_2ui (S, S, 2, MPFR_RNDN); /* exact, 1/4 <= S <= 1/2 */
|
||||
mpfr_sqrt (b, B, MPFR_RNDN); /* 1/2 <= b <= 1 */
|
||||
mpfr_add (ap, a, b, MPFR_RNDN); /* 1 <= ap <= 2 */
|
||||
mpfr_div_2ui (ap, ap, 1, MPFR_RNDN); /* exact, 1/2 <= ap <= 1 */
|
||||
mpfr_mul (Ap, ap, ap, MPFR_RNDN); /* 1/4 <= Ap <= 1 */
|
||||
mpfr_sub (Bp, Ap, S, MPFR_RNDN); /* -1/4 <= Bp <= 3/4 */
|
||||
mpfr_mul_2ui (Bp, Bp, 1, MPFR_RNDN); /* -1/2 <= Bp <= 3/2 */
|
||||
mpfr_sub (S, Ap, Bp, MPFR_RNDN);
|
||||
MPFR_ASSERTN (mpfr_cmp_ui (S, 1) < 0);
|
||||
cancel = mpfr_cmp_ui (S, 0) ? (mpfr_uexp_t) -mpfr_get_exp(S) : p;
|
||||
/* MPFR_ASSERTN (cancel >= px || cancel >= 9 * (1 << k) - 4); */
|
||||
mpfr_mul_2ui (S, S, k, MPFR_RNDN);
|
||||
mpfr_sub (D, D, S, MPFR_RNDN);
|
||||
/* stop when |A_k - B_k| <= 2^(k-p) i.e. cancel >= p-k */
|
||||
if (cancel + k >= p)
|
||||
break;
|
||||
}
|
||||
#undef b
|
||||
#undef ap
|
||||
#undef Ap
|
||||
#undef Bp
|
||||
|
||||
mpfr_div (A, B, D, MPFR_RNDN);
|
||||
|
||||
/* MPFR_ASSERTN(p >= 2 * k + 8); */
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (A, p - 2 * k - 8, px, rnd_mode)))
|
||||
break;
|
||||
|
||||
p += kmax;
|
||||
MPFR_ZIV_NEXT (loop, p);
|
||||
mpfr_set_prec (a, p);
|
||||
mpfr_set_prec (A, p);
|
||||
mpfr_set_prec (B, p);
|
||||
mpfr_set_prec (D, p);
|
||||
mpfr_set_prec (S, p);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
inex = mpfr_set (x, A, rnd_mode);
|
||||
|
||||
mpfr_clear (a);
|
||||
mpfr_clear (A);
|
||||
mpfr_clear (B);
|
||||
mpfr_clear (D);
|
||||
mpfr_clear (S);
|
||||
|
||||
return inex;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* MPFR internal constant FP numbers
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
static const mp_limb_t __gmpfr_limb1[1] = {MPFR_LIMB_HIGHBIT};
|
||||
const mpfr_t __gmpfr_one = {{2, MPFR_SIGN_POS, 1, (mp_limb_t*)__gmpfr_limb1}};
|
||||
const mpfr_t __gmpfr_two = {{2, MPFR_SIGN_POS, 2, (mp_limb_t*)__gmpfr_limb1}};
|
||||
const mpfr_t __gmpfr_four ={{2, MPFR_SIGN_POS, 3, (mp_limb_t*)__gmpfr_limb1}};
|
|
@ -0,0 +1,38 @@
|
|||
/* mpfr_copysign -- Produce a value with the magnitude of x and sign bit of y
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/*
|
||||
The computation of z with magnitude of x and sign of y:
|
||||
z = (-1)^signbit(y) * abs(x), i.e. with the same sign bit as y,
|
||||
even if z is a NaN.
|
||||
Note: This function implements copysign from the IEEE-754 standard
|
||||
when no rounding occurs (e.g. if PREC(z) >= PREC(x)).
|
||||
*/
|
||||
|
||||
#undef mpfr_copysign
|
||||
int
|
||||
mpfr_copysign (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
return mpfr_set4 (z, x, rnd_mode, MPFR_SIGN (y));
|
||||
}
|
|
@ -0,0 +1,296 @@
|
|||
/* mpfr_cos -- cosine of a floating-point number
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
static int
|
||||
mpfr_cos_fast (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inex;
|
||||
|
||||
inex = mpfr_sincos_fast (NULL, y, x, rnd_mode);
|
||||
inex = inex >> 2; /* 0: exact, 1: rounded up, 2: rounded down */
|
||||
return (inex == 2) ? -1 : inex;
|
||||
}
|
||||
|
||||
/* f <- 1 - r/2! + r^2/4! + ... + (-1)^l r^l/(2l)! + ...
|
||||
Assumes |r| < 1/2, and f, r have the same precision.
|
||||
Returns e such that the error on f is bounded by 2^e ulps.
|
||||
*/
|
||||
static int
|
||||
mpfr_cos2_aux (mpfr_ptr f, mpfr_srcptr r)
|
||||
{
|
||||
mpz_t x, t, s;
|
||||
mpfr_exp_t ex, l, m;
|
||||
mpfr_prec_t p, q;
|
||||
unsigned long i, maxi, imax;
|
||||
|
||||
MPFR_ASSERTD(mpfr_get_exp (r) <= -1);
|
||||
|
||||
/* compute minimal i such that i*(i+1) does not fit in an unsigned long,
|
||||
assuming that there are no padding bits. */
|
||||
maxi = 1UL << (CHAR_BIT * sizeof(unsigned long) / 2);
|
||||
if (maxi * (maxi / 2) == 0) /* test checked at compile time */
|
||||
{
|
||||
/* can occur only when there are padding bits. */
|
||||
/* maxi * (maxi-1) is representable iff maxi * (maxi / 2) != 0 */
|
||||
do
|
||||
maxi /= 2;
|
||||
while (maxi * (maxi / 2) == 0);
|
||||
}
|
||||
|
||||
mpz_init (x);
|
||||
mpz_init (s);
|
||||
mpz_init (t);
|
||||
ex = mpfr_get_z_2exp (x, r); /* r = x*2^ex */
|
||||
|
||||
/* remove trailing zeroes */
|
||||
l = mpz_scan1 (x, 0);
|
||||
ex += l;
|
||||
mpz_fdiv_q_2exp (x, x, l);
|
||||
|
||||
/* since |r| < 1, r = x*2^ex, and x is an integer, necessarily ex < 0 */
|
||||
|
||||
p = mpfr_get_prec (f); /* same than r */
|
||||
/* bound for number of iterations */
|
||||
imax = p / (-mpfr_get_exp (r));
|
||||
imax += (imax == 0);
|
||||
q = 2 * MPFR_INT_CEIL_LOG2(imax) + 4; /* bound for (3l)^2 */
|
||||
|
||||
mpz_set_ui (s, 1); /* initialize sum with 1 */
|
||||
mpz_mul_2exp (s, s, p + q); /* scale all values by 2^(p+q) */
|
||||
mpz_set (t, s); /* invariant: t is previous term */
|
||||
for (i = 1; (m = mpz_sizeinbase (t, 2)) >= q; i += 2)
|
||||
{
|
||||
/* adjust precision of x to that of t */
|
||||
l = mpz_sizeinbase (x, 2);
|
||||
if (l > m)
|
||||
{
|
||||
l -= m;
|
||||
mpz_fdiv_q_2exp (x, x, l);
|
||||
ex += l;
|
||||
}
|
||||
/* multiply t by r */
|
||||
mpz_mul (t, t, x);
|
||||
mpz_fdiv_q_2exp (t, t, -ex);
|
||||
/* divide t by i*(i+1) */
|
||||
if (i < maxi)
|
||||
mpz_fdiv_q_ui (t, t, i * (i + 1));
|
||||
else
|
||||
{
|
||||
mpz_fdiv_q_ui (t, t, i);
|
||||
mpz_fdiv_q_ui (t, t, i + 1);
|
||||
}
|
||||
/* if m is the (current) number of bits of t, we can consider that
|
||||
all operations on t so far had precision >= m, so we can prove
|
||||
by induction that the relative error on t is of the form
|
||||
(1+u)^(3l)-1, where |u| <= 2^(-m), and l=(i+1)/2 is the # of loops.
|
||||
Since |(1+x^2)^(1/x) - 1| <= 4x/3 for |x| <= 1/2,
|
||||
for |u| <= 1/(3l)^2, the absolute error is bounded by
|
||||
4/3*(3l)*2^(-m)*t <= 4*l since |t| < 2^m.
|
||||
Therefore the error on s is bounded by 2*l*(l+1). */
|
||||
/* add or subtract to s */
|
||||
if (i % 4 == 1)
|
||||
mpz_sub (s, s, t);
|
||||
else
|
||||
mpz_add (s, s, t);
|
||||
}
|
||||
|
||||
mpfr_set_z (f, s, MPFR_RNDN);
|
||||
mpfr_div_2ui (f, f, p + q, MPFR_RNDN);
|
||||
|
||||
mpz_clear (x);
|
||||
mpz_clear (s);
|
||||
mpz_clear (t);
|
||||
|
||||
l = (i - 1) / 2; /* number of iterations */
|
||||
return 2 * MPFR_INT_CEIL_LOG2 (l + 1) + 1; /* bound is 2l(l+1) */
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_cos (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_prec_t K0, K, precy, m, k, l;
|
||||
int inexact, reduce = 0;
|
||||
mpfr_t r, s, xr, c;
|
||||
mpfr_exp_t exps, cancel = 0, expx;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_GROUP_DECL (group);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (x));
|
||||
return mpfr_set_ui (y, 1, rnd_mode);
|
||||
}
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* cos(x) = 1-x^2/2 + ..., so error < 2^(2*EXP(x)-1) */
|
||||
expx = MPFR_GET_EXP (x);
|
||||
MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (y, __gmpfr_one, -2 * expx,
|
||||
1, 0, rnd_mode, expo, {});
|
||||
|
||||
/* Compute initial precision */
|
||||
precy = MPFR_PREC (y);
|
||||
|
||||
if (precy >= MPFR_SINCOS_THRESHOLD)
|
||||
{
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_cos_fast (y, x, rnd_mode);
|
||||
}
|
||||
|
||||
K0 = __gmpfr_isqrt (precy / 3);
|
||||
m = precy + 2 * MPFR_INT_CEIL_LOG2 (precy) + 2 * K0;
|
||||
|
||||
if (expx >= 3)
|
||||
{
|
||||
reduce = 1;
|
||||
/* As expx + m - 1 will silently be converted into mpfr_prec_t
|
||||
in the mpfr_init2 call, the assert below may be useful to
|
||||
avoid undefined behavior. */
|
||||
MPFR_ASSERTN (expx + m - 1 <= MPFR_PREC_MAX);
|
||||
mpfr_init2 (c, expx + m - 1);
|
||||
mpfr_init2 (xr, m);
|
||||
}
|
||||
|
||||
MPFR_GROUP_INIT_2 (group, m, r, s);
|
||||
MPFR_ZIV_INIT (loop, m);
|
||||
for (;;)
|
||||
{
|
||||
/* If |x| >= 4, first reduce x cmod (2*Pi) into xr, using mpfr_remainder:
|
||||
let e = EXP(x) >= 3, and m the target precision:
|
||||
(1) c <- 2*Pi [precision e+m-1, nearest]
|
||||
(2) xr <- remainder (x, c) [precision m, nearest]
|
||||
We have |c - 2*Pi| <= 1/2ulp(c) = 2^(3-e-m)
|
||||
|xr - x - k c| <= 1/2ulp(xr) <= 2^(1-m)
|
||||
|k| <= |x|/(2*Pi) <= 2^(e-2)
|
||||
Thus |xr - x - 2kPi| <= |k| |c - 2Pi| + 2^(1-m) <= 2^(2-m).
|
||||
It follows |cos(xr) - cos(x)| <= 2^(2-m). */
|
||||
if (reduce)
|
||||
{
|
||||
mpfr_const_pi (c, MPFR_RNDN);
|
||||
mpfr_mul_2ui (c, c, 1, MPFR_RNDN); /* 2Pi */
|
||||
mpfr_remainder (xr, x, c, MPFR_RNDN);
|
||||
if (MPFR_IS_ZERO(xr))
|
||||
goto ziv_next;
|
||||
/* now |xr| <= 4, thus r <= 16 below */
|
||||
mpfr_mul (r, xr, xr, MPFR_RNDU); /* err <= 1 ulp */
|
||||
}
|
||||
else
|
||||
mpfr_mul (r, x, x, MPFR_RNDU); /* err <= 1 ulp */
|
||||
|
||||
/* now |x| < 4 (or xr if reduce = 1), thus |r| <= 16 */
|
||||
|
||||
/* we need |r| < 1/2 for mpfr_cos2_aux, i.e., EXP(r) - 2K <= -1 */
|
||||
K = K0 + 1 + MAX(0, MPFR_EXP(r)) / 2;
|
||||
/* since K0 >= 0, if EXP(r) < 0, then K >= 1, thus EXP(r) - 2K <= -3;
|
||||
otherwise if EXP(r) >= 0, then K >= 1/2 + EXP(r)/2, thus
|
||||
EXP(r) - 2K <= -1 */
|
||||
|
||||
MPFR_SET_EXP (r, MPFR_GET_EXP (r) - 2 * K); /* Can't overflow! */
|
||||
|
||||
/* s <- 1 - r/2! + ... + (-1)^l r^l/(2l)! */
|
||||
l = mpfr_cos2_aux (s, r);
|
||||
/* l is the error bound in ulps on s */
|
||||
MPFR_SET_ONE (r);
|
||||
for (k = 0; k < K; k++)
|
||||
{
|
||||
mpfr_sqr (s, s, MPFR_RNDU); /* err <= 2*olderr */
|
||||
MPFR_SET_EXP (s, MPFR_GET_EXP (s) + 1); /* Can't overflow */
|
||||
mpfr_sub (s, s, r, MPFR_RNDN); /* err <= 4*olderr */
|
||||
if (MPFR_IS_ZERO(s))
|
||||
goto ziv_next;
|
||||
MPFR_ASSERTD (MPFR_GET_EXP (s) <= 1);
|
||||
}
|
||||
|
||||
/* The absolute error on s is bounded by (2l+1/3)*2^(2K-m)
|
||||
2l+1/3 <= 2l+1.
|
||||
If |x| >= 4, we need to add 2^(2-m) for the argument reduction
|
||||
by 2Pi: if K = 0, this amounts to add 4 to 2l+1/3, i.e., to add
|
||||
2 to l; if K >= 1, this amounts to add 1 to 2*l+1/3. */
|
||||
l = 2 * l + 1;
|
||||
if (reduce)
|
||||
l += (K == 0) ? 4 : 1;
|
||||
k = MPFR_INT_CEIL_LOG2 (l) + 2*K;
|
||||
/* now the error is bounded by 2^(k-m) = 2^(EXP(s)-err) */
|
||||
|
||||
exps = MPFR_GET_EXP (s);
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (s, exps + m - k, precy, rnd_mode)))
|
||||
break;
|
||||
|
||||
if (MPFR_UNLIKELY (exps == 1))
|
||||
/* s = 1 or -1, and except x=0 which was already checked above,
|
||||
cos(x) cannot be 1 or -1, so we can round if the error is less
|
||||
than 2^(-precy) for directed rounding, or 2^(-precy-1) for rounding
|
||||
to nearest. */
|
||||
{
|
||||
if (m > k && (m - k >= precy + (rnd_mode == MPFR_RNDN)))
|
||||
{
|
||||
/* If round to nearest or away, result is s = 1 or -1,
|
||||
otherwise it is round(nexttoward (s, 0)). However in order to
|
||||
have the inexact flag correctly set below, we set |s| to
|
||||
1 - 2^(-m) in all cases. */
|
||||
mpfr_nexttozero (s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (exps < cancel)
|
||||
{
|
||||
m += cancel - exps;
|
||||
cancel = exps;
|
||||
}
|
||||
|
||||
ziv_next:
|
||||
MPFR_ZIV_NEXT (loop, m);
|
||||
MPFR_GROUP_REPREC_2 (group, m, r, s);
|
||||
if (reduce)
|
||||
{
|
||||
mpfr_set_prec (xr, m);
|
||||
mpfr_set_prec (c, expx + m - 1);
|
||||
}
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
inexact = mpfr_set (y, s, rnd_mode);
|
||||
MPFR_GROUP_CLEAR (group);
|
||||
if (reduce)
|
||||
{
|
||||
mpfr_clear (xr);
|
||||
mpfr_clear (c);
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/* mpfr_cosh -- hyperbolic cosine
|
||||
|
||||
Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* The computation of cosh is done by *
|
||||
* cosh= 1/2[e^(x)+e^(-x)] */
|
||||
|
||||
int
|
||||
mpfr_cosh (mpfr_ptr y, mpfr_srcptr xt , mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t x;
|
||||
int inexact;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", xt, xt, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(xt)))
|
||||
{
|
||||
if (MPFR_IS_NAN(xt))
|
||||
{
|
||||
MPFR_SET_NAN(y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF(xt))
|
||||
{
|
||||
MPFR_SET_INF(y);
|
||||
MPFR_SET_POS(y);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_ASSERTD(MPFR_IS_ZERO(xt));
|
||||
return mpfr_set_ui (y, 1, rnd_mode); /* cosh(0) = 1 */
|
||||
}
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* cosh(x) = 1+x^2/2 + ... <= 1+x^2 for x <= 2.9828...,
|
||||
thus the error < 2^(2*EXP(x)). If x >= 1, then EXP(x) >= 1,
|
||||
thus the following will always fail. */
|
||||
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, __gmpfr_one, -2 * MPFR_GET_EXP (xt), 0,
|
||||
1, rnd_mode, inexact = _inexact; goto end);
|
||||
|
||||
MPFR_TMP_INIT_ABS(x, xt);
|
||||
/* General case */
|
||||
{
|
||||
/* Declaration of the intermediary variable */
|
||||
mpfr_t t, te;
|
||||
/* Declaration of the size variable */
|
||||
mpfr_prec_t Ny = MPFR_PREC(y); /* Precision of output variable */
|
||||
mpfr_prec_t Nt; /* Precision of the intermediary variable */
|
||||
long int err; /* Precision of error */
|
||||
MPFR_ZIV_DECL (loop);
|
||||
MPFR_GROUP_DECL (group);
|
||||
|
||||
/* compute the precision of intermediary variable */
|
||||
/* The optimal number of bits : see algorithms.tex */
|
||||
Nt = Ny + 3 + MPFR_INT_CEIL_LOG2 (Ny);
|
||||
|
||||
/* initialise of intermediary variables */
|
||||
MPFR_GROUP_INIT_2 (group, Nt, t, te);
|
||||
|
||||
/* First computation of cosh */
|
||||
MPFR_ZIV_INIT (loop, Nt);
|
||||
for (;;)
|
||||
{
|
||||
MPFR_BLOCK_DECL (flags);
|
||||
|
||||
/* Compute cosh */
|
||||
MPFR_BLOCK (flags, mpfr_exp (te, x, MPFR_RNDD)); /* exp(x) */
|
||||
/* exp can overflow (but not underflow since x>0) */
|
||||
if (MPFR_OVERFLOW (flags))
|
||||
/* cosh(x) > exp(x), cosh(x) underflows too */
|
||||
{
|
||||
inexact = mpfr_overflow (y, rnd_mode, MPFR_SIGN_POS);
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_OVERFLOW);
|
||||
break;
|
||||
}
|
||||
mpfr_ui_div (t, 1, te, MPFR_RNDU); /* 1/exp(x) */
|
||||
mpfr_add (t, te, t, MPFR_RNDU); /* exp(x) + 1/exp(x)*/
|
||||
mpfr_div_2ui (t, t, 1, MPFR_RNDN); /* 1/2(exp(x) + 1/exp(x))*/
|
||||
|
||||
/* Estimation of the error */
|
||||
err = Nt - 3;
|
||||
/* Check if we can round */
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
|
||||
{
|
||||
inexact = mpfr_set (y, t, rnd_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Actualisation of the precision */
|
||||
MPFR_ZIV_NEXT (loop, Nt);
|
||||
MPFR_GROUP_REPREC_2 (group, Nt, t, te);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
MPFR_GROUP_CLEAR (group);
|
||||
}
|
||||
|
||||
end:
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/* mpfr_cot - cotangent function.
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* the cotangent is defined by cot(x) = 1/tan(x) = cos(x)/sin(x).
|
||||
cot (NaN) = NaN.
|
||||
cot (+Inf) = csc (-Inf) = NaN.
|
||||
cot (+0) = +Inf.
|
||||
cot (-0) = -Inf.
|
||||
*/
|
||||
|
||||
#define FUNCTION mpfr_cot
|
||||
#define INVERSE mpfr_tan
|
||||
#define ACTION_NAN(y) do { MPFR_SET_NAN(y); MPFR_RET_NAN; } while (1)
|
||||
#define ACTION_INF(y) do { MPFR_SET_NAN(y); MPFR_RET_NAN; } while (1)
|
||||
#define ACTION_ZERO(y,x) do { MPFR_SET_SAME_SIGN(y,x); MPFR_SET_INF(y); \
|
||||
MPFR_RET(0); } while (1)
|
||||
|
||||
/* (This analysis is adapted from that for mpfr_coth.)
|
||||
Near x=0, cot(x) = 1/x - x/3 + ..., more precisely we have
|
||||
|cot(x) - 1/x| <= 0.36 for |x| <= 1. The error term has
|
||||
the opposite sign as 1/x, thus |cot(x)| <= |1/x|. Then:
|
||||
(i) either x is a power of two, then 1/x is exactly representable, and
|
||||
as long as 1/2*ulp(1/x) > 0.36, we can conclude;
|
||||
(ii) otherwise assume x has <= n bits, and y has <= n+1 bits, then
|
||||
|y - 1/x| >= 2^(-2n) ufp(y), where ufp means unit in first place.
|
||||
Since |cot(x) - 1/x| <= 0.36, if 2^(-2n) ufp(y) >= 0.72, then
|
||||
|y - cot(x)| >= 2^(-2n-1) ufp(y), and rounding 1/x gives the correct
|
||||
result. If x < 2^E, then y > 2^(-E), thus ufp(y) > 2^(-E-1).
|
||||
A sufficient condition is thus EXP(x) + 1 <= -2 MAX(PREC(x),PREC(Y)).
|
||||
The division can be inexact in case of underflow or overflow; but
|
||||
an underflow is not possible as emin = - emax. The overflow is a
|
||||
real overflow possibly except when |x| = 2^emin. */
|
||||
#define ACTION_TINY(y,x,r) \
|
||||
if (MPFR_EXP(x) + 1 <= -2 * (mpfr_exp_t) MAX(MPFR_PREC(x), MPFR_PREC(y))) \
|
||||
{ \
|
||||
int two2emin; \
|
||||
int signx = MPFR_SIGN(x); \
|
||||
MPFR_ASSERTN (MPFR_EMIN_MIN + MPFR_EMAX_MAX == 0); \
|
||||
if ((two2emin = mpfr_get_exp (x) == __gmpfr_emin + 1 && \
|
||||
mpfr_powerof2_raw (x))) \
|
||||
{ \
|
||||
/* Case |x| = 2^emin. 1/x is not representable; so, compute \
|
||||
1/(2x) instead (exact), and correct the result later. */ \
|
||||
mpfr_set_si_2exp (y, signx, __gmpfr_emax, MPFR_RNDN); \
|
||||
inexact = 0; \
|
||||
} \
|
||||
else \
|
||||
inexact = mpfr_ui_div (y, 1, x, r); \
|
||||
if (inexact == 0) /* x is a power of two */ \
|
||||
{ /* result always 1/x, except when rounding to zero */ \
|
||||
if (rnd_mode == MPFR_RNDA) \
|
||||
rnd_mode = (signx > 0) ? MPFR_RNDU : MPFR_RNDD; \
|
||||
if (rnd_mode == MPFR_RNDU || (rnd_mode == MPFR_RNDZ && signx < 0)) \
|
||||
{ \
|
||||
if (signx < 0) \
|
||||
mpfr_nextabove (y); /* -2^k + epsilon */ \
|
||||
inexact = 1; \
|
||||
} \
|
||||
else if (rnd_mode == MPFR_RNDD || rnd_mode == MPFR_RNDZ) \
|
||||
{ \
|
||||
if (signx > 0) \
|
||||
mpfr_nextbelow (y); /* 2^k - epsilon */ \
|
||||
inexact = -1; \
|
||||
} \
|
||||
else /* round to nearest */ \
|
||||
inexact = signx; \
|
||||
if (two2emin) \
|
||||
mpfr_mul_2ui (y, y, 1, r); /* overflow in MPFR_RNDN */ \
|
||||
} \
|
||||
/* Underflow is not possible with emin = - emax, but we cannot */ \
|
||||
/* add an assert as the underflow flag could have already been */ \
|
||||
/* set before the call to mpfr_cot. */ \
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); \
|
||||
goto end; \
|
||||
}
|
||||
|
||||
#include "gen_inverse.h"
|
|
@ -0,0 +1,93 @@
|
|||
/* mpfr_coth - Hyperbolic cotangent function.
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* the hyperbolic cotangent is defined by coth(x) = 1/tanh(x)
|
||||
coth (NaN) = NaN.
|
||||
coth (+Inf) = 1
|
||||
coth (-Inf) = -1
|
||||
coth (+0) = +Inf.
|
||||
coth (-0) = -Inf.
|
||||
*/
|
||||
|
||||
#define FUNCTION mpfr_coth
|
||||
#define INVERSE mpfr_tanh
|
||||
#define ACTION_NAN(y) do { MPFR_SET_NAN(y); MPFR_RET_NAN; } while (1)
|
||||
#define ACTION_INF(y) return mpfr_set_si (y, MPFR_IS_POS(x) ? 1 : -1, rnd_mode)
|
||||
#define ACTION_ZERO(y,x) do { MPFR_SET_SAME_SIGN(y,x); MPFR_SET_INF(y); \
|
||||
MPFR_RET(0); } while (1)
|
||||
|
||||
/* We know |coth(x)| > 1, thus if the approximation z is such that
|
||||
1 <= z <= 1 + 2^(-p) where p is the target precision, then the
|
||||
result is either 1 or nextabove(1) = 1 + 2^(1-p). */
|
||||
#define ACTION_SPECIAL \
|
||||
if (MPFR_GET_EXP(z) == 1) /* 1 <= |z| < 2 */ \
|
||||
{ \
|
||||
/* the following is exact by Sterbenz theorem */ \
|
||||
mpfr_sub_si (z, z, MPFR_SIGN(z) > 0 ? 1 : -1, MPFR_RNDN); \
|
||||
if (MPFR_IS_ZERO(z) || MPFR_GET_EXP(z) <= - (mpfr_exp_t) precy) \
|
||||
{ \
|
||||
mpfr_add_si (z, z, MPFR_SIGN(z) > 0 ? 1 : -1, MPFR_RNDN); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* The analysis is adapted from that for mpfr_csc:
|
||||
near x=0, coth(x) = 1/x + x/3 + ..., more precisely we have
|
||||
|coth(x) - 1/x| <= 0.32 for |x| <= 1. Like for csc, the error term has
|
||||
the same sign as 1/x, thus |coth(x)| >= |1/x|. Then:
|
||||
(i) either x is a power of two, then 1/x is exactly representable, and
|
||||
as long as 1/2*ulp(1/x) > 0.32, we can conclude;
|
||||
(ii) otherwise assume x has <= n bits, and y has <= n+1 bits, then
|
||||
|y - 1/x| >= 2^(-2n) ufp(y), where ufp means unit in first place.
|
||||
Since |coth(x) - 1/x| <= 0.32, if 2^(-2n) ufp(y) >= 0.64, then
|
||||
|y - coth(x)| >= 2^(-2n-1) ufp(y), and rounding 1/x gives the correct
|
||||
result. If x < 2^E, then y > 2^(-E), thus ufp(y) > 2^(-E-1).
|
||||
A sufficient condition is thus EXP(x) + 1 <= -2 MAX(PREC(x),PREC(Y)). */
|
||||
#define ACTION_TINY(y,x,r) \
|
||||
if (MPFR_EXP(x) + 1 <= -2 * (mpfr_exp_t) MAX(MPFR_PREC(x), MPFR_PREC(y))) \
|
||||
{ \
|
||||
int signx = MPFR_SIGN(x); \
|
||||
inexact = mpfr_ui_div (y, 1, x, r); \
|
||||
if (inexact == 0) /* x is a power of two */ \
|
||||
{ /* result always 1/x, except when rounding away from zero */ \
|
||||
if (rnd_mode == MPFR_RNDA) \
|
||||
rnd_mode = (signx > 0) ? MPFR_RNDU : MPFR_RNDD; \
|
||||
if (rnd_mode == MPFR_RNDU) \
|
||||
{ \
|
||||
if (signx > 0) \
|
||||
mpfr_nextabove (y); /* 2^k + epsilon */ \
|
||||
inexact = 1; \
|
||||
} \
|
||||
else if (rnd_mode == MPFR_RNDD) \
|
||||
{ \
|
||||
if (signx < 0) \
|
||||
mpfr_nextbelow (y); /* -2^k - epsilon */ \
|
||||
inexact = -1; \
|
||||
} \
|
||||
else /* round to zero, or nearest */ \
|
||||
inexact = -signx; \
|
||||
} \
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); \
|
||||
goto end; \
|
||||
}
|
||||
|
||||
#include "gen_inverse.h"
|
|
@ -0,0 +1,76 @@
|
|||
/* mpfr_csc - cosecant function.
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* the cosecant is defined by csc(x) = 1/sin(x).
|
||||
csc (NaN) = NaN.
|
||||
csc (+Inf) = csc (-Inf) = NaN.
|
||||
csc (+0) = +Inf.
|
||||
csc (-0) = -Inf.
|
||||
*/
|
||||
|
||||
#define FUNCTION mpfr_csc
|
||||
#define INVERSE mpfr_sin
|
||||
#define ACTION_NAN(y) do { MPFR_SET_NAN(y); MPFR_RET_NAN; } while (1)
|
||||
#define ACTION_INF(y) do { MPFR_SET_NAN(y); MPFR_RET_NAN; } while (1)
|
||||
#define ACTION_ZERO(y,x) do { MPFR_SET_SAME_SIGN(y,x); MPFR_SET_INF(y); \
|
||||
MPFR_RET(0); } while (1)
|
||||
/* near x=0, we have csc(x) = 1/x + x/6 + ..., more precisely we have
|
||||
|csc(x) - 1/x| <= 0.2 for |x| <= 1. The analysis is similar to that for
|
||||
gamma(x) near x=0 (see gamma.c), except here the error term has the same
|
||||
sign as 1/x, thus |csc(x)| >= |1/x|. Then:
|
||||
(i) either x is a power of two, then 1/x is exactly representable, and
|
||||
as long as 1/2*ulp(1/x) > 0.2, we can conclude;
|
||||
(ii) otherwise assume x has <= n bits, and y has <= n+1 bits, then
|
||||
|y - 1/x| >= 2^(-2n) ufp(y), where ufp means unit in first place.
|
||||
Since |csc(x) - 1/x| <= 0.2, if 2^(-2n) ufp(y) >= 0.4, then
|
||||
|y - csc(x)| >= 2^(-2n-1) ufp(y), and rounding 1/x gives the correct result.
|
||||
If x < 2^E, then y > 2^(-E), thus ufp(y) > 2^(-E-1).
|
||||
A sufficient condition is thus EXP(x) <= -2 MAX(PREC(x),PREC(Y)). */
|
||||
#define ACTION_TINY(y,x,r) \
|
||||
if (MPFR_EXP(x) <= -2 * (mpfr_exp_t) MAX(MPFR_PREC(x), MPFR_PREC(y))) \
|
||||
{ \
|
||||
int signx = MPFR_SIGN(x); \
|
||||
inexact = mpfr_ui_div (y, 1, x, r); \
|
||||
if (inexact == 0) /* x is a power of two */ \
|
||||
{ /* result always 1/x, except when rounding away from zero */ \
|
||||
if (rnd_mode == MPFR_RNDA) \
|
||||
rnd_mode = (signx > 0) ? MPFR_RNDU : MPFR_RNDD; \
|
||||
if (rnd_mode == MPFR_RNDU) \
|
||||
{ \
|
||||
if (signx > 0) \
|
||||
mpfr_nextabove (y); /* 2^k + epsilon */ \
|
||||
inexact = 1; \
|
||||
} \
|
||||
else if (rnd_mode == MPFR_RNDD) \
|
||||
{ \
|
||||
if (signx < 0) \
|
||||
mpfr_nextbelow (y); /* -2^k - epsilon */ \
|
||||
inexact = -1; \
|
||||
} \
|
||||
else /* round to zero, or nearest */ \
|
||||
inexact = -signx; \
|
||||
} \
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); \
|
||||
goto end; \
|
||||
}
|
||||
|
||||
#include "gen_inverse.h"
|
|
@ -0,0 +1,79 @@
|
|||
/* mpfr_csch - Hyperbolic cosecant function.
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* the hyperbolic cosecant is defined by csch(x) = 1/sinh(x).
|
||||
csch (NaN) = NaN.
|
||||
csch (+Inf) = +0.
|
||||
csch (-Inf) = -0.
|
||||
csch (+0) = +Inf.
|
||||
csch (-0) = -Inf.
|
||||
*/
|
||||
|
||||
#define FUNCTION mpfr_csch
|
||||
#define INVERSE mpfr_sinh
|
||||
#define ACTION_NAN(y) do { MPFR_SET_NAN(y); MPFR_RET_NAN; } while (1)
|
||||
#define ACTION_INF(y) do { MPFR_SET_SAME_SIGN(y,x); MPFR_SET_ZERO (y); \
|
||||
MPFR_RET(0); } while (1)
|
||||
#define ACTION_ZERO(y,x) do { MPFR_SET_SAME_SIGN(y,x); MPFR_SET_INF(y); \
|
||||
MPFR_RET(0); } while (1)
|
||||
|
||||
/* (This analysis is adapted from that for mpfr_csc.)
|
||||
Near x=0, we have csch(x) = 1/x - x/6 + ..., more precisely we have
|
||||
|csch(x) - 1/x| <= 0.2 for |x| <= 1. The error term has the opposite
|
||||
sign as 1/x, thus |csch(x)| <= |1/x|. Then:
|
||||
(i) either x is a power of two, then 1/x is exactly representable, and
|
||||
as long as 1/2*ulp(1/x) > 0.2, we can conclude;
|
||||
(ii) otherwise assume x has <= n bits, and y has <= n+1 bits, then
|
||||
|y - 1/x| >= 2^(-2n) ufp(y), where ufp means unit in first place.
|
||||
Since |csch(x) - 1/x| <= 0.2, if 2^(-2n) ufp(y) >= 0.4, then
|
||||
|y - csch(x)| >= 2^(-2n-1) ufp(y), and rounding 1/x gives the correct
|
||||
result. If x < 2^E, then y > 2^(-E), thus ufp(y) > 2^(-E-1).
|
||||
A sufficient condition is thus EXP(x) <= -2 MAX(PREC(x),PREC(Y)). */
|
||||
#define ACTION_TINY(y,x,r) \
|
||||
if (MPFR_EXP(x) <= -2 * (mpfr_exp_t) MAX(MPFR_PREC(x), MPFR_PREC(y))) \
|
||||
{ \
|
||||
int signx = MPFR_SIGN(x); \
|
||||
inexact = mpfr_ui_div (y, 1, x, r); \
|
||||
if (inexact == 0) /* x is a power of two */ \
|
||||
{ /* result always 1/x, except when rounding to zero */ \
|
||||
if (rnd_mode == MPFR_RNDA) \
|
||||
rnd_mode = (signx > 0) ? MPFR_RNDU : MPFR_RNDD; \
|
||||
if (rnd_mode == MPFR_RNDU || (rnd_mode == MPFR_RNDZ && signx < 0)) \
|
||||
{ \
|
||||
if (signx < 0) \
|
||||
mpfr_nextabove (y); /* -2^k + epsilon */ \
|
||||
inexact = 1; \
|
||||
} \
|
||||
else if (rnd_mode == MPFR_RNDD || rnd_mode == MPFR_RNDZ) \
|
||||
{ \
|
||||
if (signx > 0) \
|
||||
mpfr_nextbelow (y); /* 2^k - epsilon */ \
|
||||
inexact = -1; \
|
||||
} \
|
||||
else /* round to nearest */ \
|
||||
inexact = signx; \
|
||||
} \
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); \
|
||||
goto end; \
|
||||
}
|
||||
|
||||
#include "gen_inverse.h"
|
|
@ -0,0 +1,49 @@
|
|||
/* mpfr_d_div -- divide a machine double precision float
|
||||
by a multiple precision floating-point number
|
||||
|
||||
Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_d_div (mpfr_ptr a, double b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
mpfr_t d;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_LOG_FUNC (("b=%.20g c[%#R]=%R rnd=%d", b, c, c, rnd_mode),
|
||||
("a[%#R]=%R", a, a));
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
mpfr_init2 (d, IEEE_DBL_MANT_DIG);
|
||||
inexact = mpfr_set_d (d, b, rnd_mode);
|
||||
MPFR_ASSERTN (inexact == 0);
|
||||
|
||||
mpfr_clear_flags ();
|
||||
inexact = mpfr_div (a, d, c, rnd_mode);
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
|
||||
|
||||
mpfr_clear(d);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (a, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* mpfr_d_sub -- subtract a multiple precision floating-point number
|
||||
from a machine double precision float
|
||||
|
||||
Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_d_sub (mpfr_ptr a, double b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
mpfr_t d;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_LOG_FUNC (("b=%.20g c[%#R]=%R rnd=%d", b, c, c, rnd_mode),
|
||||
("a[%#R]=%R", a, a));
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
mpfr_init2 (d, IEEE_DBL_MANT_DIG);
|
||||
inexact = mpfr_set_d (d, b, rnd_mode);
|
||||
MPFR_ASSERTN (inexact == 0);
|
||||
|
||||
mpfr_clear_flags ();
|
||||
inexact = mpfr_sub (a, d, c, rnd_mode);
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
|
||||
|
||||
mpfr_clear(d);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (a, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,630 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2009-04-28.21; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
|
||||
# Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by `PROGRAMS ARGS'.
|
||||
object Object file output by `PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputing dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u="sed s,\\\\\\\\,/,g"
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say).
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
## The second -e expression handles DOS-style file names with drive letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the `deleted header file' problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the `:'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like `#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
|
||||
tr '
|
||||
' ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts `$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form `foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
# That's a tab and a space in the [].
|
||||
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
icc)
|
||||
# Intel's C compiler understands `-MD -MF file'. However on
|
||||
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
|
||||
# ICC 7.0 will fill foo.d with something like
|
||||
# foo.o: sub/foo.c
|
||||
# foo.o: sub/foo.h
|
||||
# which is wrong. We want:
|
||||
# sub/foo.o: sub/foo.c
|
||||
# sub/foo.o: sub/foo.h
|
||||
# sub/foo.c:
|
||||
# sub/foo.h:
|
||||
# ICC 7.1 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using \ :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
|
||||
sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add `dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in `foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# With Tru64 cc, shared objects can also be used to make a
|
||||
# static library. This mechanism is used in libtool 1.4 series to
|
||||
# handle both shared and static libraries in a single compilation.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# generates 2 separate objects for the 2 libraries. These two
|
||||
# compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
|
||||
tmpdepfile2=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
|
||||
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.o.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
tmpdepfile4=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
# That's a tab and a space in the [].
|
||||
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for `:'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' '
|
||||
' | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E |
|
||||
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||
sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
|
||||
echo " " >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -0,0 +1,372 @@
|
|||
/* mpfr_digamma -- digamma function of a floating-point number
|
||||
|
||||
Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* Put in s an approximation of digamma(x).
|
||||
Assumes x >= 2.
|
||||
Assumes s does not overlap with x.
|
||||
Returns an integer e such that the error is bounded by 2^e ulps
|
||||
of the result s.
|
||||
*/
|
||||
static mpfr_exp_t
|
||||
mpfr_digamma_approx (mpfr_ptr s, mpfr_srcptr x)
|
||||
{
|
||||
mpfr_prec_t p = MPFR_PREC (s);
|
||||
mpfr_t t, u, invxx;
|
||||
mpfr_exp_t e, exps, f, expu;
|
||||
mpz_t *INITIALIZED(B); /* variable B declared as initialized */
|
||||
unsigned long n0, n; /* number of allocated B[] */
|
||||
|
||||
MPFR_ASSERTN(MPFR_IS_POS(x) && (MPFR_EXP(x) >= 2));
|
||||
|
||||
mpfr_init2 (t, p);
|
||||
mpfr_init2 (u, p);
|
||||
mpfr_init2 (invxx, p);
|
||||
|
||||
mpfr_log (s, x, MPFR_RNDN); /* error <= 1/2 ulp */
|
||||
mpfr_ui_div (t, 1, x, MPFR_RNDN); /* error <= 1/2 ulp */
|
||||
mpfr_div_2exp (t, t, 1, MPFR_RNDN); /* exact */
|
||||
mpfr_sub (s, s, t, MPFR_RNDN);
|
||||
/* error <= 1/2 + 1/2*2^(EXP(olds)-EXP(s)) + 1/2*2^(EXP(t)-EXP(s)).
|
||||
For x >= 2, log(x) >= 2*(1/(2x)), thus olds >= 2t, and olds - t >= olds/2,
|
||||
thus 0 <= EXP(olds)-EXP(s) <= 1, and EXP(t)-EXP(s) <= 0, thus
|
||||
error <= 1/2 + 1/2*2 + 1/2 <= 2 ulps. */
|
||||
e = 2; /* initial error */
|
||||
mpfr_mul (invxx, x, x, MPFR_RNDZ); /* invxx = x^2 * (1 + theta)
|
||||
for |theta| <= 2^(-p) */
|
||||
mpfr_ui_div (invxx, 1, invxx, MPFR_RNDU); /* invxx = 1/x^2 * (1 + theta)^2 */
|
||||
|
||||
/* in the following we note err=xxx when the ratio between the approximation
|
||||
and the exact result can be written (1 + theta)^xxx for |theta| <= 2^(-p),
|
||||
following Higham's method */
|
||||
B = mpfr_bernoulli_internal ((mpz_t *) 0, 0);
|
||||
mpfr_set_ui (t, 1, MPFR_RNDN); /* err = 0 */
|
||||
for (n = 1;; n++)
|
||||
{
|
||||
/* compute next Bernoulli number */
|
||||
B = mpfr_bernoulli_internal (B, n);
|
||||
/* The main term is Bernoulli[2n]/(2n)/x^(2n) = B[n]/(2n+1)!(2n)/x^(2n)
|
||||
= B[n]*t[n]/(2n) where t[n]/t[n-1] = 1/(2n)/(2n+1)/x^2. */
|
||||
mpfr_mul (t, t, invxx, MPFR_RNDU); /* err = err + 3 */
|
||||
mpfr_div_ui (t, t, 2 * n, MPFR_RNDU); /* err = err + 1 */
|
||||
mpfr_div_ui (t, t, 2 * n + 1, MPFR_RNDU); /* err = err + 1 */
|
||||
/* we thus have err = 5n here */
|
||||
mpfr_div_ui (u, t, 2 * n, MPFR_RNDU); /* err = 5n+1 */
|
||||
mpfr_mul_z (u, u, B[n], MPFR_RNDU); /* err = 5n+2, and the
|
||||
absolute error is bounded
|
||||
by 10n+4 ulp(u) [Rule 11] */
|
||||
/* if the terms 'u' are decreasing by a factor two at least,
|
||||
then the error coming from those is bounded by
|
||||
sum((10n+4)/2^n, n=1..infinity) = 24 */
|
||||
exps = mpfr_get_exp (s);
|
||||
expu = mpfr_get_exp (u);
|
||||
if (expu < exps - (mpfr_exp_t) p)
|
||||
break;
|
||||
mpfr_sub (s, s, u, MPFR_RNDN); /* error <= 24 + n/2 */
|
||||
if (mpfr_get_exp (s) < exps)
|
||||
e <<= exps - mpfr_get_exp (s);
|
||||
e ++; /* error in mpfr_sub */
|
||||
f = 10 * n + 4;
|
||||
while (expu < exps)
|
||||
{
|
||||
f = (1 + f) / 2;
|
||||
expu ++;
|
||||
}
|
||||
e += f; /* total rouding error coming from 'u' term */
|
||||
}
|
||||
|
||||
n0 = ++n;
|
||||
while (n--)
|
||||
mpz_clear (B[n]);
|
||||
(*__gmp_free_func) (B, n0 * sizeof (mpz_t));
|
||||
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (u);
|
||||
mpfr_clear (invxx);
|
||||
|
||||
f = 0;
|
||||
while (e > 1)
|
||||
{
|
||||
f++;
|
||||
e = (e + 1) / 2;
|
||||
/* Invariant: 2^f * e does not decrease */
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Use the reflection formula Digamma(1-x) = Digamma(x) + Pi * cot(Pi*x),
|
||||
i.e., Digamma(x) = Digamma(1-x) - Pi * cot(Pi*x).
|
||||
Assume x < 1/2. */
|
||||
static int
|
||||
mpfr_digamma_reflection (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_prec_t p = MPFR_PREC(y) + 10, q;
|
||||
mpfr_t t, u, v;
|
||||
mpfr_exp_t e1, expv;
|
||||
int inex;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
/* we want that 1-x is exact with precision q: if 0 < x < 1/2, then
|
||||
q = PREC(x)-EXP(x) is ok, otherwise if -1 <= x < 0, q = PREC(x)-EXP(x)
|
||||
is ok, otherwise for x < -1, PREC(x) is ok if EXP(x) <= PREC(x),
|
||||
otherwise we need EXP(x) */
|
||||
if (MPFR_EXP(x) < 0)
|
||||
q = MPFR_PREC(x) + 1 - MPFR_EXP(x);
|
||||
else if (MPFR_EXP(x) <= MPFR_PREC(x))
|
||||
q = MPFR_PREC(x) + 1;
|
||||
else
|
||||
q = MPFR_EXP(x);
|
||||
mpfr_init2 (u, q);
|
||||
MPFR_ASSERTN(mpfr_ui_sub (u, 1, x, MPFR_RNDN) == 0);
|
||||
|
||||
/* if x is half an integer, cot(Pi*x) = 0, thus Digamma(x) = Digamma(1-x) */
|
||||
mpfr_mul_2exp (u, u, 1, MPFR_RNDN);
|
||||
inex = mpfr_integer_p (u);
|
||||
mpfr_div_2exp (u, u, 1, MPFR_RNDN);
|
||||
if (inex)
|
||||
{
|
||||
inex = mpfr_digamma (y, u, rnd_mode);
|
||||
goto end;
|
||||
}
|
||||
|
||||
mpfr_init2 (t, p);
|
||||
mpfr_init2 (v, p);
|
||||
|
||||
MPFR_ZIV_INIT (loop, p);
|
||||
for (;;)
|
||||
{
|
||||
mpfr_const_pi (v, MPFR_RNDN); /* v = Pi*(1+theta) for |theta|<=2^(-p) */
|
||||
mpfr_mul (t, v, x, MPFR_RNDN); /* (1+theta)^2 */
|
||||
e1 = MPFR_EXP(t) - (mpfr_exp_t) p + 1; /* bound for t: err(t) <= 2^e1 */
|
||||
mpfr_cot (t, t, MPFR_RNDN);
|
||||
/* cot(t * (1+h)) = cot(t) - theta * (1 + cot(t)^2) with |theta|<=t*h */
|
||||
if (MPFR_EXP(t) > 0)
|
||||
e1 = e1 + 2 * MPFR_EXP(t) + 1;
|
||||
else
|
||||
e1 = e1 + 1;
|
||||
/* now theta * (1 + cot(t)^2) <= 2^e1 */
|
||||
e1 += (mpfr_exp_t) p - MPFR_EXP(t); /* error is now 2^e1 ulps */
|
||||
mpfr_mul (t, t, v, MPFR_RNDN);
|
||||
e1 ++;
|
||||
mpfr_digamma (v, u, MPFR_RNDN); /* error <= 1/2 ulp */
|
||||
expv = MPFR_EXP(v);
|
||||
mpfr_sub (v, v, t, MPFR_RNDN);
|
||||
if (MPFR_EXP(v) < MPFR_EXP(t))
|
||||
e1 += MPFR_EXP(t) - MPFR_EXP(v); /* scale error for t wrt new v */
|
||||
/* now take into account the 1/2 ulp error for v */
|
||||
if (expv - MPFR_EXP(v) - 1 > e1)
|
||||
e1 = expv - MPFR_EXP(v) - 1;
|
||||
else
|
||||
e1 ++;
|
||||
e1 ++; /* rounding error for mpfr_sub */
|
||||
if (MPFR_CAN_ROUND (v, p - e1, MPFR_PREC(y), rnd_mode))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, p);
|
||||
mpfr_set_prec (t, p);
|
||||
mpfr_set_prec (v, p);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inex = mpfr_set (y, v, rnd_mode);
|
||||
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (v);
|
||||
end:
|
||||
mpfr_clear (u);
|
||||
|
||||
return inex;
|
||||
}
|
||||
|
||||
/* we have x >= 1/2 here */
|
||||
static int
|
||||
mpfr_digamma_positive (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_prec_t p = MPFR_PREC(y) + 10, q;
|
||||
mpfr_t t, u, x_plus_j;
|
||||
int inex;
|
||||
mpfr_exp_t errt, erru, expt;
|
||||
unsigned long j = 0, min;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
/* compute a precision q such that x+1 is exact */
|
||||
if (MPFR_PREC(x) < MPFR_EXP(x))
|
||||
q = MPFR_EXP(x);
|
||||
else
|
||||
q = MPFR_PREC(x) + 1;
|
||||
mpfr_init2 (x_plus_j, q);
|
||||
|
||||
mpfr_init2 (t, p);
|
||||
mpfr_init2 (u, p);
|
||||
MPFR_ZIV_INIT (loop, p);
|
||||
for(;;)
|
||||
{
|
||||
/* Lower bound for x+j in mpfr_digamma_approx call: since the smallest
|
||||
term of the divergent series for Digamma(x) is about exp(-2*Pi*x), and
|
||||
we want it to be less than 2^(-p), this gives x > p*log(2)/(2*Pi)
|
||||
i.e., x >= 0.1103 p.
|
||||
To be safe, we ensure x >= 0.25 * p.
|
||||
*/
|
||||
min = (p + 3) / 4;
|
||||
if (min < 2)
|
||||
min = 2;
|
||||
|
||||
mpfr_set (x_plus_j, x, MPFR_RNDN);
|
||||
mpfr_set_ui (u, 0, MPFR_RNDN);
|
||||
j = 0;
|
||||
while (mpfr_cmp_ui (x_plus_j, min) < 0)
|
||||
{
|
||||
j ++;
|
||||
mpfr_ui_div (t, 1, x_plus_j, MPFR_RNDN); /* err <= 1/2 ulp */
|
||||
mpfr_add (u, u, t, MPFR_RNDN);
|
||||
inex = mpfr_add_ui (x_plus_j, x_plus_j, 1, MPFR_RNDZ);
|
||||
if (inex != 0) /* we lost one bit */
|
||||
{
|
||||
q ++;
|
||||
mpfr_prec_round (x_plus_j, q, MPFR_RNDZ);
|
||||
mpfr_nextabove (x_plus_j);
|
||||
}
|
||||
/* since all terms are positive, the error is bounded by j ulps */
|
||||
}
|
||||
for (erru = 0; j > 1; erru++, j = (j + 1) / 2);
|
||||
errt = mpfr_digamma_approx (t, x_plus_j);
|
||||
expt = MPFR_EXP(t);
|
||||
mpfr_sub (t, t, u, MPFR_RNDN);
|
||||
if (MPFR_EXP(t) < expt)
|
||||
errt += expt - MPFR_EXP(t);
|
||||
if (MPFR_EXP(t) < MPFR_EXP(u))
|
||||
erru += MPFR_EXP(u) - MPFR_EXP(t);
|
||||
if (errt > erru)
|
||||
errt = errt + 1;
|
||||
else if (errt == erru)
|
||||
errt = errt + 2;
|
||||
else
|
||||
errt = erru + 1;
|
||||
if (MPFR_CAN_ROUND (t, p - errt, MPFR_PREC(y), rnd_mode))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, p);
|
||||
mpfr_set_prec (t, p);
|
||||
mpfr_set_prec (u, p);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
inex = mpfr_set (y, t, rnd_mode);
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (u);
|
||||
mpfr_clear (x_plus_j);
|
||||
return inex;
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_digamma (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inex;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(x)))
|
||||
{
|
||||
if (MPFR_IS_NAN(x))
|
||||
{
|
||||
MPFR_SET_NAN(y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF(x))
|
||||
{
|
||||
if (MPFR_IS_POS(x)) /* Digamma(+Inf) = +Inf */
|
||||
{
|
||||
MPFR_SET_SAME_SIGN(y, x);
|
||||
MPFR_SET_INF(y);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
else /* Digamma(-Inf) = NaN */
|
||||
{
|
||||
MPFR_SET_NAN(y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
}
|
||||
else /* Zero case */
|
||||
{
|
||||
/* the following works also in case of overlap */
|
||||
MPFR_SET_INF(y);
|
||||
MPFR_SET_OPPOSITE_SIGN(y, x);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Digamma is undefined for negative integers */
|
||||
if (MPFR_IS_NEG(x) && mpfr_integer_p (x))
|
||||
{
|
||||
MPFR_SET_NAN(y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
|
||||
/* now x is a normal number */
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
/* for x very small, we have Digamma(x) = -1/x - gamma + O(x), more precisely
|
||||
-1 < Digamma(x) + 1/x < 0 for -0.2 < x < 0.2, thus:
|
||||
(i) either x is a power of two, then 1/x is exactly representable, and
|
||||
as long as 1/2*ulp(1/x) > 1, we can conclude;
|
||||
(ii) otherwise assume x has <= n bits, and y has <= n+1 bits, then
|
||||
|y + 1/x| >= 2^(-2n) ufp(y), where ufp means unit in first place.
|
||||
Since |Digamma(x) + 1/x| <= 1, if 2^(-2n) ufp(y) >= 2, then
|
||||
|y - Digamma(x)| >= 2^(-2n-1)ufp(y), and rounding -1/x gives the correct result.
|
||||
If x < 2^E, then y > 2^(-E), thus ufp(y) > 2^(-E-1).
|
||||
A sufficient condition is thus EXP(x) <= -2 MAX(PREC(x),PREC(Y)). */
|
||||
if (MPFR_EXP(x) < -2)
|
||||
{
|
||||
if (MPFR_EXP(x) <= -2 * (mpfr_exp_t) MAX(MPFR_PREC(x), MPFR_PREC(y)))
|
||||
{
|
||||
int signx = MPFR_SIGN(x);
|
||||
inex = mpfr_si_div (y, -1, x, rnd_mode);
|
||||
if (inex == 0) /* x is a power of two */
|
||||
{ /* result always -1/x, except when rounding down */
|
||||
if (rnd_mode == MPFR_RNDA)
|
||||
rnd_mode = (signx > 0) ? MPFR_RNDD : MPFR_RNDU;
|
||||
if (rnd_mode == MPFR_RNDZ)
|
||||
rnd_mode = (signx > 0) ? MPFR_RNDU : MPFR_RNDD;
|
||||
if (rnd_mode == MPFR_RNDU)
|
||||
inex = 1;
|
||||
else if (rnd_mode == MPFR_RNDD)
|
||||
{
|
||||
mpfr_nextbelow (y);
|
||||
inex = -1;
|
||||
}
|
||||
else /* nearest */
|
||||
inex = 1;
|
||||
}
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (MPFR_IS_NEG(x))
|
||||
inex = mpfr_digamma_reflection (y, x, rnd_mode);
|
||||
/* if x < 1/2 we use the reflection formula */
|
||||
else if (MPFR_EXP(x) < 0)
|
||||
inex = mpfr_digamma_reflection (y, x, rnd_mode);
|
||||
else
|
||||
inex = mpfr_digamma_positive (y, x, rnd_mode);
|
||||
|
||||
end:
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inex, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* mpfr_dim -- positive difference
|
||||
|
||||
Copyright 2001, 2002, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* dim (x,y) is defined as:
|
||||
|
||||
x-y if x > y
|
||||
+0 if x <= y
|
||||
*/
|
||||
|
||||
int
|
||||
mpfr_dim (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
if (MPFR_IS_NAN(x) || MPFR_IS_NAN(y))
|
||||
{
|
||||
MPFR_SET_NAN(z);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
|
||||
if (mpfr_cmp (x,y) > 0)
|
||||
return mpfr_sub (z, x, y, rnd_mode);
|
||||
else
|
||||
{
|
||||
MPFR_SET_ZERO(z);
|
||||
MPFR_SET_POS(z);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,678 @@
|
|||
/* mpfr_div -- divide two floating-point numbers
|
||||
|
||||
Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
#ifdef DEBUG2
|
||||
#define mpfr_mpn_print(ap,n) mpfr_mpn_print3 (ap,n,MPFR_LIMB_ZERO)
|
||||
static void
|
||||
mpfr_mpn_print3 (mpfr_limb_ptr ap, mp_size_t n, mp_limb_t cy)
|
||||
{
|
||||
mp_size_t i;
|
||||
for (i = 0; i < n; i++)
|
||||
printf ("+%lu*2^%lu", (unsigned long) ap[i], (unsigned long)
|
||||
(GMP_NUMB_BITS * i));
|
||||
if (cy)
|
||||
printf ("+2^%lu", (unsigned long) (GMP_NUMB_BITS * n));
|
||||
printf ("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if {ap, an} is zero */
|
||||
static int
|
||||
mpfr_mpn_cmpzero (mpfr_limb_ptr ap, mp_size_t an)
|
||||
{
|
||||
while (an > 0)
|
||||
if (MPFR_LIKELY(ap[--an] != MPFR_LIMB_ZERO))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* compare {ap, an} and {bp, bn} >> extra,
|
||||
aligned by the more significant limbs.
|
||||
Takes into account bp[0] for extra=1.
|
||||
*/
|
||||
static int
|
||||
mpfr_mpn_cmp_aux (mpfr_limb_ptr ap, mp_size_t an,
|
||||
mpfr_limb_ptr bp, mp_size_t bn, int extra)
|
||||
{
|
||||
int cmp = 0;
|
||||
mp_size_t k;
|
||||
mp_limb_t bb;
|
||||
|
||||
if (an >= bn)
|
||||
{
|
||||
k = an - bn;
|
||||
while (cmp == 0 && bn > 0)
|
||||
{
|
||||
bn --;
|
||||
bb = (extra) ? ((bp[bn+1] << (GMP_NUMB_BITS - 1)) | (bp[bn] >> 1))
|
||||
: bp[bn];
|
||||
cmp = (ap[k + bn] > bb) ? 1 : ((ap[k + bn] < bb) ? -1 : 0);
|
||||
}
|
||||
bb = (extra) ? bp[0] << (GMP_NUMB_BITS - 1) : MPFR_LIMB_ZERO;
|
||||
while (cmp == 0 && k > 0)
|
||||
{
|
||||
k--;
|
||||
cmp = (ap[k] > bb) ? 1 : ((ap[k] < bb) ? -1 : 0);
|
||||
bb = MPFR_LIMB_ZERO; /* ensure we consider only once bp[0] & 1 */
|
||||
}
|
||||
if (cmp == 0 && bb != MPFR_LIMB_ZERO)
|
||||
cmp = -1;
|
||||
}
|
||||
else /* an < bn */
|
||||
{
|
||||
k = bn - an;
|
||||
while (cmp == 0 && an > 0)
|
||||
{
|
||||
an --;
|
||||
bb = (extra) ? ((bp[k+an+1] << (GMP_NUMB_BITS - 1)) | (bp[k+an] >> 1))
|
||||
: bp[k+an];
|
||||
if (ap[an] > bb)
|
||||
cmp = 1;
|
||||
else if (ap[an] < bb)
|
||||
cmp = -1;
|
||||
}
|
||||
while (cmp == 0 && k > 0)
|
||||
{
|
||||
k--;
|
||||
bb = (extra) ? ((bp[k+1] << (GMP_NUMB_BITS - 1)) | (bp[k] >> 1))
|
||||
: bp[k];
|
||||
cmp = (bb != MPFR_LIMB_ZERO) ? -1 : 0;
|
||||
}
|
||||
if (cmp == 0 && extra && (bp[0] & MPFR_LIMB_ONE))
|
||||
cmp = -1;
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
|
||||
/* {ap, n} <- {ap, n} - {bp, n} >> extra - cy, with cy = 0 or 1.
|
||||
Return borrow out.
|
||||
*/
|
||||
static mp_limb_t
|
||||
mpfr_mpn_sub_aux (mpfr_limb_ptr ap, mpfr_limb_ptr bp, mp_size_t n,
|
||||
mp_limb_t cy, int extra)
|
||||
{
|
||||
mp_limb_t bb, rp;
|
||||
|
||||
MPFR_ASSERTD (cy <= 1);
|
||||
while (n--)
|
||||
{
|
||||
bb = (extra) ? ((bp[1] << (GMP_NUMB_BITS-1)) | (bp[0] >> 1)) : bp[0];
|
||||
rp = ap[0] - bb - cy;
|
||||
cy = (ap[0] < bb) || (cy && ~rp == MPFR_LIMB_ZERO) ?
|
||||
MPFR_LIMB_ONE : MPFR_LIMB_ZERO;
|
||||
ap[0] = rp;
|
||||
ap ++;
|
||||
bp ++;
|
||||
}
|
||||
MPFR_ASSERTD (cy <= 1);
|
||||
return cy;
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_div (mpfr_ptr q, mpfr_srcptr u, mpfr_srcptr v, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mp_size_t q0size = MPFR_LIMB_SIZE(q); /* number of limbs of destination */
|
||||
mp_size_t usize = MPFR_LIMB_SIZE(u);
|
||||
mp_size_t vsize = MPFR_LIMB_SIZE(v);
|
||||
mp_size_t qsize; /* number of limbs of the computed quotient */
|
||||
mp_size_t qqsize;
|
||||
mp_size_t k;
|
||||
mpfr_limb_ptr q0p = MPFR_MANT(q), qp;
|
||||
mpfr_limb_ptr up = MPFR_MANT(u);
|
||||
mpfr_limb_ptr vp = MPFR_MANT(v);
|
||||
mpfr_limb_ptr ap;
|
||||
mpfr_limb_ptr bp;
|
||||
mp_limb_t qh;
|
||||
mp_limb_t sticky_u = MPFR_LIMB_ZERO;
|
||||
mp_limb_t low_u;
|
||||
mp_limb_t sticky_v = MPFR_LIMB_ZERO;
|
||||
mp_limb_t sticky;
|
||||
mp_limb_t sticky3;
|
||||
mp_limb_t round_bit = MPFR_LIMB_ZERO;
|
||||
mpfr_exp_t qexp;
|
||||
int sign_quotient;
|
||||
int extra_bit;
|
||||
int sh, sh2;
|
||||
int inex;
|
||||
int like_rndz;
|
||||
MPFR_TMP_DECL(marker);
|
||||
|
||||
MPFR_LOG_FUNC (("u[%#R]=%R v[%#R]=%R rnd=%d", u, u, v, v, rnd_mode),
|
||||
("q[%#R]=%R inexact=%d", q, q, inex));
|
||||
|
||||
/**************************************************************************
|
||||
* *
|
||||
* This part of the code deals with special cases *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
if (MPFR_UNLIKELY(MPFR_ARE_SINGULAR(u,v)))
|
||||
{
|
||||
if (MPFR_IS_NAN(u) || MPFR_IS_NAN(v))
|
||||
{
|
||||
MPFR_SET_NAN(q);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
sign_quotient = MPFR_MULT_SIGN( MPFR_SIGN(u) , MPFR_SIGN(v) );
|
||||
MPFR_SET_SIGN(q, sign_quotient);
|
||||
if (MPFR_IS_INF(u))
|
||||
{
|
||||
if (MPFR_IS_INF(v))
|
||||
{
|
||||
MPFR_SET_NAN(q);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_SET_INF(q);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
}
|
||||
else if (MPFR_IS_INF(v))
|
||||
{
|
||||
MPFR_SET_ZERO (q);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
else if (MPFR_IS_ZERO (v))
|
||||
{
|
||||
if (MPFR_IS_ZERO (u))
|
||||
{
|
||||
MPFR_SET_NAN(q);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_SET_INF(q);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (u));
|
||||
MPFR_SET_ZERO (q);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* *
|
||||
* End of the part concerning special values. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
MPFR_TMP_MARK(marker);
|
||||
|
||||
/* set sign */
|
||||
sign_quotient = MPFR_MULT_SIGN( MPFR_SIGN(u) , MPFR_SIGN(v) );
|
||||
MPFR_SET_SIGN(q, sign_quotient);
|
||||
|
||||
/* determine if an extra bit comes from the division, i.e. if the
|
||||
significand of u (as a fraction in [1/2, 1[) is larger than that
|
||||
of v */
|
||||
if (MPFR_LIKELY(up[usize - 1] != vp[vsize - 1]))
|
||||
extra_bit = (up[usize - 1] > vp[vsize - 1]) ? 1 : 0;
|
||||
else /* most significant limbs are equal, must look at further limbs */
|
||||
{
|
||||
mp_size_t l;
|
||||
|
||||
k = usize - 1;
|
||||
l = vsize - 1;
|
||||
while (k != 0 && l != 0 && up[--k] == vp[--l]);
|
||||
/* now k=0 or l=0 or up[k] != vp[l] */
|
||||
if (up[k] > vp[l])
|
||||
extra_bit = 1;
|
||||
else if (up[k] < vp[l])
|
||||
extra_bit = 0;
|
||||
/* now up[k] = vp[l], thus either k=0 or l=0 */
|
||||
else if (l == 0) /* no more divisor limb */
|
||||
extra_bit = 1;
|
||||
else /* k=0: no more dividend limb */
|
||||
extra_bit = mpfr_mpn_cmpzero (vp, l) == 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf ("extra_bit=%d\n", extra_bit);
|
||||
#endif
|
||||
|
||||
/* set exponent */
|
||||
qexp = MPFR_GET_EXP (u) - MPFR_GET_EXP (v) + extra_bit;
|
||||
|
||||
MPFR_UNSIGNED_MINUS_MODULO(sh, MPFR_PREC(q));
|
||||
|
||||
if (MPFR_UNLIKELY(rnd_mode == MPFR_RNDN && sh == 0))
|
||||
{ /* we compute the quotient with one more limb, in order to get
|
||||
the round bit in the quotient, and the remainder only contains
|
||||
sticky bits */
|
||||
qsize = q0size + 1;
|
||||
/* need to allocate memory for the quotient */
|
||||
qp = (mpfr_limb_ptr) MPFR_TMP_ALLOC (qsize * sizeof(mp_limb_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
qsize = q0size;
|
||||
qp = q0p; /* directly put the quotient in the destination */
|
||||
}
|
||||
qqsize = qsize + qsize;
|
||||
|
||||
/* prepare the dividend */
|
||||
ap = (mpfr_limb_ptr) MPFR_TMP_ALLOC (qqsize * sizeof(mp_limb_t));
|
||||
if (MPFR_LIKELY(qqsize > usize)) /* use the full dividend */
|
||||
{
|
||||
k = qqsize - usize; /* k > 0 */
|
||||
MPN_ZERO(ap, k);
|
||||
if (extra_bit)
|
||||
ap[k - 1] = mpn_rshift (ap + k, up, usize, 1);
|
||||
else
|
||||
MPN_COPY(ap + k, up, usize);
|
||||
}
|
||||
else /* truncate the dividend */
|
||||
{
|
||||
k = usize - qqsize;
|
||||
if (extra_bit)
|
||||
sticky_u = mpn_rshift (ap, up + k, qqsize, 1);
|
||||
else
|
||||
MPN_COPY(ap, up + k, qqsize);
|
||||
sticky_u = sticky_u || mpfr_mpn_cmpzero (up, k);
|
||||
}
|
||||
low_u = sticky_u;
|
||||
|
||||
/* now sticky_u is non-zero iff the truncated part of u is non-zero */
|
||||
|
||||
/* prepare the divisor */
|
||||
if (MPFR_LIKELY(vsize >= qsize))
|
||||
{
|
||||
k = vsize - qsize;
|
||||
if (qp != vp)
|
||||
bp = vp + k; /* avoid copying the divisor */
|
||||
else /* need to copy, since mpn_divrem doesn't allow overlap
|
||||
between quotient and divisor, necessarily k = 0
|
||||
since quotient and divisor are the same mpfr variable */
|
||||
{
|
||||
bp = (mpfr_limb_ptr) MPFR_TMP_ALLOC (qsize * sizeof(mp_limb_t));
|
||||
MPN_COPY(bp, vp, vsize);
|
||||
}
|
||||
sticky_v = sticky_v || mpfr_mpn_cmpzero (vp, k);
|
||||
k = 0;
|
||||
}
|
||||
else /* vsize < qsize: small divisor case */
|
||||
{
|
||||
bp = vp;
|
||||
k = qsize - vsize;
|
||||
}
|
||||
|
||||
/* we now can perform the division */
|
||||
qh = mpn_divrem (qp, 0, ap + k, qqsize - k, bp, qsize - k);
|
||||
/* warning: qh may be 1 if u1 == v1, but u < v */
|
||||
#ifdef DEBUG2
|
||||
printf ("q="); mpfr_mpn_print (qp, qsize);
|
||||
printf ("r="); mpfr_mpn_print (ap, qsize);
|
||||
#endif
|
||||
|
||||
k = qsize;
|
||||
sticky_u = sticky_u || mpfr_mpn_cmpzero (ap, k);
|
||||
|
||||
sticky = sticky_u | sticky_v;
|
||||
|
||||
/* now sticky is non-zero iff one of the following holds:
|
||||
(a) the truncated part of u is non-zero
|
||||
(b) the truncated part of v is non-zero
|
||||
(c) the remainder from division is non-zero */
|
||||
|
||||
if (MPFR_LIKELY(qsize == q0size))
|
||||
{
|
||||
sticky3 = qp[0] & MPFR_LIMB_MASK(sh); /* does nothing when sh=0 */
|
||||
sh2 = sh;
|
||||
}
|
||||
else /* qsize = q0size + 1: only happens when rnd_mode=MPFR_RNDN and sh=0 */
|
||||
{
|
||||
MPN_COPY (q0p, qp + 1, q0size);
|
||||
sticky3 = qp[0];
|
||||
sh2 = GMP_NUMB_BITS;
|
||||
}
|
||||
qp[0] ^= sticky3;
|
||||
/* sticky3 contains the truncated bits from the quotient,
|
||||
including the round bit, and 1 <= sh2 <= GMP_NUMB_BITS
|
||||
is the number of bits in sticky3 */
|
||||
inex = (sticky != MPFR_LIMB_ZERO) || (sticky3 != MPFR_LIMB_ZERO);
|
||||
#ifdef DEBUG
|
||||
printf ("sticky=%lu sticky3=%lu inex=%d\n",
|
||||
(unsigned long) sticky, (unsigned long) sticky3, inex);
|
||||
#endif
|
||||
|
||||
like_rndz = rnd_mode == MPFR_RNDZ ||
|
||||
rnd_mode == (sign_quotient < 0 ? MPFR_RNDU : MPFR_RNDD);
|
||||
|
||||
/* to round, we distinguish two cases:
|
||||
(a) vsize <= qsize: we used the full divisor
|
||||
(b) vsize > qsize: the divisor was truncated
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("vsize=%lu qsize=%lu\n",
|
||||
(unsigned long) vsize, (unsigned long) qsize);
|
||||
#endif
|
||||
if (MPFR_LIKELY(vsize <= qsize)) /* use the full divisor */
|
||||
{
|
||||
if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
|
||||
{
|
||||
round_bit = sticky3 & (MPFR_LIMB_ONE << (sh2 - 1));
|
||||
sticky = (sticky3 ^ round_bit) | sticky_u;
|
||||
}
|
||||
else if (like_rndz || inex == 0)
|
||||
sticky = (inex == 0) ? MPFR_LIMB_ZERO : MPFR_LIMB_ONE;
|
||||
else /* round away from zero */
|
||||
sticky = MPFR_LIMB_ONE;
|
||||
goto case_1;
|
||||
}
|
||||
else /* vsize > qsize: need to truncate the divisor */
|
||||
{
|
||||
if (inex == 0)
|
||||
goto truncate;
|
||||
else
|
||||
{
|
||||
/* We know the estimated quotient is an upper bound of the exact
|
||||
quotient (with rounding toward zero), with a difference of at
|
||||
most 2 in qp[0].
|
||||
Thus we can round except when sticky3 is 000...000 or 000...001
|
||||
for directed rounding, and 100...000 or 100...001 for rounding
|
||||
to nearest. (For rounding to nearest, we cannot determine the
|
||||
inexact flag for 000...000 or 000...001.)
|
||||
*/
|
||||
mp_limb_t sticky3orig = sticky3;
|
||||
if (rnd_mode == MPFR_RNDN)
|
||||
{
|
||||
round_bit = sticky3 & (MPFR_LIMB_ONE << (sh2 - 1));
|
||||
sticky3 = sticky3 ^ round_bit;
|
||||
#ifdef DEBUG
|
||||
printf ("rb=%lu sb=%lu\n",
|
||||
(unsigned long) round_bit, (unsigned long) sticky3);
|
||||
#endif
|
||||
}
|
||||
if (sticky3 != MPFR_LIMB_ZERO && sticky3 != MPFR_LIMB_ONE)
|
||||
{
|
||||
sticky = sticky3;
|
||||
goto case_1;
|
||||
}
|
||||
else /* hard case: we have to compare q1 * v0 and r + low(u),
|
||||
where q1 * v0 has qsize + (vsize-qsize) = vsize limbs, and
|
||||
r + low(u) has qsize + (usize-2*qsize) = usize-qsize limbs */
|
||||
{
|
||||
mp_size_t l;
|
||||
mpfr_limb_ptr sp;
|
||||
int cmp_s_r;
|
||||
mp_limb_t qh2;
|
||||
|
||||
sp = (mpfr_limb_ptr) MPFR_TMP_ALLOC (vsize * sizeof(mp_limb_t));
|
||||
k = vsize - qsize;
|
||||
/* sp <- {qp, qsize} * {vp, vsize-qsize} */
|
||||
qp[0] ^= sticky3orig; /* restore original quotient */
|
||||
if (qsize >= k)
|
||||
mpn_mul (sp, qp, qsize, vp, k);
|
||||
else
|
||||
mpn_mul (sp, vp, k, qp, qsize);
|
||||
if (qh)
|
||||
qh2 = mpn_add_n (sp + qsize, sp + qsize, vp, k);
|
||||
else
|
||||
qh2 = (mp_limb_t) 0;
|
||||
qp[0] ^= sticky3orig; /* restore truncated quotient */
|
||||
|
||||
/* compare qh2 + {sp, k + qsize} to {ap, qsize} + low(u) */
|
||||
cmp_s_r = (qh2 != 0) ? 1 : mpn_cmp (sp + k, ap, qsize);
|
||||
if (cmp_s_r == 0) /* compare {sp, k} and low(u) */
|
||||
{
|
||||
cmp_s_r = (usize >= qqsize) ?
|
||||
mpfr_mpn_cmp_aux (sp, k, up, usize - qqsize, extra_bit) :
|
||||
mpfr_mpn_cmpzero (sp, k);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf ("cmp(q*v0,r+u0)=%d\n", cmp_s_r);
|
||||
#endif
|
||||
/* now cmp_s_r > 0 if {sp, vsize} > {ap, qsize} + low(u)
|
||||
cmp_s_r = 0 if {sp, vsize} = {ap, qsize} + low(u)
|
||||
cmp_s_r < 0 if {sp, vsize} < {ap, qsize} + low(u) */
|
||||
if (cmp_s_r <= 0) /* quotient is in [q1, q1+1) */
|
||||
{
|
||||
sticky = (cmp_s_r == 0) ? sticky3 : MPFR_LIMB_ONE;
|
||||
goto case_1;
|
||||
}
|
||||
else /* cmp_s_r > 0, quotient is < q1: to determine if it is
|
||||
in [q1-2,q1-1] or in [q1-1,q1], we need to subtract
|
||||
the low part u0 of the dividend u0 from q*v0 */
|
||||
{
|
||||
mp_limb_t cy = MPFR_LIMB_ZERO;
|
||||
|
||||
/* subtract low(u)>>extra_bit if non-zero */
|
||||
if (qh2 != 0) /* whatever the value of {up, m + k}, it
|
||||
will be smaller than qh2 + {sp, k} */
|
||||
cmp_s_r = 1;
|
||||
else
|
||||
{
|
||||
if (low_u != MPFR_LIMB_ZERO)
|
||||
{
|
||||
mp_size_t m;
|
||||
l = usize - qqsize; /* number of low limbs in u */
|
||||
m = (l > k) ? l - k : 0;
|
||||
cy = (extra_bit) ?
|
||||
(up[m] & MPFR_LIMB_ONE) : MPFR_LIMB_ZERO;
|
||||
if (l >= k) /* u0 has more limbs than s:
|
||||
first look if {up, m} is not zero,
|
||||
and compare {sp, k} and {up + m, k} */
|
||||
{
|
||||
cy = cy || mpfr_mpn_cmpzero (up, m);
|
||||
low_u = cy;
|
||||
cy = mpfr_mpn_sub_aux (sp, up + m, k,
|
||||
cy, extra_bit);
|
||||
}
|
||||
else /* l < k: s has more limbs than u0 */
|
||||
{
|
||||
low_u = MPFR_LIMB_ZERO;
|
||||
if (cy != MPFR_LIMB_ZERO)
|
||||
cy = mpn_sub_1 (sp + k - l - 1, sp + k - l - 1,
|
||||
1, MPFR_LIMB_HIGHBIT);
|
||||
cy = mpfr_mpn_sub_aux (sp + k - l, up, l,
|
||||
cy, extra_bit);
|
||||
}
|
||||
}
|
||||
MPFR_ASSERTD (cy <= 1);
|
||||
cy = mpn_sub_1 (sp + k, sp + k, qsize, cy);
|
||||
/* subtract r */
|
||||
cy += mpn_sub_n (sp + k, sp + k, ap, qsize);
|
||||
MPFR_ASSERTD (cy <= 1);
|
||||
/* now compare {sp, ssize} to v */
|
||||
cmp_s_r = mpn_cmp (sp, vp, vsize);
|
||||
if (cmp_s_r == 0 && low_u != MPFR_LIMB_ZERO)
|
||||
cmp_s_r = 1; /* since in fact we subtracted
|
||||
less than 1 */
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf ("cmp(q*v0-(r+u0),v)=%d\n", cmp_s_r);
|
||||
#endif
|
||||
if (cmp_s_r <= 0) /* q1-1 <= u/v < q1 */
|
||||
{
|
||||
if (sticky3 == MPFR_LIMB_ONE)
|
||||
{ /* q1-1 is either representable (directed rounding),
|
||||
or the middle of two numbers (nearest) */
|
||||
sticky = (cmp_s_r) ? MPFR_LIMB_ONE : MPFR_LIMB_ZERO;
|
||||
goto case_1;
|
||||
}
|
||||
/* now necessarily sticky3=0 */
|
||||
else if (round_bit == MPFR_LIMB_ZERO)
|
||||
{ /* round_bit=0, sticky3=0: q1-1 is exact only
|
||||
when sh=0 */
|
||||
inex = (cmp_s_r || sh) ? -1 : 0;
|
||||
if (rnd_mode == MPFR_RNDN ||
|
||||
(! like_rndz && inex != 0))
|
||||
{
|
||||
inex = 1;
|
||||
goto truncate_check_qh;
|
||||
}
|
||||
else /* round down */
|
||||
goto sub_one_ulp;
|
||||
}
|
||||
else /* sticky3=0, round_bit=1 ==> rounding to nearest */
|
||||
{
|
||||
inex = cmp_s_r;
|
||||
goto truncate;
|
||||
}
|
||||
}
|
||||
else /* q1-2 < u/v < q1-1 */
|
||||
{
|
||||
/* if rnd=MPFR_RNDN, the result is q1 when
|
||||
q1-2 >= q1-2^(sh-1), i.e. sh >= 2,
|
||||
otherwise (sh=1) it is q1-2 */
|
||||
if (rnd_mode == MPFR_RNDN) /* sh > 0 */
|
||||
{
|
||||
/* Case sh=1: sb=0 always, and q1-rb is exactly
|
||||
representable, like q1-rb-2.
|
||||
rb action
|
||||
0 subtract two ulps, inex=-1
|
||||
1 truncate, inex=1
|
||||
|
||||
Case sh>1: one ulp is 2^(sh-1) >= 2
|
||||
rb sb action
|
||||
0 0 truncate, inex=1
|
||||
0 1 truncate, inex=1
|
||||
1 x truncate, inex=-1
|
||||
*/
|
||||
if (sh == 1)
|
||||
{
|
||||
if (round_bit == MPFR_LIMB_ZERO)
|
||||
{
|
||||
inex = -1;
|
||||
sh = 0;
|
||||
goto sub_two_ulp;
|
||||
}
|
||||
else
|
||||
{
|
||||
inex = 1;
|
||||
goto truncate_check_qh;
|
||||
}
|
||||
}
|
||||
else /* sh > 1 */
|
||||
{
|
||||
inex = (round_bit == MPFR_LIMB_ZERO) ? 1 : -1;
|
||||
goto truncate_check_qh;
|
||||
}
|
||||
}
|
||||
else if (like_rndz)
|
||||
{
|
||||
/* the result is down(q1-2), i.e. subtract one
|
||||
ulp if sh > 0, and two ulps if sh=0 */
|
||||
inex = -1;
|
||||
if (sh > 0)
|
||||
goto sub_one_ulp;
|
||||
else
|
||||
goto sub_two_ulp;
|
||||
}
|
||||
/* if round away from zero, the result is up(q1-1),
|
||||
which is q1 unless sh = 0, where it is q1-1 */
|
||||
else
|
||||
{
|
||||
inex = 1;
|
||||
if (sh > 0)
|
||||
goto truncate_check_qh;
|
||||
else /* sh = 0 */
|
||||
goto sub_one_ulp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case_1: /* quotient is in [q1, q1+1),
|
||||
round_bit is the round_bit (0 for directed rounding),
|
||||
sticky the sticky bit */
|
||||
if (like_rndz || (round_bit == MPFR_LIMB_ZERO && sticky == MPFR_LIMB_ZERO))
|
||||
{
|
||||
inex = round_bit == MPFR_LIMB_ZERO && sticky == MPFR_LIMB_ZERO ? 0 : -1;
|
||||
goto truncate;
|
||||
}
|
||||
else if (rnd_mode == MPFR_RNDN) /* sticky <> 0 or round <> 0 */
|
||||
{
|
||||
if (round_bit == MPFR_LIMB_ZERO) /* necessarily sticky <> 0 */
|
||||
{
|
||||
inex = -1;
|
||||
goto truncate;
|
||||
}
|
||||
/* round_bit = 1 */
|
||||
else if (sticky != MPFR_LIMB_ZERO)
|
||||
goto add_one_ulp; /* inex=1 */
|
||||
else /* round_bit=1, sticky=0 */
|
||||
goto even_rule;
|
||||
}
|
||||
else /* round away from zero, sticky <> 0 */
|
||||
goto add_one_ulp; /* with inex=1 */
|
||||
|
||||
sub_two_ulp:
|
||||
/* we cannot subtract MPFR_LIMB_MPFR_LIMB_ONE << (sh+1) since this is
|
||||
undefined for sh = GMP_NUMB_BITS */
|
||||
qh -= mpn_sub_1 (q0p, q0p, q0size, MPFR_LIMB_ONE << sh);
|
||||
/* go through */
|
||||
|
||||
sub_one_ulp:
|
||||
qh -= mpn_sub_1 (q0p, q0p, q0size, MPFR_LIMB_ONE << sh);
|
||||
/* go through truncate_check_qh */
|
||||
|
||||
truncate_check_qh:
|
||||
if (qh)
|
||||
{
|
||||
qexp ++;
|
||||
q0p[q0size - 1] = MPFR_LIMB_HIGHBIT;
|
||||
}
|
||||
goto truncate;
|
||||
|
||||
even_rule: /* has to set inex */
|
||||
inex = (q0p[0] & (MPFR_LIMB_ONE << sh)) ? 1 : -1;
|
||||
if (inex < 0)
|
||||
goto truncate;
|
||||
/* else go through add_one_ulp */
|
||||
|
||||
add_one_ulp:
|
||||
inex = 1; /* always here */
|
||||
if (mpn_add_1 (q0p, q0p, q0size, MPFR_LIMB_ONE << sh))
|
||||
{
|
||||
qexp ++;
|
||||
q0p[q0size - 1] = MPFR_LIMB_HIGHBIT;
|
||||
}
|
||||
|
||||
truncate: /* inex already set */
|
||||
|
||||
MPFR_TMP_FREE(marker);
|
||||
|
||||
/* check for underflow/overflow */
|
||||
if (MPFR_UNLIKELY(qexp > __gmpfr_emax))
|
||||
return mpfr_overflow (q, rnd_mode, sign_quotient);
|
||||
else if (MPFR_UNLIKELY(qexp < __gmpfr_emin))
|
||||
{
|
||||
if (rnd_mode == MPFR_RNDN && ((qexp < __gmpfr_emin - 1) ||
|
||||
(inex >= 0 && mpfr_powerof2_raw (q))))
|
||||
rnd_mode = MPFR_RNDZ;
|
||||
return mpfr_underflow (q, rnd_mode, sign_quotient);
|
||||
}
|
||||
MPFR_SET_EXP(q, qexp);
|
||||
|
||||
inex *= sign_quotient;
|
||||
MPFR_RET (inex);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* mpfr_div_2exp -- divide a floating-point number by a power of two
|
||||
|
||||
Copyright 1999, 2001, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* Obsolete function, use mpfr_div_2ui or mpfr_div_2si instead. */
|
||||
|
||||
#undef mpfr_div_2exp
|
||||
|
||||
int
|
||||
mpfr_div_2exp (mpfr_ptr y, mpfr_srcptr x, unsigned long int n, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
return mpfr_div_2ui (y, x, n, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* mpfr_div_2si -- divide a floating-point number by a power of two
|
||||
|
||||
Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_div_2si (mpfr_ptr y, mpfr_srcptr x, long int n, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R n=%ld rnd=%d", x, x, n, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
return mpfr_set (y, x, rnd_mode);
|
||||
else
|
||||
{
|
||||
mpfr_exp_t exp = MPFR_GET_EXP (x);
|
||||
MPFR_SETRAW (inexact, y, x, exp, rnd_mode);
|
||||
if (MPFR_UNLIKELY( n > 0 && (__gmpfr_emin > MPFR_EMAX_MAX - n ||
|
||||
exp < __gmpfr_emin + n)) )
|
||||
{
|
||||
if (rnd_mode == MPFR_RNDN &&
|
||||
(__gmpfr_emin > MPFR_EMAX_MAX - (n - 1) ||
|
||||
exp < __gmpfr_emin + (n - 1) ||
|
||||
(inexact >= 0 && mpfr_powerof2_raw (y))))
|
||||
rnd_mode = MPFR_RNDZ;
|
||||
return mpfr_underflow (y, rnd_mode, MPFR_SIGN(y));
|
||||
}
|
||||
else if (MPFR_UNLIKELY(n < 0 && (__gmpfr_emax < MPFR_EMIN_MIN - n ||
|
||||
exp > __gmpfr_emax + n)) )
|
||||
return mpfr_overflow (y, rnd_mode, MPFR_SIGN(y));
|
||||
|
||||
MPFR_SET_EXP (y, exp - n);
|
||||
}
|
||||
|
||||
MPFR_RET (inexact);
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/* mpfr_div_2ui -- divide a floating-point number by a power of two
|
||||
|
||||
Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_div_2ui (mpfr_ptr y, mpfr_srcptr x, unsigned long n, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R n=%lu rnd=%d", x, x, n, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
return mpfr_set (y, x, rnd_mode);
|
||||
else
|
||||
{
|
||||
mpfr_exp_t exp = MPFR_GET_EXP (x);
|
||||
mpfr_uexp_t diffexp;
|
||||
|
||||
MPFR_SETRAW (inexact, y, x, exp, rnd_mode);
|
||||
diffexp = (mpfr_uexp_t) exp - (mpfr_uexp_t) (__gmpfr_emin - 1);
|
||||
if (MPFR_UNLIKELY (n >= diffexp)) /* exp - n <= emin - 1 */
|
||||
{
|
||||
if (rnd_mode == MPFR_RNDN &&
|
||||
(n > diffexp || (inexact >= 0 && mpfr_powerof2_raw (y))))
|
||||
rnd_mode = MPFR_RNDZ;
|
||||
return mpfr_underflow (y, rnd_mode, MPFR_SIGN (y));
|
||||
}
|
||||
/* exp - n >= emin (no underflow, no integer overflow) */
|
||||
while (n > LONG_MAX)
|
||||
{
|
||||
n -= LONG_MAX;
|
||||
exp -= LONG_MAX; /* note: signed values */
|
||||
}
|
||||
MPFR_SET_EXP (y, exp - (long) n);
|
||||
}
|
||||
|
||||
MPFR_RET (inexact);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* mpfr_div_d -- divide a multiple precision floating-point number
|
||||
by a machine double precision float
|
||||
|
||||
Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_div_d (mpfr_ptr a, mpfr_srcptr b, double c, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
mpfr_t d;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_LOG_FUNC (("b[%#R]=%R c%.20g rnd=%d", b, b, c, rnd_mode),
|
||||
("a[%#R]=%R", a, a));
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
mpfr_init2 (d, IEEE_DBL_MANT_DIG);
|
||||
inexact = mpfr_set_d (d, c, rnd_mode);
|
||||
MPFR_ASSERTN (inexact == 0);
|
||||
|
||||
mpfr_clear_flags ();
|
||||
inexact = mpfr_div (a, b, d, rnd_mode);
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
|
||||
|
||||
mpfr_clear(d);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (a, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
/* mpfr_div_{ui,si} -- divide a floating-point number by a machine integer
|
||||
|
||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* returns 0 if result exact, non-zero otherwise */
|
||||
int
|
||||
mpfr_div_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
long i;
|
||||
int sh;
|
||||
mp_size_t xn, yn, dif;
|
||||
mp_limb_t *xp, *yp, *tmp, c, d;
|
||||
mpfr_exp_t exp;
|
||||
int inexact, middle = 1, nexttoinf;
|
||||
MPFR_TMP_DECL(marker);
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF (x))
|
||||
{
|
||||
MPFR_SET_INF (y);
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO(x));
|
||||
if (u == 0) /* 0/0 is NaN */
|
||||
{
|
||||
MPFR_SET_NAN(y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_SET_ZERO(y);
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MPFR_UNLIKELY (u <= 1))
|
||||
{
|
||||
if (u < 1)
|
||||
{
|
||||
/* x/0 is Inf since x != 0*/
|
||||
MPFR_SET_INF (y);
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
else /* y = x/1 = x */
|
||||
return mpfr_set (y, x, rnd_mode);
|
||||
}
|
||||
else if (MPFR_UNLIKELY (IS_POW2 (u)))
|
||||
return mpfr_div_2si (y, x, MPFR_INT_CEIL_LOG2 (u), rnd_mode);
|
||||
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
|
||||
MPFR_TMP_MARK (marker);
|
||||
xn = MPFR_LIMB_SIZE (x);
|
||||
yn = MPFR_LIMB_SIZE (y);
|
||||
|
||||
xp = MPFR_MANT (x);
|
||||
yp = MPFR_MANT (y);
|
||||
exp = MPFR_GET_EXP (x);
|
||||
|
||||
dif = yn + 1 - xn;
|
||||
|
||||
/* we need to store yn+1 = xn + dif limbs of the quotient */
|
||||
/* don't use tmp=yp since the mpn_lshift call below requires yp >= tmp+1 */
|
||||
tmp = (mp_limb_t*) MPFR_TMP_ALLOC ((yn + 1) * BYTES_PER_MP_LIMB);
|
||||
|
||||
c = (mp_limb_t) u;
|
||||
MPFR_ASSERTN (u == c);
|
||||
if (dif >= 0)
|
||||
c = mpn_divrem_1 (tmp, dif, xp, xn, c); /* used all the dividend */
|
||||
else /* dif < 0 i.e. xn > yn, don't use the (-dif) low limbs from x */
|
||||
c = mpn_divrem_1 (tmp, 0, xp - dif, yn + 1, c);
|
||||
|
||||
inexact = (c != 0);
|
||||
|
||||
/* First pass in estimating next bit of the quotient, in case of RNDN *
|
||||
* In case we just have the right number of bits (postpone this ?), *
|
||||
* we need to check whether the remainder is more or less than half *
|
||||
* the divisor. The test must be performed with a subtraction, so as *
|
||||
* to prevent carries. */
|
||||
|
||||
if (MPFR_LIKELY (rnd_mode == MPFR_RNDN))
|
||||
{
|
||||
if (c < (mp_limb_t) u - c) /* We have u > c */
|
||||
middle = -1;
|
||||
else if (c > (mp_limb_t) u - c)
|
||||
middle = 1;
|
||||
else
|
||||
middle = 0; /* exactly in the middle */
|
||||
}
|
||||
|
||||
/* If we believe that we are right in the middle or exact, we should check
|
||||
that we did not neglect any word of x (division large / 1 -> small). */
|
||||
|
||||
for (i=0; ((inexact == 0) || (middle == 0)) && (i < -dif); i++)
|
||||
if (xp[i])
|
||||
inexact = middle = 1; /* larger than middle */
|
||||
|
||||
/*
|
||||
If the high limb of the result is 0 (xp[xn-1] < u), remove it.
|
||||
Otherwise, compute the left shift to be performed to normalize.
|
||||
In the latter case, we discard some low bits computed. They
|
||||
contain information useful for the rounding, hence the updating
|
||||
of middle and inexact.
|
||||
*/
|
||||
|
||||
if (tmp[yn] == 0)
|
||||
{
|
||||
MPN_COPY(yp, tmp, yn);
|
||||
exp -= GMP_NUMB_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
int shlz;
|
||||
|
||||
count_leading_zeros (shlz, tmp[yn]);
|
||||
|
||||
/* shift left to normalize */
|
||||
if (MPFR_LIKELY (shlz != 0))
|
||||
{
|
||||
mp_limb_t w = tmp[0] << shlz;
|
||||
|
||||
mpn_lshift (yp, tmp + 1, yn, shlz);
|
||||
yp[0] += tmp[0] >> (GMP_NUMB_BITS - shlz);
|
||||
|
||||
if (w > (MPFR_LIMB_ONE << (GMP_NUMB_BITS - 1)))
|
||||
{ middle = 1; }
|
||||
else if (w < (MPFR_LIMB_ONE << (GMP_NUMB_BITS - 1)))
|
||||
{ middle = -1; }
|
||||
else
|
||||
{ middle = (c != 0); }
|
||||
|
||||
inexact = inexact || (w != 0);
|
||||
exp -= shlz;
|
||||
}
|
||||
else
|
||||
{ /* this happens only if u == 1 and xp[xn-1] >=
|
||||
1<<(GMP_NUMB_BITS-1). It might be better to handle the
|
||||
u == 1 case seperately ?
|
||||
*/
|
||||
|
||||
MPN_COPY (yp, tmp + 1, yn);
|
||||
}
|
||||
}
|
||||
|
||||
MPFR_UNSIGNED_MINUS_MODULO (sh, MPFR_PREC (y));
|
||||
/* it remains sh bits in less significant limb of y */
|
||||
|
||||
d = *yp & MPFR_LIMB_MASK (sh);
|
||||
*yp ^= d; /* set to zero lowest sh bits */
|
||||
|
||||
MPFR_TMP_FREE (marker);
|
||||
|
||||
if (exp < __gmpfr_emin - 1)
|
||||
return mpfr_underflow (y, rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode,
|
||||
MPFR_SIGN (y));
|
||||
|
||||
if (MPFR_UNLIKELY (d == 0 && inexact == 0))
|
||||
nexttoinf = 0; /* result is exact */
|
||||
else
|
||||
{
|
||||
MPFR_UPDATE2_RND_MODE(rnd_mode, MPFR_SIGN (y));
|
||||
switch (rnd_mode)
|
||||
{
|
||||
case MPFR_RNDZ:
|
||||
inexact = - MPFR_INT_SIGN (y); /* result is inexact */
|
||||
nexttoinf = 0;
|
||||
break;
|
||||
|
||||
case MPFR_RNDA:
|
||||
inexact = MPFR_INT_SIGN (y);
|
||||
nexttoinf = 1;
|
||||
break;
|
||||
|
||||
default: /* should be MPFR_RNDN */
|
||||
MPFR_ASSERTD (rnd_mode == MPFR_RNDN);
|
||||
/* We have one more significant bit in yn. */
|
||||
if (sh && d < (MPFR_LIMB_ONE << (sh - 1)))
|
||||
{
|
||||
inexact = - MPFR_INT_SIGN (y);
|
||||
nexttoinf = 0;
|
||||
}
|
||||
else if (sh && d > (MPFR_LIMB_ONE << (sh - 1)))
|
||||
{
|
||||
inexact = MPFR_INT_SIGN (y);
|
||||
nexttoinf = 1;
|
||||
}
|
||||
else /* sh = 0 or d = 1 << (sh-1) */
|
||||
{
|
||||
/* The first case is "false" even rounding (significant bits
|
||||
indicate even rounding, but the result is inexact, so up) ;
|
||||
The second case is the case where middle should be used to
|
||||
decide the direction of rounding (no further bit computed) ;
|
||||
The third is the true even rounding.
|
||||
*/
|
||||
if ((sh && inexact) || (!sh && middle > 0) ||
|
||||
(!inexact && *yp & (MPFR_LIMB_ONE << sh)))
|
||||
{
|
||||
inexact = MPFR_INT_SIGN (y);
|
||||
nexttoinf = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
inexact = - MPFR_INT_SIGN (y);
|
||||
nexttoinf = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nexttoinf &&
|
||||
MPFR_UNLIKELY (mpn_add_1 (yp, yp, yn, MPFR_LIMB_ONE << sh)))
|
||||
{
|
||||
exp++;
|
||||
yp[yn-1] = MPFR_LIMB_HIGHBIT;
|
||||
}
|
||||
|
||||
/* Set the exponent. Warning! One may still have an underflow. */
|
||||
MPFR_EXP (y) = exp;
|
||||
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
||||
|
||||
int mpfr_div_si (mpfr_ptr y, mpfr_srcptr x, long int u, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (u >= 0)
|
||||
res = mpfr_div_ui (y, x, u, rnd_mode);
|
||||
else
|
||||
{
|
||||
res = -mpfr_div_ui (y, x, -u, MPFR_INVERT_RND (rnd_mode));
|
||||
MPFR_CHANGE_SIGN (y);
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* mpfr_dump -- Dump a float to stdout.
|
||||
|
||||
Copyright 1999, 2001, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
void
|
||||
mpfr_dump (mpfr_srcptr u)
|
||||
{
|
||||
mpfr_print_binary(u);
|
||||
putchar('\n');
|
||||
}
|
|
@ -0,0 +1,316 @@
|
|||
/* mpfr_eint, mpfr_eint1 -- the exponential integral
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* eint1(x) = -gamma - log(x) - sum((-1)^k*z^k/k/k!, k=1..infinity) for x > 0
|
||||
= - eint(-x) for x < 0
|
||||
where
|
||||
eint (x) = gamma + log(x) + sum(z^k/k/k!, k=1..infinity) for x > 0
|
||||
eint (x) is undefined for x < 0.
|
||||
*/
|
||||
|
||||
/* compute in y an approximation of sum(x^k/k/k!, k=1..infinity),
|
||||
and return e such that the absolute error is bound by 2^e ulp(y) */
|
||||
static mpfr_exp_t
|
||||
mpfr_eint_aux (mpfr_t y, mpfr_srcptr x)
|
||||
{
|
||||
mpfr_t eps; /* dynamic (absolute) error bound on t */
|
||||
mpfr_t erru, errs;
|
||||
mpz_t m, s, t, u;
|
||||
mpfr_exp_t e, sizeinbase;
|
||||
mpfr_prec_t w = MPFR_PREC(y);
|
||||
unsigned long k;
|
||||
MPFR_GROUP_DECL (group);
|
||||
|
||||
/* for |x| <= 1, we have S := sum(x^k/k/k!, k=1..infinity) = x + R(x)
|
||||
where |R(x)| <= (x/2)^2/(1-x/2) <= 2*(x/2)^2
|
||||
thus |R(x)/x| <= |x|/2
|
||||
thus if |x| <= 2^(-PREC(y)) we have |S - o(x)| <= ulp(y) */
|
||||
|
||||
if (MPFR_GET_EXP(x) <= - (mpfr_exp_t) w)
|
||||
{
|
||||
mpfr_set (y, x, MPFR_RNDN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpz_init (s); /* initializes to 0 */
|
||||
mpz_init (t);
|
||||
mpz_init (u);
|
||||
mpz_init (m);
|
||||
MPFR_GROUP_INIT_3 (group, 31, eps, erru, errs);
|
||||
e = mpfr_get_z_2exp (m, x); /* x = m * 2^e */
|
||||
MPFR_ASSERTD (mpz_sizeinbase (m, 2) == MPFR_PREC (x));
|
||||
if (MPFR_PREC (x) > w)
|
||||
{
|
||||
e += MPFR_PREC (x) - w;
|
||||
mpz_tdiv_q_2exp (m, m, MPFR_PREC (x) - w);
|
||||
}
|
||||
/* remove trailing zeroes from m: this will speed up much cases where
|
||||
x is a small integer divided by a power of 2 */
|
||||
k = mpz_scan1 (m, 0);
|
||||
mpz_tdiv_q_2exp (m, m, k);
|
||||
e += k;
|
||||
/* initialize t to 2^w */
|
||||
mpz_set_ui (t, 1);
|
||||
mpz_mul_2exp (t, t, w);
|
||||
mpfr_set_ui (eps, 0, MPFR_RNDN); /* eps[0] = 0 */
|
||||
mpfr_set_ui (errs, 0, MPFR_RNDN);
|
||||
for (k = 1;; k++)
|
||||
{
|
||||
/* let eps[k] be the absolute error on t[k]:
|
||||
since t[k] = trunc(t[k-1]*m*2^e/k), we have
|
||||
eps[k+1] <= 1 + eps[k-1]*m*2^e/k + t[k-1]*m*2^(1-w)*2^e/k
|
||||
= 1 + (eps[k-1] + t[k-1]*2^(1-w))*m*2^e/k
|
||||
= 1 + (eps[k-1]*2^(w-1) + t[k-1])*2^(1-w)*m*2^e/k */
|
||||
mpfr_mul_2ui (eps, eps, w - 1, MPFR_RNDU);
|
||||
mpfr_add_z (eps, eps, t, MPFR_RNDU);
|
||||
MPFR_MPZ_SIZEINBASE2 (sizeinbase, m);
|
||||
mpfr_mul_2si (eps, eps, sizeinbase - (w - 1) + e, MPFR_RNDU);
|
||||
mpfr_div_ui (eps, eps, k, MPFR_RNDU);
|
||||
mpfr_add_ui (eps, eps, 1, MPFR_RNDU);
|
||||
mpz_mul (t, t, m);
|
||||
if (e < 0)
|
||||
mpz_tdiv_q_2exp (t, t, -e);
|
||||
else
|
||||
mpz_mul_2exp (t, t, e);
|
||||
mpz_tdiv_q_ui (t, t, k);
|
||||
mpz_tdiv_q_ui (u, t, k);
|
||||
mpz_add (s, s, u);
|
||||
/* the absolute error on u is <= 1 + eps[k]/k */
|
||||
mpfr_div_ui (erru, eps, k, MPFR_RNDU);
|
||||
mpfr_add_ui (erru, erru, 1, MPFR_RNDU);
|
||||
/* and that on s is the sum of all errors on u */
|
||||
mpfr_add (errs, errs, erru, MPFR_RNDU);
|
||||
/* we are done when t is smaller than errs */
|
||||
if (mpz_sgn (t) == 0)
|
||||
sizeinbase = 0;
|
||||
else
|
||||
MPFR_MPZ_SIZEINBASE2 (sizeinbase, t);
|
||||
if (sizeinbase < MPFR_GET_EXP (errs))
|
||||
break;
|
||||
}
|
||||
/* the truncation error is bounded by (|t|+eps)/k*(|x|/k + |x|^2/k^2 + ...)
|
||||
<= (|t|+eps)/k*|x|/(k-|x|) */
|
||||
mpz_abs (t, t);
|
||||
mpfr_add_z (eps, eps, t, MPFR_RNDU);
|
||||
mpfr_div_ui (eps, eps, k, MPFR_RNDU);
|
||||
mpfr_abs (erru, x, MPFR_RNDU); /* |x| */
|
||||
mpfr_mul (eps, eps, erru, MPFR_RNDU);
|
||||
mpfr_ui_sub (erru, k, erru, MPFR_RNDD);
|
||||
if (MPFR_IS_NEG (erru))
|
||||
{
|
||||
/* the truncated series does not converge, return fail */
|
||||
e = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
mpfr_div (eps, eps, erru, MPFR_RNDU);
|
||||
mpfr_add (errs, errs, eps, MPFR_RNDU);
|
||||
mpfr_set_z (y, s, MPFR_RNDN);
|
||||
mpfr_div_2ui (y, y, w, MPFR_RNDN);
|
||||
/* errs was an absolute error bound on s. We must convert it to an error
|
||||
in terms of ulp(y). Since ulp(y) = 2^(EXP(y)-PREC(y)), we must
|
||||
divide the error by 2^(EXP(y)-PREC(y)), but since we divided also
|
||||
y by 2^w = 2^PREC(y), we must simply divide by 2^EXP(y). */
|
||||
e = MPFR_GET_EXP (errs) - MPFR_GET_EXP (y);
|
||||
}
|
||||
MPFR_GROUP_CLEAR (group);
|
||||
mpz_clear (s);
|
||||
mpz_clear (t);
|
||||
mpz_clear (u);
|
||||
mpz_clear (m);
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Return in y an approximation of Ei(x) using the asymptotic expansion:
|
||||
Ei(x) = exp(x)/x * (1 + 1/x + 2/x^2 + ... + k!/x^k + ...)
|
||||
Assumes x >= PREC(y) * log(2).
|
||||
Returns the error bound in terms of ulp(y).
|
||||
*/
|
||||
static mpfr_exp_t
|
||||
mpfr_eint_asympt (mpfr_ptr y, mpfr_srcptr x)
|
||||
{
|
||||
mpfr_prec_t p = MPFR_PREC(y);
|
||||
mpfr_t invx, t, err;
|
||||
unsigned long k;
|
||||
mpfr_exp_t err_exp;
|
||||
|
||||
mpfr_init2 (t, p);
|
||||
mpfr_init2 (invx, p);
|
||||
mpfr_init2 (err, 31); /* error in ulps on y */
|
||||
mpfr_ui_div (invx, 1, x, MPFR_RNDN); /* invx = 1/x*(1+u) with |u|<=2^(1-p) */
|
||||
mpfr_set_ui (t, 1, MPFR_RNDN); /* exact */
|
||||
mpfr_set (y, t, MPFR_RNDN);
|
||||
mpfr_set_ui (err, 0, MPFR_RNDN);
|
||||
for (k = 1; MPFR_GET_EXP(t) + (mpfr_exp_t) p > MPFR_GET_EXP(y); k++)
|
||||
{
|
||||
mpfr_mul (t, t, invx, MPFR_RNDN); /* 2 more roundings */
|
||||
mpfr_mul_ui (t, t, k, MPFR_RNDN); /* 1 more rounding: t = k!/x^k*(1+u)^e
|
||||
with u=2^{-p} and |e| <= 3*k */
|
||||
/* we use the fact that |(1+u)^n-1| <= 2*|n*u| for |n*u| <= 1, thus
|
||||
the error on t is less than 6*k*2^{-p}*t <= 6*k*ulp(t) */
|
||||
/* err is in terms of ulp(y): transform it in terms of ulp(t) */
|
||||
mpfr_mul_2si (err, err, MPFR_GET_EXP(y) - MPFR_GET_EXP(t), MPFR_RNDU);
|
||||
mpfr_add_ui (err, err, 6 * k, MPFR_RNDU);
|
||||
/* transform back in terms of ulp(y) */
|
||||
mpfr_div_2si (err, err, MPFR_GET_EXP(y) - MPFR_GET_EXP(t), MPFR_RNDU);
|
||||
mpfr_add (y, y, t, MPFR_RNDN);
|
||||
}
|
||||
/* add the truncation error bounded by ulp(y): 1 ulp */
|
||||
mpfr_mul (y, y, invx, MPFR_RNDN); /* err <= 2*err + 3/2 */
|
||||
mpfr_exp (t, x, MPFR_RNDN); /* err(t) <= 1/2*ulp(t) */
|
||||
mpfr_mul (y, y, t, MPFR_RNDN); /* again: err <= 2*err + 3/2 */
|
||||
mpfr_mul_2ui (err, err, 2, MPFR_RNDU);
|
||||
mpfr_add_ui (err, err, 8, MPFR_RNDU);
|
||||
err_exp = MPFR_GET_EXP(err);
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (invx);
|
||||
mpfr_clear (err);
|
||||
return err_exp;
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_eint (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd)
|
||||
{
|
||||
int inex;
|
||||
mpfr_t tmp, ump;
|
||||
mpfr_exp_t err, te;
|
||||
mpfr_prec_t prec;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd),
|
||||
("y[%#R]=%R inexact=%d", y, y, inex));
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
/* exp(NaN) = exp(-Inf) = NaN */
|
||||
if (MPFR_IS_NAN (x) || (MPFR_IS_INF (x) && MPFR_IS_NEG(x)))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
/* eint(+inf) = +inf */
|
||||
else if (MPFR_IS_INF (x))
|
||||
{
|
||||
MPFR_SET_INF(y);
|
||||
MPFR_SET_POS(y);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
else /* eint(+/-0) = -Inf */
|
||||
{
|
||||
MPFR_SET_INF(y);
|
||||
MPFR_SET_NEG(y);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* eint(x) = NaN for x < 0 */
|
||||
if (MPFR_IS_NEG(x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* Since eint(x) >= exp(x)/x, we have log2(eint(x)) >= (x-log(x))/log(2).
|
||||
Let's compute k <= (x-log(x))/log(2) in a low precision. If k >= emax,
|
||||
then log2(eint(x)) >= emax, and eint(x) >= 2^emax, i.e. it overflows. */
|
||||
mpfr_init2 (tmp, 64);
|
||||
mpfr_init2 (ump, 64);
|
||||
mpfr_log (tmp, x, MPFR_RNDU);
|
||||
mpfr_sub (ump, x, tmp, MPFR_RNDD);
|
||||
mpfr_const_log2 (tmp, MPFR_RNDU);
|
||||
mpfr_div (ump, ump, tmp, MPFR_RNDD);
|
||||
/* FIXME: We really need mpfr_set_exp_t and mpfr_cmpfr_exp_t functions. */
|
||||
MPFR_ASSERTN (MPFR_EMAX_MAX <= LONG_MAX);
|
||||
if (mpfr_cmp_ui (ump, __gmpfr_emax) >= 0)
|
||||
{
|
||||
mpfr_clear (tmp);
|
||||
mpfr_clear (ump);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_overflow (y, rnd, 1);
|
||||
}
|
||||
|
||||
/* Init stuff */
|
||||
prec = MPFR_PREC (y) + 2 * MPFR_INT_CEIL_LOG2 (MPFR_PREC (y)) + 6;
|
||||
|
||||
/* eint() has a root 0.37250741078136663446..., so if x is near,
|
||||
already take more bits */
|
||||
if (MPFR_GET_EXP(x) == -1) /* 1/4 <= x < 1/2 */
|
||||
{
|
||||
double d;
|
||||
d = mpfr_get_d (x, MPFR_RNDN) - 0.37250741078136663;
|
||||
d = (d == 0.0) ? -53 : __gmpfr_ceil_log2 (d);
|
||||
prec += -d;
|
||||
}
|
||||
|
||||
mpfr_set_prec (tmp, prec);
|
||||
mpfr_set_prec (ump, prec);
|
||||
|
||||
MPFR_ZIV_INIT (loop, prec); /* Initialize the ZivLoop controler */
|
||||
for (;;) /* Infinite loop */
|
||||
{
|
||||
/* We need that the smallest value of k!/x^k is smaller than 2^(-p).
|
||||
The minimum is obtained for x=k, and it is smaller than e*sqrt(x)/e^x
|
||||
for x>=1. */
|
||||
if (MPFR_GET_EXP (x) > 0 && mpfr_cmp_d (x, ((double) prec +
|
||||
0.5 * (double) MPFR_GET_EXP (x)) * LOG2 + 1.0) > 0)
|
||||
err = mpfr_eint_asympt (tmp, x);
|
||||
else
|
||||
{
|
||||
err = mpfr_eint_aux (tmp, x); /* error <= 2^err ulp(tmp) */
|
||||
te = MPFR_GET_EXP(tmp);
|
||||
mpfr_const_euler (ump, MPFR_RNDN); /* 0.577 -> EXP(ump)=0 */
|
||||
mpfr_add (tmp, tmp, ump, MPFR_RNDN);
|
||||
/* error <= 1/2 + 1/2*2^(EXP(ump)-EXP(tmp)) + 2^(te-EXP(tmp)+err)
|
||||
<= 1/2 + 2^(MAX(EXP(ump), te+err+1) - EXP(tmp))
|
||||
<= 2^(MAX(0, 1 + MAX(EXP(ump), te+err+1) - EXP(tmp))) */
|
||||
err = MAX(1, te + err + 2) - MPFR_GET_EXP(tmp);
|
||||
err = MAX(0, err);
|
||||
te = MPFR_GET_EXP(tmp);
|
||||
mpfr_log (ump, x, MPFR_RNDN);
|
||||
mpfr_add (tmp, tmp, ump, MPFR_RNDN);
|
||||
/* same formula as above, except now EXP(ump) is not 0 */
|
||||
err += te + 1;
|
||||
if (MPFR_LIKELY (!MPFR_IS_ZERO (ump)))
|
||||
err = MAX (MPFR_GET_EXP (ump), err);
|
||||
err = MAX(0, err - MPFR_GET_EXP (tmp));
|
||||
}
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - err, MPFR_PREC (y), rnd)))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, prec); /* Increase used precision */
|
||||
mpfr_set_prec (tmp, prec);
|
||||
mpfr_set_prec (ump, prec);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop); /* Free the ZivLoop Controler */
|
||||
|
||||
inex = mpfr_set (y, tmp, rnd); /* Set y to the computed value */
|
||||
mpfr_clear (tmp);
|
||||
mpfr_clear (ump);
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inex, rnd);
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/* mpfr_eq -- Compare two floats up to a specified bit #.
|
||||
|
||||
Copyright 1999, 2001, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* return non-zero if the first n_bits bits of u, v are equal,
|
||||
0 otherwise */
|
||||
int
|
||||
mpfr_eq (mpfr_srcptr u, mpfr_srcptr v, unsigned long int n_bits)
|
||||
{
|
||||
mpfr_limb_srcptr up, vp;
|
||||
mp_size_t usize, vsize, size, i;
|
||||
mpfr_exp_t uexp, vexp;
|
||||
int k;
|
||||
|
||||
if (MPFR_ARE_SINGULAR(u, v))
|
||||
{
|
||||
if (MPFR_IS_NAN(u) || MPFR_IS_NAN(v))
|
||||
return 0; /* non equal */
|
||||
else if (MPFR_IS_INF(u) && MPFR_IS_INF(v))
|
||||
return (MPFR_SIGN(u) == MPFR_SIGN(v));
|
||||
else if (MPFR_IS_ZERO(u) && MPFR_IS_ZERO(v))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 1. Are the signs different? */
|
||||
if (MPFR_SIGN(u) != MPFR_SIGN(v))
|
||||
return 0;
|
||||
|
||||
uexp = MPFR_GET_EXP (u);
|
||||
vexp = MPFR_GET_EXP (v);
|
||||
|
||||
/* 2. Are the exponents different? */
|
||||
if (uexp != vexp)
|
||||
return 0; /* no bit agree */
|
||||
|
||||
usize = (MPFR_PREC(u) - 1) / GMP_NUMB_BITS + 1;
|
||||
vsize = (MPFR_PREC(v) - 1) / GMP_NUMB_BITS + 1;
|
||||
|
||||
if (vsize > usize) /* exchange u and v */
|
||||
{
|
||||
up = MPFR_MANT(v);
|
||||
vp = MPFR_MANT(u);
|
||||
size = vsize;
|
||||
vsize = usize;
|
||||
usize = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
up = MPFR_MANT(u);
|
||||
vp = MPFR_MANT(v);
|
||||
}
|
||||
|
||||
/* now usize >= vsize */
|
||||
MPFR_ASSERTD(usize >= vsize);
|
||||
|
||||
if (usize > vsize)
|
||||
{
|
||||
if ((unsigned long) vsize * GMP_NUMB_BITS < n_bits)
|
||||
{
|
||||
/* check if low min(PREC(u), n_bits) - (vsize * GMP_NUMB_BITS)
|
||||
bits from u are non-zero */
|
||||
unsigned long remains = n_bits - (vsize * GMP_NUMB_BITS);
|
||||
k = usize - vsize - 1;
|
||||
while (k >= 0 && remains >= GMP_NUMB_BITS && !up[k])
|
||||
{
|
||||
k--;
|
||||
remains -= GMP_NUMB_BITS;
|
||||
}
|
||||
/* now either k < 0: all low bits from u are zero
|
||||
or remains < GMP_NUMB_BITS: check high bits from up[k]
|
||||
or up[k] <> 0: different */
|
||||
if (k >= 0 && (((remains < GMP_NUMB_BITS) &&
|
||||
(up[k] >> (GMP_NUMB_BITS - remains))) ||
|
||||
(remains >= GMP_NUMB_BITS && up[k])))
|
||||
return 0; /* surely too different */
|
||||
}
|
||||
size = vsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = usize;
|
||||
}
|
||||
|
||||
/* now size = min (usize, vsize) */
|
||||
|
||||
/* If size is too large wrt n_bits, reduce it to look only at the
|
||||
high n_bits bits.
|
||||
Otherwise, if n_bits > size * GMP_NUMB_BITS, reduce n_bits to
|
||||
size * GMP_NUMB_BITS, since the extra low bits of one of the
|
||||
operands have already been check above. */
|
||||
if ((unsigned long) size > 1 + (n_bits - 1) / GMP_NUMB_BITS)
|
||||
size = 1 + (n_bits - 1) / GMP_NUMB_BITS;
|
||||
else if (n_bits > (unsigned long) size * GMP_NUMB_BITS)
|
||||
n_bits = size * GMP_NUMB_BITS;
|
||||
|
||||
up += usize - size;
|
||||
vp += vsize - size;
|
||||
|
||||
for (i = size - 1; i > 0 && n_bits >= GMP_NUMB_BITS; i--)
|
||||
{
|
||||
if (up[i] != vp[i])
|
||||
return 0;
|
||||
n_bits -= GMP_NUMB_BITS;
|
||||
}
|
||||
|
||||
/* now either i=0 or n_bits<GMP_NUMB_BITS */
|
||||
|
||||
/* since n_bits <= size * GMP_NUMB_BITS before the above for-loop,
|
||||
we have the invariant n_bits <= (i+1) * GMP_NUMB_BITS, thus
|
||||
we always have n_bits <= GMP_NUMB_BITS here */
|
||||
MPFR_ASSERTD(n_bits <= GMP_NUMB_BITS);
|
||||
|
||||
if (n_bits & (GMP_NUMB_BITS - 1))
|
||||
return (up[i] >> (GMP_NUMB_BITS - (n_bits & (GMP_NUMB_BITS - 1))) ==
|
||||
vp[i] >> (GMP_NUMB_BITS - (n_bits & (GMP_NUMB_BITS - 1))));
|
||||
else
|
||||
return (up[i] == vp[i]);
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
/* mpfr_erf -- error function of a floating-point number
|
||||
|
||||
Copyright 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by Ludovic Meunier and Paul Zimmermann.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
#define EXP1 2.71828182845904523536 /* exp(1) */
|
||||
|
||||
static int mpfr_erf_0 (mpfr_ptr, mpfr_srcptr, double, mpfr_rnd_t);
|
||||
|
||||
int
|
||||
mpfr_erf (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t xf;
|
||||
int inex, large;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inex));
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF (x)) /* erf(+inf) = +1, erf(-inf) = -1 */
|
||||
return mpfr_set_si (y, MPFR_INT_SIGN (x), MPFR_RNDN);
|
||||
else /* erf(+0) = +0, erf(-0) = -0 */
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (x));
|
||||
return mpfr_set (y, x, MPFR_RNDN); /* should keep the sign of x */
|
||||
}
|
||||
}
|
||||
|
||||
/* now x is neither NaN, Inf nor 0 */
|
||||
|
||||
/* first try expansion at x=0 when x is small, or asymptotic expansion
|
||||
where x is large */
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* around x=0, we have erf(x) = 2x/sqrt(Pi) (1 - x^2/3 + ...),
|
||||
with 1 - x^2/3 <= sqrt(Pi)*erf(x)/2/x <= 1 for x >= 0. This means that
|
||||
if x^2/3 < 2^(-PREC(y)-1) we can decide of the correct rounding,
|
||||
unless we have a worst-case for 2x/sqrt(Pi). */
|
||||
if (MPFR_EXP(x) < - (mpfr_exp_t) (MPFR_PREC(y) / 2))
|
||||
{
|
||||
/* we use 2x/sqrt(Pi) (1 - x^2/3) <= erf(x) <= 2x/sqrt(Pi) for x > 0
|
||||
and 2x/sqrt(Pi) <= erf(x) <= 2x/sqrt(Pi) (1 - x^2/3) for x < 0.
|
||||
In both cases |2x/sqrt(Pi) (1 - x^2/3)| <= |erf(x)| <= |2x/sqrt(Pi)|.
|
||||
We will compute l and h such that l <= |2x/sqrt(Pi) (1 - x^2/3)|
|
||||
and |2x/sqrt(Pi)| <= h. If l and h round to the same value to
|
||||
precision PREC(y) and rounding rnd_mode, then we are done. */
|
||||
mpfr_t l, h; /* lower and upper bounds for erf(x) */
|
||||
int ok, inex2;
|
||||
|
||||
mpfr_init2 (l, MPFR_PREC(y) + 17);
|
||||
mpfr_init2 (h, MPFR_PREC(y) + 17);
|
||||
/* first compute l */
|
||||
mpfr_mul (l, x, x, MPFR_RNDU);
|
||||
mpfr_div_ui (l, l, 3, MPFR_RNDU); /* upper bound on x^2/3 */
|
||||
mpfr_ui_sub (l, 1, l, MPFR_RNDZ); /* lower bound on 1 - x^2/3 */
|
||||
mpfr_const_pi (h, MPFR_RNDU); /* upper bound of Pi */
|
||||
mpfr_sqrt (h, h, MPFR_RNDU); /* upper bound on sqrt(Pi) */
|
||||
mpfr_div (l, l, h, MPFR_RNDZ); /* lower bound on 1/sqrt(Pi) (1 - x^2/3) */
|
||||
mpfr_mul_2ui (l, l, 1, MPFR_RNDZ); /* 2/sqrt(Pi) (1 - x^2/3) */
|
||||
mpfr_mul (l, l, x, MPFR_RNDZ); /* |l| is a lower bound on
|
||||
|2x/sqrt(Pi) (1 - x^2/3)| */
|
||||
/* now compute h */
|
||||
mpfr_const_pi (h, MPFR_RNDD); /* lower bound on Pi */
|
||||
mpfr_sqrt (h, h, MPFR_RNDD); /* lower bound on sqrt(Pi) */
|
||||
mpfr_div_2ui (h, h, 1, MPFR_RNDD); /* lower bound on sqrt(Pi)/2 */
|
||||
/* since sqrt(Pi)/2 < 1, the following should not underflow */
|
||||
mpfr_div (h, x, h, MPFR_IS_POS(x) ? MPFR_RNDU : MPFR_RNDD);
|
||||
/* round l and h to precision PREC(y) */
|
||||
inex = mpfr_prec_round (l, MPFR_PREC(y), rnd_mode);
|
||||
inex2 = mpfr_prec_round (h, MPFR_PREC(y), rnd_mode);
|
||||
/* Caution: we also need inex=inex2 (inex might be 0). */
|
||||
ok = SAME_SIGN (inex, inex2) && mpfr_cmp (l, h) == 0;
|
||||
if (ok)
|
||||
mpfr_set (y, h, rnd_mode);
|
||||
mpfr_clear (l);
|
||||
mpfr_clear (h);
|
||||
if (ok)
|
||||
goto end;
|
||||
/* this test can still fail for small precision, for example
|
||||
for x=-0.100E-2 with a target precision of 3 bits, since
|
||||
the error term x^2/3 is not that small. */
|
||||
}
|
||||
|
||||
mpfr_init2 (xf, 53);
|
||||
mpfr_const_log2 (xf, MPFR_RNDU);
|
||||
mpfr_div (xf, x, xf, MPFR_RNDZ); /* round to zero ensures we get a lower
|
||||
bound of |x/log(2)| */
|
||||
mpfr_mul (xf, xf, x, MPFR_RNDZ);
|
||||
large = mpfr_cmp_ui (xf, MPFR_PREC (y) + 1) > 0;
|
||||
mpfr_clear (xf);
|
||||
|
||||
/* when x goes to infinity, we have erf(x) = 1 - 1/sqrt(Pi)/exp(x^2)/x + ...
|
||||
and |erf(x) - 1| <= exp(-x^2) is true for any x >= 0, thus if
|
||||
exp(-x^2) < 2^(-PREC(y)-1) the result is 1 or 1-epsilon.
|
||||
This rewrites as x^2/log(2) > p+1. */
|
||||
if (MPFR_UNLIKELY (large))
|
||||
/* |erf x| = 1 or 1- */
|
||||
{
|
||||
mpfr_rnd_t rnd2 = MPFR_IS_POS (x) ? rnd_mode : MPFR_INVERT_RND(rnd_mode);
|
||||
if (rnd2 == MPFR_RNDN || rnd2 == MPFR_RNDU || rnd2 == MPFR_RNDA)
|
||||
{
|
||||
inex = MPFR_INT_SIGN (x);
|
||||
mpfr_set_si (y, inex, rnd2);
|
||||
}
|
||||
else /* round to zero */
|
||||
{
|
||||
inex = -MPFR_INT_SIGN (x);
|
||||
mpfr_setmax (y, 0); /* warning: setmax keeps the old sign of y */
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
}
|
||||
}
|
||||
else /* use Taylor */
|
||||
{
|
||||
double xf2;
|
||||
|
||||
/* FIXME: get rid of doubles/mpfr_get_d here */
|
||||
xf2 = mpfr_get_d (x, MPFR_RNDN);
|
||||
xf2 = xf2 * xf2; /* xf2 ~ x^2 */
|
||||
inex = mpfr_erf_0 (y, x, xf2, rnd_mode);
|
||||
}
|
||||
|
||||
end:
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inex, rnd_mode);
|
||||
}
|
||||
|
||||
/* return x*2^e */
|
||||
static double
|
||||
mul_2exp (double x, mpfr_exp_t e)
|
||||
{
|
||||
if (e > 0)
|
||||
{
|
||||
while (e--)
|
||||
x *= 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (e++)
|
||||
x /= 2.0;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/* evaluates erf(x) using the expansion at x=0:
|
||||
|
||||
erf(x) = 2/sqrt(Pi) * sum((-1)^k*x^(2k+1)/k!/(2k+1), k=0..infinity)
|
||||
|
||||
Assumes x is neither NaN nor infinite nor zero.
|
||||
Assumes also that e*x^2 <= n (target precision).
|
||||
*/
|
||||
static int
|
||||
mpfr_erf_0 (mpfr_ptr res, mpfr_srcptr x, double xf2, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_prec_t n, m;
|
||||
mpfr_exp_t nuk, sigmak;
|
||||
double tauk;
|
||||
mpfr_t y, s, t, u;
|
||||
unsigned int k;
|
||||
int log2tauk;
|
||||
int inex;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
n = MPFR_PREC (res); /* target precision */
|
||||
|
||||
/* initial working precision */
|
||||
m = n + (mpfr_prec_t) (xf2 / LOG2) + 8 + MPFR_INT_CEIL_LOG2 (n);
|
||||
|
||||
mpfr_init2 (y, m);
|
||||
mpfr_init2 (s, m);
|
||||
mpfr_init2 (t, m);
|
||||
mpfr_init2 (u, m);
|
||||
|
||||
MPFR_ZIV_INIT (loop, m);
|
||||
for (;;)
|
||||
{
|
||||
mpfr_mul (y, x, x, MPFR_RNDU); /* err <= 1 ulp */
|
||||
mpfr_set_ui (s, 1, MPFR_RNDN);
|
||||
mpfr_set_ui (t, 1, MPFR_RNDN);
|
||||
tauk = 0.0;
|
||||
|
||||
for (k = 1; ; k++)
|
||||
{
|
||||
mpfr_mul (t, y, t, MPFR_RNDU);
|
||||
mpfr_div_ui (t, t, k, MPFR_RNDU);
|
||||
mpfr_div_ui (u, t, 2 * k + 1, MPFR_RNDU);
|
||||
sigmak = MPFR_GET_EXP (s);
|
||||
if (k % 2)
|
||||
mpfr_sub (s, s, u, MPFR_RNDN);
|
||||
else
|
||||
mpfr_add (s, s, u, MPFR_RNDN);
|
||||
sigmak -= MPFR_GET_EXP(s);
|
||||
nuk = MPFR_GET_EXP(u) - MPFR_GET_EXP(s);
|
||||
|
||||
if ((nuk < - (mpfr_exp_t) m) && ((double) k >= xf2))
|
||||
break;
|
||||
|
||||
/* tauk <- 1/2 + tauk * 2^sigmak + (1+8k)*2^nuk */
|
||||
tauk = 0.5 + mul_2exp (tauk, sigmak)
|
||||
+ mul_2exp (1.0 + 8.0 * (double) k, nuk);
|
||||
}
|
||||
|
||||
mpfr_mul (s, x, s, MPFR_RNDU);
|
||||
MPFR_SET_EXP (s, MPFR_GET_EXP (s) + 1);
|
||||
|
||||
mpfr_const_pi (t, MPFR_RNDZ);
|
||||
mpfr_sqrt (t, t, MPFR_RNDZ);
|
||||
mpfr_div (s, s, t, MPFR_RNDN);
|
||||
tauk = 4.0 * tauk + 11.0; /* final ulp-error on s */
|
||||
log2tauk = __gmpfr_ceil_log2 (tauk);
|
||||
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (s, m - log2tauk, n, rnd_mode)))
|
||||
break;
|
||||
|
||||
/* Actualisation of the precision */
|
||||
MPFR_ZIV_NEXT (loop, m);
|
||||
mpfr_set_prec (y, m);
|
||||
mpfr_set_prec (s, m);
|
||||
mpfr_set_prec (t, m);
|
||||
mpfr_set_prec (u, m);
|
||||
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inex = mpfr_set (res, s, rnd_mode);
|
||||
|
||||
mpfr_clear (y);
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (u);
|
||||
mpfr_clear (s);
|
||||
|
||||
return inex;
|
||||
}
|
|
@ -0,0 +1,276 @@
|
|||
/* mpfr_erfc -- The Complementary Error Function of a floating-point number
|
||||
|
||||
Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* erfc(x) = 1 - erf(x) */
|
||||
|
||||
/* Put in y an approximation of erfc(x) for large x, using formulae 7.1.23 and
|
||||
7.1.24 from Abramowitz and Stegun.
|
||||
Returns e such that the error is bounded by 2^e ulp(y),
|
||||
or returns 0 in case of underflow.
|
||||
*/
|
||||
static mpfr_exp_t
|
||||
mpfr_erfc_asympt (mpfr_ptr y, mpfr_srcptr x)
|
||||
{
|
||||
mpfr_t t, xx, err;
|
||||
unsigned long k;
|
||||
mpfr_prec_t prec = MPFR_PREC(y);
|
||||
mpfr_exp_t exp_err;
|
||||
|
||||
mpfr_init2 (t, prec);
|
||||
mpfr_init2 (xx, prec);
|
||||
mpfr_init2 (err, 31);
|
||||
/* let u = 2^(1-p), and let us represent the error as (1+u)^err
|
||||
with a bound for err */
|
||||
mpfr_mul (xx, x, x, MPFR_RNDD); /* err <= 1 */
|
||||
mpfr_ui_div (xx, 1, xx, MPFR_RNDU); /* upper bound for 1/(2x^2), err <= 2 */
|
||||
mpfr_div_2ui (xx, xx, 1, MPFR_RNDU); /* exact */
|
||||
mpfr_set_ui (t, 1, MPFR_RNDN); /* current term, exact */
|
||||
mpfr_set (y, t, MPFR_RNDN); /* current sum */
|
||||
mpfr_set_ui (err, 0, MPFR_RNDN);
|
||||
for (k = 1; ; k++)
|
||||
{
|
||||
mpfr_mul_ui (t, t, 2 * k - 1, MPFR_RNDU); /* err <= 4k-3 */
|
||||
mpfr_mul (t, t, xx, MPFR_RNDU); /* err <= 4k */
|
||||
/* for -1 < x < 1, and |nx| < 1, we have |(1+x)^n| <= 1+7/4|nx|.
|
||||
Indeed, for x>=0: log((1+x)^n) = n*log(1+x) <= n*x. Let y=n*x < 1,
|
||||
then exp(y) <= 1+7/4*y.
|
||||
For x<=0, let x=-x, we can prove by induction that (1-x)^n >= 1-n*x.*/
|
||||
mpfr_mul_2si (err, err, MPFR_GET_EXP (y) - MPFR_GET_EXP (t), MPFR_RNDU);
|
||||
mpfr_add_ui (err, err, 14 * k, MPFR_RNDU); /* 2^(1-p) * t <= 2 ulp(t) */
|
||||
mpfr_div_2si (err, err, MPFR_GET_EXP (y) - MPFR_GET_EXP (t), MPFR_RNDU);
|
||||
if (MPFR_GET_EXP (t) + (mpfr_exp_t) prec <= MPFR_GET_EXP (y))
|
||||
{
|
||||
/* the truncation error is bounded by |t| < ulp(y) */
|
||||
mpfr_add_ui (err, err, 1, MPFR_RNDU);
|
||||
break;
|
||||
}
|
||||
if (k & 1)
|
||||
mpfr_sub (y, y, t, MPFR_RNDN);
|
||||
else
|
||||
mpfr_add (y, y, t, MPFR_RNDN);
|
||||
}
|
||||
/* the error on y is bounded by err*ulp(y) */
|
||||
mpfr_mul (t, x, x, MPFR_RNDU); /* rel. err <= 2^(1-p) */
|
||||
mpfr_div_2ui (err, err, 3, MPFR_RNDU); /* err/8 */
|
||||
mpfr_add (err, err, t, MPFR_RNDU); /* err/8 + xx */
|
||||
mpfr_mul_2ui (err, err, 3, MPFR_RNDU); /* err + 8*xx */
|
||||
mpfr_exp (t, t, MPFR_RNDU); /* err <= 1/2*ulp(t) + err(x*x)*t
|
||||
<= 1/2*ulp(t)+2*|x*x|*ulp(t)
|
||||
<= (2*|x*x|+1/2)*ulp(t) */
|
||||
mpfr_mul (t, t, x, MPFR_RNDN); /* err <= 1/2*ulp(t) + (4*|x*x|+1)*ulp(t)
|
||||
<= (4*|x*x|+3/2)*ulp(t) */
|
||||
mpfr_const_pi (xx, MPFR_RNDZ); /* err <= ulp(Pi) */
|
||||
mpfr_sqrt (xx, xx, MPFR_RNDN); /* err <= 1/2*ulp(xx) + ulp(Pi)/2/sqrt(Pi)
|
||||
<= 3/2*ulp(xx) */
|
||||
mpfr_mul (t, t, xx, MPFR_RNDN); /* err <= (8 |xx| + 13/2) * ulp(t) */
|
||||
mpfr_div (y, y, t, MPFR_RNDN); /* the relative error on input y is bounded
|
||||
by (1+u)^err with u = 2^(1-p), that on
|
||||
t is bounded by (1+u)^(8 |xx| + 13/2),
|
||||
thus that on output y is bounded by
|
||||
8 |xx| + 7 + err. */
|
||||
|
||||
if (MPFR_IS_ZERO(y))
|
||||
{
|
||||
/* If y is zero, most probably we have underflow. We check it directly
|
||||
using the fact that erfc(x) <= exp(-x^2)/sqrt(Pi)/x for x >= 0.
|
||||
We compute an upper approximation of exp(-x^2)/sqrt(Pi)/x.
|
||||
*/
|
||||
mpfr_mul (t, x, x, MPFR_RNDD); /* t <= x^2 */
|
||||
mpfr_neg (t, t, MPFR_RNDU); /* -x^2 <= t */
|
||||
mpfr_exp (t, t, MPFR_RNDU); /* exp(-x^2) <= t */
|
||||
mpfr_const_pi (xx, MPFR_RNDD); /* xx <= sqrt(Pi), cached */
|
||||
mpfr_mul (xx, xx, x, MPFR_RNDD); /* xx <= sqrt(Pi)*x */
|
||||
mpfr_div (y, t, xx, MPFR_RNDN); /* if y is zero, this means that the upper
|
||||
approximation of exp(-x^2)/sqrt(Pi)/x
|
||||
is nearer from 0 than from 2^(-emin-1),
|
||||
thus we have underflow. */
|
||||
exp_err = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mpfr_add_ui (err, err, 7, MPFR_RNDU);
|
||||
exp_err = MPFR_GET_EXP (err);
|
||||
}
|
||||
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (xx);
|
||||
mpfr_clear (err);
|
||||
return exp_err;
|
||||
}
|
||||
|
||||
int
|
||||
mpfr_erfc (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd)
|
||||
{
|
||||
int inex;
|
||||
mpfr_t tmp;
|
||||
mpfr_exp_t te, err;
|
||||
mpfr_prec_t prec;
|
||||
mpfr_exp_t emin = mpfr_get_emin ();
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd),
|
||||
("y[%#R]=%R inexact=%d", y, y, inex));
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
/* erfc(+inf) = 0+, erfc(-inf) = 2 erfc (0) = 1 */
|
||||
else if (MPFR_IS_INF (x))
|
||||
return mpfr_set_ui (y, MPFR_IS_POS (x) ? 0 : 2, rnd);
|
||||
else
|
||||
return mpfr_set_ui (y, 1, rnd);
|
||||
}
|
||||
|
||||
if (MPFR_SIGN (x) > 0)
|
||||
{
|
||||
/* by default, emin = 1-2^30, thus the smallest representable
|
||||
number is 1/2*2^emin = 2^(-2^30):
|
||||
for x >= 27282, erfc(x) < 2^(-2^30-1), and
|
||||
for x >= 1787897414, erfc(x) < 2^(-2^62-1).
|
||||
*/
|
||||
if ((emin >= -1073741823 && mpfr_cmp_ui (x, 27282) >= 0) ||
|
||||
mpfr_cmp_ui (x, 1787897414) >= 0)
|
||||
{
|
||||
/* May be incorrect if MPFR_EMAX_MAX >= 2^62. */
|
||||
MPFR_ASSERTN ((MPFR_EMAX_MAX >> 31) >> 31 == 0);
|
||||
return mpfr_underflow (y, (rnd == MPFR_RNDN) ? MPFR_RNDZ : rnd, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Init stuff */
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
if (MPFR_SIGN (x) < 0)
|
||||
{
|
||||
mpfr_exp_t e = MPFR_EXP(x);
|
||||
/* For x < 0 going to -infinity, erfc(x) tends to 2 by below.
|
||||
More precisely, we have 2 + 1/sqrt(Pi)/x/exp(x^2) < erfc(x) < 2.
|
||||
Thus log2 |2 - erfc(x)| <= -log2|x| - x^2 / log(2).
|
||||
If |2 - erfc(x)| < 2^(-PREC(y)) then the result is either 2 or
|
||||
nextbelow(2).
|
||||
For x <= -27282, -log2|x| - x^2 / log(2) <= -2^30.
|
||||
*/
|
||||
if ((MPFR_PREC(y) <= 7 && e >= 2) || /* x <= -2 */
|
||||
(MPFR_PREC(y) <= 25 && e >= 3) || /* x <= -4 */
|
||||
(MPFR_PREC(y) <= 120 && mpfr_cmp_si (x, -9) <= 0) ||
|
||||
mpfr_cmp_si (x, -27282) <= 0)
|
||||
{
|
||||
near_two:
|
||||
mpfr_set_ui (y, 2, MPFR_RNDN);
|
||||
mpfr_set_inexflag ();
|
||||
if (rnd == MPFR_RNDZ || rnd == MPFR_RNDD)
|
||||
{
|
||||
mpfr_nextbelow (y);
|
||||
inex = -1;
|
||||
}
|
||||
else
|
||||
inex = 1;
|
||||
goto end;
|
||||
}
|
||||
else if (e >= 3) /* more accurate test */
|
||||
{
|
||||
mpfr_t t, u;
|
||||
int near_2;
|
||||
mpfr_init2 (t, 32);
|
||||
mpfr_init2 (u, 32);
|
||||
/* the following is 1/log(2) rounded to zero on 32 bits */
|
||||
mpfr_set_str_binary (t, "1.0111000101010100011101100101001");
|
||||
mpfr_sqr (u, x, MPFR_RNDZ);
|
||||
mpfr_mul (t, t, u, MPFR_RNDZ); /* t <= x^2/log(2) */
|
||||
mpfr_neg (u, x, MPFR_RNDZ); /* 0 <= u <= |x| */
|
||||
mpfr_log2 (u, u, MPFR_RNDZ); /* u <= log2(|x|) */
|
||||
mpfr_add (t, t, u, MPFR_RNDZ); /* t <= log2|x| + x^2 / log(2) */
|
||||
/* Taking into account that mpfr_exp_t >= mpfr_prec_t */
|
||||
mpfr_set_exp_t (u, MPFR_PREC (y), MPFR_RNDU);
|
||||
near_2 = mpfr_cmp (t, u) >= 0; /* 1 if PREC(y) <= u <= t <= ... */
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (u);
|
||||
if (near_2)
|
||||
goto near_two;
|
||||
}
|
||||
}
|
||||
|
||||
/* erfc(x) ~ 1, with error < 2^(EXP(x)+1) */
|
||||
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, __gmpfr_one, - MPFR_GET_EXP (x) - 1,
|
||||
0, MPFR_SIGN(x) < 0,
|
||||
rnd, inex = _inexact; goto end);
|
||||
|
||||
prec = MPFR_PREC (y) + MPFR_INT_CEIL_LOG2 (MPFR_PREC (y)) + 3;
|
||||
if (MPFR_GET_EXP (x) > 0)
|
||||
prec += 2 * MPFR_GET_EXP(x);
|
||||
|
||||
mpfr_init2 (tmp, prec);
|
||||
|
||||
MPFR_ZIV_INIT (loop, prec); /* Initialize the ZivLoop controler */
|
||||
for (;;) /* Infinite loop */
|
||||
{
|
||||
/* use asymptotic formula only whenever x^2 >= p*log(2),
|
||||
otherwise it will not converge */
|
||||
if (MPFR_SIGN (x) > 0 &&
|
||||
2 * MPFR_GET_EXP (x) - 2 >= MPFR_INT_CEIL_LOG2 (prec))
|
||||
/* we have x^2 >= p in that case */
|
||||
{
|
||||
err = mpfr_erfc_asympt (tmp, x);
|
||||
if (err == 0) /* underflow case */
|
||||
{
|
||||
mpfr_clear (tmp);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_underflow (y, (rnd == MPFR_RNDN) ? MPFR_RNDZ : rnd, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mpfr_erf (tmp, x, MPFR_RNDN);
|
||||
MPFR_ASSERTD (!MPFR_IS_SINGULAR (tmp)); /* FIXME: 0 only for x=0 ? */
|
||||
te = MPFR_GET_EXP (tmp);
|
||||
mpfr_ui_sub (tmp, 1, tmp, MPFR_RNDN);
|
||||
/* See error analysis in algorithms.tex for details */
|
||||
if (MPFR_IS_ZERO (tmp))
|
||||
{
|
||||
prec *= 2;
|
||||
err = prec; /* ensures MPFR_CAN_ROUND fails */
|
||||
}
|
||||
else
|
||||
err = MAX (te - MPFR_GET_EXP (tmp), 0) + 1;
|
||||
}
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - err, MPFR_PREC (y), rnd)))
|
||||
break;
|
||||
MPFR_ZIV_NEXT (loop, prec); /* Increase used precision */
|
||||
mpfr_set_prec (tmp, prec);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop); /* Free the ZivLoop Controler */
|
||||
|
||||
inex = mpfr_set (y, tmp, rnd); /* Set y to the computed value */
|
||||
mpfr_clear (tmp);
|
||||
|
||||
end:
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inex, rnd);
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
This directory contains simple examples.
|
||||
|
||||
These examples currently use the old rounding mode macros (GMP_RNDN, etc.)
|
||||
instead of the new ones, which are not compatible with MPFR 2.x.
|
|
@ -0,0 +1,97 @@
|
|||
/* Test of the double rounding effect.
|
||||
*
|
||||
* This example was presented at the CNC'2 summer school on MPFR and MPC
|
||||
* at LORIA, Nancy, France.
|
||||
*
|
||||
* Arguments: max difference of exponents dmax, significand size n.
|
||||
* Optional argument: extended precision p (with double rounding).
|
||||
*
|
||||
* Return all the couples of positive machine numbers (x,y) such that
|
||||
* 1/2 <= y < 1, 0 <= Ex - Ey <= dmax, x - y is exactly representable
|
||||
* in precision n and the results of floor(x/y) in the rounding modes
|
||||
* toward 0 and to nearest are different.
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <mpfr.h>
|
||||
|
||||
#define PRECN x, y, z
|
||||
#define VARS PRECN, t
|
||||
|
||||
static unsigned long
|
||||
eval (mpfr_t x, mpfr_t y, mpfr_t z, mpfr_t t, mpfr_rnd_t rnd)
|
||||
{
|
||||
mpfr_div (t, x, y, rnd); /* the division x/y in precision p */
|
||||
mpfr_set (z, t, rnd); /* the rounding to the precision n */
|
||||
mpfr_rint_floor (z, z, rnd);
|
||||
return mpfr_get_ui (z, rnd);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int dmax, n, p;
|
||||
mpfr_t VARS;
|
||||
|
||||
if (argc != 3 && argc != 4)
|
||||
{
|
||||
fprintf (stderr, "Usage: divworst <dmax> <n> [ <p> ]\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dmax = atoi (argv[1]);
|
||||
n = atoi (argv[2]);
|
||||
p = argc == 3 ? n : atoi (argv[3]);
|
||||
if (p < n)
|
||||
{
|
||||
fprintf (stderr, "divworst: p must be greater or equal to n\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mpfr_inits2 (n, PRECN, (mpfr_ptr) 0);
|
||||
mpfr_init2 (t, p);
|
||||
|
||||
for (mpfr_set_ui_2exp (x, 1, -1, GMP_RNDN);
|
||||
mpfr_get_exp (x) <= dmax;
|
||||
mpfr_nextabove (x))
|
||||
for (mpfr_set_ui_2exp (y, 1, -1, GMP_RNDN);
|
||||
mpfr_get_exp (y) == 0;
|
||||
mpfr_nextabove (y))
|
||||
{
|
||||
unsigned long rz, rn;
|
||||
|
||||
if (mpfr_sub (z, x, y, GMP_RNDZ) != 0)
|
||||
continue; /* x - y is not representable in precision n */
|
||||
rz = eval (x, y, z, t, GMP_RNDZ);
|
||||
rn = eval (x, y, z, t, GMP_RNDN);
|
||||
if (rz == rn)
|
||||
continue;
|
||||
mpfr_printf ("x = %.*Rb ; y = %.*Rb ; Z: %lu ; N: %lu\n",
|
||||
n - 1, x, n - 1, y, rz, rn);
|
||||
}
|
||||
|
||||
mpfr_clears (VARS, (mpfr_ptr) 0);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/* This example was presented at the CNC'2 summer school on MPFR and MPC at
|
||||
* LORIA, Nancy, France. It shows how one can use different rounding modes.
|
||||
* This example implements the OddRoundedAdd algorithm, which returns the
|
||||
* sum z = x + y rounded-to-odd:
|
||||
* * RO(z) = z if z is exactly representable;
|
||||
* * otherwise RO(z) is the value among RD(z) and RU(z) whose
|
||||
* least significant bit is a one.
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmp.h>
|
||||
#include <mpfr.h>
|
||||
|
||||
#define LIST x, y, d, u, e, z
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
mpfr_t LIST;
|
||||
mpfr_prec_t prec;
|
||||
int pprec; /* will be prec - 1 for mpfr_printf */
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
fprintf (stderr, "Usage: rndo-add <prec> <x> <y>\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
prec = atoi (argv[1]);
|
||||
if (prec < 2)
|
||||
{
|
||||
fprintf (stderr, "rndo-add: bad precision\n");
|
||||
exit (1);
|
||||
}
|
||||
pprec = prec - 1;
|
||||
|
||||
mpfr_inits2 (prec, LIST, (mpfr_ptr) 0);
|
||||
|
||||
if (mpfr_set_str (x, argv[2], 0, GMP_RNDN))
|
||||
{
|
||||
fprintf (stderr, "rndo-add: bad x value\n");
|
||||
exit (1);
|
||||
}
|
||||
mpfr_printf ("x = %.*Rb\n", pprec, x);
|
||||
|
||||
if (mpfr_set_str (y, argv[3], 0, GMP_RNDN))
|
||||
{
|
||||
fprintf (stderr, "rndo-add: bad y value\n");
|
||||
exit (1);
|
||||
}
|
||||
mpfr_printf ("y = %.*Rb\n", pprec, y);
|
||||
|
||||
mpfr_add (d, x, y, GMP_RNDD);
|
||||
mpfr_printf ("d = %.*Rb\n", pprec, d);
|
||||
|
||||
mpfr_add (u, x, y, GMP_RNDU);
|
||||
mpfr_printf ("u = %.*Rb\n", pprec, u);
|
||||
|
||||
mpfr_add (e, d, u, GMP_RNDN);
|
||||
mpfr_div_2ui (e, e, 1, GMP_RNDN);
|
||||
mpfr_printf ("e = %.*Rb\n", pprec, e);
|
||||
|
||||
mpfr_sub (z, u, e, GMP_RNDN);
|
||||
mpfr_add (z, z, d, GMP_RNDN);
|
||||
mpfr_printf ("z = %.*Rb\n", pprec, z);
|
||||
|
||||
mpfr_clears (LIST, (mpfr_ptr) 0);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* This is the example given and commented on the MPFR web site:
|
||||
* http://www.mpfr.org/sample.html
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gmp.h>
|
||||
#include <mpfr.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
unsigned int i;
|
||||
mpfr_t s, t, u;
|
||||
|
||||
mpfr_init2 (t, 200);
|
||||
mpfr_set_d (t, 1.0, GMP_RNDD);
|
||||
mpfr_init2 (s, 200);
|
||||
mpfr_set_d (s, 1.0, GMP_RNDD);
|
||||
mpfr_init2 (u, 200);
|
||||
for (i = 1; i <= 100; i++)
|
||||
{
|
||||
mpfr_mul_ui (t, t, i, GMP_RNDU);
|
||||
mpfr_set_d (u, 1.0, GMP_RNDD);
|
||||
mpfr_div (u, u, t, GMP_RNDD);
|
||||
mpfr_add (s, s, u, GMP_RNDD);
|
||||
}
|
||||
printf ("Sum is ");
|
||||
mpfr_out_str (stdout, 10, 0, s, GMP_RNDD);
|
||||
putchar ('\n');
|
||||
mpfr_clear (s);
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (u);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Output various information about GMP and MPFR.
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <gmp.h>
|
||||
#include <mpfr.h>
|
||||
|
||||
/* The following failure can occur if GMP has been rebuilt with
|
||||
* a different ABI, e.g.
|
||||
* 1. GMP built with ABI=mode32.
|
||||
* 2. MPFR built against this GMP version.
|
||||
* 3. GMP rebuilt with ABI=32.
|
||||
*/
|
||||
static void failure_test (void)
|
||||
{
|
||||
mpfr_t x;
|
||||
|
||||
mpfr_init2 (x, 128);
|
||||
mpfr_set_str (x, "17", 0, GMP_RNDN);
|
||||
if (mpfr_cmp_ui (x, 17) != 0)
|
||||
printf ("\nFailure in mpfr_set_str! Probably an unmatched ABI!\n");
|
||||
mpfr_clear (x);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
unsigned long c;
|
||||
mp_limb_t t[4] = { -1, -1, -1, -1 };
|
||||
|
||||
#if defined(__cplusplus)
|
||||
printf ("A C++ compiler is used.\n");
|
||||
#endif
|
||||
|
||||
printf ("GMP ..... Library: %-12s Header: %d.%d.%d\n",
|
||||
gmp_version, __GNU_MP_VERSION, __GNU_MP_VERSION_MINOR,
|
||||
__GNU_MP_VERSION_PATCHLEVEL);
|
||||
|
||||
printf ("MPFR .... Library: %-12s Header: %s (based on %d.%d.%d)\n",
|
||||
mpfr_get_version (), MPFR_VERSION_STRING, MPFR_VERSION_MAJOR,
|
||||
MPFR_VERSION_MINOR, MPFR_VERSION_PATCHLEVEL);
|
||||
printf ("MPFR patches: %s\n\n", mpfr_get_patches ());
|
||||
|
||||
#ifdef __GMP_CC
|
||||
printf ("__GMP_CC = \"%s\"\n", __GMP_CC);
|
||||
#endif
|
||||
#ifdef __GMP_CFLAGS
|
||||
printf ("__GMP_CFLAGS = \"%s\"\n", __GMP_CFLAGS);
|
||||
#endif
|
||||
printf ("GMP_LIMB_BITS = %d\n", (int) GMP_LIMB_BITS);
|
||||
printf ("GMP_NAIL_BITS = %d\n", (int) GMP_NAIL_BITS);
|
||||
printf ("GMP_NUMB_BITS = %d\n", (int) GMP_NUMB_BITS);
|
||||
printf ("mp_bits_per_limb = %d\n", (int) mp_bits_per_limb);
|
||||
printf ("sizeof(mp_limb_t) = %d\n", (int) sizeof(mp_limb_t));
|
||||
if (mp_bits_per_limb != GMP_LIMB_BITS)
|
||||
printf ("Warning! mp_bits_per_limb != GMP_LIMB_BITS\n");
|
||||
if (GMP_LIMB_BITS != sizeof(mp_limb_t) * CHAR_BIT)
|
||||
printf ("Warning! GMP_LIMB_BITS != sizeof(mp_limb_t) * CHAR_BIT\n");
|
||||
|
||||
c = mpn_popcount (t, 1);
|
||||
printf ("The GMP library expects %lu bits in a mp_limb_t.\n", c);
|
||||
if (c != GMP_LIMB_BITS)
|
||||
printf ("Warning! This is different from GMP_LIMB_BITS!\n"
|
||||
"Different ABI caused by a GMP library upgrade?\n");
|
||||
|
||||
failure_test ();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,336 @@
|
|||
/* Exception flags and utilities.
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
unsigned int MPFR_THREAD_ATTR __gmpfr_flags = 0;
|
||||
|
||||
mpfr_exp_t MPFR_THREAD_ATTR __gmpfr_emin = MPFR_EMIN_DEFAULT;
|
||||
mpfr_exp_t MPFR_THREAD_ATTR __gmpfr_emax = MPFR_EMAX_DEFAULT;
|
||||
|
||||
#undef mpfr_get_emin
|
||||
|
||||
mpfr_exp_t
|
||||
mpfr_get_emin (void)
|
||||
{
|
||||
return __gmpfr_emin;
|
||||
}
|
||||
|
||||
#undef mpfr_set_emin
|
||||
|
||||
int
|
||||
mpfr_set_emin (mpfr_exp_t exponent)
|
||||
{
|
||||
if (exponent >= MPFR_EMIN_MIN && exponent <= MPFR_EMIN_MAX)
|
||||
{
|
||||
__gmpfr_emin = exponent;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
mpfr_exp_t
|
||||
mpfr_get_emin_min (void)
|
||||
{
|
||||
return MPFR_EMIN_MIN;
|
||||
}
|
||||
|
||||
mpfr_exp_t
|
||||
mpfr_get_emin_max (void)
|
||||
{
|
||||
return MPFR_EMIN_MAX;
|
||||
}
|
||||
|
||||
#undef mpfr_get_emax
|
||||
|
||||
mpfr_exp_t
|
||||
mpfr_get_emax (void)
|
||||
{
|
||||
return __gmpfr_emax;
|
||||
}
|
||||
|
||||
#undef mpfr_set_emax
|
||||
|
||||
int
|
||||
mpfr_set_emax (mpfr_exp_t exponent)
|
||||
{
|
||||
if (exponent >= MPFR_EMAX_MIN && exponent <= MPFR_EMAX_MAX)
|
||||
{
|
||||
__gmpfr_emax = exponent;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
mpfr_exp_t
|
||||
mpfr_get_emax_min (void)
|
||||
{
|
||||
return MPFR_EMAX_MIN;
|
||||
}
|
||||
mpfr_exp_t
|
||||
mpfr_get_emax_max (void)
|
||||
{
|
||||
return MPFR_EMAX_MAX;
|
||||
}
|
||||
|
||||
|
||||
#undef mpfr_clear_flags
|
||||
|
||||
void
|
||||
mpfr_clear_flags (void)
|
||||
{
|
||||
__gmpfr_flags = 0;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_underflow
|
||||
|
||||
void
|
||||
mpfr_clear_underflow (void)
|
||||
{
|
||||
__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_UNDERFLOW;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_overflow
|
||||
|
||||
void
|
||||
mpfr_clear_overflow (void)
|
||||
{
|
||||
__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_OVERFLOW;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_nanflag
|
||||
|
||||
void
|
||||
mpfr_clear_nanflag (void)
|
||||
{
|
||||
__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_NAN;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_inexflag
|
||||
|
||||
void
|
||||
mpfr_clear_inexflag (void)
|
||||
{
|
||||
__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_INEXACT;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_erangeflag
|
||||
|
||||
void
|
||||
mpfr_clear_erangeflag (void)
|
||||
{
|
||||
__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_underflow
|
||||
|
||||
void
|
||||
mpfr_set_underflow (void)
|
||||
{
|
||||
__gmpfr_flags |= MPFR_FLAGS_UNDERFLOW;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_overflow
|
||||
|
||||
void
|
||||
mpfr_set_overflow (void)
|
||||
{
|
||||
__gmpfr_flags |= MPFR_FLAGS_OVERFLOW;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_nanflag
|
||||
|
||||
void
|
||||
mpfr_set_nanflag (void)
|
||||
{
|
||||
__gmpfr_flags |= MPFR_FLAGS_NAN;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_inexflag
|
||||
|
||||
void
|
||||
mpfr_set_inexflag (void)
|
||||
{
|
||||
__gmpfr_flags |= MPFR_FLAGS_INEXACT;
|
||||
}
|
||||
|
||||
#undef mpfr_clear_erangeflag
|
||||
|
||||
void
|
||||
mpfr_set_erangeflag (void)
|
||||
{
|
||||
__gmpfr_flags |= MPFR_FLAGS_ERANGE;
|
||||
}
|
||||
|
||||
|
||||
#undef mpfr_check_range
|
||||
|
||||
int
|
||||
mpfr_check_range (mpfr_ptr x, int t, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
if (MPFR_LIKELY( MPFR_IS_PURE_FP(x)) )
|
||||
{ /* x is a non-zero FP */
|
||||
mpfr_exp_t exp = MPFR_EXP (x); /* Do not use MPFR_GET_EXP */
|
||||
if (MPFR_UNLIKELY( exp < __gmpfr_emin) )
|
||||
{
|
||||
/* The following test is necessary because in the rounding to the
|
||||
* nearest mode, mpfr_underflow always rounds away from 0. In
|
||||
* this rounding mode, we need to round to 0 if:
|
||||
* _ |x| < 2^(emin-2), or
|
||||
* _ |x| = 2^(emin-2) and the absolute value of the exact
|
||||
* result is <= 2^(emin-2).
|
||||
*/
|
||||
if (rnd_mode == MPFR_RNDN &&
|
||||
(exp + 1 < __gmpfr_emin ||
|
||||
(mpfr_powerof2_raw(x) &&
|
||||
(MPFR_IS_NEG(x) ? t <= 0 : t >= 0))))
|
||||
rnd_mode = MPFR_RNDZ;
|
||||
return mpfr_underflow(x, rnd_mode, MPFR_SIGN(x));
|
||||
}
|
||||
if (MPFR_UNLIKELY( exp > __gmpfr_emax) )
|
||||
return mpfr_overflow (x, rnd_mode, MPFR_SIGN(x));
|
||||
}
|
||||
else if (MPFR_UNLIKELY (t != 0 && MPFR_IS_INF (x)))
|
||||
{
|
||||
/* We need to do the following because most MPFR functions are
|
||||
* implemented in the following way:
|
||||
* Ziv's loop:
|
||||
* | Compute an approximation to the result and an error bound.
|
||||
* | Possible underflow/overflow detection -> return.
|
||||
* | If can_round, break (exit the loop).
|
||||
* | Otherwise, increase the working precision and loop.
|
||||
* Round the approximation in the target precision. <== See below
|
||||
* Restore the flags (that could have been set due to underflows
|
||||
* or overflows during the internal computations).
|
||||
* Execute: return mpfr_check_range (...).
|
||||
* The problem is that an overflow could be generated when rounding the
|
||||
* approximation (in general, such an overflow could not be detected
|
||||
* earlier), and the overflow flag is lost when the flags are restored.
|
||||
* This can occur only when the rounding yields an exponent change
|
||||
* and the new exponent is larger than the maximum exponent, so that
|
||||
* an infinity is necessarily obtained.
|
||||
* So, the simplest solution is to detect this overflow case here in
|
||||
* mpfr_check_range, which is easy to do since the rounded result is
|
||||
* necessarily an inexact infinity.
|
||||
*/
|
||||
__gmpfr_flags |= MPFR_FLAGS_OVERFLOW;
|
||||
}
|
||||
MPFR_RET (t); /* propagate inexact ternary value, unlike most functions */
|
||||
}
|
||||
|
||||
#undef mpfr_underflow_p
|
||||
|
||||
int
|
||||
mpfr_underflow_p (void)
|
||||
{
|
||||
return __gmpfr_flags & MPFR_FLAGS_UNDERFLOW;
|
||||
}
|
||||
|
||||
#undef mpfr_overflow_p
|
||||
|
||||
int
|
||||
mpfr_overflow_p (void)
|
||||
{
|
||||
return __gmpfr_flags & MPFR_FLAGS_OVERFLOW;
|
||||
}
|
||||
|
||||
#undef mpfr_nanflag_p
|
||||
|
||||
int
|
||||
mpfr_nanflag_p (void)
|
||||
{
|
||||
return __gmpfr_flags & MPFR_FLAGS_NAN;
|
||||
}
|
||||
|
||||
#undef mpfr_inexflag_p
|
||||
|
||||
int
|
||||
mpfr_inexflag_p (void)
|
||||
{
|
||||
return __gmpfr_flags & MPFR_FLAGS_INEXACT;
|
||||
}
|
||||
|
||||
#undef mpfr_erangeflag_p
|
||||
|
||||
int
|
||||
mpfr_erangeflag_p (void)
|
||||
{
|
||||
return __gmpfr_flags & MPFR_FLAGS_ERANGE;
|
||||
}
|
||||
|
||||
/* #undef mpfr_underflow */
|
||||
|
||||
/* Note: In the rounding to the nearest mode, mpfr_underflow
|
||||
always rounds away from 0. In this rounding mode, you must call
|
||||
mpfr_underflow with rnd_mode = MPFR_RNDZ if the exact result
|
||||
is <= 2^(emin-2) in absolute value. */
|
||||
|
||||
int
|
||||
mpfr_underflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign)
|
||||
{
|
||||
int inex;
|
||||
|
||||
MPFR_ASSERT_SIGN (sign);
|
||||
|
||||
if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0))
|
||||
{
|
||||
MPFR_SET_ZERO(x);
|
||||
inex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mpfr_setmin (x, __gmpfr_emin);
|
||||
inex = 1;
|
||||
}
|
||||
MPFR_SET_SIGN(x, sign);
|
||||
__gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW;
|
||||
return sign > 0 ? inex : -inex;
|
||||
}
|
||||
|
||||
/* #undef mpfr_overflow */
|
||||
|
||||
int
|
||||
mpfr_overflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign)
|
||||
{
|
||||
int inex;
|
||||
|
||||
MPFR_ASSERT_SIGN(sign);
|
||||
if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0))
|
||||
{
|
||||
mpfr_setmax (x, __gmpfr_emax);
|
||||
inex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_SET_INF(x);
|
||||
inex = 1;
|
||||
}
|
||||
MPFR_SET_SIGN(x,sign);
|
||||
__gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW;
|
||||
return sign > 0 ? inex : -inex;
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/* mpfr_exp -- exponential of a floating-point number
|
||||
|
||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
int
|
||||
mpfr_exp (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_exp_t expx;
|
||||
mpfr_prec_t precy;
|
||||
int inexact;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(x) ))
|
||||
{
|
||||
if (MPFR_IS_NAN(x))
|
||||
{
|
||||
MPFR_SET_NAN(y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF(x))
|
||||
{
|
||||
if (MPFR_IS_POS(x))
|
||||
MPFR_SET_INF(y);
|
||||
else
|
||||
MPFR_SET_ZERO(y);
|
||||
MPFR_SET_POS(y);
|
||||
MPFR_RET(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_ASSERTD(MPFR_IS_ZERO(x));
|
||||
return mpfr_set_ui (y, 1, rnd_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* First, let's detect most overflow and underflow cases. */
|
||||
{
|
||||
mpfr_t e, bound;
|
||||
|
||||
/* We must extended the exponent range and save the flags now. */
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
mpfr_init2 (e, sizeof (mpfr_exp_t) * CHAR_BIT);
|
||||
mpfr_init2 (bound, 32);
|
||||
|
||||
inexact = mpfr_set_exp_t (e, expo.saved_emax, MPFR_RNDN);
|
||||
MPFR_ASSERTD (inexact == 0);
|
||||
mpfr_const_log2 (bound, expo.saved_emax < 0 ? MPFR_RNDD : MPFR_RNDU);
|
||||
mpfr_mul (bound, bound, e, MPFR_RNDU);
|
||||
if (MPFR_UNLIKELY (mpfr_cmp (x, bound) >= 0))
|
||||
{
|
||||
/* x > log(2^emax), thus exp(x) > 2^emax */
|
||||
mpfr_clears (e, bound, (mpfr_ptr) 0);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_overflow (y, rnd_mode, 1);
|
||||
}
|
||||
|
||||
inexact = mpfr_set_exp_t (e, expo.saved_emin, MPFR_RNDN);
|
||||
MPFR_ASSERTD (inexact == 0);
|
||||
inexact = mpfr_sub_ui (e, e, 2, MPFR_RNDN);
|
||||
MPFR_ASSERTD (inexact == 0);
|
||||
mpfr_const_log2 (bound, expo.saved_emin < 0 ? MPFR_RNDU : MPFR_RNDD);
|
||||
mpfr_mul (bound, bound, e, MPFR_RNDD);
|
||||
if (MPFR_UNLIKELY (mpfr_cmp (x, bound) <= 0))
|
||||
{
|
||||
/* x < log(2^(emin - 2)), thus exp(x) < 2^(emin - 2) */
|
||||
mpfr_clears (e, bound, (mpfr_ptr) 0);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_underflow (y, rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode,
|
||||
1);
|
||||
}
|
||||
|
||||
/* Other overflow/underflow cases must be detected
|
||||
by the generic routines. */
|
||||
mpfr_clears (e, bound, (mpfr_ptr) 0);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
}
|
||||
|
||||
expx = MPFR_GET_EXP (x);
|
||||
precy = MPFR_PREC (y);
|
||||
|
||||
/* if x < 2^(-precy), then exp(x) i.e. gives 1 +/- 1 ulp(1) */
|
||||
if (MPFR_UNLIKELY (expx < 0 && (mpfr_uexp_t) (-expx) > precy))
|
||||
{
|
||||
mpfr_exp_t emin = __gmpfr_emin;
|
||||
mpfr_exp_t emax = __gmpfr_emax;
|
||||
int signx = MPFR_SIGN (x);
|
||||
|
||||
MPFR_SET_POS (y);
|
||||
if (MPFR_IS_NEG_SIGN (signx) && (rnd_mode == MPFR_RNDD ||
|
||||
rnd_mode == MPFR_RNDZ))
|
||||
{
|
||||
__gmpfr_emin = 0;
|
||||
__gmpfr_emax = 0;
|
||||
mpfr_setmax (y, 0); /* y = 1 - epsilon */
|
||||
inexact = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
__gmpfr_emin = 1;
|
||||
__gmpfr_emax = 1;
|
||||
mpfr_setmin (y, 1); /* y = 1 */
|
||||
if (MPFR_IS_POS_SIGN (signx) && (rnd_mode == MPFR_RNDU ||
|
||||
rnd_mode == MPFR_RNDA))
|
||||
{
|
||||
mp_size_t yn;
|
||||
int sh;
|
||||
|
||||
yn = 1 + (MPFR_PREC(y) - 1) / GMP_NUMB_BITS;
|
||||
sh = (mpfr_prec_t) yn * GMP_NUMB_BITS - MPFR_PREC(y);
|
||||
MPFR_MANT(y)[0] += MPFR_LIMB_ONE << sh;
|
||||
inexact = 1;
|
||||
}
|
||||
else
|
||||
inexact = -MPFR_FROM_SIGN_TO_INT(signx);
|
||||
}
|
||||
|
||||
__gmpfr_emin = emin;
|
||||
__gmpfr_emax = emax;
|
||||
}
|
||||
else /* General case */
|
||||
{
|
||||
if (MPFR_UNLIKELY (precy >= MPFR_EXP_THRESHOLD))
|
||||
/* mpfr_exp_3 saves the exponent range and flags itself, otherwise
|
||||
the flag changes in mpfr_exp_3 are lost */
|
||||
inexact = mpfr_exp_3 (y, x, rnd_mode); /* O(M(n) log(n)^2) */
|
||||
else
|
||||
{
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
inexact = mpfr_exp_2 (y, x, rnd_mode); /* O(n^(1/3) M(n)) */
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
}
|
||||
}
|
||||
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/* mpfr_exp10 -- power of 10 function 10^y
|
||||
|
||||
Copyright 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
mpfr_exp10 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
return mpfr_ui_pow (y, 10, x, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/* mpfr_exp2 -- power of 2 function 2^y
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* The computation of y = 2^z is done by *
|
||||
* y = exp(z*log(2)). The result is exact iff z is an integer. */
|
||||
|
||||
int
|
||||
mpfr_exp2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
long xint;
|
||||
mpfr_t xfrac;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
else if (MPFR_IS_INF (x))
|
||||
{
|
||||
if (MPFR_IS_POS (x))
|
||||
MPFR_SET_INF (y);
|
||||
else
|
||||
MPFR_SET_ZERO (y);
|
||||
MPFR_SET_POS (y);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
else /* 2^0 = 1 */
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO(x));
|
||||
return mpfr_set_ui (y, 1, rnd_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* since the smallest representable non-zero float is 1/2*2^__gmpfr_emin,
|
||||
if x < __gmpfr_emin - 1, the result is either 1/2*2^__gmpfr_emin or 0 */
|
||||
MPFR_ASSERTN (MPFR_EMIN_MIN >= LONG_MIN + 2);
|
||||
if (MPFR_UNLIKELY (mpfr_cmp_si (x, __gmpfr_emin - 1) < 0))
|
||||
{
|
||||
mpfr_rnd_t rnd2 = rnd_mode;
|
||||
/* in round to nearest mode, round to zero when x <= __gmpfr_emin-2 */
|
||||
if (rnd_mode == MPFR_RNDN &&
|
||||
mpfr_cmp_si_2exp (x, __gmpfr_emin - 2, 0) <= 0)
|
||||
rnd2 = MPFR_RNDZ;
|
||||
return mpfr_underflow (y, rnd2, 1);
|
||||
}
|
||||
|
||||
MPFR_ASSERTN (MPFR_EMAX_MAX <= LONG_MAX);
|
||||
if (MPFR_UNLIKELY (mpfr_cmp_si (x, __gmpfr_emax) >= 0))
|
||||
return mpfr_overflow (y, rnd_mode, 1);
|
||||
|
||||
/* We now know that emin - 1 <= x < emax. */
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* 2^x = 1 + x*log(2) + O(x^2) for x near zero, and for |x| <= 1 we have
|
||||
|2^x - 1| <= x < 2^EXP(x). If x > 0 we must round away from 0 (dir=1);
|
||||
if x < 0 we must round toward 0 (dir=0). */
|
||||
MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (y, __gmpfr_one, - MPFR_GET_EXP (x), 0,
|
||||
MPFR_SIGN(x) > 0, rnd_mode, expo, {});
|
||||
|
||||
xint = mpfr_get_si (x, MPFR_RNDZ);
|
||||
mpfr_init2 (xfrac, MPFR_PREC (x));
|
||||
mpfr_sub_si (xfrac, x, xint, MPFR_RNDN); /* exact */
|
||||
|
||||
if (MPFR_IS_ZERO (xfrac))
|
||||
{
|
||||
mpfr_set_ui (y, 1, MPFR_RNDN);
|
||||
inexact = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Declaration of the intermediary variable */
|
||||
mpfr_t t;
|
||||
|
||||
/* Declaration of the size variable */
|
||||
mpfr_prec_t Ny = MPFR_PREC(y); /* target precision */
|
||||
mpfr_prec_t Nt; /* working precision */
|
||||
mpfr_exp_t err; /* error */
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
/* compute the precision of intermediary variable */
|
||||
/* the optimal number of bits : see algorithms.tex */
|
||||
Nt = Ny + 5 + MPFR_INT_CEIL_LOG2 (Ny);
|
||||
|
||||
/* initialise of intermediary variable */
|
||||
mpfr_init2 (t, Nt);
|
||||
|
||||
/* First computation */
|
||||
MPFR_ZIV_INIT (loop, Nt);
|
||||
for (;;)
|
||||
{
|
||||
/* compute exp(x*ln(2))*/
|
||||
mpfr_const_log2 (t, MPFR_RNDU); /* ln(2) */
|
||||
mpfr_mul (t, xfrac, t, MPFR_RNDU); /* xfrac * ln(2) */
|
||||
err = Nt - (MPFR_GET_EXP (t) + 2); /* Estimate of the error */
|
||||
mpfr_exp (t, t, MPFR_RNDN); /* exp(xfrac * ln(2)) */
|
||||
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
|
||||
break;
|
||||
|
||||
/* Actualisation of the precision */
|
||||
MPFR_ZIV_NEXT (loop, Nt);
|
||||
mpfr_set_prec (t, Nt);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
inexact = mpfr_set (y, t, rnd_mode);
|
||||
|
||||
mpfr_clear (t);
|
||||
}
|
||||
|
||||
mpfr_clear (xfrac);
|
||||
mpfr_clear_flags ();
|
||||
mpfr_mul_2si (y, y, xint, MPFR_RNDN); /* exact or overflow */
|
||||
/* Note: We can have an overflow only when t was rounded up to 2. */
|
||||
MPFR_ASSERTD (MPFR_IS_PURE_FP (y) || inexact > 0);
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,333 @@
|
|||
/* mpfr_exp -- exponential of a floating-point number
|
||||
|
||||
Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H /* for MPFR_MPZ_SIZEINBASE2 */
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* y <- exp(p/2^r) within 1 ulp, using 2^m terms from the series
|
||||
Assume |p/2^r| < 1.
|
||||
We use the following binary splitting formula:
|
||||
P(a,b) = p if a+1=b, P(a,c)*P(c,b) otherwise
|
||||
Q(a,b) = a*2^r if a+1=b [except Q(0,1)=1], Q(a,c)*Q(c,b) otherwise
|
||||
T(a,b) = P(a,b) if a+1=b, Q(c,b)*T(a,c)+P(a,c)*T(c,b) otherwise
|
||||
Then exp(p/2^r) ~ T(0,i)/Q(0,i) for i so that (p/2^r)^i/i! is small enough.
|
||||
|
||||
Since P(a,b) = p^(b-a), and we consider only values of b-a of the form 2^j,
|
||||
we don't need to compute P(), we only precompute p^(2^j) in the ptoj[] array
|
||||
below.
|
||||
|
||||
Since Q(a,b) is divisible by 2^(r*(b-a-1)), we don't compute the power of
|
||||
two part.
|
||||
*/
|
||||
static void
|
||||
mpfr_exp_rational (mpfr_ptr y, mpz_ptr p, long r, int m,
|
||||
mpz_t *Q, mpfr_prec_t *mult)
|
||||
{
|
||||
unsigned long n, i, j;
|
||||
mpz_t *S, *ptoj;
|
||||
mpfr_prec_t *log2_nb_terms;
|
||||
mpfr_exp_t diff, expo;
|
||||
mpfr_prec_t precy = MPFR_PREC(y), prec_i_have, prec_ptoj;
|
||||
int k, l;
|
||||
|
||||
MPFR_ASSERTN ((size_t) m < sizeof (long) * CHAR_BIT - 1);
|
||||
|
||||
S = Q + (m+1);
|
||||
ptoj = Q + 2*(m+1); /* ptoj[i] = mantissa^(2^i) */
|
||||
log2_nb_terms = mult + (m+1);
|
||||
|
||||
/* Normalize p */
|
||||
MPFR_ASSERTD (mpz_cmp_ui (p, 0) != 0);
|
||||
n = mpz_scan1 (p, 0); /* number of trailing zeros in p */
|
||||
mpz_tdiv_q_2exp (p, p, n);
|
||||
r -= n; /* since |p/2^r| < 1 and p >= 1, r >= 1 */
|
||||
|
||||
/* Set initial var */
|
||||
mpz_set (ptoj[0], p);
|
||||
for (k = 1; k < m; k++)
|
||||
mpz_mul (ptoj[k], ptoj[k-1], ptoj[k-1]); /* ptoj[k] = p^(2^k) */
|
||||
mpz_set_ui (Q[0], 1);
|
||||
mpz_set_ui (S[0], 1);
|
||||
k = 0;
|
||||
mult[0] = 0; /* the multiplier P[k]/Q[k] for the remaining terms
|
||||
satisfies P[k]/Q[k] <= 2^(-mult[k]) */
|
||||
log2_nb_terms[0] = 0; /* log2(#terms) [exact in 1st loop where 2^k] */
|
||||
prec_i_have = 0;
|
||||
|
||||
/* Main Loop */
|
||||
n = 1UL << m;
|
||||
for (i = 1; (prec_i_have < precy) && (i < n); i++)
|
||||
{
|
||||
/* invariant: Q[0]*Q[1]*...*Q[k] equals i! */
|
||||
k++;
|
||||
log2_nb_terms[k] = 0; /* 1 term */
|
||||
mpz_set_ui (Q[k], i + 1);
|
||||
mpz_set_ui (S[k], i + 1);
|
||||
j = i + 1; /* we have computed j = i+1 terms so far */
|
||||
l = 0;
|
||||
while ((j & 1) == 0) /* combine and reduce */
|
||||
{
|
||||
/* invariant: S[k] corresponds to 2^l consecutive terms */
|
||||
mpz_mul (S[k], S[k], ptoj[l]);
|
||||
mpz_mul (S[k-1], S[k-1], Q[k]);
|
||||
/* Q[k] corresponds to 2^l consecutive terms too.
|
||||
Since it does not contains the factor 2^(r*2^l),
|
||||
when going from l to l+1 we need to multiply
|
||||
by 2^(r*2^(l+1))/2^(r*2^l) = 2^(r*2^l) */
|
||||
mpz_mul_2exp (S[k-1], S[k-1], r << l);
|
||||
mpz_add (S[k-1], S[k-1], S[k]);
|
||||
mpz_mul (Q[k-1], Q[k-1], Q[k]);
|
||||
log2_nb_terms[k-1] ++; /* number of terms in S[k-1]
|
||||
is a power of 2 by construction */
|
||||
MPFR_MPZ_SIZEINBASE2 (prec_i_have, Q[k]);
|
||||
MPFR_MPZ_SIZEINBASE2 (prec_ptoj, ptoj[l]);
|
||||
mult[k-1] += prec_i_have + (r << l) - prec_ptoj - 1;
|
||||
prec_i_have = mult[k] = mult[k-1];
|
||||
/* since mult[k] >= mult[k-1] + nbits(Q[k]),
|
||||
we have Q[0]*...*Q[k] <= 2^mult[k] = 2^prec_i_have */
|
||||
l ++;
|
||||
j >>= 1;
|
||||
k --;
|
||||
}
|
||||
}
|
||||
|
||||
/* accumulate all products in S[0] and Q[0]. Warning: contrary to above,
|
||||
here we do not have log2_nb_terms[k-1] = log2_nb_terms[k]+1. */
|
||||
l = 0; /* number of accumulated terms in the right part S[k]/Q[k] */
|
||||
while (k > 0)
|
||||
{
|
||||
j = log2_nb_terms[k-1];
|
||||
mpz_mul (S[k], S[k], ptoj[j]);
|
||||
mpz_mul (S[k-1], S[k-1], Q[k]);
|
||||
l += 1 << log2_nb_terms[k];
|
||||
mpz_mul_2exp (S[k-1], S[k-1], r * l);
|
||||
mpz_add (S[k-1], S[k-1], S[k]);
|
||||
mpz_mul (Q[k-1], Q[k-1], Q[k]);
|
||||
k--;
|
||||
}
|
||||
|
||||
/* Q[0] now equals i! */
|
||||
MPFR_MPZ_SIZEINBASE2 (prec_i_have, S[0]);
|
||||
diff = (mpfr_exp_t) prec_i_have - 2 * (mpfr_exp_t) precy;
|
||||
expo = diff;
|
||||
if (diff >= 0)
|
||||
mpz_fdiv_q_2exp (S[0], S[0], diff);
|
||||
else
|
||||
mpz_mul_2exp (S[0], S[0], -diff);
|
||||
|
||||
MPFR_MPZ_SIZEINBASE2 (prec_i_have, Q[0]);
|
||||
diff = (mpfr_exp_t) prec_i_have - (mpfr_prec_t) precy;
|
||||
expo -= diff;
|
||||
if (diff > 0)
|
||||
mpz_fdiv_q_2exp (Q[0], Q[0], diff);
|
||||
else
|
||||
mpz_mul_2exp (Q[0], Q[0], -diff);
|
||||
|
||||
mpz_tdiv_q (S[0], S[0], Q[0]);
|
||||
mpfr_set_z (y, S[0], MPFR_RNDD);
|
||||
MPFR_SET_EXP (y, MPFR_GET_EXP (y) + expo - r * (i - 1) );
|
||||
}
|
||||
|
||||
#define shift (GMP_NUMB_BITS/2)
|
||||
|
||||
int
|
||||
mpfr_exp_3 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t t, x_copy, tmp;
|
||||
mpz_t uk;
|
||||
mpfr_exp_t ttt, shift_x;
|
||||
unsigned long twopoweri;
|
||||
mpz_t *P;
|
||||
mpfr_prec_t *mult;
|
||||
int i, k, loop;
|
||||
int prec_x;
|
||||
mpfr_prec_t realprec, Prec;
|
||||
int iter;
|
||||
int inexact = 0;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_ZIV_DECL (ziv_loop);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* decompose x */
|
||||
/* we first write x = 1.xxxxxxxxxxxxx
|
||||
----- k bits -- */
|
||||
prec_x = MPFR_INT_CEIL_LOG2 (MPFR_PREC (x)) - MPFR_LOG2_GMP_NUMB_BITS;
|
||||
if (prec_x < 0)
|
||||
prec_x = 0;
|
||||
|
||||
ttt = MPFR_GET_EXP (x);
|
||||
mpfr_init2 (x_copy, MPFR_PREC(x));
|
||||
mpfr_set (x_copy, x, MPFR_RNDD);
|
||||
|
||||
/* we shift to get a number less than 1 */
|
||||
if (ttt > 0)
|
||||
{
|
||||
shift_x = ttt;
|
||||
mpfr_div_2ui (x_copy, x, ttt, MPFR_RNDN);
|
||||
ttt = MPFR_GET_EXP (x_copy);
|
||||
}
|
||||
else
|
||||
shift_x = 0;
|
||||
MPFR_ASSERTD (ttt <= 0);
|
||||
|
||||
/* Init prec and vars */
|
||||
realprec = MPFR_PREC (y) + MPFR_INT_CEIL_LOG2 (prec_x + MPFR_PREC (y));
|
||||
Prec = realprec + shift + 2 + shift_x;
|
||||
mpfr_init2 (t, Prec);
|
||||
mpfr_init2 (tmp, Prec);
|
||||
mpz_init (uk);
|
||||
|
||||
/* Main loop */
|
||||
MPFR_ZIV_INIT (ziv_loop, realprec);
|
||||
for (;;)
|
||||
{
|
||||
int scaled = 0;
|
||||
MPFR_BLOCK_DECL (flags);
|
||||
|
||||
k = MPFR_INT_CEIL_LOG2 (Prec) - MPFR_LOG2_GMP_NUMB_BITS;
|
||||
|
||||
/* now we have to extract */
|
||||
twopoweri = GMP_NUMB_BITS;
|
||||
|
||||
/* Allocate tables */
|
||||
P = (mpz_t*) (*__gmp_allocate_func) (3*(k+2)*sizeof(mpz_t));
|
||||
for (i = 0; i < 3*(k+2); i++)
|
||||
mpz_init (P[i]);
|
||||
mult = (mpfr_prec_t*) (*__gmp_allocate_func) (2*(k+2)*sizeof(mpfr_prec_t));
|
||||
|
||||
/* Particular case for i==0 */
|
||||
mpfr_extract (uk, x_copy, 0);
|
||||
MPFR_ASSERTD (mpz_cmp_ui (uk, 0) != 0);
|
||||
mpfr_exp_rational (tmp, uk, shift + twopoweri - ttt, k + 1, P, mult);
|
||||
for (loop = 0; loop < shift; loop++)
|
||||
mpfr_sqr (tmp, tmp, MPFR_RNDD);
|
||||
twopoweri *= 2;
|
||||
|
||||
/* General case */
|
||||
iter = (k <= prec_x) ? k : prec_x;
|
||||
for (i = 1; i <= iter; i++)
|
||||
{
|
||||
mpfr_extract (uk, x_copy, i);
|
||||
if (MPFR_LIKELY (mpz_cmp_ui (uk, 0) != 0))
|
||||
{
|
||||
mpfr_exp_rational (t, uk, twopoweri - ttt, k - i + 1, P, mult);
|
||||
mpfr_mul (tmp, tmp, t, MPFR_RNDD);
|
||||
}
|
||||
MPFR_ASSERTN (twopoweri <= LONG_MAX/2);
|
||||
twopoweri *=2;
|
||||
}
|
||||
|
||||
/* Clear tables */
|
||||
for (i = 0; i < 3*(k+2); i++)
|
||||
mpz_clear (P[i]);
|
||||
(*__gmp_free_func) (P, 3*(k+2)*sizeof(mpz_t));
|
||||
(*__gmp_free_func) (mult, 2*(k+2)*sizeof(mpfr_prec_t));
|
||||
|
||||
if (shift_x > 0)
|
||||
{
|
||||
MPFR_BLOCK (flags, {
|
||||
for (loop = 0; loop < shift_x - 1; loop++)
|
||||
mpfr_sqr (tmp, tmp, MPFR_RNDD);
|
||||
mpfr_sqr (t, tmp, MPFR_RNDD);
|
||||
} );
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags)))
|
||||
{
|
||||
/* tmp <= exact result, so that it is a real overflow. */
|
||||
inexact = mpfr_overflow (y, rnd_mode, 1);
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_OVERFLOW);
|
||||
break;
|
||||
}
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_UNDERFLOW (flags)))
|
||||
{
|
||||
/* This may be a spurious underflow. So, let's scale
|
||||
the result. */
|
||||
mpfr_mul_2ui (tmp, tmp, 1, MPFR_RNDD); /* no overflow, exact */
|
||||
mpfr_sqr (t, tmp, MPFR_RNDD);
|
||||
if (MPFR_IS_ZERO (t))
|
||||
{
|
||||
/* approximate result < 2^(emin - 3), thus
|
||||
exact result < 2^(emin - 2). */
|
||||
inexact = mpfr_underflow (y, (rnd_mode == MPFR_RNDN) ?
|
||||
MPFR_RNDZ : rnd_mode, 1);
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_UNDERFLOW);
|
||||
break;
|
||||
}
|
||||
scaled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mpfr_can_round (shift_x > 0 ? t : tmp, realprec, MPFR_RNDD, MPFR_RNDZ,
|
||||
MPFR_PREC(y) + (rnd_mode == MPFR_RNDN)))
|
||||
{
|
||||
inexact = mpfr_set (y, shift_x > 0 ? t : tmp, rnd_mode);
|
||||
if (MPFR_UNLIKELY (scaled && MPFR_IS_PURE_FP (y)))
|
||||
{
|
||||
int inex2;
|
||||
mpfr_exp_t ey;
|
||||
|
||||
/* The result has been scaled and needs to be corrected. */
|
||||
ey = MPFR_GET_EXP (y);
|
||||
inex2 = mpfr_mul_2si (y, y, -2, rnd_mode);
|
||||
if (inex2) /* underflow */
|
||||
{
|
||||
if (rnd_mode == MPFR_RNDN && inexact < 0 &&
|
||||
MPFR_IS_ZERO (y) && ey == __gmpfr_emin + 1)
|
||||
{
|
||||
/* Double rounding case: in MPFR_RNDN, the scaled
|
||||
result has been rounded downward to 2^emin.
|
||||
As the exact result is > 2^(emin - 2), correct
|
||||
rounding must be done upward. */
|
||||
/* TODO: make sure in coverage tests that this line
|
||||
is reached. */
|
||||
inexact = mpfr_underflow (y, MPFR_RNDU, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No double rounding. */
|
||||
inexact = inex2;
|
||||
}
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_UNDERFLOW);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
MPFR_ZIV_NEXT (ziv_loop, realprec);
|
||||
Prec = realprec + shift + 2 + shift_x;
|
||||
mpfr_set_prec (t, Prec);
|
||||
mpfr_set_prec (tmp, Prec);
|
||||
}
|
||||
MPFR_ZIV_FREE (ziv_loop);
|
||||
|
||||
mpz_clear (uk);
|
||||
mpfr_clear (tmp);
|
||||
mpfr_clear (t);
|
||||
mpfr_clear (x_copy);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return inexact;
|
||||
}
|
|
@ -0,0 +1,414 @@
|
|||
/* mpfr_exp_2 -- exponential of a floating-point number
|
||||
using algorithms in O(n^(1/2)*M(n)) and O(n^(1/3)*M(n))
|
||||
|
||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* #define DEBUG */
|
||||
#define MPFR_NEED_LONGLONG_H /* for count_leading_zeros */
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
static unsigned long
|
||||
mpfr_exp2_aux (mpz_t, mpfr_srcptr, mpfr_prec_t, mpfr_exp_t *);
|
||||
static unsigned long
|
||||
mpfr_exp2_aux2 (mpz_t, mpfr_srcptr, mpfr_prec_t, mpfr_exp_t *);
|
||||
static mpfr_exp_t
|
||||
mpz_normalize (mpz_t, mpz_t, mpfr_exp_t);
|
||||
static mpfr_exp_t
|
||||
mpz_normalize2 (mpz_t, mpz_t, mpfr_exp_t, mpfr_exp_t);
|
||||
|
||||
/* if k = the number of bits of z > q, divides z by 2^(k-q) and returns k-q.
|
||||
Otherwise do nothing and return 0.
|
||||
*/
|
||||
static mpfr_exp_t
|
||||
mpz_normalize (mpz_t rop, mpz_t z, mpfr_exp_t q)
|
||||
{
|
||||
size_t k;
|
||||
|
||||
MPFR_MPZ_SIZEINBASE2 (k, z);
|
||||
MPFR_ASSERTD (k == (mpfr_uexp_t) k);
|
||||
if (q < 0 || (mpfr_uexp_t) k > (mpfr_uexp_t) q)
|
||||
{
|
||||
mpz_fdiv_q_2exp (rop, z, (unsigned long) ((mpfr_uexp_t) k - q));
|
||||
return (mpfr_exp_t) k - q;
|
||||
}
|
||||
if (MPFR_UNLIKELY(rop != z))
|
||||
mpz_set (rop, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if expz > target, shift z by (expz-target) bits to the left.
|
||||
if expz < target, shift z by (target-expz) bits to the right.
|
||||
Returns target.
|
||||
*/
|
||||
static mpfr_exp_t
|
||||
mpz_normalize2 (mpz_t rop, mpz_t z, mpfr_exp_t expz, mpfr_exp_t target)
|
||||
{
|
||||
if (target > expz)
|
||||
mpz_fdiv_q_2exp (rop, z, target - expz);
|
||||
else
|
||||
mpz_mul_2exp (rop, z, expz - target);
|
||||
return target;
|
||||
}
|
||||
|
||||
/* use Brent's formula exp(x) = (1+r+r^2/2!+r^3/3!+...)^(2^K)*2^n
|
||||
where x = n*log(2)+(2^K)*r
|
||||
together with the Paterson-Stockmeyer O(t^(1/2)) algorithm for the
|
||||
evaluation of power series. The resulting complexity is O(n^(1/3)*M(n)).
|
||||
This function returns with the exact flags due to exp.
|
||||
*/
|
||||
int
|
||||
mpfr_exp_2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
long n;
|
||||
unsigned long K, k, l, err; /* FIXME: Which type ? */
|
||||
int error_r;
|
||||
mpfr_exp_t exps;
|
||||
mpfr_prec_t q, precy;
|
||||
int inexact;
|
||||
mpfr_t r, s;
|
||||
mpz_t ss;
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
|
||||
("y[%#R]=%R inexact=%d", y, y, inexact));
|
||||
|
||||
precy = MPFR_PREC(y);
|
||||
|
||||
/* Warning: we cannot use the 'double' type here, since on 64-bit machines
|
||||
x may be as large as 2^62*log(2) without overflow, and then x/log(2)
|
||||
is about 2^62: not every integer of that size can be represented as a
|
||||
'double', thus the argument reduction would fail. */
|
||||
if (MPFR_GET_EXP (x) <= -2)
|
||||
/* |x| <= 0.25, thus n = round(x/log(2)) = 0 */
|
||||
n = 0;
|
||||
else
|
||||
{
|
||||
mpfr_init2 (r, sizeof (long) * CHAR_BIT);
|
||||
mpfr_const_log2 (r, MPFR_RNDZ);
|
||||
mpfr_div (r, x, r, MPFR_RNDN);
|
||||
n = mpfr_get_si (r, MPFR_RNDN);
|
||||
mpfr_clear (r);
|
||||
}
|
||||
MPFR_LOG_MSG (("d(x)=%1.30e n=%ld\n", mpfr_get_d1(x), n));
|
||||
|
||||
/* error bounds the cancelled bits in x - n*log(2) */
|
||||
if (MPFR_UNLIKELY (n == 0))
|
||||
error_r = 0;
|
||||
else
|
||||
count_leading_zeros (error_r, (mp_limb_t) SAFE_ABS (unsigned long, n));
|
||||
error_r = GMP_NUMB_BITS - error_r + 2;
|
||||
|
||||
/* for the O(n^(1/2)*M(n)) method, the Taylor series computation of
|
||||
n/K terms costs about n/(2K) multiplications when computed in fixed
|
||||
point */
|
||||
K = (precy < MPFR_EXP_2_THRESHOLD) ? __gmpfr_isqrt ((precy + 1) / 2)
|
||||
: __gmpfr_cuberoot (4*precy);
|
||||
l = (precy - 1) / K + 1;
|
||||
err = K + MPFR_INT_CEIL_LOG2 (2 * l + 18);
|
||||
/* add K extra bits, i.e. failure probability <= 1/2^K = O(1/precy) */
|
||||
q = precy + err + K + 5;
|
||||
|
||||
/* Note: due to the mpfr_prec_round below, it is not possible to use
|
||||
the MPFR_GROUP_* macros here. */
|
||||
mpfr_init2 (r, q + error_r);
|
||||
mpfr_init2 (s, q + error_r);
|
||||
|
||||
/* the algorithm consists in computing an upper bound of exp(x) using
|
||||
a precision of q bits, and see if we can round to MPFR_PREC(y) taking
|
||||
into account the maximal error. Otherwise we increase q. */
|
||||
MPFR_ZIV_INIT (loop, q);
|
||||
for (;;)
|
||||
{
|
||||
MPFR_LOG_MSG (("n=%ld K=%lu l=%lu q=%lu error_r=%d\n",
|
||||
n, K, l, (unsigned long) q, error_r));
|
||||
|
||||
/* First reduce the argument to r = x - n * log(2),
|
||||
so that r is small in absolute value. We want an upper
|
||||
bound on r to get an upper bound on exp(x). */
|
||||
|
||||
/* if n<0, we have to get an upper bound of log(2)
|
||||
in order to get an upper bound of r = x-n*log(2) */
|
||||
mpfr_const_log2 (s, (n >= 0) ? MPFR_RNDZ : MPFR_RNDU);
|
||||
/* s is within 1 ulp of log(2) */
|
||||
|
||||
mpfr_mul_ui (r, s, (n < 0) ? -n : n, (n >= 0) ? MPFR_RNDZ : MPFR_RNDU);
|
||||
/* r is within 3 ulps of |n|*log(2) */
|
||||
if (n < 0)
|
||||
MPFR_CHANGE_SIGN (r);
|
||||
/* r <= n*log(2), within 3 ulps */
|
||||
|
||||
MPFR_LOG_VAR (x);
|
||||
MPFR_LOG_VAR (r);
|
||||
|
||||
mpfr_sub (r, x, r, MPFR_RNDU);
|
||||
/* possible cancellation here: if r is zero, increase the working
|
||||
precision (Ziv's loop); otherwise, the error on r is at most
|
||||
3*2^(EXP(old_r)-EXP(new_r)) ulps */
|
||||
|
||||
if (MPFR_IS_PURE_FP (r))
|
||||
{
|
||||
mpfr_exp_t cancel;
|
||||
|
||||
/* number of cancelled bits */
|
||||
cancel = MPFR_GET_EXP (x) - MPFR_GET_EXP (r);
|
||||
if (cancel < 0) /* this might happen in the second loop if x is
|
||||
tiny negative: the initial n is 0, then in the
|
||||
first loop n becomes -1 and r = x + log(2) */
|
||||
cancel = 0;
|
||||
while (MPFR_IS_NEG (r))
|
||||
{ /* initial approximation n was too large */
|
||||
n--;
|
||||
mpfr_add (r, r, s, MPFR_RNDU);
|
||||
}
|
||||
mpfr_prec_round (r, q, MPFR_RNDU);
|
||||
MPFR_LOG_VAR (r);
|
||||
MPFR_ASSERTD (MPFR_IS_POS (r));
|
||||
mpfr_div_2ui (r, r, K, MPFR_RNDU); /* r = (x-n*log(2))/2^K, exact */
|
||||
|
||||
mpz_init (ss);
|
||||
exps = mpfr_get_z_2exp (ss, s);
|
||||
/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! */
|
||||
MPFR_ASSERTD (MPFR_IS_PURE_FP (r) && MPFR_EXP (r) < 0);
|
||||
l = (precy < MPFR_EXP_2_THRESHOLD)
|
||||
? mpfr_exp2_aux (ss, r, q, &exps) /* naive method */
|
||||
: mpfr_exp2_aux2 (ss, r, q, &exps); /* Paterson/Stockmeyer meth */
|
||||
|
||||
MPFR_LOG_MSG (("l=%lu q=%lu (K+l)*q^2=%1.3e\n",
|
||||
l, (unsigned long) q, (K + l) * (double) q * q));
|
||||
|
||||
for (k = 0; k < K; k++)
|
||||
{
|
||||
mpz_mul (ss, ss, ss);
|
||||
exps <<= 1;
|
||||
exps += mpz_normalize (ss, ss, q);
|
||||
}
|
||||
mpfr_set_z (s, ss, MPFR_RNDN);
|
||||
|
||||
MPFR_SET_EXP(s, MPFR_GET_EXP (s) + exps);
|
||||
mpz_clear (ss);
|
||||
|
||||
/* error is at most 2^K*l, plus cancel+2 to take into account of
|
||||
the error of 3*2^(EXP(old_r)-EXP(new_r)) on r */
|
||||
K += MPFR_INT_CEIL_LOG2 (l) + cancel + 2;
|
||||
|
||||
MPFR_LOG_MSG (("before mult. by 2^n:\n", 0));
|
||||
MPFR_LOG_VAR (s);
|
||||
MPFR_LOG_MSG (("err=%lu bits\n", K));
|
||||
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (s, q - K, precy, rnd_mode)))
|
||||
{
|
||||
mpfr_clear_flags ();
|
||||
inexact = mpfr_mul_2si (y, s, n, rnd_mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MPFR_ZIV_NEXT (loop, q);
|
||||
mpfr_set_prec (r, q);
|
||||
mpfr_set_prec (s, q);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
mpfr_clear (r);
|
||||
mpfr_clear (s);
|
||||
|
||||
return inexact;
|
||||
}
|
||||
|
||||
/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! while MPFR_EXP(r^l/l!)+MPFR_EXPR(r)>-q
|
||||
using naive method with O(l) multiplications.
|
||||
Return the number of iterations l.
|
||||
The absolute error on s is less than 3*l*(l+1)*2^(-q).
|
||||
Version using fixed-point arithmetic with mpz instead
|
||||
of mpfr for internal computations.
|
||||
s must have at least qn+1 limbs (qn should be enough, but currently fails
|
||||
since mpz_mul_2exp(s, s, q-1) reallocates qn+1 limbs)
|
||||
*/
|
||||
static unsigned long
|
||||
mpfr_exp2_aux (mpz_t s, mpfr_srcptr r, mpfr_prec_t q, mpfr_exp_t *exps)
|
||||
{
|
||||
unsigned long l;
|
||||
mpfr_exp_t dif, expt, expr;
|
||||
mp_size_t qn;
|
||||
mpz_t t, rr;
|
||||
mp_size_t sbit, tbit;
|
||||
|
||||
MPFR_ASSERTN (MPFR_IS_PURE_FP (r));
|
||||
|
||||
qn = 1 + (q-1)/GMP_NUMB_BITS;
|
||||
expt = 0;
|
||||
*exps = 1 - (mpfr_exp_t) q; /* s = 2^(q-1) */
|
||||
mpz_init (t);
|
||||
mpz_init (rr);
|
||||
mpz_set_ui(t, 1);
|
||||
mpz_set_ui(s, 1);
|
||||
mpz_mul_2exp(s, s, q-1);
|
||||
expr = mpfr_get_z_2exp(rr, r); /* no error here */
|
||||
|
||||
l = 0;
|
||||
for (;;) {
|
||||
l++;
|
||||
mpz_mul(t, t, rr);
|
||||
expt += expr;
|
||||
MPFR_MPZ_SIZEINBASE2 (sbit, s);
|
||||
MPFR_MPZ_SIZEINBASE2 (tbit, t);
|
||||
dif = *exps + sbit - expt - tbit;
|
||||
/* truncates the bits of t which are < ulp(s) = 2^(1-q) */
|
||||
expt += mpz_normalize(t, t, (mpfr_exp_t) q-dif); /* error at most 2^(1-q) */
|
||||
mpz_fdiv_q_ui (t, t, l); /* error at most 2^(1-q) */
|
||||
/* the error wrt t^l/l! is here at most 3*l*ulp(s) */
|
||||
MPFR_ASSERTD (expt == *exps);
|
||||
if (mpz_sgn (t) == 0)
|
||||
break;
|
||||
mpz_add(s, s, t); /* no error here: exact */
|
||||
/* ensures rr has the same size as t: after several shifts, the error
|
||||
on rr is still at most ulp(t)=ulp(s) */
|
||||
MPFR_MPZ_SIZEINBASE2 (tbit, t);
|
||||
expr += mpz_normalize(rr, rr, tbit);
|
||||
}
|
||||
|
||||
mpz_clear (t);
|
||||
mpz_clear (rr);
|
||||
|
||||
return 3 * l * (l + 1);
|
||||
}
|
||||
|
||||
/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! while MPFR_EXP(r^l/l!)+MPFR_EXPR(r)>-q
|
||||
using Paterson-Stockmeyer algorithm with O(sqrt(l)) multiplications.
|
||||
Return l.
|
||||
Uses m multiplications of full size and 2l/m of decreasing size,
|
||||
i.e. a total equivalent to about m+l/m full multiplications,
|
||||
i.e. 2*sqrt(l) for m=sqrt(l).
|
||||
Version using mpz. ss must have at least (sizer+1) limbs.
|
||||
The error is bounded by (l^2+4*l) ulps where l is the return value.
|
||||
*/
|
||||
static unsigned long
|
||||
mpfr_exp2_aux2 (mpz_t s, mpfr_srcptr r, mpfr_prec_t q, mpfr_exp_t *exps)
|
||||
{
|
||||
mpfr_exp_t expr, *expR, expt;
|
||||
mp_size_t sizer;
|
||||
mpfr_prec_t ql;
|
||||
unsigned long l, m, i;
|
||||
mpz_t t, *R, rr, tmp;
|
||||
mp_size_t sbit, rrbit;
|
||||
MPFR_TMP_DECL(marker);
|
||||
|
||||
/* estimate value of l */
|
||||
MPFR_ASSERTD (MPFR_GET_EXP (r) < 0);
|
||||
l = q / (- MPFR_GET_EXP (r));
|
||||
m = __gmpfr_isqrt (l);
|
||||
/* we access R[2], thus we need m >= 2 */
|
||||
if (m < 2)
|
||||
m = 2;
|
||||
|
||||
MPFR_TMP_MARK(marker);
|
||||
R = (mpz_t*) MPFR_TMP_ALLOC ((m + 1) * sizeof (mpz_t)); /* R[i] is r^i */
|
||||
expR = (mpfr_exp_t*) MPFR_TMP_ALLOC((m + 1) * sizeof (mpfr_exp_t));
|
||||
/* expR[i] is the exponent for R[i] */
|
||||
sizer = MPFR_LIMB_SIZE(r);
|
||||
mpz_init (tmp);
|
||||
mpz_init (rr);
|
||||
mpz_init (t);
|
||||
mpz_set_ui (s, 0);
|
||||
*exps = 1 - q; /* 1 ulp = 2^(1-q) */
|
||||
for (i = 0 ; i <= m ; i++)
|
||||
mpz_init (R[i]);
|
||||
expR[1] = mpfr_get_z_2exp (R[1], r); /* exact operation: no error */
|
||||
expR[1] = mpz_normalize2 (R[1], R[1], expR[1], 1 - q); /* error <= 1 ulp */
|
||||
mpz_mul (t, R[1], R[1]); /* err(t) <= 2 ulps */
|
||||
mpz_fdiv_q_2exp (R[2], t, q - 1); /* err(R[2]) <= 3 ulps */
|
||||
expR[2] = 1 - q;
|
||||
for (i = 3 ; i <= m ; i++)
|
||||
{
|
||||
if ((i & 1) == 1)
|
||||
mpz_mul (t, R[i-1], R[1]); /* err(t) <= 2*i-2 */
|
||||
else
|
||||
mpz_mul (t, R[i/2], R[i/2]);
|
||||
mpz_fdiv_q_2exp (R[i], t, q - 1); /* err(R[i]) <= 2*i-1 ulps */
|
||||
expR[i] = 1 - q;
|
||||
}
|
||||
mpz_set_ui (R[0], 1);
|
||||
mpz_mul_2exp (R[0], R[0], q-1);
|
||||
expR[0] = 1-q; /* R[0]=1 */
|
||||
mpz_set_ui (rr, 1);
|
||||
expr = 0; /* rr contains r^l/l! */
|
||||
/* by induction: err(rr) <= 2*l ulps */
|
||||
|
||||
l = 0;
|
||||
ql = q; /* precision used for current giant step */
|
||||
do
|
||||
{
|
||||
/* all R[i] must have exponent 1-ql */
|
||||
if (l != 0)
|
||||
for (i = 0 ; i < m ; i++)
|
||||
expR[i] = mpz_normalize2 (R[i], R[i], expR[i], 1 - ql);
|
||||
/* the absolute error on R[i]*rr is still 2*i-1 ulps */
|
||||
expt = mpz_normalize2 (t, R[m-1], expR[m-1], 1 - ql);
|
||||
/* err(t) <= 2*m-1 ulps */
|
||||
/* computes t = 1 + r/(l+1) + ... + r^(m-1)*l!/(l+m-1)!
|
||||
using Horner's scheme */
|
||||
for (i = m-1 ; i-- != 0 ; )
|
||||
{
|
||||
mpz_fdiv_q_ui (t, t, l+i+1); /* err(t) += 1 ulp */
|
||||
mpz_add (t, t, R[i]);
|
||||
}
|
||||
/* now err(t) <= (3m-2) ulps */
|
||||
|
||||
/* now multiplies t by r^l/l! and adds to s */
|
||||
mpz_mul (t, t, rr);
|
||||
expt += expr;
|
||||
expt = mpz_normalize2 (t, t, expt, *exps);
|
||||
/* err(t) <= (3m-1) + err_rr(l) <= (3m-2) + 2*l */
|
||||
MPFR_ASSERTD (expt == *exps);
|
||||
mpz_add (s, s, t); /* no error here */
|
||||
|
||||
/* updates rr, the multiplication of the factors l+i could be done
|
||||
using binary splitting too, but it is not sure it would save much */
|
||||
mpz_mul (t, rr, R[m]); /* err(t) <= err(rr) + 2m-1 */
|
||||
expr += expR[m];
|
||||
mpz_set_ui (tmp, 1);
|
||||
for (i = 1 ; i <= m ; i++)
|
||||
mpz_mul_ui (tmp, tmp, l + i);
|
||||
mpz_fdiv_q (t, t, tmp); /* err(t) <= err(rr) + 2m */
|
||||
l += m;
|
||||
if (MPFR_UNLIKELY (mpz_sgn (t) == 0))
|
||||
break;
|
||||
expr += mpz_normalize (rr, t, ql); /* err_rr(l+1) <= err_rr(l) + 2m+1 */
|
||||
if (MPFR_UNLIKELY (mpz_sgn (rr) == 0))
|
||||
rrbit = 1;
|
||||
else
|
||||
MPFR_MPZ_SIZEINBASE2 (rrbit, rr);
|
||||
MPFR_MPZ_SIZEINBASE2 (sbit, s);
|
||||
ql = q - *exps - sbit + expr + rrbit;
|
||||
/* TODO: Wrong cast. I don't want what is right, but this is
|
||||
certainly wrong */
|
||||
}
|
||||
while ((size_t) expr + rrbit > (size_t) -q);
|
||||
|
||||
for (i = 0 ; i <= m ; i++)
|
||||
mpz_clear (R[i]);
|
||||
MPFR_TMP_FREE(marker);
|
||||
mpz_clear (rr);
|
||||
mpz_clear (t);
|
||||
mpz_clear (tmp);
|
||||
|
||||
return l * (l + 4);
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/* mpfr_expm1 -- Compute exp(x)-1
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* The computation of expm1 is done by
|
||||
expm1(x)=exp(x)-1
|
||||
*/
|
||||
|
||||
int
|
||||
mpfr_expm1 (mpfr_ptr y, mpfr_srcptr x , mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
int inexact;
|
||||
mpfr_exp_t ex;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
|
||||
{
|
||||
if (MPFR_IS_NAN (x))
|
||||
{
|
||||
MPFR_SET_NAN (y);
|
||||
MPFR_RET_NAN;
|
||||
}
|
||||
/* check for inf or -inf (expm1(-inf)=-1) */
|
||||
else if (MPFR_IS_INF (x))
|
||||
{
|
||||
if (MPFR_IS_POS (x))
|
||||
{
|
||||
MPFR_SET_INF (y);
|
||||
MPFR_SET_POS (y);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
else
|
||||
return mpfr_set_si (y, -1, rnd_mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFR_ASSERTD (MPFR_IS_ZERO (x));
|
||||
MPFR_SET_ZERO (y); /* expm1(+/- 0) = +/- 0 */
|
||||
MPFR_SET_SAME_SIGN (y, x);
|
||||
MPFR_RET (0);
|
||||
}
|
||||
}
|
||||
|
||||
ex = MPFR_GET_EXP (x);
|
||||
if (ex < 0)
|
||||
{
|
||||
/* For -1 < x < 0, abs(expm1(x)-x) < x^2/2.
|
||||
For 0 < x < 1, abs(expm1(x)-x) < x^2. */
|
||||
if (MPFR_IS_POS (x))
|
||||
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, - ex, 0, 1, rnd_mode, {});
|
||||
else
|
||||
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, - ex, 1, 0, rnd_mode, {});
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
if (MPFR_IS_NEG (x) && ex > 5) /* x <= -32 */
|
||||
{
|
||||
mpfr_t minus_one, t;
|
||||
mpfr_exp_t err;
|
||||
|
||||
mpfr_init2 (minus_one, 2);
|
||||
mpfr_init2 (t, 64);
|
||||
mpfr_set_si (minus_one, -1, MPFR_RNDN);
|
||||
mpfr_const_log2 (t, MPFR_RNDU); /* round upward since x is negative */
|
||||
mpfr_div (t, x, t, MPFR_RNDU); /* > x / ln(2) */
|
||||
err = mpfr_cmp_si (t, MPFR_EMIN_MIN >= -LONG_MAX ?
|
||||
MPFR_EMIN_MIN : -LONG_MAX) <= 0 ?
|
||||
- (MPFR_EMIN_MIN >= -LONG_MAX ? MPFR_EMIN_MIN : -LONG_MAX) :
|
||||
- mpfr_get_si (t, MPFR_RNDU);
|
||||
/* exp(x) = 2^(x/ln(2))
|
||||
<= 2^max(MPFR_EMIN_MIN,-LONG_MAX,ceil(x/ln(2)+epsilon))
|
||||
with epsilon > 0 */
|
||||
mpfr_clear (t);
|
||||
MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (y, minus_one, err, 0, 0, rnd_mode,
|
||||
expo, { mpfr_clear (minus_one); });
|
||||
mpfr_clear (minus_one);
|
||||
}
|
||||
|
||||
/* General case */
|
||||
{
|
||||
/* Declaration of the intermediary variable */
|
||||
mpfr_t t;
|
||||
/* Declaration of the size variable */
|
||||
mpfr_prec_t Ny = MPFR_PREC(y); /* target precision */
|
||||
mpfr_prec_t Nt; /* working precision */
|
||||
mpfr_exp_t err, exp_te; /* error */
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
/* compute the precision of intermediary variable */
|
||||
/* the optimal number of bits : see algorithms.tex */
|
||||
Nt = Ny + MPFR_INT_CEIL_LOG2 (Ny) + 6;
|
||||
|
||||
/* if |x| is smaller than 2^(-e), we will loose about e bits in the
|
||||
subtraction exp(x) - 1 */
|
||||
if (ex < 0)
|
||||
Nt += - ex;
|
||||
|
||||
/* initialize auxiliary variable */
|
||||
mpfr_init2 (t, Nt);
|
||||
|
||||
/* First computation of expm1 */
|
||||
MPFR_ZIV_INIT (loop, Nt);
|
||||
for (;;)
|
||||
{
|
||||
MPFR_BLOCK_DECL (flags);
|
||||
|
||||
/* exp(x) may overflow and underflow */
|
||||
MPFR_BLOCK (flags, mpfr_exp (t, x, MPFR_RNDN));
|
||||
if (MPFR_OVERFLOW (flags))
|
||||
{
|
||||
inexact = mpfr_overflow (y, rnd_mode, MPFR_SIGN_POS);
|
||||
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_OVERFLOW);
|
||||
break;
|
||||
}
|
||||
else if (MPFR_UNDERFLOW (flags))
|
||||
{
|
||||
inexact = mpfr_set_si (y, -1, rnd_mode);
|
||||
MPFR_ASSERTD (inexact == 0);
|
||||
inexact = -1;
|
||||
if (MPFR_IS_LIKE_RNDZ (rnd_mode, 1))
|
||||
{
|
||||
inexact = 1;
|
||||
mpfr_nexttozero (y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
exp_te = MPFR_GET_EXP (t); /* FIXME: exp(x) may overflow! */
|
||||
mpfr_sub_ui (t, t, 1, MPFR_RNDN); /* exp(x)-1 */
|
||||
|
||||
/* error estimate */
|
||||
/*err=Nt-(__gmpfr_ceil_log2(1+pow(2,MPFR_EXP(te)-MPFR_EXP(t))));*/
|
||||
err = Nt - (MAX (exp_te - MPFR_GET_EXP (t), 0) + 1);
|
||||
|
||||
if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
|
||||
{
|
||||
inexact = mpfr_set (y, t, rnd_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
/* increase the precision */
|
||||
MPFR_ZIV_NEXT (loop, Nt);
|
||||
mpfr_set_prec (t, Nt);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
mpfr_clear (t);
|
||||
}
|
||||
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/* mpfr_extract -- bit-extraction function for the binary splitting algorithm
|
||||
|
||||
Copyright 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* given 0 <= |p| < 1, this function extracts limbs of p and puts them in y.
|
||||
It is mainly designed for the "binary splitting" algorithm.
|
||||
|
||||
More precisely, if B = 2^GMP_NUMB_BITS:
|
||||
- for i=0, y = floor(p * B)
|
||||
- for i>0, y = (p * B^(2^i)) mod B^(2^(i-1))
|
||||
*/
|
||||
|
||||
void
|
||||
mpfr_extract (mpz_ptr y, mpfr_srcptr p, unsigned int i)
|
||||
{
|
||||
unsigned long two_i = 1UL << i;
|
||||
unsigned long two_i_2 = i ? two_i / 2 : 1;
|
||||
mp_size_t size_p = MPFR_LIMB_SIZE (p);
|
||||
|
||||
/* as 0 <= |p| < 1, we don't have to care with infinities, NaN, ... */
|
||||
MPFR_ASSERTD (!MPFR_IS_SINGULAR (p));
|
||||
|
||||
_mpz_realloc (y, two_i_2);
|
||||
if ((mpfr_uexp_t) size_p < two_i)
|
||||
{
|
||||
MPN_ZERO (PTR(y), two_i_2);
|
||||
if ((mpfr_uexp_t) size_p >= two_i_2)
|
||||
MPN_COPY (PTR(y) + two_i - size_p, MPFR_MANT(p), size_p - two_i_2);
|
||||
}
|
||||
else
|
||||
MPN_COPY (PTR(y), MPFR_MANT(p) + size_p - two_i, two_i_2);
|
||||
|
||||
MPN_NORMALIZE (PTR(y), two_i_2);
|
||||
SIZ(y) = (MPFR_IS_NEG (p)) ? -two_i_2 : two_i_2;
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/* mpfr_fac_ui -- factorial of a non-negative integer
|
||||
|
||||
Copyright 2001, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define MPFR_NEED_LONGLONG_H
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
/* The computation of n! is done by
|
||||
|
||||
n!=prod^{n}_{i=1}i
|
||||
*/
|
||||
|
||||
/* FIXME: efficient problems with large arguments; see comments in gamma.c. */
|
||||
|
||||
int
|
||||
mpfr_fac_ui (mpfr_ptr y, unsigned long int x, mpfr_rnd_t rnd_mode)
|
||||
{
|
||||
mpfr_t t; /* Variable of Intermediary Calculation*/
|
||||
unsigned long i;
|
||||
int round, inexact;
|
||||
|
||||
mpfr_prec_t Ny; /* Precision of output variable */
|
||||
mpfr_prec_t Nt; /* Precision of Intermediary Calculation variable */
|
||||
mpfr_prec_t err; /* Precision of error */
|
||||
|
||||
mpfr_rnd_t rnd;
|
||||
MPFR_SAVE_EXPO_DECL (expo);
|
||||
MPFR_ZIV_DECL (loop);
|
||||
|
||||
/***** test x = 0 and x == 1******/
|
||||
if (MPFR_UNLIKELY (x <= 1))
|
||||
return mpfr_set_ui (y, 1, rnd_mode); /* 0! = 1 and 1! = 1 */
|
||||
|
||||
MPFR_SAVE_EXPO_MARK (expo);
|
||||
|
||||
/* Initialisation of the Precision */
|
||||
Ny = MPFR_PREC (y);
|
||||
|
||||
/* compute the size of intermediary variable */
|
||||
Nt = Ny + 2 * MPFR_INT_CEIL_LOG2 (x) + 7;
|
||||
|
||||
mpfr_init2 (t, Nt); /* initialise of intermediary variable */
|
||||
|
||||
rnd = MPFR_RNDZ;
|
||||
MPFR_ZIV_INIT (loop, Nt);
|
||||
for (;;)
|
||||
{
|
||||
/* compute factorial */
|
||||
inexact = mpfr_set_ui (t, 1, rnd);
|
||||
for (i = 2 ; i <= x ; i++)
|
||||
{
|
||||
round = mpfr_mul_ui (t, t, i, rnd);
|
||||
/* assume the first inexact product gives the sign
|
||||
of difference: is that always correct? */
|
||||
if (inexact == 0)
|
||||
inexact = round;
|
||||
}
|
||||
|
||||
err = Nt - 1 - MPFR_INT_CEIL_LOG2 (Nt);
|
||||
|
||||
round = !inexact || mpfr_can_round (t, err, rnd, MPFR_RNDZ,
|
||||
Ny + (rnd_mode == MPFR_RNDN));
|
||||
|
||||
if (MPFR_LIKELY (round))
|
||||
{
|
||||
/* If inexact = 0, then t is exactly x!, so round is the
|
||||
correct inexact flag.
|
||||
Otherwise, t != x! since we rounded to zero or away. */
|
||||
round = mpfr_set (y, t, rnd_mode);
|
||||
if (inexact == 0)
|
||||
{
|
||||
inexact = round;
|
||||
break;
|
||||
}
|
||||
else if ((inexact < 0 && round <= 0)
|
||||
|| (inexact > 0 && round >= 0))
|
||||
break;
|
||||
else /* inexact and round have opposite signs: we cannot
|
||||
compute the inexact flag. Restart using the
|
||||
symmetric rounding. */
|
||||
rnd = (rnd == MPFR_RNDZ) ? MPFR_RNDU : MPFR_RNDZ;
|
||||
}
|
||||
MPFR_ZIV_NEXT (loop, Nt);
|
||||
mpfr_set_prec (t, Nt);
|
||||
}
|
||||
MPFR_ZIV_FREE (loop);
|
||||
|
||||
mpfr_clear (t);
|
||||
MPFR_SAVE_EXPO_FREE (expo);
|
||||
return mpfr_check_range (y, inexact, rnd_mode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,454 @@
|
|||
@c MPFR tweak: Have this in mpfr.texi to help texinfo-mode
|
||||
@c @node GNU Free Documentation License
|
||||
@c @appendixsec GNU Free Documentation License
|
||||
|
||||
@cindex GNU Free Documentation License
|
||||
@center Version 1.2, November 2002
|
||||
|
||||
@display
|
||||
Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
|
||||
51 Franklin St, 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.
|
||||
@end display
|
||||
|
||||
@enumerate 0
|
||||
@item
|
||||
PREAMBLE
|
||||
|
||||
The purpose of this License is to make a manual, textbook, or other
|
||||
functional and useful document @dfn{free} in the sense of freedom: to
|
||||
assure everyone the effective freedom to copy and redistribute it,
|
||||
with or without modifying it, either commercially or noncommercially.
|
||||
Secondarily, this License preserves for the author and publisher a way
|
||||
to get credit for their work, while not being considered responsible
|
||||
for modifications made by others.
|
||||
|
||||
This License is a kind of ``copyleft'', which means that derivative
|
||||
works of the document must themselves be free in the same sense. It
|
||||
complements the GNU General Public License, which is a copyleft
|
||||
license designed for free software.
|
||||
|
||||
We have designed this License in order to use it for manuals for free
|
||||
software, because free software needs free documentation: a free
|
||||
program should come with manuals providing the same freedoms that the
|
||||
software does. But this License is not limited to software manuals;
|
||||
it can be used for any textual work, regardless of subject matter or
|
||||
whether it is published as a printed book. We recommend this License
|
||||
principally for works whose purpose is instruction or reference.
|
||||
|
||||
@item
|
||||
APPLICABILITY AND DEFINITIONS
|
||||
|
||||
This License applies to any manual or other work, in any medium, that
|
||||
contains a notice placed by the copyright holder saying it can be
|
||||
distributed under the terms of this License. Such a notice grants a
|
||||
world-wide, royalty-free license, unlimited in duration, to use that
|
||||
work under the conditions stated herein. The ``Document'', below,
|
||||
refers to any such manual or work. Any member of the public is a
|
||||
licensee, and is addressed as ``you''. You accept the license if you
|
||||
copy, modify or distribute the work in a way requiring permission
|
||||
under copyright law.
|
||||
|
||||
A ``Modified Version'' of the Document means any work containing the
|
||||
Document or a portion of it, either copied verbatim, or with
|
||||
modifications and/or translated into another language.
|
||||
|
||||
A ``Secondary Section'' is a named appendix or a front-matter section
|
||||
of the Document that deals exclusively with the relationship of the
|
||||
publishers or authors of the Document to the Document's overall
|
||||
subject (or to related matters) and contains nothing that could fall
|
||||
directly within that overall subject. (Thus, if the Document is in
|
||||
part a textbook of mathematics, a Secondary Section may not explain
|
||||
any mathematics.) The relationship could be a matter of historical
|
||||
connection with the subject or with related matters, or of legal,
|
||||
commercial, philosophical, ethical or political position regarding
|
||||
them.
|
||||
|
||||
The ``Invariant Sections'' are certain Secondary Sections whose titles
|
||||
are designated, as being those of Invariant Sections, in the notice
|
||||
that says that the Document is released under this License. If a
|
||||
section does not fit the above definition of Secondary then it is not
|
||||
allowed to be designated as Invariant. The Document may contain zero
|
||||
Invariant Sections. If the Document does not identify any Invariant
|
||||
Sections then there are none.
|
||||
|
||||
The ``Cover Texts'' are certain short passages of text that are listed,
|
||||
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
|
||||
the Document is released under this License. A Front-Cover Text may
|
||||
be at most 5 words, and a Back-Cover Text may be at most 25 words.
|
||||
|
||||
A ``Transparent'' copy of the Document means a machine-readable copy,
|
||||
represented in a format whose specification is available to the
|
||||
general public, that is suitable for revising the document
|
||||
straightforwardly with generic text editors or (for images composed of
|
||||
pixels) generic paint programs or (for drawings) some widely available
|
||||
drawing editor, and that is suitable for input to text formatters or
|
||||
for automatic translation to a variety of formats suitable for input
|
||||
to text formatters. A copy made in an otherwise Transparent file
|
||||
format whose markup, or absence of markup, has been arranged to thwart
|
||||
or discourage subsequent modification by readers is not Transparent.
|
||||
An image format is not Transparent if used for any substantial amount
|
||||
of text. A copy that is not ``Transparent'' is called ``Opaque''.
|
||||
|
||||
Examples of suitable formats for Transparent copies include plain
|
||||
@sc{ascii} without markup, Texinfo input format, La@TeX{} input
|
||||
format, @acronym{SGML} or @acronym{XML} using a publicly available
|
||||
@acronym{DTD}, and standard-conforming simple @acronym{HTML},
|
||||
PostScript or @acronym{PDF} designed for human modification. Examples
|
||||
of transparent image formats include @acronym{PNG}, @acronym{XCF} and
|
||||
@acronym{JPG}. Opaque formats include proprietary formats that can be
|
||||
read and edited only by proprietary word processors, @acronym{SGML} or
|
||||
@acronym{XML} for which the @acronym{DTD} and/or processing tools are
|
||||
not generally available, and the machine-generated @acronym{HTML},
|
||||
PostScript or @acronym{PDF} produced by some word processors for
|
||||
output purposes only.
|
||||
|
||||
The ``Title Page'' means, for a printed book, the title page itself,
|
||||
plus such following pages as are needed to hold, legibly, the material
|
||||
this License requires to appear in the title page. For works in
|
||||
formats which do not have any title page as such, ``Title Page'' means
|
||||
the text near the most prominent appearance of the work's title,
|
||||
preceding the beginning of the body of the text.
|
||||
|
||||
A section ``Entitled XYZ'' means a named subunit of the Document whose
|
||||
title either is precisely XYZ or contains XYZ in parentheses following
|
||||
text that translates XYZ in another language. (Here XYZ stands for a
|
||||
specific section name mentioned below, such as ``Acknowledgements'',
|
||||
``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
|
||||
of such a section when you modify the Document means that it remains a
|
||||
section ``Entitled XYZ'' according to this definition.
|
||||
|
||||
The Document may include Warranty Disclaimers next to the notice which
|
||||
states that this License applies to the Document. These Warranty
|
||||
Disclaimers are considered to be included by reference in this
|
||||
License, but only as regards disclaiming warranties: any other
|
||||
implication that these Warranty Disclaimers may have is void and has
|
||||
no effect on the meaning of this License.
|
||||
|
||||
@item
|
||||
VERBATIM COPYING
|
||||
|
||||
You may copy and distribute the Document in any medium, either
|
||||
commercially or noncommercially, provided that this License, the
|
||||
copyright notices, and the license notice saying this License applies
|
||||
to the Document are reproduced in all copies, and that you add no other
|
||||
conditions whatsoever to those of this License. You may not use
|
||||
technical measures to obstruct or control the reading or further
|
||||
copying of the copies you make or distribute. However, you may accept
|
||||
compensation in exchange for copies. If you distribute a large enough
|
||||
number of copies you must also follow the conditions in section 3.
|
||||
|
||||
You may also lend copies, under the same conditions stated above, and
|
||||
you may publicly display copies.
|
||||
|
||||
@item
|
||||
COPYING IN QUANTITY
|
||||
|
||||
If you publish printed copies (or copies in media that commonly have
|
||||
printed covers) of the Document, numbering more than 100, and the
|
||||
Document's license notice requires Cover Texts, you must enclose the
|
||||
copies in covers that carry, clearly and legibly, all these Cover
|
||||
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
|
||||
the back cover. Both covers must also clearly and legibly identify
|
||||
you as the publisher of these copies. The front cover must present
|
||||
the full title with all words of the title equally prominent and
|
||||
visible. You may add other material on the covers in addition.
|
||||
Copying with changes limited to the covers, as long as they preserve
|
||||
the title of the Document and satisfy these conditions, can be treated
|
||||
as verbatim copying in other respects.
|
||||
|
||||
If the required texts for either cover are too voluminous to fit
|
||||
legibly, you should put the first ones listed (as many as fit
|
||||
reasonably) on the actual cover, and continue the rest onto adjacent
|
||||
pages.
|
||||
|
||||
If you publish or distribute Opaque copies of the Document numbering
|
||||
more than 100, you must either include a machine-readable Transparent
|
||||
copy along with each Opaque copy, or state in or with each Opaque copy
|
||||
a computer-network location from which the general network-using
|
||||
public has access to download using public-standard network protocols
|
||||
a complete Transparent copy of the Document, free of added material.
|
||||
If you use the latter option, you must take reasonably prudent steps,
|
||||
when you begin distribution of Opaque copies in quantity, to ensure
|
||||
that this Transparent copy will remain thus accessible at the stated
|
||||
location until at least one year after the last time you distribute an
|
||||
Opaque copy (directly or through your agents or retailers) of that
|
||||
edition to the public.
|
||||
|
||||
It is requested, but not required, that you contact the authors of the
|
||||
Document well before redistributing any large number of copies, to give
|
||||
them a chance to provide you with an updated version of the Document.
|
||||
|
||||
@item
|
||||
MODIFICATIONS
|
||||
|
||||
You may copy and distribute a Modified Version of the Document under
|
||||
the conditions of sections 2 and 3 above, provided that you release
|
||||
the Modified Version under precisely this License, with the Modified
|
||||
Version filling the role of the Document, thus licensing distribution
|
||||
and modification of the Modified Version to whoever possesses a copy
|
||||
of it. In addition, you must do these things in the Modified Version:
|
||||
|
||||
@enumerate A
|
||||
@item
|
||||
Use in the Title Page (and on the covers, if any) a title distinct
|
||||
from that of the Document, and from those of previous versions
|
||||
(which should, if there were any, be listed in the History section
|
||||
of the Document). You may use the same title as a previous version
|
||||
if the original publisher of that version gives permission.
|
||||
|
||||
@item
|
||||
List on the Title Page, as authors, one or more persons or entities
|
||||
responsible for authorship of the modifications in the Modified
|
||||
Version, together with at least five of the principal authors of the
|
||||
Document (all of its principal authors, if it has fewer than five),
|
||||
unless they release you from this requirement.
|
||||
|
||||
@item
|
||||
State on the Title page the name of the publisher of the
|
||||
Modified Version, as the publisher.
|
||||
|
||||
@item
|
||||
Preserve all the copyright notices of the Document.
|
||||
|
||||
@item
|
||||
Add an appropriate copyright notice for your modifications
|
||||
adjacent to the other copyright notices.
|
||||
|
||||
@item
|
||||
Include, immediately after the copyright notices, a license notice
|
||||
giving the public permission to use the Modified Version under the
|
||||
terms of this License, in the form shown in the Addendum below.
|
||||
|
||||
@item
|
||||
Preserve in that license notice the full lists of Invariant Sections
|
||||
and required Cover Texts given in the Document's license notice.
|
||||
|
||||
@item
|
||||
Include an unaltered copy of this License.
|
||||
|
||||
@item
|
||||
Preserve the section Entitled ``History'', Preserve its Title, and add
|
||||
to it an item stating at least the title, year, new authors, and
|
||||
publisher of the Modified Version as given on the Title Page. If
|
||||
there is no section Entitled ``History'' in the Document, create one
|
||||
stating the title, year, authors, and publisher of the Document as
|
||||
given on its Title Page, then add an item describing the Modified
|
||||
Version as stated in the previous sentence.
|
||||
|
||||
@item
|
||||
Preserve the network location, if any, given in the Document for
|
||||
public access to a Transparent copy of the Document, and likewise
|
||||
the network locations given in the Document for previous versions
|
||||
it was based on. These may be placed in the ``History'' section.
|
||||
You may omit a network location for a work that was published at
|
||||
least four years before the Document itself, or if the original
|
||||
publisher of the version it refers to gives permission.
|
||||
|
||||
@item
|
||||
For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
|
||||
the Title of the section, and preserve in the section all the
|
||||
substance and tone of each of the contributor acknowledgements and/or
|
||||
dedications given therein.
|
||||
|
||||
@item
|
||||
Preserve all the Invariant Sections of the Document,
|
||||
unaltered in their text and in their titles. Section numbers
|
||||
or the equivalent are not considered part of the section titles.
|
||||
|
||||
@item
|
||||
Delete any section Entitled ``Endorsements''. Such a section
|
||||
may not be included in the Modified Version.
|
||||
|
||||
@item
|
||||
Do not retitle any existing section to be Entitled ``Endorsements'' or
|
||||
to conflict in title with any Invariant Section.
|
||||
|
||||
@item
|
||||
Preserve any Warranty Disclaimers.
|
||||
@end enumerate
|
||||
|
||||
If the Modified Version includes new front-matter sections or
|
||||
appendices that qualify as Secondary Sections and contain no material
|
||||
copied from the Document, you may at your option designate some or all
|
||||
of these sections as invariant. To do this, add their titles to the
|
||||
list of Invariant Sections in the Modified Version's license notice.
|
||||
These titles must be distinct from any other section titles.
|
||||
|
||||
You may add a section Entitled ``Endorsements'', provided it contains
|
||||
nothing but endorsements of your Modified Version by various
|
||||
parties---for example, statements of peer review or that the text has
|
||||
been approved by an organization as the authoritative definition of a
|
||||
standard.
|
||||
|
||||
You may add a passage of up to five words as a Front-Cover Text, and a
|
||||
passage of up to 25 words as a Back-Cover Text, to the end of the list
|
||||
of Cover Texts in the Modified Version. Only one passage of
|
||||
Front-Cover Text and one of Back-Cover Text may be added by (or
|
||||
through arrangements made by) any one entity. If the Document already
|
||||
includes a cover text for the same cover, previously added by you or
|
||||
by arrangement made by the same entity you are acting on behalf of,
|
||||
you may not add another; but you may replace the old one, on explicit
|
||||
permission from the previous publisher that added the old one.
|
||||
|
||||
The author(s) and publisher(s) of the Document do not by this License
|
||||
give permission to use their names for publicity for or to assert or
|
||||
imply endorsement of any Modified Version.
|
||||
|
||||
@item
|
||||
COMBINING DOCUMENTS
|
||||
|
||||
You may combine the Document with other documents released under this
|
||||
License, under the terms defined in section 4 above for modified
|
||||
versions, provided that you include in the combination all of the
|
||||
Invariant Sections of all of the original documents, unmodified, and
|
||||
list them all as Invariant Sections of your combined work in its
|
||||
license notice, and that you preserve all their Warranty Disclaimers.
|
||||
|
||||
The combined work need only contain one copy of this License, and
|
||||
multiple identical Invariant Sections may be replaced with a single
|
||||
copy. If there are multiple Invariant Sections with the same name but
|
||||
different contents, make the title of each such section unique by
|
||||
adding at the end of it, in parentheses, the name of the original
|
||||
author or publisher of that section if known, or else a unique number.
|
||||
Make the same adjustment to the section titles in the list of
|
||||
Invariant Sections in the license notice of the combined work.
|
||||
|
||||
In the combination, you must combine any sections Entitled ``History''
|
||||
in the various original documents, forming one section Entitled
|
||||
``History''; likewise combine any sections Entitled ``Acknowledgements'',
|
||||
and any sections Entitled ``Dedications''. You must delete all
|
||||
sections Entitled ``Endorsements.''
|
||||
|
||||
@item
|
||||
COLLECTIONS OF DOCUMENTS
|
||||
|
||||
You may make a collection consisting of the Document and other documents
|
||||
released under this License, and replace the individual copies of this
|
||||
License in the various documents with a single copy that is included in
|
||||
the collection, provided that you follow the rules of this License for
|
||||
verbatim copying of each of the documents in all other respects.
|
||||
|
||||
You may extract a single document from such a collection, and distribute
|
||||
it individually under this License, provided you insert a copy of this
|
||||
License into the extracted document, and follow this License in all
|
||||
other respects regarding verbatim copying of that document.
|
||||
|
||||
@item
|
||||
AGGREGATION WITH INDEPENDENT WORKS
|
||||
|
||||
A compilation of the Document or its derivatives with other separate
|
||||
and independent documents or works, in or on a volume of a storage or
|
||||
distribution medium, is called an ``aggregate'' if the copyright
|
||||
resulting from the compilation is not used to limit the legal rights
|
||||
of the compilation's users beyond what the individual works permit.
|
||||
When the Document is included in an aggregate, this License does not
|
||||
apply to the other works in the aggregate which are not themselves
|
||||
derivative works of the Document.
|
||||
|
||||
If the Cover Text requirement of section 3 is applicable to these
|
||||
copies of the Document, then if the Document is less than one half of
|
||||
the entire aggregate, the Document's Cover Texts may be placed on
|
||||
covers that bracket the Document within the aggregate, or the
|
||||
electronic equivalent of covers if the Document is in electronic form.
|
||||
Otherwise they must appear on printed covers that bracket the whole
|
||||
aggregate.
|
||||
|
||||
@item
|
||||
TRANSLATION
|
||||
|
||||
Translation is considered a kind of modification, so you may
|
||||
distribute translations of the Document under the terms of section 4.
|
||||
Replacing Invariant Sections with translations requires special
|
||||
permission from their copyright holders, but you may include
|
||||
translations of some or all Invariant Sections in addition to the
|
||||
original versions of these Invariant Sections. You may include a
|
||||
translation of this License, and all the license notices in the
|
||||
Document, and any Warranty Disclaimers, provided that you also include
|
||||
the original English version of this License and the original versions
|
||||
of those notices and disclaimers. In case of a disagreement between
|
||||
the translation and the original version of this License or a notice
|
||||
or disclaimer, the original version will prevail.
|
||||
|
||||
If a section in the Document is Entitled ``Acknowledgements'',
|
||||
``Dedications'', or ``History'', the requirement (section 4) to Preserve
|
||||
its Title (section 1) will typically require changing the actual
|
||||
title.
|
||||
|
||||
@item
|
||||
TERMINATION
|
||||
|
||||
You may not copy, modify, sublicense, or distribute the Document except
|
||||
as expressly provided for under this License. Any other attempt to
|
||||
copy, modify, sublicense or distribute the Document 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.
|
||||
|
||||
@item
|
||||
FUTURE REVISIONS OF THIS LICENSE
|
||||
|
||||
The Free Software Foundation may publish new, revised versions
|
||||
of the GNU Free Documentation 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. See
|
||||
@uref{http://www.gnu.org/copyleft/}.
|
||||
|
||||
Each version of the License is given a distinguishing version number.
|
||||
If the Document specifies that a particular numbered version of this
|
||||
License ``or any later version'' applies to it, you have the option of
|
||||
following the terms and conditions either of that specified version or
|
||||
of any later version that has been published (not as a draft) by the
|
||||
Free Software Foundation. If the Document does not specify a version
|
||||
number of this License, you may choose any version ever published (not
|
||||
as a draft) by the Free Software Foundation.
|
||||
@end enumerate
|
||||
|
||||
@page
|
||||
@c MPFR tweak: Use @appendixsec
|
||||
@c @appendixsubsec ADDENDUM: How to use this License for your documents
|
||||
@appendixsec ADDENDUM: How to Use This License For Your Documents
|
||||
|
||||
To use this License in a document you have written, include a copy of
|
||||
the License in the document and put the following copyright and
|
||||
license notices just after the title page:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
Copyright (C) @var{year} @var{your name}.
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2
|
||||
or any later version published by the Free Software Foundation;
|
||||
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
|
||||
Texts. A copy of the license is included in the section entitled ``GNU
|
||||
Free Documentation License''.
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
|
||||
replace the ``with...Texts.'' line with this:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
with the Invariant Sections being @var{list their titles}, with
|
||||
the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
|
||||
being @var{list}.
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
If you have Invariant Sections without Cover Texts, or some other
|
||||
combination of the three, merge those two alternatives to suit the
|
||||
situation.
|
||||
|
||||
If your document contains nontrivial examples of program code, we
|
||||
recommend releasing these examples in parallel under your choice of
|
||||
free software license, such as the GNU General Public License,
|
||||
to permit their use in free software.
|
||||
|
||||
@c Local Variables:
|
||||
@c ispell-local-pdict: "ispell-dict"
|
||||
@c End:
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/* mpfr_fits_intmax_p -- test whether an mpfr fits an intmax_t.
|
||||
|
||||
Copyright 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h" /* for a build within gmp */
|
||||
#endif
|
||||
|
||||
/* The ISO C99 standard specifies that in C++ implementations the
|
||||
INTMAX_MAX, ... macros should only be defined if explicitly requested. */
|
||||
#if defined __cplusplus
|
||||
# define __STDC_LIMIT_MACROS
|
||||
# define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h> /* for intmax_t */
|
||||
#else
|
||||
# if HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
#ifdef _MPFR_H_HAVE_INTMAX_T
|
||||
|
||||
/* We can't use fits_s.h <= mpfr_cmp_ui */
|
||||
int
|
||||
mpfr_fits_intmax_p (mpfr_srcptr f, mpfr_rnd_t rnd)
|
||||
{
|
||||
mpfr_exp_t e;
|
||||
int prec;
|
||||
mpfr_t x, y;
|
||||
int neg;
|
||||
int res;
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f)))
|
||||
/* Zero always fit */
|
||||
return MPFR_IS_ZERO (f) ? 1 : 0;
|
||||
|
||||
/* now it fits if either
|
||||
(a) MINIMUM <= f <= MAXIMUM
|
||||
(b) or MINIMUM <= round(f, prec(slong), rnd) <= MAXIMUM */
|
||||
|
||||
e = MPFR_EXP (f);
|
||||
if (e < 1)
|
||||
return 1; /* |f| < 1: always fits */
|
||||
|
||||
neg = MPFR_IS_NEG (f);
|
||||
|
||||
/* let EXTREMUM be MAXIMUM if f > 0, and MINIMUM if f < 0 */
|
||||
|
||||
/* first compute prec(EXTREMUM), this could be done at configure time,
|
||||
but the result can depend on neg (the loop is moved inside the "if"
|
||||
to give the compiler a better chance to compute prec statically) */
|
||||
if (neg)
|
||||
{
|
||||
uintmax_t s;
|
||||
/* In C89, the division on negative integers isn't well-defined. */
|
||||
s = SAFE_ABS (uintmax_t, MPFR_INTMAX_MIN);
|
||||
for (prec = 0; s != 0; s /= 2, prec ++);
|
||||
}
|
||||
else
|
||||
{
|
||||
intmax_t s;
|
||||
s = MPFR_INTMAX_MAX;
|
||||
for (prec = 0; s != 0; s /= 2, prec ++);
|
||||
}
|
||||
|
||||
/* EXTREMUM needs prec bits, i.e. 2^(prec-1) <= |EXTREMUM| < 2^prec */
|
||||
|
||||
/* if e <= prec - 1, then f < 2^(prec-1) <= |EXTREMUM| */
|
||||
if (e <= prec - 1)
|
||||
return 1;
|
||||
|
||||
/* if e >= prec + 1, then f >= 2^prec > |EXTREMUM| */
|
||||
if (e >= prec + 1)
|
||||
return 0;
|
||||
|
||||
MPFR_ASSERTD (e == prec);
|
||||
|
||||
/* hard case: first round to prec bits, then check */
|
||||
mpfr_init2 (x, prec);
|
||||
mpfr_set (x, f, rnd);
|
||||
|
||||
if (neg)
|
||||
{
|
||||
mpfr_init2 (y, prec);
|
||||
mpfr_set_sj (y, MPFR_INTMAX_MIN, MPFR_RNDN);
|
||||
res = mpfr_cmp (x, y) >= 0;
|
||||
mpfr_clear (y);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = MPFR_GET_EXP (x) == e;
|
||||
}
|
||||
|
||||
mpfr_clear (x);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,86 @@
|
|||
/* mpfr_fits_*_p -- test whether an mpfr fits a C signed type.
|
||||
|
||||
Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
Copied from mpf/fits_s.h.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "mpfr-impl.h"
|
||||
|
||||
int
|
||||
FUNCTION (mpfr_srcptr f, mpfr_rnd_t rnd)
|
||||
{
|
||||
mpfr_exp_t e;
|
||||
int prec;
|
||||
mpfr_t x;
|
||||
int neg;
|
||||
int res;
|
||||
|
||||
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f)))
|
||||
/* Zero always fit */
|
||||
return MPFR_IS_ZERO (f) ? 1 : 0;
|
||||
|
||||
/* now it fits if either
|
||||
(a) MINIMUM <= f <= MAXIMUM
|
||||
(b) or MINIMUM <= round(f, prec(slong), rnd) <= MAXIMUM */
|
||||
|
||||
e = MPFR_GET_EXP (f);
|
||||
if (e < 1)
|
||||
return 1; /* |f| < 1: always fits */
|
||||
|
||||
neg = MPFR_IS_NEG (f);
|
||||
|
||||
/* let EXTREMUM be MAXIMUM if f > 0, and MINIMUM if f < 0 */
|
||||
|
||||
/* first compute prec(EXTREMUM), this could be done at configure time,
|
||||
but the result can depend on neg (the loop is moved inside the "if"
|
||||
to give the compiler a better chance to compute prec statically) */
|
||||
if (neg)
|
||||
{
|
||||
unsigned TYPE s;
|
||||
/* In C89, the division on negative integers isn't well-defined. */
|
||||
s = SAFE_ABS (unsigned TYPE, MINIMUM);
|
||||
for (prec = 0; s != 0; s /= 2, prec ++);
|
||||
}
|
||||
else
|
||||
{
|
||||
TYPE s;
|
||||
s = MAXIMUM;
|
||||
for (prec = 0; s != 0; s /= 2, prec ++);
|
||||
}
|
||||
|
||||
/* EXTREMUM needs prec bits, i.e. 2^(prec-1) <= |EXTREMUM| < 2^prec */
|
||||
|
||||
/* if e <= prec - 1, then f < 2^(prec-1) <= |EXTREMUM| */
|
||||
if (e <= prec - 1)
|
||||
return 1;
|
||||
|
||||
/* if e >= prec + 1, then f >= 2^prec > |EXTREMUM| */
|
||||
if (e >= prec + 1)
|
||||
return 0;
|
||||
|
||||
MPFR_ASSERTD (e == prec);
|
||||
|
||||
/* hard case: first round to prec bits, then check */
|
||||
mpfr_init2 (x, prec);
|
||||
mpfr_set (x, f, rnd);
|
||||
res = neg ? (mpfr_cmp_si (x, MINIMUM) >= 0) : (MPFR_GET_EXP (x) == e);
|
||||
mpfr_clear (x);
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* mpfr_fits_sint_p -- test whether an mpfr fits an int.
|
||||
|
||||
Copyright 2003, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define FUNCTION mpfr_fits_sint_p
|
||||
#define MAXIMUM INT_MAX
|
||||
#define MINIMUM INT_MIN
|
||||
#define TYPE int
|
||||
|
||||
#include "fits_s.h"
|
|
@ -0,0 +1,28 @@
|
|||
/* mpfr_fits_slong_p -- test whether an mpfr fits a long.
|
||||
|
||||
Copyright 2003, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
Contributed by the Arenaire and Cacao projects, INRIA.
|
||||
|
||||
This file is part of the GNU MPFR Library.
|
||||
|
||||
The GNU MPFR 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The GNU MPFR 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 the GNU MPFR Library; see the file COPYING.LESSER. If not, see
|
||||
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define FUNCTION mpfr_fits_slong_p
|
||||
#define MAXIMUM LONG_MAX
|
||||
#define MINIMUM LONG_MIN
|
||||
#define TYPE long
|
||||
|
||||
#include "fits_s.h"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue