gmpy2-2.1.0b3/ 0000775 0001750 0001750 00000000000 13530663166 012660 5 ustar case case 0000000 0000000 gmpy2-2.1.0b3/COPYING 0000664 0001750 0001750 00000104513 13105222070 013676 0 ustar case case 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
gmpy2-2.1.0b3/COPYING.LESSER 0000664 0001750 0001750 00000016743 13105222070 014701 0 ustar case case 0000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
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.
gmpy2-2.1.0b3/INSTALL 0000664 0001750 0001750 00000005600 13356026702 013705 0 ustar case case 0000000 0000000 Installing gmpy2 on Unix/Linux
------------------------------
Many Linux distributions provide gmpy2 in their repositories. Please check
your distribution's repositories first.
Requirements
------------
gmpy2 requires recent versions of GMP, MPFR and MPC. Specifically, gmpy2
requires GMP 5.0.0 or later, MPFR 3.1.0 or later, and MPC 1.0.0 or later.
Quick Instructions
------------------
To manually compile gmpy2, you will need to install the development libraries
for Python, GMP, MPFR, and MPC are installed. The package names vary between
distributions. "python-dev", "python2-dev", or "python3.4-dev" are typical
package names for the Python development files. Installing the MPC development
package should automatically install the GMP and MPFR development packages.
"libmpc-dev" is a typical name for the MPC development package.
Once the required development libraries have been installed, compiling should
be as simple as:
$ cd
$ python setup.py build_ext
$ sudo python setup.py install
If this fails, read on.
Detailed Instructions
---------------------
If your Linux distribution does not support recent versions of GMP, MPFR and
MPC, you will need to compile your own versions. To avoid any possible conflict
with existing libraries on your system, it is recommended to build a statically
linked version of gmpy2. The following instructions assume the GMP, MPFR, MPC,
and gmpy2 source files are all located in $HOME/src and the static libraries
are installed into $HOME/static
1. Create the desired destination directory for the GMP, MPFR, and MPC
libraries.
$ mkdir $HOME/static
2. Download and un-tar the GMP source code. Change to GMP source directory and
compile GMP.
$ cd $HOME/src/gmp-6.0.0
$ ./configure --prefix=$HOME/static --enable-static --disable-shared --with-pic
$ make
$ make check
$ make install
3. Download and un-tar the MPFR source code. Change to MPFR source directory
and compile MPFR.
$ cd $HOME/src/mpfr-3.1.2
$ ./configure --prefix=$HOME/static --enable-static --disable-shared --with-pic --with-gmp=$HOME/static
$ make
$ make check
$ make install
4. Download and un-tar the MPC source code. Change to MPC source directory
and compile MPC.
$ cd $HOME/src/mpc-1.0.3
$ ./configure --prefix=$HOME/static --enable-static --disable-shared --with-pic --with-gmp=$HOME/static --with-mpfr=$HOME/static
$ make
$ make check
$ make install
5. Compile gmpy2 and specify the location of GMP, MPFR and MPC.
$ cd $HOME/src/gmpy2-2.1.0
$ python setup.py build_ext --static=$HOME/static install
If you get a "permission denied" error message, you may need to use:
$ python setup.py build_ext --static=$HOME/static
$ sudo python setup.py install
Installing gmpy2 on Windows
---------------------------
Please see windows_build.txt (preferred) or msys2_build.txt (alpha).
gmpy2-2.1.0b3/MANIFEST.in 0000664 0001750 0001750 00000000234 13356026702 014410 0 ustar case case 0000000 0000000 include README
include INSTALL
include COPYING
include docs/*
include test/*
include COPYING.LESSER
include src/*
include gmpy2/gmpy2.h
include gmpy2/*.pxd
gmpy2-2.1.0b3/PKG-INFO 0000664 0001750 0001750 00000004163 13530663166 013761 0 ustar case case 0000000 0000000 Metadata-Version: 1.1
Name: gmpy2
Version: 2.1.0b3
Summary: gmpy2 interface to GMP, MPFR, and MPC for Python 2.7 and 3.4+
Home-page: https://github.com/aleaxit/gmpy
Author: Case Van Horsen
Author-email: casevh@gmail.com
License: LGPL-3.0+
Description: gmpy2 is an optimized, C-coded Python extension module that supports fast
multiple-precision arithmetic. gmpy2 is based on the original gmpy module.
gmpy2 adds support for correctly rounded multiple-precision real arithmetic
(using the MPFR library) and complex arithmetic (using the MPC library).
The gmpy2 2.0.x series is a stable version that is only receiving bug fixes.
The main development branch (2.1.x) was extensively refactored. The most
significant changes are support for thread-safe contexts and context methods.
gmpy2 is available at https://pypi.python.org/pypi/gmpy2/
Documentation is available at https://gmpy2.readthedocs.io/en/latest/
Keywords: gmp mpfr mpc multiple-precision arbitrary-precision precision bignum
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Classifier: Natural Language :: English
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Programming Language :: C
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
gmpy2-2.1.0b3/README 0000664 0001750 0001750 00000001223 13356026702 013531 0 ustar case case 0000000 0000000 gmpy2 is an optimized, C-coded Python extension module that supports fast
multiple-precision arithmetic. gmpy2 is based on the original gmpy module.
gmpy2 adds support for correctly rounded multiple-precision real arithmetic
(using the MPFR library) and complex arithmetic (using the MPC library).
The gmpy2 2.0.x series is a stable version that is only receiving bug fixes.
The main development branch (2.1.x) was extensively refactored. The most
significant changes are support for thread-safe contexts and context methods.
gmpy2 is available at https://pypi.python.org/pypi/gmpy2/
Documentation is available at https://gmpy2.readthedocs.io/en/latest/
gmpy2-2.1.0b3/docs/ 0000775 0001750 0001750 00000000000 13530663166 013610 5 ustar case case 0000000 0000000 gmpy2-2.1.0b3/docs/Makefile 0000664 0001750 0001750 00000011263 13244654531 015251 0 ustar case case 0000000 0000000 # Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
help:
@echo "Please use \`make ' where is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
create_static:
if [ ! -d _static ]; then mkdir _static; fi
clean:
-rm -rf $(BUILDDIR)/*
html: create_static
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml: create_static
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml: create_static
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle: create_static
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json: create_static
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GMPY2.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GMPY2.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/GMPY2"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GMPY2"
@echo "# devhelp"
epub: create_static
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex: create_static
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf: create_static
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
make -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text: create_static
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man: create_static
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
gmpy2-2.1.0b3/docs/advmpz.rst 0000664 0001750 0001750 00000020220 13356026702 015632 0 ustar case case 0000000 0000000 Multiple-precision Integers (Advanced topics)
=============================================
The xmpz type
-------------
gmpy2 provides access to an experimental integer type called *xmpz*. The
*xmpz* type is a mutable integer type. In-place operations (+=, //=, etc.)
modify the original object and do not create a new object. Instances of
*xmpz* cannot be used as dictionary keys.
::
>>> import gmpy2
>>> from gmpy2 import xmpz
>>> a = xmpz(123)
>>> b = a
>>> a += 1
>>> a
xmpz(124)
>>> b
xmpz(124)
The ability to change an *xmpz* object in-place allows for efficient and rapid
bit manipulation.
Individual bits can be set or cleared::
>>> a[10]=1
>>> a
xmpz(1148)
Slice notation is supported. The bits referenced by a slice can be either 'read
from' or 'written to'. To clear a slice of bits, use a source value of 0. In
2s-complement format, 0 is represented by an arbitrary number of 0-bits. To set
a slice of bits, use a source value of ~0. The *tilde* operator inverts, or
complements the bits in an integer. (~0 is -1 so you can also use -1.) In
2s-complement format, -1 is represented by an arbitrary number of 1-bits.
If a value for *stop* is specified in a slice assignment and the actual
bit-length of the *xmpz* is less than *stop*, then the destination *xmpz* is
logically padded with 0-bits to length *stop*.
::
>>> a=xmpz(0)
>>> a[8:16] = ~0
>>> bin(a)
'0b1111111100000000'
>>> a[4:12] = ~a[4:12]
>>> bin(a)
'0b1111000011110000'
Bits can be reversed::
>>> bin(a)
'0b10001111100'
>>> a[::] = a[::-1]
>>> bin(a)
'0b111110001'
The *iter_bits()* method returns a generator that returns True or False for each
bit position. The methods *iter_clear()*, and *iter_set()* return generators
that return the bit positions that are 1 or 0. The methods support arguments
*start* and *stop* that define the beginning and ending bit positions that are
used. To mimic the behavior of slices. the bit positions checked include *start*
but the last position checked is *stop* - 1.
::
>>> a=xmpz(117)
>>> bin(a)
'0b1110101'
>>> list(a.iter_bits())
[True, False, True, False, True, True, True]
>>> list(a.iter_clear())
[1, 3]
>>> list(a.iter_set())
[0, 2, 4, 5, 6]
>>> list(a.iter_bits(stop=12))
[True, False, True, False, True, True, True, False, False, False, False, False]
The following program uses the Sieve of Eratosthenes to generate a list of
prime numbers.
::
from __future__ import print_function
import time
import gmpy2
def sieve(limit=1000000):
'''Returns a generator that yields the prime numbers up to limit.'''
# Increment by 1 to account for the fact that slices do not include
# the last index value but we do want to include the last value for
# calculating a list of primes.
sieve_limit = gmpy2.isqrt(limit) + 1
limit += 1
# Mark bit positions 0 and 1 as not prime.
bitmap = gmpy2.xmpz(3)
# Process 2 separately. This allows us to use p+p for the step size
# when sieving the remaining primes.
bitmap[4 : limit : 2] = -1
# Sieve the remaining primes.
for p in bitmap.iter_clear(3, sieve_limit):
bitmap[p*p : limit : p+p] = -1
return bitmap.iter_clear(2, limit)
if __name__ == "__main__":
start = time.time()
result = list(sieve())
print(time.time() - start)
print(len(result))
Advanced Number Theory Functions
--------------------------------
The following functions are based on mpz_lucas.c and mpz_prp.c by David
Cleaver.
A good reference for probable prime testing is
http://www.pseudoprime.com/pseudo.html
**is_bpsw_prp(...)**
is_bpsw_prp(n) will return True if *n* is a Baillie-Pomerance-Selfridge-Wagstaff
probable prime. A BPSW probable prime passes the is_strong_prp() test with base
2 and the is_selfridge_prp() test.
**is_euler_prp(...)**
is_euler_prp(n,a) will return True if *n* is an Euler (also known as
Solovay-Strassen) probable prime to the base *a*.
| Assuming:
| gcd(n, a) == 1
| n is odd
|
| Then an Euler probable prime requires:
| a**((n-1)/2) == 1 (mod n)
**is_extra_strong_lucas_prp(...)**
is_extra_strong_lucas_prp(n,p) will return True if *n* is an extra strong
Lucas probable prime with parameters (p,1).
| Assuming:
| n is odd
| D = p*p - 4, D != 0
| gcd(n, 2*D) == 1
| n = s*(2**r) + Jacobi(D,n), s odd
|
| Then an extra strong Lucas probable prime requires:
| lucasu(p,1,s) == 0 (mod n)
| or
| lucasv(p,1,s) == +/-2 (mod n)
| or
| lucasv(p,1,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r
**is_fermat_prp(...)**
is_fermat_prp(n,a) will return True if *n* is a Fermat probable prime to the
base a.
| Assuming:
| gcd(n,a) == 1
|
| Then a Fermat probable prime requires:
| a**(n-1) == 1 (mod n)
**is_fibonacci_prp(...)**
is_fibonacci_prp(n,p,q) will return True if *n* is a Fibonacci
probable prime with parameters (p,q).
| Assuming:
| n is odd
| p > 0, q = +/-1
| p*p - 4*q != 0
|
| Then a Fibonacci probable prime requires:
| lucasv(p,q,n) == p (mod n).
**is_lucas_prp(...)**
is_lucas_prp(n,p,q) will return True if *n* is a Lucas probable prime with
parameters (p,q).
| Assuming:
| n is odd
| D = p*p - 4*q, D != 0
| gcd(n, 2*q*D) == 1
|
| Then a Lucas probable prime requires:
| lucasu(p,q,n - Jacobi(D,n)) == 0 (mod n)
**is_selfridge_prp(...)**
is_selfridge_prp(n) will return True if *n* is a Lucas probable prime with
Selfidge parameters (p,q). The Selfridge parameters are chosen by finding
the first element D in the sequence {5, -7, 9, -11, 13, ...} such that
Jacobi(D,n) == -1. Let p=1 and q = (1-D)/4 and then perform a Lucas
probable prime test.
**is_strong_bpsw_prp(...)**
is_strong_bpsw_prp(n) will return True if *n* is a strong
Baillie-Pomerance-Selfridge-Wagstaff probable prime. A strong BPSW
probable prime passes the is_strong_prp() test with base 2 and the
is_strongselfridge_prp() test.
**is_strong_lucas_prp(...)**
is_strong_lucas_prp(n,p,q) will return True if *n* is a strong Lucas
probable prime with parameters (p,q).
| Assuming:
| n is odd
| D = p*p - 4*q, D != 0
| gcd(n, 2*q*D) == 1
| n = s*(2**r) + Jacobi(D,n), s odd
|
| Then a strong Lucas probable prime requires:
| lucasu(p,q,s) == 0 (mod n)
| or
| lucasv(p,q,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r
**is_strong_prp(...)**
is_strong_prp(n,a) will return True if *n* is a strong (also known as
Miller-Rabin) probable prime to the base a.
| Assuming:
| gcd(n,a) == 1
| n is odd
| n = s*(2**r) + 1, with s odd
|
| Then a strong probable prime requires one of the following is true:
| a**s == 1 (mod n)
| or
| a**(s*(2**t)) == -1 (mod n) for some t, 0 <= t < r.
**is_strong_selfridge_prp(...)**
is_strong_selfridge_prp(n) will return True if *n* is a strong Lucas
probable prime with Selfidge parameters (p,q). The Selfridge parameters are
chosen by finding the first element D in the sequence
{5, -7, 9, -11, 13, ...} such that Jacobi(D,n) == -1. Let p=1 and
q = (1-D)/4 and then perform a strong Lucas probable prime test.
**lucasu(...)**
lucasu(p,q,k) will return the k-th element of the Lucas U sequence defined
by p,q. p*p - 4*q must not equal 0; k must be greater than or equal to 0.
**lucasu_mod(...)**
lucasu_mod(p,q,k,n) will return the k-th element of the Lucas U sequence
defined by p,q (mod n). p*p - 4*q must not equal 0; k must be greater than
or equal to 0; n must be greater than 0.
**lucasv(...)**
lucasv(p,q,k) will return the k-th element of the Lucas V sequence defined
by parameters (p,q). p*p - 4*q must not equal 0; k must be greater than or
equal to 0.
**lucasv_mod(...)**
lucasv_mod(p,q,k,n) will return the k-th element of the Lucas V sequence
defined by parameters (p,q) (mod n). p*p - 4*q must not equal 0; k must be
greater than or equal to 0; n must be greater than 0.
gmpy2-2.1.0b3/docs/conf.py 0000664 0001750 0001750 00000015577 13463454541 015126 0 ustar case case 0000000 0000000 # -*- coding: utf-8 -*-
#
# gmpy2 documentation build configuration file, created by
# sphinx-quickstart on Fri Feb 24 19:56:16 2012.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.imgmath']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'gmpy2'
copyright = u'2012, 2013, 2014, 2017, 2018, 2019 Case Van Horsen'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2.1'
# The full version, including alpha/beta/rc tags.
release = '2.1.0b1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'gmpy2doc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'gmpy2.tex', 'gmpy2 Documentation',
'Case Van Horsen', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'gmpy2', 'gmpy2 Documentation',
['Case Van Horsen'], 3)
]
gmpy2-2.1.0b3/docs/conversion.rst 0000664 0001750 0001750 00000003162 13441640452 016523 0 ustar case case 0000000 0000000 Conversion methods and gmpy2's numbers
======================================
Conversion methods
------------------
A python object could interact with gmpy2 if it implements one of the following methods:
- **__mpz__** : return an object of .
- **__mpq__** : return an object of .
- **__mpfr__** : return an object of .
- **__mpc__** : return an object of .
| Implementing on of these methods allow gmpy2 to convert a python object into a gmpy2 type.
| Example::
>>> from gmpy2 import mpz
>>> class CustInt:
... def __init__(self, x):
... self.x = x
... def __mpz__(self):
... return mpz(self.x)
...
>>> ci = CustInt(5)
>>> z = mpz(ci); z
mpz(5)
>>> type(z)
Arithmetic operations
---------------------
| gmpy2 allow arithmetic operations between gmpy2 numbers and objects with conversion methods.
| Operation with object that implements floating conversion and exact conversion methods are not supported.
| That means that only the following cases are supported:
- An integer type have to implement **__mpz__**
- A rational type have to implement **__mpq__** and can implement **__mpz__**
- A real type have to implement **__mpfr__**
- A complex type have to implement **__mpc__** and can implement **__mpfr__**
Examples::
>>> from gmpy2 import mpz, mpq, mpfr, mpc
>>> class Q:
... def __mpz__(self): return mpz(1)
... def __mpq__(self): return mpq(3,2)
>>> q = Q()
>>> mpz(2) + q
mpq(7,2)
>>> mpq(1,2) * q
mpq(3,4)
>>> mpfr(10) * q
mpfr('15.0')
gmpy2-2.1.0b3/docs/cython.rst 0000664 0001750 0001750 00000010142 13244654531 015642 0 ustar case case 0000000 0000000 Cython usage
============
The gmpy2 module provides a C-API that can be conveniently used from Cython.
All types and functions are declared in the header gmpy2.pxd that is installed
automatically in your Python path together with the library.
Initialization
--------------
In order to use the C-API you need to make one call to the function **void import_gmpy2(void)**.
Types
-----
The types **mpz**, **mpq**, **mpfr** and **mpc** are declared as extension
types in gmpy2.pxd. They correspond respectively to the C structures
**MPZ_Object**, **MPQ_Object**, **MPFR_Object** and **MPC_Object**.
Fast type checking can be done with the following C functions
**bint MPZ_Check(object)**
equivalent to **isinstance(obj, mpz)**
**bint MPQ_Check(object)**
equivalent to **isinstance(obj, mpq)**
**bint MPFR_Check(object)**
equivalent to **isinstance(obj, mpfr)**
**bint MPC_Check(object)**
equivalent to **isinstance(obj, mpc)**
Object creation
---------------
To create a new gmpy2 types there are four basic functions
**mpz GMPy_MPZ_New(void * ctx)**
create a new mpz object from a given context ctx
**mpq GMPy_MPQ_New(void * ctx)**
create a new mpq object from a given context ctx
**mpfr MPFR_New(void * ctx, mpfr_prec_t prec)**
create a new mpfr object with given context ctx and precision prec
**mpc MPC_New(void * ctx, mpfr_prec_t rprec, mpfr_prec_t iprec)**
create a new mpc object with given context ctx, precisions rprec and iprec of
respectively real and imaginary parts
The context can be set to **NULL** and controls the default behavior (e.g. precision).
The gmpy2.pxd header also provides convenience macro to wrap a (copy of) a mpz_t, mpq_t, mpfr_t
or a mpc_t object into the corresponding gmpy2 type.
**mpz GMPy_MPZ_From_mpz(mpz_srcptr z)**
return a new mpz object with a given mpz_t value z
**mpq GMPy_MPQ_From_mpq(mpq_srcptr q)**
return a new mpq object from a given mpq_t value q
**mpq GMPy_MPQ_From_mpz(mpz_srcptr num, mpz_srcptr den)**
return a new mpq object with a given mpz_t numerator num and mpz_t denominator den
**mpfr GMPy_MPFR_From_mpfr(mpfr_srcptr x)**
return a new mpfr object with a given mpfr_t value x
**mpc GMPy_MPC_From_mpc(mpc_srcptr c)**
return a new mpc object with a given mpc_t value c
**mpc GMPy_MPC_From_mpfr(mpfr_srcptr re, mpfr_srcptr im)**
return a new mpc object with a given mpfr_t real part re and mpfr_t imaginary part im
Access to the underlying C type
--------------------------------
Each of the gmpy2 objects has a field corresponding to the underlying C
type. The following functions give access to this field
**mpz_t MPZ(mpz)**
**mpq_t MPQ(mpq)**
**mpfr_t MPFR(mpfr)**
**mpc_t MPC(mpc)**
Compilation
------------
The header gmpy2.pxd as well as the C header gmpy2.h from which it depends
are installed in the Python path. In order to make Cython and the C compiler aware
of the existence of these files, the Python path should be part of the include
directories.
Recall that **import_gmpy2()** needs to be called *before* any other function of
the C-API.
Here is a minimal example of a Cython file test_gmpy2.pyx
::
"A minimal setup.py for compiling test_gmpy2.pyx"
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
import sys
ext = Extension("test_gmpy2", ["test_gmpy2.pyx"], include_dirs=sys.path, libraries=['gmp', 'mpfr', 'mpc'])
setup(
name="cython_gmpy_test",
ext_modules=cythonize([ext], include_path=sys.path)
)
The corresponding setup.py is given below.
::
"A minimal cython file test_gmpy2.pyx"
from gmpy2 cimport *
cdef extern from "gmp.h":
void mpz_set_si(mpz_t, long)
import_gmpy2() # needed to initialize the C-API
cdef mpz z = GMPy_MPZ_New(NULL)
mpz_set_si(MPZ(z), -7)
print(z + 3)
With these two files in the same repository, you should be able to compile your
module using
::
$ python setup.py build_ext --inplace
For more about compilation and installation of cython files and extension
modules, please refer to the official documentation of Cython and distutils.
gmpy2-2.1.0b3/docs/history.rst 0000664 0001750 0001750 00000017730 13463456636 016062 0 ustar case case 0000000 0000000 Changes for gmpy2 releases
==========================
Changes in gmpy2 2.1.0b1
------------------------
* Added cmp() and cmp_abs().
* Improved compatibility with _numbers_ protocol.
* Many bug fixes.
Changes in gmpy2 2.1.a05
------------------------
* Fix qdiv() not returning mpz() when it should.
* Added root_of_unity().
Changes in gmpy2 2.1.0a4
------------------------
* Fix issue 204; missing file for Cython.
* Additional support for MPFR 4
- Add fmma() and fmms()
Changes in gmpy2 2.1.0a3
------------------------
* Updates to setup.py.
* Initial support for MPFR4
- Add nrandom()
- grandom() now calls nrandom twice; may return different values versus
MPFR3
- Add rootn(); same as root() except different sign when taking even root
of -0.0
Changes in gmpy2 2.1.0a2
------------------------
* Revised build process.
* Removal of unused code/macros.
* Cleanup of Cython interface.
Changes in gmpy2 2.1.0a1
------------------------
* Thread-safe contexts are now supported. Properly integrating thread-safe
contexts required an extensive rewrite of almost all internal functions.
* MPFR and MPC are now required. It is no longer possible to build a version
of gmpy2 that only supports the GMP library.
* The function inverse() now raises an exception if the inverse does not
exist.
* Context methods have been added for MPFR/MPC related functions.
* A new context option (*rational_division*) has been added that changes the
behavior of integer division involving *mpz* instances to return a rational
result instead of a floating point result.
* gmpy2 types are now registered in the numeric tower.
* In previous versions of gmpy2, *gmpy2.mpz* was a factory function that
returned an *mpz* instance. *gmpy2.mpz* is now an actual type. The same
is true for the other gmpy2 types.
* If a Python object has an __mpz__ method, it will be called bye *mpz()* to
allow an unrecognized type to be converted to an mpz instance. The same is
true for the other gmpy2 types.
* A new C-API and Cython interface has been added.
Changes in gmpy2 2.0.4
----------------------
* Fix bit_scan0() for negative values.
* Changes to setup.py to allow static linking.
* Fix performance regression with mpmath and Python 3.
Changes in gmpy2 2.0.3
----------------------
* Fix lucas2() and atanh(); they were returning incorrect values.
Changes in gmpy2 2.0.2
----------------------
* Rebuild Windows binary installers due to MPIR 2.6.0 bug in next_prime().
* Another fix for is_extra_strong_lucas_prp().
Changes in gmpy2 2.0.1
----------------------
* Updated setup.py to work in more situations.
* Corrected exception handling in basic operations with mpfr type.
* Correct InvalidOperation exception not raised in certain circumstances.
* invert() now raises an exception if the modular inverse does not exist.
* Fixed internal exception in is_bpsw_prp() and is_strong_bpsw_prp().
* Updated is_extra_strong_lucas_prp() to latest version.
Changes in gmpy2 2.0.0
----------------------
* Fix segmentation fault in _mpmath_normalize (an undocumented helper function
specifically for mpmath.)
* Improved setup.py See below for documentation on the changes.
* Fix issues when compiled without support for MPFR.
* Conversion of too large an mpz to float now raises OverflowError instead of
returning *inf*.
* Renamed min2()/max2() to minnum()/maxnum()
* The build and install process (i.e. setup.py) has been completely rewritten.
See the Installation section for more information.
* get_context() no longer accepts keyword arguments.
Known issues in gmpy2 2.0.0
-----------------------------
* The test suite is still incomplete.
Changes in gmpy2 2.0.0b4
------------------------
* Added __ceil__, __floor__, __trunc__, and __round__ methods to mpz and mpq
types.
* Added __complex__ to mpc type.
* round(mpfr) now correctly returns an mpz type.
* If no arguments are given to mpz, mpq, mpfr, mpc, and xmpz, return 0 of the
appropriate type.
* Fix broken comparison between mpz and mpq when mpz is on the left.
* Added __sizeof__ to all types. *Note: sys.getsizeof() calls __sizeof__ to get
the memory size of a gmpy2 object. The returned value reflects the size of the
allocated memory which may be larger than the actual minimum memory required
by the object.*
Known issues in gmpy2 2.0.0b4
-----------------------------
* The new test suite (test/runtest.py) is incomplete and some tests fail on
Python 2.x due to formatting issues.
Changes in gmpy2 2.0.0b3
------------------------
* mp_version(), mpc_version(), and mpfr_version() now return normal strings on
Python 2.x instead of Unicode strings.
* Faster conversion of the standard library Fraction type to mpq.
* Improved conversion of the Decimal type to mpfr.
* Consistently return OverflowError when converting "inf".
* Fix mpz.__format__() when the format code includes "#".
* Add is_infinite() and deprecate is_inf().
* Add is_finite() and deprecate is_number().
* Fixed the various is_XXX() tests when used with mpc.
* Added caching for mpc objects.
* Faster code path for basic operation is both operands are mpfr or mpc.
* Fix mpfr + float segmentation fault.
Changes in gmpy2 2.0.0b2
------------------------
* Allow xmpz slice assignment to increase length of xmpz instance by specifying
a value for stop.
* Fixed reference counting bug in several is_xxx_prp() tests.
* Added iter_bits(), iter_clear(), iter_set() methods to xmpz.
* Added powmod() for easy access to three argument pow().
* Removed addmul() and submul() which were added in 2.0.0b1 since they are
slower than just using Python code.
* Bug fix in gcd_ext when both arguments are not mpz.
* Added ieee() to create contexts for 32, 64, or 128 bit floats.
* Bug fix in context() not setting emax/emin correctly if they had been changed
earlier.
* Contexts can be directly used in with statement without requiring
set_context()/local_context() sequence.
* local_context() now accepts an optional context.
Changes in gmpy2 2.0.0b1 and earlier
------------------------------------
* Renamed functions that manipulate individual bits to bit_XXX() to align with
bit_length().
* Added caching for mpq.
* Added rootrem(), fib2(), lucas(), lucas2().
* Support changed hash function in Python 3.2.
* Added is_even(), is_odd().
* Add caching of the calculated hash value.
* Add xmpz (mutable mpz) type.
* Fix mpq formatting issue.
* Add read/write bit access using slices to xmpz.
* Add read-only bit access using slices to mpz.
* Add pack()/unpack() methods to split/join an integer into n-bit chunks.
* Add support for MPFR (casevh)
* Removed fcoform float conversion modifier.
* Add support for MPC.
* Added context manager.
* Allow building with just GMP/MPIR if MPFR not available.
* Allow building with GMP/MPIR and MPFR if MPC not available.
* Removed most instance methods in favor of gmpy2.function. The general guideline
is that *properties* of an instance can be done via instance methods but
*functions* that return a new result are done using gmpy2.function.
* Added __ceil__, __floor__, and __trunc__ methods since they are called by
math.ceil(), math.floor(), and math.trunc().
* Removed gmpy2.pow() to avoid conflicts.
* Removed gmpy2._copy and added xmpz.copy.
* Added support for __format__.
* Added as_integer_ratio, as_mantissa_exp, as_simple_fraction.
* Updated rich_compare.
* Require MPFR 3.1.0+ to get divby0 support.
* Added fsum(), degrees(), radians().
* Updated random number generation support.
* Changed license to LGPL 3+.
* Added lucasu, lucasu_mod, lucasv, and lucasv_mod.
*Based on code contributed by David Cleaver.*
* Added probable-prime tests.
*Based on code contributed by David Cleaver.*
* Added to_binary()/from_binary.
* Renamed numdigits() to num_digits().
* Added keyword precision to constants.
* Added addmul() and submul().
* Added __round__(), round2(), round_away() for mpfr.
* round() is no longer a module level function.
* Renamed module functions min()/max() to min2()/max2().
* No longer conflicts with builtin min() and max()
* Removed set_debug() and related functionality.
gmpy2-2.1.0b3/docs/index.rst 0000664 0001750 0001750 00000001002 13441640452 015434 0 ustar case case 0000000 0000000 .. gmpy2 documentation master file, created by
sphinx-quickstart on Fri Feb 24 19:56:16 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to gmpy2's documentation!
=================================
Contents:
.. toctree::
:maxdepth: 2
intro
overview
mpz
advmpz
mpq
mpfr
mpc
cython
conversion
history
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
gmpy2-2.1.0b3/docs/intro.rst 0000664 0001750 0001750 00000013566 13463457612 015512 0 ustar case case 0000000 0000000 Introduction to gmpy2
=====================
gmpy2 is a C-coded Python extension module that supports multiple-precision
arithmetic. gmpy2 is the successor to the original gmpy module. The gmpy module
only supported the GMP multiple-precision library. gmpy2 adds support for the
MPFR (correctly rounded real floating-point arithmetic) and MPC (correctly
rounded complex floating-point arithmetic) libraries. gmpy2 also updates the
API and naming conventions to be more consistent and support the additional
functionality.
The following libraries are supported:
* GMP for integer and rational arithmetic
Home page: http://gmplib.org
* MPIR is based on the GMP library but adds support for Microsoft's Visual
Studio compiler. It is used to create the Windows binaries.
Home page: http://www.mpir.org
* MPFR for correctly rounded real floating-point arithmetic
Home page: http://www.mpfr.org
* MPC for correctly rounded complex floating-point arithmetic
Home page: http://mpc.multiprecision.org
* Generalized Lucas sequences and primality tests are based on the following
code:
mpz_lucas: http://sourceforge.net/projects/mpzlucas/
mpz_prp: http://sourceforge.net/projects/mpzprp/
gmpy2 Versions
--------------
This manual documents the two major versions of gmpy2. Sections that are
specific to a particular version will be identified as such.
The 2.0 version is the stable release that only receives bug fixes and very
minor updates. Version 2.1 is currently under active development and includes
several new capabilities. Most gmpy2 2.0 code should run unchanged with
gmpy2 2.1.
The most significant change in gmpy2 2.1 is support for thread-safe contexts.
This change required extensive refactoring of almost all internal functions.
Please see the History chapter for a detail list of the changes.
Installation
============
Installing gmpy2 on Windows
---------------------------
Pre-compiled versions of gmpy2 2.0.8 are available at
`https://pypi.org/project/gmpy2/`.
A pre-compiled version of gmpy2 2.1.0a1 is available at
`https://pypi.org/project/gmpy2/2.1.0a1/`. Updated Windows versions should be
available again beginning with version 2.1.0b1.
Installing gmpy2 on Unix/Linux
------------------------------
Requirements
^^^^^^^^^^^^
gmpy2 has only been tested with the most recent versions of GMP, MPFR and MPC.
Specifically, for integer and rational support, gmpy2 requires GMP 5.0.x or
later. To support multiple-precision floating point arithmetic, MPFR 3.1.x or
later is required. MPC 1.0.1 or later is required for complex arithmetic.
Short Instructions
^^^^^^^^^^^^^^^^^^
gmpy2 requires the development files for GMP, MPFR, and MPC. The actual package
that provides these files varies between Linux distributions. Installing
"libmpc-dev" (or its equivalent) is usually sufficient.
If your system has the development libraries installed, compiling should be as
simple as:
::
cd
python setup.py build_ext --force install --force
If this fails, read on.
Detailed Instructions
^^^^^^^^^^^^^^^^^^^^^
Note: You really shouldn't need to do this. Unless you need the capabilities
provided a newer GMP/MPFR/MPC, you should use the versions provided by your
distribution.
If your Linux distribution does not support recent versions of GMP, MPFR and
MPC, you will need to compile your own versions. To avoid any possible conflict
with existing libraries on your system, it is recommended to use a directory
not normally used by your distribution.
Create the desired destination directory for GMP, MPFR, and MPC.
::
$ mkdir /home/<>/local
Download and un-tar the GMP source code. Change to the GMP source directory and
compile GMP.
::
$ cd /home/<>/local/src/gmp-6.1.2
$ ./configure --prefix=/home/<>/local
$ make
$ make check
$ make install
Download and un-tar the MPFR source code. Change to the MPFR source directory
and compile MPFR.
::
$ cd /home/<>/local/src/mpfr-4.0.1
$ ./configure --prefix=/home/<>/local --with-gmp=/home/<>/local
$ make
$ make check
$ make install
Download and un-tar the MPC source code. Change to the MPC source directory
and compile MPC.
::
$ cd /home/<>/local/src/mpc-1.1.0
$ ./configure --prefix=/home/<>/local --with-gmp=/home/<>/local --with-mpfr=/home/<>/local
$ make
$ make check
$ make install
Compile gmpy2 and specify the location of GMP, MPFR and MPC. The location of
the GMP, MPFR, and MPC libraries is embedded into the gmpy2 library so the new
versions of GMP, MPFR, and MPC do not need to be installed the system library
directories. The prefix directory is added to the beginning of the directories
that are checked so it will be found first.
::
$ python setup.py install --prefix=/home/case/local
If you get a "permission denied" error message, you may need to use::
$ python setup.py build --prefix=/home/case/local
$ sudo python setup.py install --prefix=/home/case/local
Options for setup.py
^^^^^^^^^^^^^^^^^^^^
**--force**
Ignore the timestamps on all files and recompile. Normally, the results of a
previous compile are cached. To force gmpy2 to recognize external changes
(updated version of GMP, etc.), you will need to use this option.
**--mpir**
Force the use of MPIR instead of GMP. GMP is the default library on non-Windows
operating systems.
**--gmp**
Force the use of GMP instead of MPIR. MPIR is the default library on Windows
operating systems.
**--shared=<...>**
Add the specified directory prefix to the beginning of the list of
directories that are searched for GMP, MPFR, and MPC shared libraries.
**--static=<...>**
Create a statically linked library using libraries from the specified path,
or from the operating system's default library location if no path is specified
gmpy2-2.1.0b3/docs/make.bat 0000775 0001750 0001750 00000010635 13170047220 015210 0 ustar case case 0000000 0000000 @ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^` where ^ is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\GMPY2.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\GMPY2.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end
gmpy2-2.1.0b3/docs/mpc.rst 0000664 0001750 0001750 00000023515 13433671427 015130 0 ustar case case 0000000 0000000 Multiple-precision Complex
==========================
gmpy2 adds a multiple-precision complex type called *mpc* that is based on the
MPC library. The context manager settings for *mpfr* arithmetic are applied to
*mpc* arithmetic by default. It is possible to specify different precision and
rounding modes for both the real and imaginary components of an *mpc*.
::
>>> import gmpy2
>>> from gmpy2 import mpc
>>> gmpy2.sqrt(mpc("1+2j"))
mpc('1.272019649514069+0.78615137775742328j')
>>> gmpy2.get_context(real_prec=100,imag_prec=200)
context(precision=53, real_prec=100, imag_prec=200,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=True,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
trap_expbound=False,
allow_complex=False)
>>> gmpy2.sqrt(mpc("1+2j"))
mpc('1.2720196495140689642524224617376+0.78615137775742328606955858584295892952312205783772323766490213j',(100,200))
Exceptions are normally raised in Python when the result of a real operation
is not defined over the reals; for example, ``sqrt(-4)`` will raise an
exception. The default context in gmpy2 implements the same behavior but by
setting allow_complex to True, complex results will be returned.
::
>>> import gmpy2
>>> from gmpy2 import mpc
>>> gmpy2.sqrt(-4)
mpfr('nan')
>>> gmpy2.get_context(allow_complex=True)
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=True,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
trap_expbound=False,
allow_complex=True)
>>> gmpy2.sqrt(-4)
mpc('0.0+2.0j')
mpc Methods
-----------
**conjugate()**
Returns the complex conjugate.
**digits()**
Returns a two element tuple where each element represents the real and
imaginary components as a 3-tuple containing the mantissa, the exponent,
and the number of bits of precision. The mantissa is represented as a
string in the specified base with up to 'prec' digits. If 'prec' is 0, as
many digits that are available are returned. No more digits than available
given x's precision are returned. 'base' must be between 2 and 62,
inclusive.
mpc Attributes
--------------
**imag**
Returns the imaginary component.
**precision**
Returns a 2-tuple containing the precision of the real and imaginary
components.
**rc**
Returns a 2-tuple containing the ternary value of the real and imaginary
components. The ternary value is 0 if the value of the component is exactly
equal to the exact, infinite precision value. If the result code is 1, then
the value of the component is greater than the exact value. If the result
code is -1, then the value of the component is less than the exact,
infinite precision value.
**real**
Returns the real component.
mpc Functions
-------------
**acos(...)**
acos(x) returns the arc-cosine of x.
**acosh(...)**
acosh(x) returns the inverse hyperbolic cosine of x.
**add(...)**
add(x, y) returns x + y. The type of the result is based on the types of
the arguments.
**asin(...)**
asin(x) returns the arc-sine of x.
**asinh(...)**
asinh(x) return the inverse hyperbolic sine of x.
**atan(...)**
atan(x) returns the arc-tangent of x.
**atanh(...)**
atanh(x) returns the inverse hyperbolic tangent of x.
**cos(...)**
cos(x) returns the cosine of x.
**cosh(...)**
cosh(x) returns the hyperbolic cosine of x.
**div(...)**
div(x, y) returns x / y. The type of the result is based on the types of
the arguments.
**div_2exp(...)**
div_2exp(x, n) returns an 'mpfr' or 'mpc' divided by 2**n.
**exp(...)**
exp(x) returns e**x.
**fma(...)**
fma(x, y, z) returns correctly rounded result of (x * y) + z.
**fms(...)**
fms(x, y, z) returns correctly rounded result of (x * y) - z.
**is_inf(...)**
is_inf(x) returns True if either the real or imaginary component of x is
Infinity or -Infinity.
**is_nan(...)**
is_nan(x) returns True if either the real or imaginary component of x is
NaN (Not-A-Number).
**is_zero(...)**
is_zero(x) returns True if x is zero.
**log(...)**
log(x) returns the natural logarithm of x.
**log10(...)**
log10(x) returns the base-10 logarithm of x.
**mpc(...)**
mpc() returns an *mpc* object set to 0.0+0.0j.
mpc(c[, precision=0]) returns a new 'mpc' object from an existing complex
number (either a Python complex object or another 'mpc' object). If the
precision is not specified, then the precision is taken from the current
context. The rounding mode is always taken from the current context.
mpc(r[, i=0[, precision=0]]) returns a new 'mpc' object by converting two
non-complex numbers into the real and imaginary components of an 'mpc'
object. If the precision is not specified, then the precision is taken from
the current context. The rounding mode is always taken from the current
context.
mpc(s[, [precision=0[, base=10]]) returns a new 'mpc' object by converting
a string s into a complex number. If base is omitted, then a base-10
representation is assumed otherwise a base between 2 and 36 can be
specified. If the precision is not specified, then the precision is taken
from the current context. The rounding mode is always taken from the
current context.
In addition to the standard Python string representation of a complex
number: ``"1+2j"``, the string representation used by the MPC library:
``"(1 2)"`` is also supported.
.. note::
The precision can be specified either a single number that is used for
both the real and imaginary components, or as a 2-tuple that can
specify different precisions for the real and imaginary components.
**mpc_random(...)**
mpfc_random(random_state) returns a uniformly distributed number in the
unit square [0,1]x[0,1]. The parameter *random_state* must be created by
random_state() first.
**mul(...)**
mul(x, y) returns x * y. The type of the result is based on the types of
the arguments.
**mul_2exp(...)**
mul_2exp(x, n) returns 'mpfr' or 'mpc' multiplied by 2**n.
**norm(...)**
norm(x) returns the norm of a complex x. The norm(x) is defined as
x.real**2 + x.imag**2. abs(x) is the square root of norm(x).
**phase(...)**
phase(x) returns the phase angle, also known as argument, of a complex x.
**polar(...)**
polar(x) returns the polar coordinate form of a complex x that is in
rectangular form.
**proj(...)**
proj(x) returns the projection of a complex x on to the Riemann sphere.
**rect(...)**
rect(x) returns the polar coordinate form of a complex x that is in
rectangular form.
**root_of_unity(...)**
root_of_unity(n, k) returns the n-th root of mpc(1) raised to the k-th
power. Requires MPC 1.1.0 or greater.
**sin(...)**
sin(x) returns the sine of x.
**sinh(...)**
sinh(x) returns the hyberbolic sine of x.
**sqrt(...)**
sqrt(x) returns the square root of x. If x is integer, rational, or real,
then an *mpfr* will be returned. If x is complex, then an *mpc* will
be returned. If context.allow_complex is True, negative values of x
will return an *mpc*.
**square(...)**
square(x) returns x * x. The type of the result is based on the types of
the arguments.
**sub(...)**
sub(x, y) returns x - y. The type of the result is based on the types of
the arguments.
**tan(...)**
tan(x) returns the tangent of x. x is measured in radians.
**tanh(...)**
tanh(x) returns the hyperbolic tangent of x.
mpc Formatting
--------------
The *mpc* type supports the __format__() special method to allow custom output
formatting.
**__format__(...)**
x.__format__(fmt) returns a Python string by formatting 'x' using the
format string 'fmt'. A valid format string consists of:
| optional alignment code:
| '<' -> left shifted in field
| '>' -> right shifted in field
| '^' -> centered in field
| optional leading sign code
| '+' -> always display leading sign
| '-' -> only display minus for negative values
| ' ' -> minus for negative values, space for positive values
| optional width.real_precision.imag_precision
| optional rounding mode:
| 'U' -> round toward plus infinity
| 'D' -> round toward minus infinity
| 'Z' -> round toward zero
| 'N' -> round to nearest
| optional output style:
| 'P' -> Python style, 1+2j, (default)
| 'M' -> MPC style, (1 2)
| optional conversion code:
| 'a','A' -> hex format
| 'b' -> binary format
| 'e','E' -> scientific format
| 'f','F' -> fixed point format
| 'g','G' -> fixed or scientific format
.. note::
The formatting codes must be specified in the order shown above.
::
>>> import gmpy2
>>> from gmpy2 import mpc
>>> a=gmpy2.sqrt(mpc("1+2j"))
>>> a
mpc('1.272019649514069+0.78615137775742328j')
>>> "{0:.4.4Mf}".format(a)
'(1.2720 0.7862)'
>>> "{0:.4.4f}".format(a)
'1.2720+0.7862j'
>>> "{0:^20.4.4U}".format(a)
' 1.2721+0.7862j '
>>> "{0:^20.4.4D}".format(a)
' 1.2720+0.7861j '
gmpy2-2.1.0b3/docs/mpfr.rst 0000664 0001750 0001750 00000066472 13372302125 015312 0 ustar case case 0000000 0000000 Multiple-precision Reals
========================
gmpy2 replaces the *mpf* type from gmpy 1.x with a new *mpfr* type based on
the MPFR library. The new *mpfr* type supports correct rounding, selectable
rounding modes, and many trigonometric, exponential, and special functions. A
*context manager* is used to control precision, rounding modes, and the
behavior of exceptions.
The default precision of an *mpfr* is 53 bits - the same precision as Python's
*float* type. If the precision is changed, then ``mpfr(float('1.2'))`` differs
from ``mpfr('1.2')``. To take advantage of the higher precision provided by
the *mpfr* type, always pass constants as strings.
::
>>> import gmpy2
>>> from gmpy2 import mpfr
>>> mpfr('1.2')
mpfr('1.2')
>>> mpfr(float('1.2'))
mpfr('1.2')
>>> gmpy2.get_context().precision=100
>>> mpfr('1.2')
mpfr('1.2000000000000000000000000000006',100)
>>> mpfr(float('1.2'))
mpfr('1.1999999999999999555910790149937',100)
>>>
Contexts
--------
.. warning::
Contexts and context managers are not thread-safe! Modifying the context
in one thread will impact all other threads.
A *context* is used to control the behavior of *mpfr* and *mpc* arithmetic.
In addition to controlling the precision, the rounding mode can be specified,
minimum and maximum exponent values can be changed, various exceptions can be
raised or ignored, gradual underflow can be enabled, and returning complex
results can be enabled.
``gmpy2.context()`` creates a new context with all options set to default.
``gmpy2.set_context(ctx)`` will set the active context to *ctx*.
``gmpy2.get_context()`` will return a reference to the active context. Note
that contexts are mutable: modifying the reference returned by get_context()
will modify the active context until a new context is enabled with
set_context(). The ``copy()`` method of a context will return a copy of the
context.
The following example just modifies the precision. The remaining options will
be discussed later.
::
>>> gmpy2.set_context(gmpy2.context())
>>> gmpy2.get_context()
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
trap_expbound=False,
allow_complex=False)
>>> gmpy2.sqrt(5)
mpfr('2.2360679774997898')
>>> gmpy2.get_context().precision=100
>>> gmpy2.sqrt(5)
mpfr('2.2360679774997896964091736687316',100)
>>> gmpy2.get_context().precision+=20
>>> gmpy2.sqrt(5)
mpfr('2.2360679774997896964091736687312762351',120)
>>> ctx=gmpy2.get_context()
>>> ctx.precision+=20
>>> gmpy2.sqrt(5)
mpfr('2.2360679774997896964091736687312762354406182',140)
>>> gmpy2.set_context(gmpy2.context())
>>> gmpy2.sqrt(5)
mpfr('2.2360679774997898')
>>> ctx.precision+=20
>>> gmpy2.sqrt(5)
mpfr('2.2360679774997898')
>>> gmpy2.set_context(ctx)
>>> gmpy2.sqrt(5)
mpfr('2.2360679774997896964091736687312762354406183596116',160)
>>>
Context Attributes
------------------
**precision**
This attribute controls the precision of an *mpfr* result. The precision
is specified in bits, not decimal digits. The maximum precision that can
be specified is platform dependent and can be retrieved with
**get_max_precision()**.
.. note::
Specifying a value for precision that is too close to the maximum precision
will cause the MPFR library to fail.
**real_prec**
This attribute controls the precision of the real part of an *mpc* result.
If the value is ``Default``, then the value of the precision attribute is
used.
**imag_prec**
This attribute controls the precision of the imaginary part of an *mpc*
result. If the value is ``Default``, then the value of real_prec is used.
**round**
There are five rounding modes available to *mpfr* types:
``RoundAwayZero``
The result is rounded away from 0.0.
``RoundDown``
The result is rounded towards -Infinity.
``RoundToNearest``
Round to the nearest value; ties are rounded to an even value.
``RoundToZero``
The result is rounded towards 0.0.
``RoundUp``
The result is rounded towards +Infinity.
**real_round**
This attribute controls the rounding mode for the real part of an *mpc*
result. If the value is ``Default``, then the value of the round attribute
is used. Note: ``RoundAwayZero`` is not a valid rounding mode for *mpc*.
**imag_round**
This attribute controls the rounding mode for the imaginary part of an
*mpc* result. If the value is ``Default``, then the value of the real_round
attribute is used. Note: ``RoundAwayZero`` is not a valid rounding mode for
*mpc*.
**emax**
This attribute controls the maximum allowed exponent of an *mpfr* result.
The maximum exponent is platform dependent and can be retrieved with
**get_emax_max()**.
**emin**
This attribute controls the minimum allowed exponent of an *mpfr* result.
The minimum exponent is platform dependent and can be retrieved with
**get_emin_min()**.
.. note::
It is possible to change the values of emin/emax such that previous *mpfr*
values are no longer valid numbers but should either underflow to +/-0.0 or
overflow to +/-Infinity. To raise an exception if this occurs, see
**trap_expbound**.
**subnormalize**
The usual IEEE-754 floating point representation supports gradual underflow
when the minimum exponent is reached. The MFPR library does not enable
gradual underflow by default but it can be enabled to precisely mimic the
results of IEEE-754 floating point operations.
**trap_underflow**
If set to ``False``, a result that is smaller than the smallest possible
*mpfr* given the current exponent range will be replaced by +/-0.0. If set
to ``True``, an ``UnderflowResultError`` exception is raised.
**underflow**
This flag is not user controllable. It is automatically set if a result
underflowed to +/-0.0 and trap_underflow is ``False``.
**trap_overflow**
If set to ``False``, a result that is larger than the largest possible
*mpfr* given the current exponent range will be replaced by +/-Infinity. If
set to ``True``, an ``OverflowResultError`` exception is raised.
**overflow**
This flag is not user controllable. It is automatically set if a result
overflowed to +/-Infinity and trap_overflow is ``False``.
**trap_inexact**
This attribute controls whether or not an ``InexactResultError`` exception
is raised if an inexact result is returned. To check if the result is
greater or less than the exact result, check the **rc** attribute of the
*mpfr* result.
**inexact**
This flag is not user controllable. It is automatically set if an inexact
result is returned.
**trap_invalid**
This attribute controls whether or not an ``InvalidOperationError``
exception is raised if a numerical result is not defined. A special
NaN (Not-A-Number) value will be returned if an exception is not raised.
The ``InvalidOperationError`` is a sub-class of Python's ``ValueError``.
For example, ``gmpy2.sqrt(-2)`` will normally return *mpfr('nan')*.
However, if allow_complex is set to ``True``, then an *mpc* result will
be returned.
**invalid**
This flag is not user controllable. It is automatically set if an invalid
(Not-A-Number) result is returned.
**trap_erange**
This attribute controls whether or not a ``RangeError`` exception is raised
when certain operations are performed on NaN and/or Infinity values.
Setting trap_erange to ``True`` can be used to raise an exception if
comparisons are attempted with a NaN.
::
>>> gmpy2.set_context(gmpy2.context())
>>> mpfr('nan') == mpfr('nan')
False
>>> gmpy2.get_context().trap_erange=True
>>> mpfr('nan') == mpfr('nan')
Traceback (most recent call last):
File "", line 1, in
gmpy2.RangeError: comparison with NaN
>>>
**erange**
This flag is not user controllable. It is automatically set if an erange
error occurred.
**trap_divzero**
This attribute controls whether or not a ``DivisionByZeroError`` exception
is raised if division by 0 occurs. The ``DivisionByZeroError`` is a
sub-class of Python's ``ZeroDivisionError``.
**divzero**
This flag is not user controllable. It is automatically set if a division
by zero occurred and NaN result was returned.
**trap_expbound**
This attribute controls whether or not an ``ExponentOutOfBoundsError``
exception is raised if exponents in an operand are outside the current
emin/emax limits.
**allow_complex**
This attribute controls whether or not an *mpc* result can be returned if
an *mpfr* result would normally not be possible.
Context Methods
---------------
**clear_flags()**
Clear the underflow, overflow, inexact, invalid, erange, and divzero flags.
**copy()**
Return a copy of the context.
Contexts and the with statement
-------------------------------
Contexts can also be used in conjunction with Python's ``with ...`` statement to
temporarily change the context settings for a block of code and then restore the
original settings when the block of code exits.
``gmpy2.local_context()`` first save the current context and then creates a new
context based on a context passed as the first argument, or the current context
if no context is passed. The new context is modified if any optional keyword
arguments are given. The original active context is restored when the block
completes.
In the following example, the current context is saved by ``gmpy2.local_context()``
and then the block begins with a copy of the default context and the precision
set to 100. When the block is finished, the original context is restored.
::
>>> with gmpy2.local_context(gmpy2.context(), precision=100) as ctx:
... print(gmpy2.sqrt(2))
... ctx.precision += 100
... print(gmpy2.sqrt(2))
...
1.4142135623730950488016887242092
1.4142135623730950488016887242096980785696718753769480731766796
>>>
A context object can also be used directly to create a context manager block.
However, instead of restoring the context to the active context when the
``with ...`` statement is executed, the restored context is the context used
before any keyword argument modifications.
The code:
::
with gmpy2.ieee(64) as ctx:
is equivalent to:
::
gmpy2.set_context(gmpy2.ieee(64))
with gmpy2.local_context() as ctx:
Contexts that implement the standard *single*, *double*, and *quadruple* precision
floating point types can be created using **ieee()**.
mpfr Methods
------------
**as_integer_ratio()**
Returns a 2-tuple containing the numerator and denominator after converting
the *mpfr* object into the exact rational equivalent. The return 2-tuple
is equivalent to Python's as_integer_ratio() method of built-in float
objects.
**as_mantissa_exp()**
Returns a 2-tuple containing the mantissa and exponent.
**as_simple_fraction()**
Returns an *mpq* containing the simplest rational value that approximates
the *mpfr* value with an error less than 1/(2**precision).
**conjugate()**
Returns the complex conjugate. For *mpfr* objects, returns a copy of the
original object.
**digits()**
Returns a 3-tuple containing the mantissa, the exponent, and the number
of bits of precision. The mantissa is represented as a string in the
specified base with up to 'prec' digits. If 'prec' is 0, as many digits
that are available are returned. No more digits than available given x's
precision are returned. 'base' must be between 2 and 62, inclusive.
**is_integer()**
Returns True if the *mpfr* object is an integer.
mpfr Attributes
---------------
**imag**
Returns the imaginary component. For *mpfr* objects, returns 0.
**precision**
Returns the precision of the *mpfr* object.
**rc**
The result code (also known as ternary value in the MPFR documentation)
is 0 if the value of the *mpfr* object is exactly equal to the exact,
infinite precision value. If the result code is 1, then the value of the
*mpfr* object is greater than the exact value. If the result code is -1,
then the value of the *mpfr* object is less than the exact, infinite
precision value.
**real**
Returns the real component. For *mpfr* objects, returns a copy of the
original object.
mpfr Functions
--------------
**acos(...)**
acos(x) returns the arc-cosine of x. x is measured in radians. If
context.allow_complex is True, then an *mpc* result will be returned for
abs(x) > 1.
**acosh(...)**
acosh(x) returns the inverse hyperbolic cosine of x.
**add(...)**
add(x, y) returns x + y. The type of the result is based on the types of
the arguments.
**agm(...)**
agm(x, y) returns the arithmetic-geometric mean of x and y.
**ai(...)**
ai(x) returns the Airy function of x.
**asin(...)**
asin(x) returns the arc-sine of x. x is measured in radians. If
context.allow_complex is True, then an *mpc* result will be returned for
abs(x) > 1.
**asinh(...)**
asinh(x) return the inverse hyperbolic sine of x.
**atan(...)**
atan(x) returns the arc-tangent of x. x is measured in radians.
**atan2(...)**
atan2(y, x) returns the arc-tangent of (y/x).
**atanh(...)**
atanh(x) returns the inverse hyperbolic tangent of x. If
context.allow_complex is True, then an *mpc* result will be returned for
abs(x) > 1.
**cbrt(...)**
cbrt(x) returns the cube root of x.
**ceil(...)**
ceil(x) returns the 'mpfr' that is the smallest integer >= x.
**check_range(...)**
check_range(x) return a new 'mpfr' with exponent that lies within the
current range of emin and emax.
**const_catalan(...)**
const_catalan([precision=0]) returns the Catalan's constant using the
specified precision. If no precision is specified, the default precision
is used.
**const_euler(...)**
const_euler([precision=0]) returns the Euler's constant using the specified
precision. If no precision is specified, the default precision is used.
**const_log2(...)**
const_log2([precision=0]) returns the log2 constant using the specified
precision. If no precision is specified, the default precision is used.
**const_pi(...)**
const_pi([precision=0]) returns the constant pi using the specified
precision. If no precision is specified, the default precision is used.
**context(...)**
context() returns a new context manager controlling MPFR and MPC
arithmetic.
**cos(...)**
cos(x) returns the cosine of x. x is measured in radians.
**cosh(...)**
cosh(x) returns the hyperbolic cosine of x.
**cot(...)**
cot(x) returns the cotangent of x. x is measured in radians.
**coth(...)**
coth(x) returns the hyperbolic cotangent of x.
**csc(...)**
csc(x) returns the cosecant of x. x is measured in radians.
**csch(...)**
csch(x) returns the hyperbolic cosecant of x.
**degrees(...)**
degrees(x) converts an angle measurement x from radians to degrees.
**digamma(...)**
digamma(x) returns the digamma of x.
**div(...)**
div(x, y) returns x / y. The type of the result is based on the types of
the arguments.
**div_2exp(...)**
div_2exp(x, n) returns an 'mpfr' or 'mpc' divided by 2**n.
**eint(...)**
eint(x) returns the exponential integral of x.
**erf(...)**
erf(x) returns the error function of x.
**erfc(...)**
erfc(x) returns the complementary error function of x.
**exp(...)**
exp(x) returns e**x.
**exp10(...)**
exp10(x) returns 10**x.
**exp2(...)**
exp2(x) returns 2**x.
**expm1(...)**
expm1(x) returns e**x - 1. expm1() is more accurate than exp(x) - 1 when
x is small.
**f2q(...)**
f2q(x[,err]) returns the simplest *mpq* approximating x to within relative
error err. Default is the precision of x. Uses Stern-Brocot tree to find
the simplest approximation. An *mpz* is returned if the denominator
is 1. If err<0, error sought is 2.0 ** err.
**factorial(...)**
factorial(n) returns the floating-point approximation to the factorial
of n.
See fac(n) to get the exact integer result.
**floor(...)**
floor(x) returns the 'mpfr' that is the smallest integer <= x.
**fma(...)**
fma(x, y, z) returns correctly rounded result of (x * y) + z.
**fmma(...)**
fmma(x, y, z, t) returns correctly rounded result of (x * y) + (z * t).
Requires MPFR 4.
**fmms(...)**
fmms(x, y, z, t) returns correctly rounded result of (x * y) - (z * t).
Requires MPFR 4.
**fmod(...)**
fmod(x, y) returns x - n*y where n is the integer quotient of x/y, rounded
to 0.
**fms(...)**
fms(x, y, z) returns correctly rounded result of (x * y) - z.
**frac(...)**
frac(x) returns the fractional part of x.
**frexp(...)**
frexp(x) returns a tuple containing the exponent and mantissa of x.
**fsum(...)**
fsum(iterable) returns the accurate sum of the values in the iterable.
**gamma(...)**
gamma(x) returns the gamma of x.
**get_exp(...)**
get_exp(mpfr) returns the exponent of an *mpfr*. Returns 0 for NaN or
Infinity and sets the erange flag and will raise an exception if trap_erange
is set.
**hypot(...)**
hypot(y, x) returns square root of (x**2 + y**2).
**ieee(...)**
ieee(bitwidth) returns a context with settings for 32-bit (aka single),
64-bit (aka double), or 128-bit (aka quadruple) precision floating
point types.
**inf(...)**
inf(n) returns an *mpfr* initialized to Infinity with the same sign as n.
If n is not given, +Infinity is returned.
**is_finite(...)**
is_finite(x) returns True if x is an actual number (i.e. not NaN or
Infinity).
**is_inf(...)**
is_inf(x) returns True if x is Infinity or -Infinity.
.. note::
**is_inf()** is deprecated; please use **if_infinite()**.
**is_infinite(...)**
is_infinite(x) returns True if x Infinity or -Infinity.
**is_nan(...)**
is_nan(x) returns True if x is NaN (Not-A-Number).
**is_number(...)**
is_number(x) returns True if x is an actual number (i.e. not NaN or
Infinity).
.. note::
**is_number()** is deprecated; please use **is_finite()**.
**is_regular(...)**
is_regular(x) returns True if x is not zero, NaN, or Infinity.
**is_signed(...)**
is_signed(x) returns True if the sign bit of x is set.
**is_unordered(...)**
is_unordered(x,y) returns True if either x and/or y is NaN.
**is_zero(...)**
is_zero(x) returns True if x is zero.
**j0(...)**
j0(x) returns the Bessel function of the first kind of order 0 of x.
**j1(...)**
j1(x) returns the Bessel function of the first kind of order 1 of x.
**jn(...)**
jn(x,n) returns the Bessel function of the first kind of order n of x.
**lgamma(...)**
lgamma(x) returns a tuple containing the logarithm of the absolute value of
gamma(x) and the sign of gamma(x)
**li2(...)**
li2(x) returns the real part of dilogarithm of x.
**lngamma(...)**
lngamma(x) returns the logarithm of gamma(x).
**log(...)**
log(x) returns the natural logarithm of x.
**log10(...)**
log10(x) returns the base-10 logarithm of x.
**log1p(...)**
log1p(x) returns the natural logarithm of (1+x).
**log2(...)**
log2(x) returns the base-2 logarithm of x.
**max2(...)**
max2(x, y) returns the maximum of x and y. The result may be rounded to
match the current context. Use the builtin max() to get an exact copy of
the largest object without any rounding.
**min2(...)**
min2(x, y) returns the minimum of x and y. The result may be rounded to
match the current context. Use the builtin min() to get an exact copy of
the smallest object without any rounding.
**modf(...)**
modf(x) returns a tuple containing the integer and fractional portions
of x.
**mpfr(...)**
mpfr() returns and *mpfr* object set to 0.0.
mpfr(n[, precision=0]) returns an *mpfr* object after converting a numeric
value n. If no precision, or a precision of 0, is specified; the precision
is taken from the current context.
mpfr(s[, precision=0[, [base=0]]) returns an *mpfr* object after converting
a string 's' made up of digits in the given base, possibly with fractional
part (with period as a separator) and/or exponent (with exponent marker
'e' for base<=10, else '@'). If no precision, or a precision of 0, is
specified; the precision is taken from the current context. The base of the
string representation must be 0 or in the interval 2 ... 62. If the base
is 0, the leading digits of the string are used to identify the base: 0b
implies base=2, 0x implies base=16, otherwise base=10 is assumed.
**mpfr_from_old_binary(...)**
mpfr_from_old_binary(string) returns an *mpfr* from a GMPY 1.x binary mpf
format. Please use to_binary()/from_binary() to convert GMPY2 objects to or
from a binary format.
**mpfr_grandom(...)**
mpfr_grandom(random_state) returns two random numbers with Gaussian
distribution. The parameter *random_state* must be created by random_state()
first.
**mpfr_random(...)**
mpfr_random(random_state) returns a uniformly distributed number between
[0,1]. The parameter *random_state* must be created by random_state() first.
**mul(...)**
mul(x, y) returns x * y. The type of the result is based on the types of
the arguments.
**mul_2exp(...)**
mul_2exp(x, n) returns 'mpfr' or 'mpc' multiplied by 2**n.
**nan(...)**
nan() returns an 'mpfr' initialized to NaN (Not-A-Number).
**next_above(...)**
next_above(x) returns the next 'mpfr' from x toward +Infinity.
**next_below(...)**
next_below(x) returns the next 'mpfr' from x toward -Infinity.
**radians(...)**
radians(x) converts an angle measurement x from degrees to radians.
**rec_sqrt(...)**
rec_sqrt(x) returns the reciprocal of the square root of x.
**reldiff(...)**
reldiff(x, y) returns the relative difference between x and y. Result is
equal to abs(x-y)/x.
**remainder(...)**
remainder(x, y) returns x - n*y where n is the integer quotient of x/y,
rounded to the nearest integer and ties rounded to even.
**remquo(...)**
remquo(x, y) returns a tuple containing the remainder(x,y) and the low bits
of the quotient.
**rint(...)**
rint(x) returns x rounded to the nearest integer using the current rounding
mode.
**rint_ceil(...)**
rint_ceil(x) returns x rounded to the nearest integer by first rounding to
the next higher or equal integer and then, if needed, using the current
rounding mode.
**rint_floor(...)**
rint_floor(x) returns x rounded to the nearest integer by first rounding to
the next lower or equal integer and then, if needed, using the current
rounding mode.
**rint_round(...)**
rint_round(x) returns x rounded to the nearest integer by first rounding to
the nearest integer (ties away from 0) and then, if needed, using the
current rounding mode.
**rint_trunc(...)**
rint_trunc(x) returns x rounded to the nearest integer by first rounding
towards zero and then, if needed, using the current rounding mode.
**root(...)**
root(x, n) returns n-th root of x. The result always an *mpfr*.
**round2(...)**
round2(x[, n]) returns x rounded to n bits. Uses default precision if n is
not specified. See round_away() to access the mpfr_round() function. Use
the builtin round() to round x to n decimal digits.
**round_away(...)**
round_away(x) returns an *mpfr* by rounding x the nearest integer, with
ties rounded away from 0.
**sec(...)**
sec(x) returns the secant of x. x is measured in radians.
**sech(...)**
sech(x) returns the hyperbolic secant of x.
**set_exp(...)**
set_exp(x, n) sets the exponent of a given *mpfr* to n. If n is outside the
range of valid exponents, set_exp() will set the erange flag and either
return the original value or raise an exception if trap_erange is set.
**set_sign(...)**
set_sign(x, bool) returns a copy of x with it's sign bit set if *bool*
evaluates to True.
**sign(...)**
sign(x) returns -1 if x < 0, 0 if x == 0, or +1 if x >0.
**sin(...)**
sin(x) returns the sine of x. x is measured in radians.
**sin_cos(...)**
sin_cos(x) returns a tuple containing the sine and cosine of x. x is
measured in radians.
**sinh(...)**
sinh(x) returns the hyberbolic sine of x.
**sinh_cosh(...)**
sinh_cosh(x) returns a tuple containing the hyperbolic sine and cosine of
x.
**sqrt(...)**
sqrt(x) returns the square root of x. If x is integer, rational, or real,
then an *mpfr* will be returned. If x is complex, then an *mpc* will
be returned. If context.allow_complex is True, negative values of x
will return an *mpc*.
**square(...)**
square(x) returns x * x. The type of the result is based on the types of
the arguments.
**sub(...)**
sub(x, y) returns x - y. The type of the result is based on the types of
the arguments.
**tan(...)**
tan(x) returns the tangent of x. x is measured in radians.
**tanh(...)**
tanh(x) returns the hyperbolic tangent of x.
**trunc(...)**
trunc(x) returns an 'mpfr' that is x truncated towards 0. Same as
x.floor() if x>=0 or x.ceil() if x<0.
**y0(...)**
y0(x) returns the Bessel function of the second kind of order 0 of x.
**y1(...)**
y1(x) returns the Bessel function of the second kind of order 1 of x.
**yn(...)**
yn(x,n) returns the Bessel function of the second kind of order n of x.
**zero(...)**
zero(n) returns an *mpfr* initialized to 0.0 with the same sign as n.
If n is not given, +0.0 is returned.
**zeta(...)**
zeta(x) returns the Riemann zeta of x.
mpfr Formatting
---------------
The *mpfr* type supports the __format__() special method to allow custom output
formatting.
**__format__(...)**
x.__format__(fmt) returns a Python string by formatting 'x' using the
format string 'fmt'. A valid format string consists of:
| optional alignment code:
| '<' -> left shifted in field
| '>' -> right shifted in field
| '^' -> centered in field
| optional leading sign code
| '+' -> always display leading sign
| '-' -> only display minus for negative values
| ' ' -> minus for negative values, space for positive values
| optional width.precision
| optional rounding mode:
| 'U' -> round toward plus infinity
| 'D' -> round toward minus infinity
| 'Y' -> round away from zero
| 'Z' -> round toward zero
| 'N' -> round to nearest
| optional conversion code:
| 'a','A' -> hex format
| 'b' -> binary format
| 'e','E' -> scientific format
| 'f','F' -> fixed point format
| 'g','G' -> fixed or scientific format
.. note::
The formatting codes must be specified in the order shown above.
::
>>> import gmpy2
>>> from gmpy2 import mpfr
>>> a=mpfr("1.23456")
>>> "{0:15.3f}".format(a)
' 1.235'
>>> "{0:15.3Uf}".format(a)
' 1.235'
>>> "{0:15.3Df}".format(a)
' 1.234'
>>> "{0:.3Df}".format(a)
'1.234'
>>> "{0:+.3Df}".format(a)
'+1.234'
gmpy2-2.1.0b3/docs/mpq.rst 0000664 0001750 0001750 00000004171 13356026702 015135 0 ustar case case 0000000 0000000 Multiple-precision Rationals
============================
gmpy2 provides a rational type call *mpq*. It should be a replacement for
Python's fractions.Fraction module.
::
>>> import gmpy2
>>> from gmpy2 import mpq
>>> mpq(1,7)
mpq(1,7)
>>> mpq(1,7) * 11
mpq(11,7)
>>> mpq(11,7)/13
mpq(11,91)
mpq Methods
-----------
**digits(...)**
x.digits([base=10]) returns a Python string representing *x* in the
given base (2 to 62, default is 10). A leading '-' is present if *x* < 0,
but no leading '+' is present if *x* >= 0.
mpq Attributes
--------------
**denominator**
x.denominator returns the denominator of *x*.
**numerator**
x.numerator returns the numerator of *x*.
mpq Functions
-------------
**add(...)**
add(x, y) returns *x* + *y*. The result type depends on the input
types.
**div(...)**
div(x, y) returns *x* / *y*. The result type depends on the input
types.
**f2q(...)**
f2q(x[, err]) returns the best *mpq* approximating *x* to within
relative error *err*. Default is the precision of *x*. If *x* is not an
*mpfr*, it is converted to an *mpfr*. Uses Stern-Brocot tree to find the
best approximation. An *mpz* is returned if the denominator is 1. If
*err* < 0, then the relative error sought is 2.0 ** *err*.
**mpq(...)**
mpq() returns an *mpq* object set to 0/1.
mpq(n) returns an *mpq* object with a numeric value *n*. Decimal and
Fraction values are converted exactly.
mpq(n, m) returns an *mpq* object with a numeric value *n* / *m*.
mpq(s[, base=10]) returns an *mpq* object from a string *s* made up of
digits in the given base. *s* may be made up of two numbers in the same
base separated by a '/' character. If *base* == 10, then an embedded '.'
indicates a number with a decimal fractional part.
**mul(...)**
mul(x, y) returns *x* \* *y*. The result type depends on the input
types.
**qdiv(...)**
qdiv(x[, y=1]) returns *x/y* as *mpz* if possible, or as *mpq* if *x*
is not exactly divisible by *y*.
**sub(...)**
sub(x, y) returns *x* - *y*. The result type depends on the input
types.
gmpy2-2.1.0b3/docs/mpz.rst 0000664 0001750 0001750 00000033761 13466164454 015166 0 ustar case case 0000000 0000000 Multiple-precision Integers
===========================
The gmpy2 *mpz* type supports arbitrary precision integers. It should be a
drop-in replacement for Python's *long* type. Depending on the platform and the
specific operation, an *mpz* will be faster than Python's *long* once the
precision exceeds 20 to 50 digits. All the special integer functions in GMP are
supported.
Examples
--------
::
>>> import gmpy2
>>> from gmpy2 import mpz
>>> mpz('123') + 1
mpz(124)
>>> 10 - mpz(1)
mpz(9)
>>> gmpy2.is_prime(17)
True
.. note::
The use of ``from gmpy2 import *`` is not recommended. The names in gmpy2
have been chosen to avoid conflict with Python's builtin names but gmpy2
does use names that may conflict with other modules or variable names.
mpz Methods
-----------
**bit_clear(...)**
x.bit_clear(n) returns a copy of *x* with bit *n* set to 0.
**bit_flip(...)**
x.bit_flip(n) returns a copy of *x* with bit *n* inverted.
**bit_length(...)**
x.bit_length() returns the number of significant bits in the radix-2
representation of *x*. For compatibility with Python, mpz(0).bit_length()
returns 0.
**bit_scan0(...)**
x.bit_scan0(n) returns the index of the first 0-bit of *x* with
index >= *n*. If there are no more 0-bits in *x* at or above index *n*
(which can only happen for *x* < 0, assuming an infinitely long 2's
complement format), then None is returned. *n* must be >= 0.
**bit_scan1(...)**
x.bit_scan1(n) returns the index of the first 1-bit of *x* with
index >= *n*. If there are no more 1-bits in *x* at or above index *n*
(which can only happen for *x* >= 0, assuming an infinitely long 2's
complement format), then None is returned. *n* must be >= 0.
**bit_set(...)**
x.bit_set(n) returns a copy of *x* with bit *n* set to 1.
**bit_test(...)**
x.bit_test(n) returns True if bit *n* of *x* is set, and False if it
is not set.
**conjugtae(...)**
Return the conjugate of x (which is just a new reference to x since x
not a complex number).
**denominator(...)**
x.denominator() returns mpz(1).
**digits(...)**
x.digits([base=10]) returns a string representing *x* in radix *base*.
**imag**
Return the imaginary component of an *mpz*. Always *mpz(0)*.
**is_congruent(...)**
x.is_congruent(y, m) returns True if *x* is congruent to *y* modulo *m*,
else returns False.
**is_divisible(...)**
x.is_divisible(d) returns True if *x* is divisible by *d*, else returns
False.
**is_even(...)**
x.is_even() returns True if *x* is even, else returns False.
**is_odd(...)**
x.is_odd() returns True if *x* is even, else returns False.
**is_power(...)**
x.is_power() returns True if *x* is a perfect power (there exists integers
*y* and *n* > 1, such that x=y**n), else returns False.
**is_prime(...)**
x.is_prime() returns True if *x* is _probably_ prime, else False if *x* is
definitely composite.
See the documentation for *gmpy2.is_prime* for details on the underlaying
primality tests that are performed.
**is_square(...)**
x.is_square() returns True if *x* is a perfect square, else returns False.
**num_digits(...)**
x.num_digits([base=10]) returns the length of the string representing
the absolute value of *x* in radix *base*. The result is correct if base is
a power of 2. For other bases, the result is usually correct but may
be 1 too large. *base* can range between 2 and 62, inclusive.
**numerator(...)**
x.numerator() returns a copy of *x*.
**real(...)**
x.real returns a copy of *x*.
mpz Functions
-------------
**add(...)**
add(x, y) returns *x* + *y*. The result type depends on the input
types.
**bincoef(...)**
bincoef(x, n) returns the binomial coefficient. *n* must be >= 0.
**bit_clear(...)**
bit_clear(x, n) returns a copy of *x* with bit *n* set to 0.
**bit_flip(...)**
bit_flip(x, n) returns a copy of *x* with bit *n* inverted.
**bit_length(...)**
bit_length(x) returns the number of significant bits in the radix-2
representation of *x*. For compatibility with Python, mpz(0).bit_length()
returns 0 while mpz(0).num_digits(2) returns 1.
**bit_mask(...)**
bit_mask(n) returns an *mpz* object exactly *n* bits in length with all
bits set.
**bit_scan0(...)**
bit_scan0(x, n) returns the index of the first 0-bit of *x* with
index >= *n*. If there are no more 0-bits in *x* at or above index *n*
(which can only happen for *x* < 0, assuming an infinitely long 2's
complement format), then None is returned. *n* must be >= 0.
**bit_scan1(...)**
bit_scan1(x, n) returns the index of the first 1-bit of *x* with
index >= *n*. If there are no more 1-bits in *x* at or above index *n*
(which can only happen for *x* >= 0, assuming an infinitely long 2's
complement format), then None is returned. *n* must be >= 0.
**bit_set(...)**
bit_set(x, n) returns a copy of *x* with bit *n* set to 1.
**bit_test(...)**
bit_test(x, n) returns True if bit *n* of *x* is set, and False if it
is not set.
**c_div(...)**
c_div(x, y) returns the quotient of *x* divided by *y*. The quotient is
rounded towards +Inf (ceiling rounding). *x* and *y* must be integers.
**c_div_2exp(...)**
c_div_2exp(x, n) returns the quotient of *x* divided by 2**n. The
quotient is rounded towards +Inf (ceiling rounding). *x* must be an integer
and *n* must be > 0.
**c_divmod(...)**
c_divmod(x, y) returns the quotient and remainder of *x* divided by
*y*. The quotient is rounded towards +Inf (ceiling rounding) and the
remainder will have the opposite sign of *y*. *x* and *y* must be integers.
**c_divmod_2exp(...)**
c_divmod_2exp(x ,n) returns the quotient and remainder of *x* divided
by 2**n. The quotient is rounded towards +Inf (ceiling rounding) and the
remainder will be negative or zero. *x* must be an integer and *n* must
be > 0.
**c_mod(...)**
c_mod(x, y) returns the remainder of *x* divided by *y*. The remainder
will have the opposite sign of *y*. *x* and *y* must be integers.
**c_mod_2exp(...)**
c_mod_2exp(x, n) returns the remainder of *x* divided by 2**n. The
remainder will be negative. *x* must be an integer and *n* must be > 0.
**comb(...)**
comb(x, n) returns the number of combinations of *x* things, taking *n*
at a time. *n* must be >= 0.
**digits(...)**
digits(x[, base=10]) returns a string representing *x* in radix *base*.
**div(...)**
div(x, y) returns *x* / *y*. The result type depends on the input
types.
**divexact(...)**
divexact(x, y) returns the quotient of *x* divided by *y*. Faster than
standard division but requires the remainder is zero!
**divm(...)**
divm(a, b, m) returns *x* such that *b* * *x* == *a* modulo *m*. Raises
a ZeroDivisionError exception if no such value *x* exists.
**f_div(...)**
f_div(x, y) returns the quotient of *x* divided by *y*. The quotient
is rounded towards -Inf (floor rounding). *x* and *y* must be integers.
**f_div_2exp(...)**
f_div_2exp(x, n) returns the quotient of *x* divided by 2**n. The
quotient is rounded towards -Inf (floor rounding). *x* must be an integer
and *n* must be > 0.
**f_divmod(...)**
f_divmod(x, y) returns the quotient and remainder of *x* divided by
*y*. The quotient is rounded towards -Inf (floor rounding) and the
remainder will have the same sign as *y*. *x* and *y* must be integers.
**f_divmod_2exp(...)**
f_divmod_2exp(x, n) returns quotient and remainder after dividing *x*
by 2**n. The quotient is rounded towards -Inf (floor rounding) and the
remainder will be positive. *x* must be an integer and *n* must be > 0.
**f_mod(...)**
f_mod(x, y) returns the remainder of *x* divided by *y*. The remainder
will have the same sign as *y*. *x* and *y* must be integers.
**f_mod_2exp(...)**
f_mod_2exp(x, n) returns remainder of *x* divided by 2**n. The
remainder will be positive. *x* must be an integer and *n* must be > 0.
**fac(...)**
fac(n) returns the exact factorial of *n*. Use factorial() to get the
floating-point approximation.
**fib(...)**
fib(n) returns the *n*-th Fibonacci number.
**fib2(...)**
fib2(n) returns a 2-tuple with the (*n*-1)-th and *n*-th Fibonacci
numbers.
**gcd(...)**
gcd(a, b) returns the greatest common divisor of integers *a* and
*b*.
**gcdext(...)**
gcdext(a, b) returns a 3-element tuple (*g*, *s*, *t*) such that
*g* == gcd(*a*, *b*) and *g* == *a* * *s* + *b* * *t*
**hamdist(...)**
hamdist(x, y) returns the Hamming distance (number of bit-positions
where the bits differ) between integers *x* and *y*.
**invert(...)**
invert(x, m) returns *y* such that *x* * *y* == 1 modulo *m*, or 0
if no such *y* exists.
**iroot(...)**
iroot(x,n) returns a 2-element tuple (*y*, *b*) such that *y* is the integer
*n*-th root of *x* and *b* is True if the root is exact. *x* must be >= 0
and *n* must be > 0.
**iroot_rem(...)**
iroot_rem(x,n) returns a 2-element tuple (*y*, *r*) such that *y* is
the integer *n*-th root of *x* and *x* = y**n + *r*. *x* must be >= 0 and
*n* must be > 0.
**is_even(...)**
is_even(x) returns True if *x* is even, False otherwise.
**is_odd(...)**
is_odd(x) returns True if *x* is odd, False otherwise.
**is_power(...)**
is_power(x) returns True if *x* is a perfect power, False otherwise.
**is_prime(...)**
is_prime(x[, n=25]) returns True if *x* is **probably** prime. False
is returned if *x* is definitely composite. *x* is checked for small
divisors and up to *n* Miller-Rabin tests are performed. The actual tests
performed may vary based on version of GMP or MPIR used.
**is_square(...)**
is_square(x) returns True if *x* is a perfect square, False otherwise.
**isqrt(...)**
isqrt(x) returns the integer square root of an integer *x*. *x* must be
>= 0.
**isqrt_rem(...)**
isqrt_rem(x) returns a 2-tuple (*s*, *t*) such that *s* = isqrt(*x*)
and *t* = *x* - *s* * *s*. *x* must be >= 0.
**jacobi(...)**
jacobi(x, y) returns the Jacobi symbol (*x* | *y*). *y* must be odd and
> 0.
**kronecker(...)**
kronecker(x, y) returns the Kronecker-Jacobi symbol (*x* | *y*).
**lcm(...)**
lcm(a, b) returns the lowest common multiple of integers *a* and *b*.
**legendre(...)**
legendre(x, y) returns the Legendre symbol (*x* | *y*). *y* is assumed
to be an odd prime.
**lucas(...)**
lucas(n) returns the *n*-th Lucas number.
**lucas2(...)**
lucas2(n) returns a 2-tuple with the (*n*-1)-th and *n*-th Lucas
numbers.
**mpz(...)**
mpz() returns a new *mpz* object set to 0.
mpz(n) returns a new *mpz* object from a numeric value *n*. If *n* is
not an integer, it will be truncated to an integer.
mpz(s[, base=0]) returns a new *mpz* object from a string *s* made of
digits in the given base. If base = 0, then binary, octal, or hex Python
strings are recognized by leading 0b, 0o, or 0x characters. Otherwise the
string is assumed to be decimal. Values for base can range between 2 and 62.
**mpz_random(...)**
mpz_random(random_state, n) returns a uniformly distributed random
integer between 0 and *n*-1. The parameter *random_state* must be created
by random_state() first.
**mpz_rrandomb(...)**
mpz_rrandomb(random_state, b) returns a random integer between 0 and
2**b - 1 with long sequences of zeros and one in its binary representation.
The parameter *random_state* must be created by random_state() first.
**mpz_urandomb(...)**
mpz_urandomb(random_state, b) returns a uniformly distributed random
integer between 0 and 2**b - 1. The parameter *random_state* must be
created by random_state() first.
**mul(...)**
mul(x, y) returns *x* \* *y*. The result type depends on the input
types.
**next_prime(...)**
next_prime(x) returns the next **probable** prime number > *x*.
**num_digits(...)**
num_digits(x[, base=10]) returns the length of the string representing
the absolute value of *x* in radix *base*. The result is correct if base is
a power of 2. For other bases, the result is usually correct but may
be 1 too large. *base* can range between 2 and 62, inclusive.
**popcount(...)**
popcount(x) returns the number of bits with value 1 in *x*. If *x* < 0,
the number of bits with value 1 is infinite so -1 is returned in that case.
**powmod(...)**
powmod(x, y, m) returns (*x* ** *y*) mod *m*. The exponent *y* can be
negative, and the correct result will be returned if the inverse of *x*
mod *m* exists. Otherwise, a ValueError is raised.
**remove(...)**
remove(x, f) will remove the factor *f* from *x* as many times as possible
and return a 2-tuple (*y*, *m*) where *y* = *x* // (*f* ** *m*). *f* does
not divide *y*. *m* is the multiplicity of the factor *f* in *x*. *f* must
be > 1.
**sub(...)**
sub(x, y) returns *x* - *y*. The result type depends on the input
types.
**t_div(...)**
t_div(x, y) returns the quotient of *x* divided by *y*. The quotient
is rounded towards zero (truncation). *x* and *y* must be integers.
**t_div_2exp(...)**
t_div_2exp(x, n) returns the quotient of *x* divided by 2**n. The
quotient is rounded towards zero (truncation). *n* must be > 0.
**t_divmod(...)**
t_divmod(x, y) returns the quotient and remainder of *x* divided by
*y*. The quotient is rounded towards zero (truncation) and the remainder
will have the same sign as *x*. *x* and *y* must be integers.
**t_divmod_2exp(...)**
t_divmod_2exp(x, n) returns the quotient and remainder of *x* divided
by 2**n. The quotient is rounded towards zero (truncation) and the
remainder will have the same sign as *x*. *x* must be an integer and *n*
must be > 0.
**t_mod(...)**
t_mod(x, y) returns the remainder of *x* divided by *y*. The remainder
will have the same sign as *x*. *x* and *y* must be integers.
**t_mod_2exp(...)**
t_mod_2exp(x, n) returns the remainder of *x* divided by 2**n. The
remainder will have the same sign as *x*. *x* must be an integer and *n*
must be > 0.
gmpy2-2.1.0b3/docs/overview.rst 0000664 0001750 0001750 00000012240 13356026702 016202 0 ustar case case 0000000 0000000 Overview of gmpy2
=================
Tutorial
--------
The *mpz* type is compatible with Python's built-in int/long type but is
significantly faster for large values. The cutover point for performance varies,
but can be as low as 20 to 40 digits. A variety of additional integer functions
are provided.
::
>>> import gmpy2
>>> from gmpy2 import mpz,mpq,mpfr,mpc
>>> mpz(99) * 43
mpz(4257)
>>> pow(mpz(99), 37, 59)
mpz(18)
>>> gmpy2.isqrt(99)
mpz(9)
>>> gmpy2.isqrt_rem(99)
(mpz(9), mpz(18))
>>> gmpy2.gcd(123,27)
mpz(3)
>>> gmpy2.lcm(123,27)
mpz(1107)
The *mpq* type is compatible with the *fractions.Fraction* type included with
Python.
::
>>> mpq(3,7)/7
mpq(3,49)
>>> mpq(45,3) * mpq(11,8)
mpq(165,8)
The most significant new features in gmpy2 are support for correctly rounded
arbitrary precision real and complex arithmetic based on the MPFR and MPC
libraries. Floating point contexts are used to control exceptional conditions.
For example, division by zero can either return an Infinity or raise an exception.
::
>>> mpfr(1)/7
mpfr('0.14285714285714285')
>>> gmpy2.get_context().precision=200
>>> mpfr(1)/7
mpfr('0.1428571428571428571428571428571428571428571428571428571428571',200)
>>> gmpy2.get_context()
context(precision=200, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=True,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
trap_expbound=False,
allow_complex=False)
>>> mpfr(1)/0
mpfr('inf')
>>> gmpy2.get_context().trap_divzero=True
>>> mpfr(1)/0
Traceback (most recent call last):
File "", line 1, in
gmpy2.DivisionByZeroError: 'mpfr' division by zero in division
>>> gmpy2.get_context()
context(precision=200, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=True,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=True, divzero=True,
trap_expbound=False,
allow_complex=False)
>>> gmpy2.sqrt(mpfr(-2))
mpfr('nan')
>>> gmpy2.get_context().allow_complex=True
>>> gmpy2.get_context().precision=53
>>> gmpy2.sqrt(mpfr(-2))
mpc('0.0+1.4142135623730951j')
>>>
>>> gmpy2.set_context(gmpy2.context())
>>> with gmpy2.local_context() as ctx:
... print(gmpy2.const_pi())
... ctx.precision+=20
... print(gmpy2.const_pi())
... ctx.precision+=20
... print(gmpy2.const_pi())
...
3.1415926535897931
3.1415926535897932384628
3.1415926535897932384626433831
>>> print(gmpy2.const_pi())
3.1415926535897931
>>>
Miscellaneous gmpy2 Functions
-----------------------------
**from_binary(...)**
from_binary(bytes) returns a gmpy2 object from a byte sequence created by
to_binary().
**get_cache(...)**
get_cache() returns the current cache size (number of objects) and the
maximum size per object (number of limbs).
gmpy2 maintains an internal list of freed *mpz*, *xmpz*, *mpq*, *mpfr*, and
*mpc* objects for reuse. The cache significantly improves performance but
also increases the memory footprint.
**license(...)**
license() returns the gmpy2 license information.
**mp_limbsize(...)**
mp_limbsize() returns the number of bits per limb used by the GMP or MPIR
library.
**mp_version(...)**
mp_version() returns the version of the GMP or MPIR library.
**mpc_version(...)**
mpc_version() returns the version of the MPC library.
**mpfr_version(...)**
mpfr_version() returns the version of the MPFR library.
**random_state(...)**
random_state([seed]) returns a new object containing state information for
the random number generator. An optional integer argument can be specified
as the seed value. Only the Mersenne Twister random number generator is
supported.
**set_cache(...)**
set_cache(number, size) updates the maximum number of freed objects of each
type that are cached and the maximum size (in limbs) of each object. The
maximum number of objects of each type that can be cached is 1000. The
maximum size of an object is 16384. The maximum size of an object is
approximately 64K on 32-bit systems and 128K on 64-bit systems.
.. note::
The caching options are global to gmpy2. Changes are not thread-safe. A
change in one thread will impact all threads.
**to_binary(...)**
to_binary(x) returns a byte sequence from a gmpy2 object. All object types
are supported.
**version(...)**
version() returns the version of gmpy2.
gmpy2-2.1.0b3/gmpy2/ 0000775 0001750 0001750 00000000000 13530663166 013716 5 ustar case case 0000000 0000000 gmpy2-2.1.0b3/gmpy2/__init__.pxd 0000664 0001750 0001750 00000000033 13356026702 016161 0 ustar case case 0000000 0000000 from gmpy2.gmpy2 cimport *
gmpy2-2.1.0b3/gmpy2/__init__.py 0000664 0001750 0001750 00000000575 13425750522 016032 0 ustar case case 0000000 0000000 from .gmpy2 import *
# Internal variables/functions are not imported by * above.
# These are used by some python level functions and are needed
# at the top level.
# Use try...except to for static builds were _C_API is not available.
try:
from .gmpy2 import _C_API, _mpmath_normalize, _mpmath_create
except ImportError:
from .gmpy2 import _mpmath_normalize, _mpmath_create
gmpy2-2.1.0b3/gmpy2/gmpy2.h 0000664 0001750 0001750 00000051007 13525427233 015125 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
gmpy C API extension header file.
Part of Python's gmpy module since version 0.4
Created by Pearu Peterson , November 2000.
Edited by A. Martelli , December 2000.
Edited by Case Van Horsen , 2009, 2010, 2011.
Version 1.02, February 2007.
Version 1.03, June 2008
Version 1.04, June 2008 (no changes)
Version 1.05, February 2009 (support MPIR)
Version 1.20, January 2010 (remove obsolete MS hacks) casevh
Version 2.00, April 2010 (change to gmpy2) casevh
October 2010 (added Py_hash_t) casevh
December 2010 (added mpfr, mpc) casevh
January 2011 (add Pygmpy_context) casevh
April 2011 (split into multiple files) casevh
Version 2.10 August 2014 (reflect major rewrite during 2013/2014) casevh
*/
#ifndef Py_GMPYMODULE_H
#define Py_GMPYMODULE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Structure of gmpy2.h
*
* Revised 17-APR-2017 casevh
*
* 1. Checks for specific Python versions.
* 2. Include headers for GMP/MPIR, MPFR, and MPC.
* 3. Define public C-API.
* 1. Define gmpy2 types.
* 2. Define the public API.
*
*/
/* Check for minimum Python version requirements. */
#if PY_VERSION_HEX < 0x02060000
# error "GMPY2 requires Python 2.6 or later."
#endif
/* Include headers for GMP/MPIR, MPFR, and MPC. */
#ifdef MPIR
# include
#else
# include
#endif
#include
#include
/* Check MPFR and MPC versions. */
#if (!defined(MPC_VERSION) || (MPC_VERSION < MPC_VERSION_NUM(1,0,3)))
# error "GMPY2 requires MPC 1.0.3 or later."
#endif
#if (defined(MPC_VERSION) && (MPC_VERSION >= MPC_VERSION_NUM(1,1,0)))
# define MPC_110
#endif
#if PY_VERSION_HEX < 0x030200A4
typedef long Py_hash_t;
typedef unsigned long Py_uhash_t;
# define _PyHASH_IMAG 1000003
#endif
/* The native_si and native_ui types correspond to long long on Windows 64. They
* should only be used with the MPIR library (not MPFR/MPC).
*/
#if defined(MPIR) && defined(_WIN64)
typedef long long native_si;
typedef unsigned long long native_ui;
#define GMPy_Integer_AsNative_siAndError GMPy_Integer_AsLongLongAndError
#define GMPy_Integer_AsNative_uiAndError GMPy_Integer_AsUnsignedLongLongAndError
#else
typedef long native_si;
typedef unsigned long native_ui;
#define GMPy_Integer_AsNative_siAndError GMPy_Integer_AsLongAndError
#define GMPy_Integer_AsNative_uiAndError GMPy_Integer_AsUnsignedLongAndError
#endif
/* GMPY2 Public API */
/* Types
* MPZ_Object
* XMPZ_Object (mutable version of MPZ_Object)
* MPQ_Object
* XMPQ_Object (mutable version of MPQ_Object)
* MPFR_Object
* XMPFR_Object (mutable version of MPFR_Object)
* MPC_Object
* XMPC_Object (mutable version of MPC_Object)
* CTXT_Object
* CTXT_Manager_Object
* RandomState_Object
*/
typedef struct {
PyObject_HEAD
mpz_t z;
Py_hash_t hash_cache;
} MPZ_Object;
typedef struct {
PyObject_HEAD
mpz_t z;
} XMPZ_Object;
typedef struct {
PyObject_HEAD
mpq_t q;
Py_hash_t hash_cache;
} MPQ_Object;
typedef struct {
PyObject_HEAD
mpfr_t f;
Py_hash_t hash_cache;
int rc;
} MPFR_Object;
typedef struct {
PyObject_HEAD
mpc_t c;
Py_hash_t hash_cache;
int rc;
} MPC_Object;
typedef struct {
PyObject_HEAD
gmp_randstate_t state;
} RandomState_Object;
typedef struct {
mpfr_prec_t mpfr_prec; /* current precision in bits, for MPFR */
mpfr_rnd_t mpfr_round; /* current rounding mode for float (MPFR) */
mpfr_exp_t emax; /* maximum exponent */
mpfr_exp_t emin; /* minimum exponent */
int subnormalize; /* if 1, subnormalization is performed */
int underflow; /* did an underflow occur? */
int overflow; /* did an overflow occur? */
int inexact; /* was the result inexact? */
int invalid; /* invalid operation (i.e. NaN)? */
int erange; /* did a range error occur? */
int divzero; /* divided by zero? */
int traps; /* if 0, do not trap any exceptions */
/* if not 0, then raise traps per bits above */
mpfr_prec_t real_prec; /* current precision in bits, for Re(MPC) */
mpfr_prec_t imag_prec; /* current precision in bits, for Im(MPC) */
mpfr_rnd_t real_round; /* current rounding mode for Re(MPC) */
mpfr_rnd_t imag_round; /* current rounding mode for Im(MPC) */
int allow_complex; /* if 1, allow mpfr functions to return an mpc */
int rational_division; /* if 1, mpz/mpz returns an mpq result */
} gmpy_context;
typedef struct {
PyObject_HEAD
gmpy_context ctx;
#ifndef WITHOUT_THREADS
PyThreadState *tstate;
#endif
} CTXT_Object;
typedef struct {
PyObject_HEAD
CTXT_Object *new_context; /* Context that will be returned when
* __enter__ is called. */
CTXT_Object *old_context; /* Context that will restored when
* __exit__ is called. */
} CTXT_Manager_Object;
#define MPZ(obj) (((MPZ_Object*)(obj))->z)
#define MPQ(obj) (((MPQ_Object*)(obj))->q)
#define MPFR(obj) (((MPFR_Object*)(obj))->f)
#define MPC(obj) (((MPC_Object*)(obj))->c)
/* Start of the C-API definitions */
#define MPZ_Type_NUM 0
#define XMPZ_Type_NUM 1
#define MPQ_Type_NUM 2
#define XMPQ_Type_NUM 3
#define MPFR_Type_NUM 4
#define XMPFR_Type_NUM 5
#define MPC_Type_NUM 6
#define XMPC_Type_NUM 7
#define CTXT_Type_NUM 8
#define CTXT_Manager_Type_NUM 9
#define RandomState_Type_NUM 10
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPZ_New_NUM 11
#define GMPy_MPZ_New_RETURN MPZ_Object *
#define GMPy_MPZ_New_PROTO (CTXT_Object *context)
#define GMPy_MPZ_NewInit_NUM 12
#define GMPy_MPZ_NewInit_RETURN PyObject *
#define GMPy_MPZ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPZ_Dealloc_NUM 13
#define GMPy_MPZ_Dealloc_RETURN void
#define GMPy_MPZ_Dealloc_PROTO (MPZ_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPZ_ConvertArg_NUM 14
#define GMPy_MPZ_ConvertArg_RETURN int
#define GMPy_MPZ_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_XMPZ_New_NUM 15
#define GMPy_XMPZ_New_RETURN XMPZ_Object *
#define GMPy_XMPZ_New_PROTO (CTXT_Object *context)
#define GMPy_XMPZ_NewInit_NUM 16
#define GMPy_XMPZ_NewInit_RETURN PyObject *
#define GMPy_XMPZ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_XMPZ_Dealloc_NUM 17
#define GMPy_XMPZ_Dealloc_RETURN void
#define GMPy_XMPZ_Dealloc_PROTO (XMPZ_Object *self)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPQ_New_NUM 18
#define GMPy_MPQ_New_RETURN MPQ_Object *
#define GMPy_MPQ_New_PROTO (CTXT_Object *context)
#define GMPy_MPQ_NewInit_NUM 19
#define GMPy_MPQ_NewInit_RETURN PyObject *
#define GMPy_MPQ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPQ_Dealloc_NUM 20
#define GMPy_MPQ_Dealloc_RETURN void
#define GMPy_MPQ_Dealloc_PROTO (MPQ_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPQ_ConvertArg_NUM 21
#define GMPy_MPQ_ConvertArg_RETURN int
#define GMPy_MPQ_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPFR_New_NUM 22
#define GMPy_MPFR_New_RETURN MPFR_Object *
#define GMPy_MPFR_New_PROTO (mpfr_prec_t bits, CTXT_Object *context)
#define GMPy_MPFR_NewInit_NUM 23
#define GMPy_MPFR_NewInit_RETURN PyObject *
#define GMPy_MPFR_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPFR_Dealloc_NUM 24
#define GMPy_MPFR_Dealloc_RETURN void
#define GMPy_MPFR_Dealloc_PROTO (MPFR_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPFR_ConvertArg_NUM 25
#define GMPy_MPFR_ConvertArg_RETURN int
#define GMPy_MPFR_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPC_New_NUM 26
#define GMPy_MPC_New_RETURN MPC_Object *
#define GMPy_MPC_New_PROTO (mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context)
#define GMPy_MPC_NewInit_NUM 27
#define GMPy_MPC_NewInit_RETURN PyObject *
#define GMPy_MPC_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPC_Dealloc_NUM 28
#define GMPy_MPC_Dealloc_RETURN void
#define GMPy_MPC_Dealloc_PROTO (MPC_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPC_ConvertArg_NUM 29
#define GMPy_MPC_ConvertArg_RETURN int
#define GMPy_MPC_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* Total number of C-API pointers. */
#define GMPy_API_pointers 30
/* End of C-API definitions. */
#ifdef GMPY2_MODULE
/* Define various macros to deal with differences between Python 2 and 3. */
#if (PY_MAJOR_VERSION == 3)
#define PY3
#define Py2or3String_FromString PyUnicode_FromString
#define Py2or3String_FromFormat PyUnicode_FromFormat
#define Py2or3String_Check PyUnicode_Check
#define Py2or3String_Format PyUnicode_Format
#define Py2or3String_AsString PyUnicode_AS_DATA
#define PyStrOrUnicode_Check(op) (PyBytes_Check(op) || PyUnicode_Check(op))
#define PyIntOrLong_FromLong PyLong_FromLong
#define PyIntOrLong_Check(op) PyLong_Check(op)
#define PyIntOrLong_FromSize_t PyLong_FromSize_t
#define PyIntOrLong_FromSsize_t PyLong_FromSsize_t
#define PyIntOrLong_AsSsize_t PyLong_AsSsize_t
#define PyIntOrLong_AsLong PyLong_AsLong
#else
#define PY2
#define Py2or3String_FromString PyString_FromString
#define Py2or3String_FromFormat PyString_FromFormat
#define Py2or3String_Check PyString_Check
#define Py2or3String_Format PyString_Format
#define Py2or3String_AsString PyString_AsString
#define PyStrOrUnicode_Check(op) (PyString_Check(op) || PyUnicode_Check(op))
#define PyIntOrLong_FromLong PyInt_FromLong
#define PyIntOrLong_Check(op) (PyInt_Check(op) || PyLong_Check(op))
#define PyIntOrLong_FromSize_t PyInt_FromSize_t
#define PyIntOrLong_FromSsize_t PyInt_FromSsize_t
#define PyIntOrLong_AsSsize_t PyInt_AsSsize_t
#define PyIntOrLong_AsLong PyInt_AsLong
#endif
#ifndef ABS
# define ABS(a) (((a) < 0) ? -(a) : (a))
#endif
#if defined(MS_WIN32) && defined(_MSC_VER)
/* so one won't need to link explicitly to gmp.lib...: */
# if defined(MPIR)
# pragma comment(lib,"mpir.lib")
# else
# pragma comment(lib,"gmp.lib")
# endif
# define USE_ALLOCA 1
# define inline __inline
#endif
#ifdef __GNUC__
# define USE_ALLOCA 1
#endif
#ifndef alloca
# ifdef __GNUC__
# define alloca __builtin_alloca
# else
# ifdef _MSC_VER
# include
# define alloca _alloca
# else
# if HAVE_ALLOCA_H
# include
# else
char *alloca ();
# endif
# endif
# endif
#endif
#define ALLOC_THRESHOLD 8192
#define INDEX_ERROR(msg) PyErr_SetString(PyExc_IndexError, msg)
#define TYPE_ERROR(msg) PyErr_SetString(PyExc_TypeError, msg)
#define VALUE_ERROR(msg) PyErr_SetString(PyExc_ValueError, msg)
#define ZERO_ERROR(msg) PyErr_SetString(PyExc_ZeroDivisionError, msg)
#define SYSTEM_ERROR(msg) PyErr_SetString(PyExc_SystemError, msg)
#define OVERFLOW_ERROR(msg) PyErr_SetString(PyExc_OverflowError, msg)
#define RUNTIME_ERROR(msg) PyErr_SetString(PyExc_RuntimeError, msg)
#define GMPY_DEFAULT -1
/* To prevent excessive memory usage, we don't want to save very large
* numbers in the cache. The default value specified in the options
* structure is 128 words (512 bytes on 32-bit platforms, 1024 bytes on
* 64-bit platforms).
*/
#define MAX_CACHE_LIMBS 16384
/* The maximum number of objects that can be saved in a cache is specified
* here. The default value is 100.*/
#define MAX_CACHE 1000
#ifdef USE_ALLOCA
# define TEMP_ALLOC(B, S) \
if(S < ALLOC_THRESHOLD) { \
B = alloca(S); \
} else { \
if(!(B = malloc(S))) { \
PyErr_NoMemory(); \
return NULL; \
} \
}
# define TEMP_FREE(B, S) if(S >= ALLOC_THRESHOLD) free(B)
#else
# define TEMP_ALLOC(B, S) \
if(!(B = malloc(S))) { \
PyErr_NoMemory(); \
return NULL; \
}
# define TEMP_FREE(B, S) free(B)
#endif
/* Various defs to mask differences between Python versions. */
#define Py_RETURN_NOTIMPLEMENTED \
return Py_INCREF(Py_NotImplemented), Py_NotImplemented
#ifndef Py_SIZE
# define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
#endif
#ifndef Py_TYPE
# define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#endif
/* Import a collection of general purpose macros. */
#include "gmpy2_macros.h"
/* Import the files that complete the definition of the types defined above. */
#include "gmpy2_mpz.h"
#include "gmpy2_xmpz.h"
#include "gmpy2_mpq.h"
#include "gmpy2_mpfr.h"
#include "gmpy2_mpc.h"
#include "gmpy2_context.h"
#include "gmpy2_random.h"
/* Import the header files that provide the various functions. */
/* Support object caching, creation, and deletion. */
#include "gmpy2_cache.h"
/* Suport for miscellaneous functions (ie. version, license, etc.). */
#include "gmpy2_misc.h"
/* Support conversion to/from binary format. */
#include "gmpy2_binary.h"
/* Support for mpz/xmpz specific functions. */
#include "gmpy2_convert.h"
#include "gmpy2_convert_utils.h"
#include "gmpy2_convert_gmp.h"
#include "gmpy2_convert_mpfr.h"
#include "gmpy2_convert_mpc.h"
#include "gmpy2_mpz_divmod.h"
#include "gmpy2_mpz_divmod2exp.h"
#include "gmpy2_mpz_pack.h"
#include "gmpy2_mpz_bitops.h"
#include "gmpy2_mpz_inplace.h"
#include "gmpy2_mpz_misc.h"
#include "gmpy2_xmpz_inplace.h"
#include "gmpy2_xmpz_misc.h"
/* Support for mpq specific functions. */
#include "gmpy2_mpq_misc.h"
/* Support for mpfr specific functions. */
#include "gmpy2_mpfr_misc.h"
/* Support for mpc specific functions. */
#include "gmpy2_mpc_misc.h"
/* Support Lucas sequences. */
#include "gmpy_mpz_lucas.h"
/* Support probable-prime tests. */
#include "gmpy_mpz_prp.h"
/* Support higher-level Python methods and functions; generally not
* specific to a single type.
*/
#include "gmpy2_abs.h"
#include "gmpy2_add.h"
#include "gmpy2_divmod.h"
#include "gmpy2_floordiv.h"
#include "gmpy2_minus.h"
#include "gmpy2_mod.h"
#include "gmpy2_mul.h"
#include "gmpy2_plus.h"
#include "gmpy2_pow.h"
#include "gmpy2_sub.h"
#include "gmpy2_truediv.h"
#include "gmpy2_math.h"
#include "gmpy2_const.h"
#include "gmpy2_square.h"
#include "gmpy2_format.h"
#include "gmpy2_hash.h"
#include "gmpy2_fused.h"
#include "gmpy2_muldiv_2exp.h"
#include "gmpy2_predicate.h"
#include "gmpy2_sign.h"
#include "gmpy2_richcompare.h"
#include "gmpy2_cmp.h"
#ifdef VECTOR
# include "gmpy2_vector.h"
#endif /* defined(VECTOR) */
#else /* defined(GMPY2_MODULE) */
/* This section is used for other C-coded modules that use gmpy2's API. */
static void **GMPy_C_API;
#define MPZ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPZ_Type_NUM])
#define XMPZ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPZ_Type_NUM])
#define MPQ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPQ_Type_NUM])
#define XMPQ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPQ_Type_NUM])
#define MPFR_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPFR_Type_NUM])
#define XMPFR_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPFR_Type_NUM])
#define MPC_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPC_Type_NUM])
#define XMPC_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPC_Type_NUM])
#define GMPy_MPZ_New (*(GMPy_MPZ_New_RETURN (*)GMPy_MPZ_New_PROTO) GMPy_C_API[GMPy_MPZ_New_NUM])
#define GMPy_MPZ_NewInit (*(GMPy_MPZ_NewInit_RETURN (*)GMPy_MPZ_NewInit_PROTO) GMPy_C_API[GMPy_MPZ_NewInit_NUM])
#define GMPy_MPZ_Dealloc (*(GMPy_MPZ_Dealloc_RETURN (*)GMPy_MPZ_Dealloc_PROTO) GMPy_C_API[GMPy_MPZ_Dealloc_NUM])
#define GMPy_MPZ_ConvertArg (*(GMPy_MPZ_ConvertArg_RETURN (*)GMPy_MPZ_ConvertArg_PROTO) GMPy_C_API[GMPy_MPZ_ConvertArg_NUM])
#define GMPy_XMPZ_New (*(GMPy_XMPZ_New_RETURN (*)GMPy_XMPZ_New_PROTO) GMPy_C_API[GMPy_XMPZ_New_NUM])
#define GMPy_XMPZ_NewInit (*(GMPy_XMPZ_NewInit_RETURN (*)GMPy_XMPZ_NewInit_PROTO) GMPy_C_API[GMPy_XMPZ_NewInit_NUM])
#define GMPy_XMPZ_Dealloc (*(GMPy_XMPZ_Dealloc_RETURN (*)GMPy_XMPZ_Dealloc_PROTO) GMPy_C_API[GMPy_XMPZ_Dealloc_NUM])
#define GMPy_MPQ_New (*(GMPy_MPQ_New_RETURN (*)GMPy_MPQ_New_PROTO) GMPy_C_API[GMPy_MPQ_New_NUM])
#define GMPy_MPQ_NewInit (*(GMPy_MPQ_NewInit_RETURN (*)GMPy_MPQ_NewInit_PROTO) GMPy_C_API[GMPy_MPQ_NewInit_NUM])
#define GMPy_MPQ_Dealloc (*(GMPy_MPQ_Dealloc_RETURN (*)GMPy_MPQ_Dealloc_PROTO) GMPy_C_API[GMPy_MPQ_Dealloc_NUM])
#define GMPy_MPQ_ConvertArg (*(GMPy_MPQ_ConvertArg_RETURN (*)GMPy_MPQ_ConvertArg_PROTO) GMPy_C_API[GMPy_MPQ_ConvertArg_NUM])
#define GMPy_MPFR_New (*(GMPy_MPFR_New_RETURN (*)GMPy_MPFR_New_PROTO) GMPy_C_API[GMPy_MPFR_New_NUM])
#define GMPy_MPFR_NewInit (*(GMPy_MPFR_NewInit_RETURN (*)GMPy_MPFR_NewInit_PROTO) GMPy_C_API[GMPy_MPFR_NewInit_NUM])
#define GMPy_MPFR_Dealloc (*(GMPy_MPFR_Dealloc_RETURN (*)GMPy_MPFR_Dealloc_PROTO) GMPy_C_API[GMPy_MPFR_Dealloc_NUM])
#define GMPy_MPFR_ConvertArg (*(GMPy_MPFR_ConvertArg_RETURN (*)GMPy_MPFR_ConvertArg_PROTO) GMPy_C_API[GMPy_MPFR_ConvertArg_NUM])
#define GMPy_MPC_New (*(GMPy_MPC_New_RETURN (*)GMPy_MPC_New_PROTO) GMPy_C_API[GMPy_MPC_New_NUM])
#define GMPy_MPC_NewInit (*(GMPy_MPC_NewInit_RETURN (*)GMPy_MPC_NewInit_PROTO) GMPy_C_API[GMPy_MPC_NewInit_NUM])
#define GMPy_MPC_Dealloc (*(GMPy_MPC_Dealloc_RETURN (*)GMPy_MPC_Dealloc_PROTO) GMPy_C_API[GMPy_MPC_Dealloc_NUM])
#define GMPy_MPC_ConvertArg (*(GMPy_MPC_ConvertArg_RETURN (*)GMPy_MPC_ConvertArg_PROTO) GMPy_C_API[GMPy_MPC_ConvertArg_NUM])
static int
import_gmpy2(void)
{
GMPy_C_API = (void **)PyCapsule_Import("gmpy2._C_API", 0);
return (GMPy_C_API != NULL) ? 0 : -1;
}
#endif /* defined(GMPY2_MODULE) */
#ifdef __cplusplus
}
#endif /* defined(__cplusplus */
#endif /* !defined(Py_GMPYMODULE_H */
gmpy2-2.1.0b3/gmpy2/gmpy2.pxd 0000664 0001750 0001750 00000011111 13356026702 015457 0 ustar case case 0000000 0000000 cdef extern from "gmp.h":
# gmp integers
ctypedef long mp_limb_t
ctypedef struct __mpz_struct:
int _mp_alloc
int _mp_size
mp_limb_t* _mp_d
ctypedef __mpz_struct mpz_t[1]
ctypedef __mpz_struct *mpz_ptr
ctypedef const __mpz_struct *mpz_srcptr
# gmp rationals
ctypedef struct __mpq_struct:
__mpz_struct _mp_num
__mpz_struct _mp_den
ctypedef __mpq_struct mpq_t[1]
ctypedef __mpq_struct *mpq_ptr
ctypedef const __mpq_struct *mpq_srcptr
void mpz_set(mpz_t rop, mpz_t op)
void mpq_set(mpq_ptr rop, mpq_srcptr op)
void mpq_set_num(mpq_t rational, mpz_t numerator)
void mpq_set_den(mpq_t rational, mpz_t denominator)
cdef extern from "mpfr.h":
# mpfr reals
ctypedef int mpfr_sign_t
ctypedef long mpfr_prec_t
ctypedef long mpfr_exp_t
ctypedef struct __mpfr_struct:
mpfr_prec_t _mpfr_prec
mpfr_sign_t _mpfr_sign
mpfr_exp_t _mpfr_exp
mp_limb_t* _mpfr_d
ctypedef __mpfr_struct mpfr_t[1]
ctypedef __mpfr_struct *mpfr_ptr
ctypedef const __mpfr_struct *mpfr_srcptr
ctypedef enum mpfr_rnd_t:
MPFR_RNDN
MPFR_RNDZ
MPFR_RNDU
MPFR_RNDD
MPFR_RNDA
MPFR_RNDF
MPFR_RNDNA
mpfr_prec_t mpfr_get_prec(mpfr_t x)
int mpfr_set(mpfr_t rop, mpfr_t op, mpfr_rnd_t rnd)
cdef extern from "mpc.h":
# mpc complexes
ctypedef struct __mpc_struct:
mpfr_t re
mpfr_t im
ctypedef __mpc_struct mpc_t[1];
ctypedef __mpc_struct *mpc_ptr;
ctypedef const __mpc_struct *mpc_srcptr;
ctypedef enum mpc_rnd_t:
MPC_RNDNN
MPC_RNDNZ
MPC_RNDNU
MPC_RNDND
MPC_RNDZN
MPC_RNDZZ
MPC_RNDZU
MPC_RNDZD
MPC_RNDUN
MPC_RNDUZ
MPC_RNDUU
MPC_RNDUD
MPC_RNDDN
MPC_RNDDZ
MPC_RNDDU
MPC_RNDDD
mpfr_prec_t mpc_get_prec(mpc_srcptr x)
void mpc_get_prec2(mpfr_prec_t *pr, mpfr_prec_t *pi, mpc_srcptr x)
int mpc_set(mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
int mpc_set_fr_fr(mpc_ptr rop, mpfr_srcptr rp, mpfr_srcptr ip, mpc_rnd_t rnd)
cdef extern from "gmpy2.h":
# Initialize the C-API
# This must be called before any other functions, but not to access
# the types.
cdef int import_gmpy2() except -1
# Object types
ctypedef class gmpy2.mpz [object MPZ_Object]:
cdef mpz_t z
ctypedef class gmpy2.mpq [object MPQ_Object]:
cdef mpq_t q
ctypedef class gmpy2.mpfr [object MPFR_Object]:
cdef mpfr_t f
cdef int rc
ctypedef class gmpy2.mpc [object MPC_Object]:
cdef mpc_t c
cdef int rc
# Object creation
cdef mpz GMPy_MPZ_New(void *)
cdef mpq GMPy_MPQ_New(void *)
cdef mpfr GMPy_MPFR_New(mpfr_prec_t prec, void *)
cdef mpc GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, void *)
# C field access
cdef mpz_t MPZ(mpz)
cdef mpq_t MPQ(mpq)
cdef mpfr_t MPFR(mpfr)
cdef mpc_t MPC(mpc)
# Type check
cdef bint MPZ_Check(object)
cdef bint MPQ_Check(object)
cdef bint MPFR_Check(object)
cdef bint MPC_Check(object)
# Build a gmpy2 mpz from a gmp mpz
cdef inline mpz GMPy_MPZ_From_mpz(mpz_srcptr z):
cdef mpz res = GMPy_MPZ_New(NULL)
mpz_set(res.z, z)
return res
# Build a gmpy2 mpq from a gmp mpq
cdef inline mpq GMPy_MPQ_From_mpq(mpq_srcptr q):
cdef mpq res = GMPy_MPQ_New(NULL)
mpq_set(res.q, q)
return res
# Build a gmpy2 mpq from gmp mpz numerator and denominator
cdef inline mpq GMPy_MPQ_From_mpz(mpz_srcptr num, mpz_srcptr den):
cdef mpq res = GMPy_MPQ_New(NULL)
mpq_set_num(res.q, num)
mpq_set_den(res.q, den)
return res
# Build a gmpy2 mpfr from a mpfr
cdef inline mpfr GMPy_MPFR_From_mpfr(mpfr_srcptr x):
cdef mpfr res = GMPy_MPFR_New(mpfr_get_prec(x), NULL)
mpfr_set(res.f, x, MPFR_RNDN)
return res
# Build a gmpy2 mpc from a mpc
cdef inline mpc GMPy_MPC_From_mpc(mpc_srcptr c):
cdef mpfr_prec_t pr
cdef mpfr_prec_t pi
mpc_get_prec2(&pr, &pi, c)
cdef mpc res = GMPy_MPC_New(pr, pi, NULL)
mpc_set(res.c, c, MPC_RNDNN)
return res
# Build a gmpy2 mpc from a real part mpfr and an imaginary part mpfr
cdef inline mpc GMPy_MPC_From_mpfr(mpfr_srcptr re, mpfr_srcptr im):
cdef mpc res = GMPy_MPC_New(mpfr_get_prec(re), mpfr_get_prec(im), NULL)
# We intentionally use MPFR funtions instead of MPC functions here
# in order not to add an unneeded dependency on MPC. It's probably
# faster too this way.
mpfr_set(res.c.re, re, MPFR_RNDN)
mpfr_set(res.c.im, im, MPFR_RNDN)
return res
gmpy2-2.1.0b3/gmpy2.egg-info/ 0000775 0001750 0001750 00000000000 13530663166 015410 5 ustar case case 0000000 0000000 gmpy2-2.1.0b3/gmpy2.egg-info/PKG-INFO 0000664 0001750 0001750 00000004163 13530663166 016511 0 ustar case case 0000000 0000000 Metadata-Version: 1.1
Name: gmpy2
Version: 2.1.0b3
Summary: gmpy2 interface to GMP, MPFR, and MPC for Python 2.7 and 3.4+
Home-page: https://github.com/aleaxit/gmpy
Author: Case Van Horsen
Author-email: casevh@gmail.com
License: LGPL-3.0+
Description: gmpy2 is an optimized, C-coded Python extension module that supports fast
multiple-precision arithmetic. gmpy2 is based on the original gmpy module.
gmpy2 adds support for correctly rounded multiple-precision real arithmetic
(using the MPFR library) and complex arithmetic (using the MPC library).
The gmpy2 2.0.x series is a stable version that is only receiving bug fixes.
The main development branch (2.1.x) was extensively refactored. The most
significant changes are support for thread-safe contexts and context methods.
gmpy2 is available at https://pypi.python.org/pypi/gmpy2/
Documentation is available at https://gmpy2.readthedocs.io/en/latest/
Keywords: gmp mpfr mpc multiple-precision arbitrary-precision precision bignum
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Classifier: Natural Language :: English
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Programming Language :: C
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
gmpy2-2.1.0b3/gmpy2.egg-info/SOURCES.txt 0000664 0001750 0001750 00000011017 13530663166 017274 0 ustar case case 0000000 0000000 COPYING
COPYING.LESSER
INSTALL
MANIFEST.in
README
msys2_build.txt
setup.py
windows_build.txt
docs/Makefile
docs/advmpz.rst
docs/conf.py
docs/conversion.rst
docs/cython.rst
docs/history.rst
docs/index.rst
docs/intro.rst
docs/make.bat
docs/mpc.rst
docs/mpfr.rst
docs/mpq.rst
docs/mpz.rst
docs/overview.rst
gmpy2/__init__.pxd
gmpy2/__init__.py
gmpy2/gmpy2.h
gmpy2/gmpy2.pxd
gmpy2.egg-info/PKG-INFO
gmpy2.egg-info/SOURCES.txt
gmpy2.egg-info/dependency_links.txt
gmpy2.egg-info/not-zip-safe
gmpy2.egg-info/top_level.txt
src/gmpy2.c
src/gmpy2.h
src/gmpy2.pxd
src/gmpy2_abs.c
src/gmpy2_abs.h
src/gmpy2_add.c
src/gmpy2_add.h
src/gmpy2_binary.c
src/gmpy2_binary.h
src/gmpy2_cache.c
src/gmpy2_cache.h
src/gmpy2_cmp.c
src/gmpy2_cmp.h
src/gmpy2_const.c
src/gmpy2_const.h
src/gmpy2_context.c
src/gmpy2_context.h
src/gmpy2_convert.c
src/gmpy2_convert.h
src/gmpy2_convert_gmp.c
src/gmpy2_convert_gmp.h
src/gmpy2_convert_mpc.c
src/gmpy2_convert_mpc.h
src/gmpy2_convert_mpfr.c
src/gmpy2_convert_mpfr.h
src/gmpy2_convert_utils.c
src/gmpy2_convert_utils.h
src/gmpy2_divmod.c
src/gmpy2_divmod.h
src/gmpy2_floordiv.c
src/gmpy2_floordiv.h
src/gmpy2_format.c
src/gmpy2_format.h
src/gmpy2_fused.c
src/gmpy2_fused.h
src/gmpy2_hash.c
src/gmpy2_hash.h
src/gmpy2_macros.h
src/gmpy2_math.c
src/gmpy2_math.h
src/gmpy2_minus.c
src/gmpy2_minus.h
src/gmpy2_misc.c
src/gmpy2_misc.h
src/gmpy2_mod.c
src/gmpy2_mod.h
src/gmpy2_mpc.c
src/gmpy2_mpc.h
src/gmpy2_mpc_misc.c
src/gmpy2_mpc_misc.h
src/gmpy2_mpfr.c
src/gmpy2_mpfr.h
src/gmpy2_mpfr_misc.c
src/gmpy2_mpfr_misc.h
src/gmpy2_mpmath.c
src/gmpy2_mpq.c
src/gmpy2_mpq.h
src/gmpy2_mpq_misc.c
src/gmpy2_mpq_misc.h
src/gmpy2_mpz.c
src/gmpy2_mpz.h
src/gmpy2_mpz_bitops.c
src/gmpy2_mpz_bitops.h
src/gmpy2_mpz_divmod.c
src/gmpy2_mpz_divmod.h
src/gmpy2_mpz_divmod2exp.c
src/gmpy2_mpz_divmod2exp.h
src/gmpy2_mpz_inplace.c
src/gmpy2_mpz_inplace.h
src/gmpy2_mpz_misc.c
src/gmpy2_mpz_misc.h
src/gmpy2_mpz_pack.c
src/gmpy2_mpz_pack.h
src/gmpy2_mul.c
src/gmpy2_mul.h
src/gmpy2_muldiv_2exp.c
src/gmpy2_muldiv_2exp.h
src/gmpy2_plus.c
src/gmpy2_plus.h
src/gmpy2_pow.c
src/gmpy2_pow.h
src/gmpy2_predicate.c
src/gmpy2_predicate.h
src/gmpy2_random.c
src/gmpy2_random.h
src/gmpy2_richcompare.c
src/gmpy2_richcompare.h
src/gmpy2_sign.c
src/gmpy2_sign.h
src/gmpy2_square.c
src/gmpy2_square.h
src/gmpy2_sub.c
src/gmpy2_sub.h
src/gmpy2_truediv.c
src/gmpy2_truediv.h
src/gmpy2_types.h
src/gmpy2_vector.c
src/gmpy2_vector.h
src/gmpy2_xmpz.c
src/gmpy2_xmpz.h
src/gmpy2_xmpz_inplace.c
src/gmpy2_xmpz_inplace.h
src/gmpy2_xmpz_misc.c
src/gmpy2_xmpz_misc.h
src/gmpy_mpz_lucas.c
src/gmpy_mpz_lucas.h
src/gmpy_mpz_prp.c
src/gmpy_mpz_prp.h
src/mpz_pylong.c
test/gmpy_test.py
test/runtests.py
test/supportclasses.py
test/supportclasses.pyc
test/test_abs.txt
test/test_context.txt
test/test_gmpy2_abs.txt
test/test_gmpy2_add.txt
test/test_gmpy2_binary.txt
test/test_gmpy2_cmp.txt
test/test_gmpy2_comp.txt
test/test_gmpy2_const.txt
test/test_gmpy2_constructors.txt
test/test_gmpy2_convert.txt
test/test_gmpy2_divmod.txt
test/test_gmpy2_floordiv.txt
test/test_gmpy2_format.txt
test/test_gmpy2_fused.txt
test/test_gmpy2_lucas.txt
test/test_gmpy2_math.txt
test/test_gmpy2_minus.txt
test/test_gmpy2_mpfr_misc.txt
test/test_gmpy2_mpq_misc.txt
test/test_gmpy2_mpq_misc_py2.txt
test/test_gmpy2_mpq_misc_py3.txt
test/test_gmpy2_mpz_bitops.txt
test/test_gmpy2_mpz_divmod.txt
test/test_gmpy2_mpz_divmod2exp.txt
test/test_gmpy2_mpz_inplace.txt
test/test_gmpy2_mpz_misc.txt
test/test_gmpy2_mpz_misc_py2.txt
test/test_gmpy2_mpz_misc_py3.txt
test/test_gmpy2_mul.txt
test/test_gmpy2_muldiv_2exp.txt
test/test_gmpy2_plus.txt
test/test_gmpy2_pow.txt
test/test_gmpy2_predicate.txt
test/test_gmpy2_prp.txt
test/test_gmpy2_root.txt
test/test_gmpy2_square.txt
test/test_gmpy2_sub.txt
test/test_gmpy2_xmpz_inplace.txt
test/test_gmpy2_xmpz_misc.txt
test/test_misc.txt
test/test_mpc.txt
test/test_mpc_create.txt
test/test_mpc_exp_log.txt
test/test_mpc_to_from_binary.txt
test/test_mpc_trig.txt
test/test_mpfr.txt
test/test_mpfr4_fused.txt
test/test_mpfr4_random.txt
test/test_mpfr_create.txt
test/test_mpfr_dec.txt
test/test_mpfr_exp_log.txt
test/test_mpfr_min_max.txt
test/test_mpfr_special.txt
test/test_mpfr_subnormalize.txt
test/test_mpfr_to_from_binary.txt
test/test_mpfr_trig.txt
test/test_mpq.txt
test/test_mpq_to_from_binary.txt
test/test_mpz.txt
test/test_mpz_args.py
test/test_mpz_args.pyc
test/test_mpz_bit.txt
test/test_mpz_create.txt
test/test_mpz_functions.txt
test/test_mpz_io.txt
test/test_mpz_pack_unpack.txt
test/test_mpz_random.txt
test/test_mpz_template.txt
test/test_mpz_to_from_binary.txt
test/test_pack.py
test/test_pack.pyc
test/test_py32_hash.txt gmpy2-2.1.0b3/gmpy2.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 13530663166 021456 0 ustar case case 0000000 0000000
gmpy2-2.1.0b3/gmpy2.egg-info/not-zip-safe 0000664 0001750 0001750 00000000001 13244310701 017620 0 ustar case case 0000000 0000000
gmpy2-2.1.0b3/gmpy2.egg-info/top_level.txt 0000664 0001750 0001750 00000000006 13530663166 020136 0 ustar case case 0000000 0000000 gmpy2
gmpy2-2.1.0b3/msys2_build.txt 0000664 0001750 0001750 00000027605 13244653673 015673 0 ustar case case 0000000 0000000 Building gmpy2 with MSYS2
=========================
Note: These instructions are a work in progress!
From the MSYS2 home page:
http://sourceforge.net/projects/msys2/
MSYS2 is a Cygwin-derived Posix-like environment for Windows. The name is a
contraction of Minimal SYStem 2, and aims to provide support to facilitate
using the bash shell, Autotools, revision control systems and the like for
building native Windows applications using MinGW-w64 toolchains.
Installing MSYS2
================
MSYS2 installation instructions can be found at:
http://sourceforge.net/p/msys2/wiki/MSYS2%20installation/
Some of the examples assume the 64-bit version of MSYS2 is installed. If you
install the 32-bit version of MSYS2, you will need to change any references
of C:\msys64 to C:\msys32.
After following the installation and upgrade steps documented above, you will
need to install the MinGW compiler toolchain(s). Both toolchains can be
installed at the same time. To install the 64-bit toolchain:
$ pacman -S mingw-w64-x86_64-toolchain
To install the 32-bit toolchain:
$ pacman -S mingw-w64-i686-toolchain
The following additional packages should also be installed:
$ pacman -S patch m4 lzip wget tar make diffutils
The MSYS2 build environment
===========================
The build process is split into two phases. During phase 1 we use the MSYS2
environment to build statically linked versions of GMP, MPFR, and MPC. Once
those libraries are build, we will use the Windows command prompt to build
the actual gmpy2 extension (DLL). We do not use the versions of Python
included with MSYS2 or MinGW to compile gmpy2.
Commands that must be executed from an MSYS2 shell are preceded by "$".
Commands that must be executed from a Windows command prompt are preceded
by ">". You will need to run the commands *after* "$" or ">".
The MSYS2 environment provides three different command line operating
environments.
* msys2_shell.bat is the general-purpose shell but it does not provide
access to the MinGW compiler suite.
* mingw64_shell.bat provides access to the 64-bit MinGW compiler suite.
* mingw32_shell.bat provides access to the 32-bit MinGW compiler suite.
MSYS2 does include versions of GMP, MPFR, and MPC but we will compile our
own version directly from the source. We will specify the options that are
appropriate for building a statically linked Windows DLL.
MSYS2 can support both MinGW32 and MinGW64 toolchains simultaneously. We
use /mingw32/opt and /mingw64/opt as the destinations for the 32-bit and
64-bit versions of GMP, MPFR, and MPC. The sources for GMP, MPFR, and MPC
will be placed in /mingw32/src or /mingw64/opt.
64-bit Build
============
# Start the appropriate shell: MSYS2 WinGW 64-bit
# Create a new directies as the destinations for GMP, MPFR, and MPC.
$ mkdir /mingw64/opt
$ mkdir /mingw64/src
# Download and uncompress GMP, MPFR, and MPC
$ cd /mingw64/src
# Download GMP
$ wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.lz
$ tar xf gmp-6.1.2.tar.lz
# Download MPFR and any patches
$ wget http://www.mpfr.org/mpfr-current/mpfr-3.1.5.tar.bz2
$ tar xf mpfr-3.1.5.tar.bz2
$ cd mpfr-3.1.5/
$ wget http://www.mpfr.org/mpfr-current/allpatches
$ patch -N -Z -p1 < allpatches
$ cd ..
# Download MPC
$ wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz
$ tar xf mpc-1.0.3.tar.gz
# Compile GMP
$ cd gmp-6.1.2/
$ ./configure --prefix=/mingw64/opt --enable-static --disable-shared --enable-fat --with-pic
*Experimental for mingw64 build*
mp_bitcnt_t should really be a 64-bit unsigned integer. The following sed
command makes the change. It should only be used for 64-bit builds.
This will require changes to gmpy2 source also. See gmpy2_convert_utils.h.
$ mv gmp.h gmp.original
$ sed 's/typedef\s*unsigned\s*long\s*int\s*mp_bitcnt_t/typedef unsigned long long int mp_bitcnt_t/g' gmp.original > gmp.h
$ make
$ make check
$ make install
$ cd ..
# Compile MPFR
$ cd mpfr-3.1.5/
$ ./configure --prefix=/mingw64/opt --enable-static --disable-shared --disable-thread-safe --enable-gmp-internals --with-pic --with-gmp=/mingw64/opt
$ make
$ make check
$ make install
$ cd ..
# Compile MPC
$ cd mpc-1.0.3/
$ ./configure --prefix=/mingw64/opt --enable-static --disable-shared --with-pic --with-gmp=/mingw64/opt --with-mpfr=/mingw64/opt
$ make
$ make check
$ make install
$ cd ..
32-bit Build
============
# Start the appropriate shell: MSYS2 WinGW 32-bit
# Create a new directies as the destinations for GMP, MPFR, and MPC/
$ mkdir /mingw32/opt
$ mkdir /mingw32/src
# Download and uncompress GMP, MPFR, and MPC
$ cd /mingw32/src
# Download GMP
$ wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.lz
$ tar xf gmp-6.1.2.tar.lz
# Download MPFR and any patches
$ wget http://www.mpfr.org/mpfr-current/mpfr-3.1.5.tar.bz2
$ tar xf mpfr-3.1.5.tar.bz2
$ cd mpfr-3.1.5/
$ wget http://www.mpfr.org/mpfr-current/allpatches
$ patch -N -Z -p1 < allpatches
$ cd ..
# Download MPC
$ wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz
$ tar xf mpc-1.0.3.tar.gz
# Compile GMP
$ cd gmp-6.1.2/
$ ./configure --prefix=/mingw32/opt --enable-static --disable-shared --enable-fat --with-pic
$ make
$ make check
$ make install
$ cd ..
# Compile MPFR
$ cd mpfr-3.1.5/
$ ./configure --prefix=/mingw32/opt --enable-static --disable-shared --disable-thread-safe --enable-gmp-internals --with-pic --with-gmp=/mingw32/opt
$ make
$ make check
$ make install
$ cd ..
# Compile MPC
$ cd mpc-1.0.3/
$ ./configure --prefix=/mingw32/opt --enable-static --disable-shared --with-pic --with-gmp=/mingw32/opt --with-mpfr=/mingw32/opt
$ make
$ make check
$ make install
$ cd ..
The Windows build environment
=============================
# Configure Windows command prompt - GCC
The MinGW toolchain must be accessible by the normal Windows installation of
Python. The 64-bit MinGW toolchain is located in C:\msys64\mingw64\bin. The
32-bit MinGW toolchain is located in C:\msys64\mingw32\bin. The MinGW
location can be added to the system Path permanently or can be added manually
after starting the Windows command prompt. We will do it manually. After
starting the Windows command prompt, add either the 64-bit or 32-bit
MinGW to the Path with one of the following commands:
> set Path=C:\msys64\mingw64\bin;%Path%
-- or --
> set Path=C:\msys64\mingw32\bin;%Path%
To verfiy the MinGW toolchain is accessible, the command "gcc -v" should
return information about the gcc compiler.
Note: All the remaining instructions assume this step has been completed and
that "gcc -v" returns information for the correct version of gcc.
# Configure Windows command prompt - Python
The Python interpreter does not need to be accessible via the path. You can
specify the full path name to start a particular version. To simplify the
compilation of multiple versions of gmpy2, I have adopted the following
approach:
# 32-bit versions of Python are installed in C:\32
# 64-bit versions of Python are installed in C:\64
# Aliases are defined to create shortcuts for invoking a Python interpreter
I use the following batch file to configure a command prompt for 32-bit builds:
@echo off
doskey py26=C:\32\Python26\python.exe $*
doskey py27=C:\32\Python27\python.exe $*
doskey py34=C:\32\Python34\python.exe $*
doskey py35=C:\32\Python35\python.exe $*
doskey py36=C:\32\Python36\python.exe $*
set Path=C:\msys64\mingw32\bin;%Path%
I use the following batch file to configure a command prompt for 64-bit builds:
@echo off
doskey py26=C:\64\Python26\python.exe $*
doskey py27=C:\64\Python27\python.exe $*
doskey py34=C:\64\Python34\python.exe $*
doskey py35=C:\64\Python35\python.exe $*
doskey py36=C:\64\Python36\python.exe $*
set Path=C:\msys64\mingw64\bin;%Path%
# Modify distutils library
The gmpy2 extension is built using the distutils module. Recent versions of
the gcc compiler no longer support an option that is used by older versions
of distutils. In the file "cygwincompiler.py", remove all occurences of the
"-mno-cygwin" option. The "-mno-cygwin" option was already removed in Python
2.7.8, 3.3.5, and 3.4.1. The option was present in Python 2.6.6 and 3.2.5.
You will need to check your specific version.
In the file "cygwincompiler.py", find the definition for the class
"Mingw32CCompiler". In the "__init__" function comment out the line:
"self.dll_libraries = get_msvcr()".
In the file "cygwincompiler.py", find the definition for the class
"Mingw32CCompiler". Under self.set_executables(...), change -O to -O2 and
add "-fno-strict-aliasing" and "-fwrapv". After changes, it should look like
self.set_executables(compiler='gcc -O2 -Wall -fno-strict-aliasing -fwrapv',
compiler_so='gcc -mdll -O2 -Wall -fno-strict-aliasing -fwrapv',
compiler_cxx='g++ -O2 -Wall -fno-strict-aliasing -fwrapv',
linker_exe='gcc',
linker_so='%s %s %s'
% (self.linker_dll, shared_option,
entry_point))
# Patch C:\Python27\include\pyconfig.h
In that file, search for the text #ifdef _WIN64 and cut out the following
three lines:
#ifdef _WIN64
#define MS_WIN64
#endif
Search for the text #ifdef _MSC_VER earlier in the file. Paste in the
cut-out lines, ABOVE the #ifdef _MSC_VER.
# Create a libpython.a file
MinGW requires a libpythonXX.a file that contains information about the C-API
functions that exist in pythonXX.dll. Follow these steps for your version of
Python.
Note: The DLL locations are from a Windows 10 64-bit system with both 32-bit
and 64-bit versions of a Python version installed. Your location may
vary.
# For a 32-bit versions (with mingw32 on the path)
> cd C:\32\Python27\libs
> gendef c:\Windows\SysWOW64\python27.dll
> dlltool --dllname c:\Windows\SysWOW64\python27.dll --def python27.def --output-lib libpython27.a
# For a 64-bit version (with mingw64 on the path)
> cd C:\64\Python27\libs
> gendef c:\Windows\System32\python27.dll
> dlltool --dllname c:\Windows\System32\python27.dll --def python27.def --output-lib libpython27.a
# To compile gmpy2
py27 setup.py build_ext --msys2 --prefix=c:\msys64\mingwXX\opt
# To install to a local Python installation (after compiling)
py27 setup.py install
-------------------
misc
cd C:\32\Python27\libs
gendef c:\Windows\SysWOW64\python27.dll
dlltool --dllname c:\Windows\SysWOW64\python27.dll --def python27.def --output-lib libpython27.a
cd C:\32\Python32\libs
gendef c:\Windows\SysWOW64\python32.dll
dlltool --dllname c:\Windows\SysWOW64\python32.dll --def python32.def --output-lib libpython32.a
cd C:\32\Python33\libs
gendef c:\Windows\SysWOW64\python33.dll
dlltool --dllname c:\Windows\SysWOW64\python33.dll --def python33.def --output-lib libpython33.a
cd C:\32\Python34\libs
gendef c:\Windows\SysWOW64\python34.dll
dlltool --dllname c:\Windows\SysWOW64\python34.dll --def python34.def --output-lib libpython34.a
cd C:\64\Python27\libs
gendef c:\Windows\System32\python27.dll
dlltool --dllname c:\Windows\System32\python27.dll --def python27.def --output-lib libpython27.a
cd C:\64\Python32\libs
gendef c:\Windows\System32\python32.dll
dlltool --dllname c:\Windows\System32\python32.dll --def python32.def --output-lib libpython32.a
cd C:\64\Python33\libs
gendef c:\Windows\System32\python33.dll
dlltool --dllname c:\Windows\System32\python33.dll --def python33.def --output-lib libpython33.a
cd C:\64\Python34\libs
gendef c:\Windows\System32\python34.dll
dlltool --dllname c:\Windows\System32\python34.dll --def python34.def --output-lib libpython34.a
gmpy2-2.1.0b3/setup.cfg 0000664 0001750 0001750 00000000046 13530663166 014501 0 ustar case case 0000000 0000000 [egg_info]
tag_build =
tag_date = 0
gmpy2-2.1.0b3/setup.py 0000664 0001750 0001750 00000012247 13530662251 014372 0 ustar case case 0000000 0000000 import platform
import os
from setuptools import setup, find_packages, Extension
from setuptools.command.build_ext import build_ext
ON_WINDOWS = platform.system() == 'Windows'
_comp_args = ["DSHARED=1"]
sources = ['src/gmpy2.c']
# Utility function to read the contents of the README file.
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
class Gmpy2Build(build_ext):
description = "Build gmpy2 with custom build options"
user_options = build_ext.user_options + [
('fast', None,
"Depend on MPFR and MPC internal implementations details"
"(even more than the standard build)"),
('gcov', None, "Enable GCC code coverage collection"),
('vector', None, "Include the vector_XXX() functions;"
"they are unstable and under active development"),
('mpir', None, "Enable use of mpir library instead of gmp."
"gmp is the default on Posix systems while mpir the default on"
"Windows and MSVC. Deprecated; will be removed."),
('static', None, "Enable static linking compile time options."),
('static-dir=', None, "Enable static linking and specify location."),
('gdb', None, "Build with debug symbols."),
]
def initialize_options(self):
build_ext.initialize_options(self)
self.fast = False
self.gcov = False
self.vector = False
self.mpir = False
self.static = False
self.static_dir = False
self.gdb = False
def finalize_options(self):
build_ext.finalize_options(self)
if self.fast:
_comp_args.append('DFAST=1')
if self.gcov:
if ON_WINDOWS:
raise ValueError("Cannot enable GCC code coverage on Windows")
_comp_args.append('DGCOV=1')
_comp_args.append('O0')
_comp_args.append('-coverage')
self.libraries.append('gcov')
if self.vector:
_comp_args.append('DVECTOR=1')
if self.static:
_comp_args.remove('DSHARED=1')
_comp_args.append('DSTATIC=1')
if self.gdb:
_comp_args.append('ggdb')
if self.static_dir:
_comp_args.remove('DSHARED=1')
_comp_args.append('DSTATIC=1')
self.include_dirs.append(self.static_dir + '/include')
self.library_dirs.append(self.static_dir + '/lib')
def build_extensions(self):
compiler = self.compiler.compiler_type
if compiler == 'mingw32':
_comp_args.append('DMSYS2=1')
if self.mpir:
_comp_args.append('DMPIR=1')
self.libraries.append('mpir')
if 'gmp' in self.libraries:
self.libraries.remove('gmp')
elif self.mpir or ON_WINDOWS:
# --mpir or on Windows and MSVC
_comp_args.append('DMPIR=1')
self.libraries.append('mpir')
if 'gmp' in self.libraries:
self.libraries.remove('gmp')
if ON_WINDOWS and not self.static:
# MSVC shared build
_comp_args.append('DMSC_USE_DLL')
_prefix = '-' if compiler != 'msvc' else '/'
for i in range(len(_comp_args)):
_comp_args[i] = ''.join([_prefix, _comp_args[i]])
build_ext.build_extensions(self)
extensions = [
Extension('gmpy2.gmpy2',
sources=sources,
include_dirs=['./src'],
libraries=['mpc','mpfr','gmp'],
extra_compile_args=_comp_args,
)
]
cmdclass = {'build_ext': Gmpy2Build}
setup(
name="gmpy2",
version="2.1.0b3",
author="Case Van Horsen",
author_email="casevh@gmail.com",
cmdclass=cmdclass,
license="LGPL-3.0+",
url="https://github.com/aleaxit/gmpy",
description="gmpy2 interface to GMP, MPFR, "
"and MPC for Python 2.7 and 3.4+",
long_description=read('README'),
zip_safe=False,
include_package_data=True,
package_data={'gmpy2': [
'*.pxd',
'gmpy2.h',
]},
packages=find_packages(),
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)',
'Natural Language :: English',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Programming Language :: C',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Scientific/Engineering :: Mathematics',
'Topic :: Software Development :: Libraries :: Python Modules',
],
keywords="gmp mpfr mpc multiple-precision arbitrary-precision precision bignum",
ext_modules=extensions,
)
gmpy2-2.1.0b3/src/ 0000775 0001750 0001750 00000000000 13530663166 013447 5 ustar case case 0000000 0000000 gmpy2-2.1.0b3/src/gmpy2.c 0000664 0001750 0001750 00000165036 13530662465 014665 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Todo list
* ---------
* Add all MPFR and MPC functions as context methods.
* All MPFR and MPC functions need to set exponent range on entry. The
* current approach where only set_context() and context.__enter__ set
* the exponent range fails for context methods.
* Should a read-only (or template) context prevent the setting of
* exception flags?
* Add context option to control the result of integer division:
* integer (mpz), exact (mpq), or true (mpfr).
* Add modular arithmetic functions.
* Implement Chinese Remainder Theorem.
* Update PRP code.
*/
/*
* originally written for GMP-2.0 (by AMK...?)
* Rewritten by Niels Möller, May 1996
*
* Version for GMP-4, Python 2.X, with support for MSVC++6,
* addition of mpf's, &c: Alex Martelli (now aleaxit@gmail.com, Nov 2000).
* cleanups & reorgs leading to 1.0: Alex Martelli (until Aug 2003)
* further cleanups and bugfixes leading to 1.01, Alex Martelli (Nov 2005)
* minor bugfixes+new decimal (&c) support to 1.02, Alex Martelli (Feb 2006)
* various bugfixes for 64-bit platforms, 1.03, aleaxit and casevh (Jun 2008)
* rich comparisons, 1.04, aleaxit and casevh (Jan 2009)
* support for Python 3.x, 1.10, casevh (Oct 2009)
*
* Some hacks by Gustavo Niemeyer .
*
* 0.1, pre-alpha; date: 2000-11-06 first placed on sourceforge
*
* 0.2, still pre-alpha: 2000-11-15: bugfixes re formatting (tx, Peanu!)
* no tags on oct() and hex() of mpz's
* insert 'tagoff' in options (gmpy.mpz() vs mpz() in repr) (for Peanu!)
* speedups for _nonzero & _cmp (tx, Peanu!)
* slight speedup (7/8%?) for excess reallocs 4<->8 bytes (Peanu's help!)
* added copy/fcopy; bin; fib; remove
*
* 0.3, still pre-alpha, but...:
* performance tweaks via mpz-caching & fixed-constants
* added get/set functions for zcache, zco min/max
* added get-only function for versions (of gmp, and of gmpy)
* removed all 'traces' of mutability (to be re-done... much later!)
* cleaned up all of the mpz_cmp_ui(X,0) to mpz_sgn(X)
* cleaned up Py_BuildValue usage (N vs O, explicit-() for tuples)
* added numdigits, lowbits, root, next_prime, invert, popcount,
* hamdist, scan0, scan1
* renamed bin to bincoef
*
* 0.4:
* split gmpy.c/gmpy.h introducing C-API interface (Pearu's suggestion)
* cleanup some casts using Pearu's new macros
* further cache-tweaks at Pearu's suggestion (macros introduced)
* added sign (Pearu's request), getbit, setbit
* added docstrings
* renamed copy functions to start with _ ('internal, private')
* added .comb as a synonym of .bincoef
*
* 0.5:
* added jacobi, legendre, kronecker
* added random-number generation, seed set/save, shuffling
* added mpq (at last!-)
*
* 0.6: (lots of good ideas from Pearu once more!-):
* fixed silly bugs in kronecker and mpq_abs
* gmpy-level workaround for scan0/scan1 bugs (?) in GMP 3.1.1
* added qdiv; anynum->mpq substituted for all such conversions
* (also anynum->mpz and anynum->mpf by analogy, with care!)
* added global.fcoform for optional use of intermediate string in
* float2mpf (used for any float->mpf conversion)
* added set_fcoform function for global.fcoform access
* general cleanup of sources; added alloca for MSVC++;
* many sundry minor bugfixes & uniformization;
* a little useful refactoring (more would be good...)
* added caching of mpq objects
* power for mpq
* Stern-Brocot algorithm for mpf->mpq (also exposed as f2q)
* also used for float->mpq
* with stricter tracking of mpf's requested-precision
* added getrprec method to mpf, getrprec module-function
* exposed ceil, floor and trunc methods/functions for mpf's
* changed a couple exceptions from Value to ZeroDivision
* added 'qual' and 'floa' options to gmpy.rand
*
* 0.7: (good feedback from Keith Briggs, some advice from Tim Peters
* and Fred Lundh -- thanks all!):
* fixed bug of '"%d" where "%ld" was meant' in many places
* and other sundry minor warnings given by gcc
* fixed hash (delegating to Python) so mp[nqz](x) will
* produce the same value as hash(x) for any Python number x
* workaround for GMP 3.1.1 bug, mpz_root wrongly returning
* 'exact' for non-exact root if dest==source, which stopped
* needed value-error for inexact mpq**mpq operations
* determined correct 'actual precision' of floats
* explicitly stored precision with binary-form mpf's
* extended explicit-bits request to all ->mpf operations
* (good in itself, plus, preparing for future MPFR)
* removed the limitation of no binary-form for <0 mpz
* introduced macros to parse args, for conciseness
*
* 0.8: (again, requests & suggestions by great Pearu!)
* raise test coverage 72.5% -> 90.0%
* introduced callbacks (not documented/tested for now;
* Pearu will test/support/document in PySymbolic)
* some errors went undiagnosed, caused crash: now fixed
* workaround for GMP bug(?s?) in mpz_fits_... (?)
* added exposure of mpf_ sqrt and pow_ui
*
* 0.9: (ditto)
* change ValueError to OverflowError for 'too-large' errors
* fix bug in mpq_pow (negative base, exp. with odd denominator)
* (fix now corrected -- _even_ denominator is the error!)
* fixed gcc warnings reported by K. Briggs
*
* 0.9b:
* support GMP 4 (but added no GMP4-only functionality yet)
*
* 0.9c:
* updated tests to 0.9, better coverage
*
* 1.0:
* minor cleanups, ensure support for Python 2.3
* fixed misdiagnosis of some argument counts in macro
* SELF_ONE_ARG_CONVERTED (tx to Paul Rubin!)
*
* 1.01:
* cleanups, ensure support for Python 2.4.1 on MacOSX 10.4/XCode 2.1
* as well as Python 2.2 and 2.3 (on MacOSX and Linux)
* fixed memory leak on divm (thanks to mensanator@aol.com)
* fixed bug on mpq('123') [[str2mpq on string w/o a slash]]
* added floordiv and truediv operators, and tests for them
* NOT tested on GMP 3 (have none left around...), ONLY on GMP 4.*
*
* 1.02:
* fix warning in comparison of mpq's
* added support of mpq('12.34') [[string w/o a slash, but with a dot]]
* fixes for 64-bit build (thanks to a patch by dmcooke)
* added experimental support for decimal.Decimal (and user-coded types)
* via wider use of special conversion methods (if present) and their
* sly insertion on-the-fly into the decimal.Decimal class (!)
* two bugfixes, thanks to Simon Burton
* Brought back into C89 compliance (thanks to Chip Turner), had
* drifted to C99 (declarations in the middle of the code).
* Python 2.5 support (Py_ssize_t, __index__) thanks to Chip Turner
* Pushed coverage to 93.3% (missing only "sanity check" level error
* tests [mostly for out-of-memory conditions], output to stderr
* conditioned by global.debug, & a couple of very obscure cases)
*
* 1.03:
* Fixed the bug that caused crashes on gmpy.mpf(float('inf')) and
* other such conversions, implicit and explicit
* Fixed a bug in get_zconst's prototype affecting 64-bit machines,
* thanks to Gary Bunting
* Fixed a bug in hashing on 64-bit systems. hash(long) now equals
* hash(mpz) for large values. (casevh)
* Changed int() to return a long value instead of OverFlowError.
* Complies with PEP 237. (casevh)
* Added support in setup.py for darwinports/macports build of GMP
* on MacOSX. (aleaxit)
*
* 1.04:
* Avoid GMP/mingw32 bug when converting very small floats to mpz.
* (casevh)
* Significant performance improvement for long->mpz and mpz->long.
* (casevh)
* Added "rich comparisons" to mpz, mpq and mpf types (aleaxit)
* Added additional tests (casevh, aleaxit)
* Fixed bug when converting very large mpz to str (casevh)
* Faster conversion from mpz->binary and binary->mpz (casevh)
* Added support for pickling (casevh)
* Added divexact (casevh)
* Fixed mpf comparisons by rounding mpf results when GMP returns
* a longer result. Added fround() (casevh)
* Added bit_length (Thanks Mario Pernici)
* Added helper functions for mpmath (casevh)
* Faster conversion from mpq->binary and binary->mpq (casevh)
* Recognize MPIR, mpir_version() (casevh)
*
* 1.10:
* Remove dependancy on pymemcompat.h (casevh)
* Remove callback (casevh)
* Added support for -DMPIR to include MPIR instead of GMP (casevh)
* Major code revisions to add support for Python 3.x (casevh)
* Fixed bug in binary() and qbinary() (casevh)
* Fixed bug in rich comparisons (casevh)
* Added % and divmod support to mpq and mpf (casevh)
* Changed memory allocation functions to use PyMem (casevh)
* Removed small number interning (casevh)
* Added tdivmod, cdivmod, and fdivmod (casevh)
* Added more helper functions for mpmath (casevh)
* Faster mpz<>PyLong conversion (casevh)
* Faster hash(mpz) (casevh)
*
* 1.11:
* Recognize True/False (bug in 1.10) (casevh)
* Optimize argument handling (casevh)
* Added caching for mpz (casevh)
*
************************************************************************
*
* 2.0.0 alpha and b1:
* Added caching for mpq (casevh)
* Added rootrem, fib2, lucas, lucas2 (casevh)
* Removed mpf.setprec(), use mpf.round() (casevh)
* Fix test compatibility with Python 3.1.2 and 3.2 (casevh)
* Support changed hash function in Python 3.2 (casevh)
* Added is_even, is_odd (casevh)
* Rename to gmpy2 to allow backwards incompatible changes (casevh)
* Remove old random number functions, to be replaced later (casevh)
* Add caching of the calculated hash value (casevh)
* Add xmpz (mutable mpz) type (casevh)
* Fix mpq formatting issue (casevh)
* Add read/write bit access using slices to xmpz (casevh)
* Add read-only bit access using slices to mpz (casevh)
* Add pack()/unpack() methods (casevh)
* Remove tagoff option (casevh)
* Add support for MPFR (casevh)
* Debug messages only available if compiled with -DDEBUG (casevh)
* Removed fcoform float conversion modifier (casevh)
* Add support for MPC (casevh)
* Renamed 'mpf' to 'mpfr' to reflect use of MPFR (casevh)
* Added context manager (casevh)
* Allow building with just GMP/MPIR if MPFR not available (casevh)
* Allow building with GMP/MPIR and MPFR if MPC not available (casevh)
* Removed most instance methods in favor of gmpy2.method (casevh)
* Added __ceil__, __floor__, and __trunc__ methods (casevh)
* Removed gmpy2.pow to avoid conflicts (casevh)
* Removed gmpy2._copy and added xmpz.copy (casevh)
* Added support for __format__ (casevh)
* Completed support for MPC (casevh)
* Added as_integer_ratio, as_mantissa_exp, as_simple_fraction (casevh)
* Update rich_compare (casevh)
* Require MPFR 3.1.0+ to get divby0 support (casevh)
* Added fsum(), degrees(), radians() (casevh)
* Renamed context() -> local_context(), new_context() -> context() (casevh)
* Added get_context() (casevh)
* Added random number generation support (casevh)
* Changed license to LGPL 3+ (casevh)
* Added lucasu, lucasu_mod, lucasv, and lucasv_mod (casevh)
* (Based on code contributed by David Cleaver.)
* Added probable-prime tests (casevh)
* (Based on code contributed by David Cleaver.)
* Added to_binary()/from_binary (casevh)
* Renamed numdigits() to num_digits() (casevh)
* Added keyword precision to constants (casevh)
* Added addmul() and submul() (casevh)
* Added __round__(), round2(), round_away() for mpfr (casevh)
* round() is no longer a module level function (casevh)
* pow() is no longer a module level function (casevh)
* Renamed module functions min()/max() to min2()/max2() (casevh)
* No longer conflicts with builtin min() and max()
* Removed set_debug() and related functionality (casevh)
* Released as 2.0.0b1
*
* 2.0.0b2
* Allow xmpz slice assignment to increase length of xmpz instance by
* specifying a value for stop (casevh)
* Fixed ref-count bug in several is_xxx_prp tests (casevh)
* Added iter_bits, iter_clear, iter_set methods to xmpz (casevh)
* Added powmod() for easy access to three argument pow() (casevh)
* Removed addmul() and submul() since they are slower than (casevh)
* just using Python code
* Bug fix in gcd_ext when both arguments are not mpz (casevh)
* Added ieee() to create contexts for 32, 64, or 128 bit floats (casevh)
* Bug fix in context() not setting emax/emin correctly if they (casevh)
* had been changed earlier
* Contexts can be directly used in with statement without (casevh)
* requiring set_context()/local_context() sequence
* local_context() now accepts an optional context (casevh)
*
* 2.0.0b3
* mp_version(), mpc_version(), and mpfr_version() shouldn't (casevh)
* return Unicode on Python 2.x
* Fix warnings when shifting 32-bit integer by 32 bits (casevh)
* Faster conversion of Fraction to gmpy2 types (casevh)
* Fix conversion with Decimal, especially on Python 3.3 (casevh)
* Consistently return OverflowError when converting "inf" (casevh)
* Fix mpz.__format__() with # code (casevh)
* Add is_infinite(), deprecate is_inf() (casevh)
* Add is_finite(), deprecate is_number() (casevh)
* Fixed issues with mpc() and various is_XXX() functions (casevh)
* Fixed error handling with mpc(); mpc(1,"nan") is properly (casevh)
* handled
* Added caching for mpc objects; faster when real and (casevh)
* imaginary precisions are equal
* Add optimal path for mpfr/mpc + - * / when both operands (casevh)
* have the same type
* Fix mpfr + float segmentation fault (casevh)
*
* 2.0.0b4
* Add __ceil__, __floor__, __trunc__, __round__ to mpz & mpq (casevh)
* Add __complex__ to mpc (casevh)
* round(mpfr) now correctly returns an mpz (casevh)
* Add mpz.denominator and mpz.numerator (casevh)
* mpz() returns mpz(0); also xmpz, mpq, mpfr, and mpc (casevh)
* Fix bug when comparing mpz to mpq (with mpz on left) (casevh)
* Add __sizeof__ (casevh)
*
* 2.0.0
* Fix segfault in _mpmath_normalize if rnd not specified (casevh)
* Improved setup.py (casevh)
* Fix issues encountered when compiled without MPFR support (casevh)
* Conversion of too large an mpz to float now raises OverflowError (casevh)
* Renamed module functions min2()/max2() to minnum()/maxnum() (casevh)
* Added copy() method to contexts (casevh)
* get_context() no longer supports keyword arguments (casevh)
*
************************************************************************
*
* 2.1.0
* Improvements to setup.py.
* Add thread-safe contexts.
* MPFR and MPC are now required.
* Invalid Operation exception now raised for addition, etc.
* inverse() now raises exception if inverse does not exist.
* Add context methods.
* Major code refactoring required to properly support thread-safe
* contexts.
* __str__ and __repr__ no longer append "L" on Python 2.
* mpq(mpfr) now returns the exact result.
* Fix repr(mpc) for precision >325 bits.
* Intermediate conversions of Integer to mpfr are now done with the
* full precision of the Integer.
* Remove support for interaction with Decimal type.
* No longer attempt to override the memory allocation functions.
* Register gmpy2 types into the numeric tower.
* mpz(x) call int(x) if mpz() does not know how to convert x
* directly.
* Convert `mpz` to a type using __new__ instead of a factory
* function.
*
* 2.1.0a1
* Initial release.
*
* 2.1.0a2
* Revised build process.
* Removal of unused code/macros.
* Cleanup of Cython interface.
*
* 2.1.0a3
* Updates to setup.py.
* Initial support for MPFR4
* - Add nrandom()
* - grandom() now calls nrandom twice; may return different values versus
* MPFR3
* - Add rootn(); same as root() except different sign when taking even root
* of -0.0
*
* 2.1.0a4
* Fix issue 204; missing file for Cython.
* Additional support for MPFR 4
* - Add fmma() and fmms()
*
* 2.1.0a5
* Fix qdiv() not returning mpz() when it should.
* Added root_of_unity()
*
* 2.1.0b1
* Added cmp() and cmp_abs().
* Improved compatibility with _numbers_ protocol.
* Many bug fixes.
*
* 2.1.0b2
* Many bug fixes.
*
* 2.1.0b3
* Version bump only.
*
************************************************************************
*
* Discussion on sizes of C integer types.
*
* GMP, MPIR, MPFR, and MPC use typedef to create integer objects with
* different sizes. It can become confusing to map the different types
* onto the standard C types used by Python's C API. Below are external
* types and how they map to C types. The assumptions are verified when
* the module is initialized.
*
* mp_limb_t: This is usually an 'unsigned long' but is an 'unsigned
* long long' on MPIR/64-bit Windows.
*
* mp_bitcnt_t: This is usually an 'unsigned long' but is an 'unsigned
* long long' on MPIR/64-bit Windows. 'size_t' is the best match.
*
* mp_size_t: This is a 'long'.
*
* mpfr_rnd_t: This is an 'int'.
*
* mpfr_prec_t: This is a 'long'.
*
* mpfr_sign_t: This is an 'int'.
*
* mpfr_exp_t: This is currently the same as mp_exp_t but will change
* to a signed 64-bit integer in the future.
*
* mpc_rnd_t: This is an 'int'.
*
* mpc_prec_t: See mpfr_exp_t.
*
************************************************************************
*/
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include
#include
#include
#include
#include
#include
/*
* we do have a dependence on Python's internals, specifically:
* how Python "long int"s are internally represented.
*/
#include "longintrepr.h"
#define GMPY2_MODULE
#include "gmpy2.h"
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Global data declarations begin here. *
* NOTE: Because of these global declarations, GMPY2 is not thread-safe! *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* The following global strings are used by gmpy_misc.c. */
char gmpy_version[] = "2.1.0b3";
char gmpy_license[] = "\
The GMPY2 source code is licensed under LGPL 3 or later. The supported \
versions of the GMP/MPIR, MPFR, and MPC libraries are also licensed under \
LGPL 3 or later.";
/* The following global structures are used by gmpy_cache.c.
*/
struct gmpy_global {
int cache_size; /* size of cache, for all caches */
int cache_obsize; /* maximum size of the objects that are cached */
mpz_t tempz; /* Temporary variable used for integer conversions */
MPZ_Object **gmpympzcache;
int in_gmpympzcache;
XMPZ_Object **gmpyxmpzcache;
int in_gmpyxmpzcache;
MPQ_Object **gmpympqcache;
int in_gmpympqcache;
MPFR_Object **gmpympfrcache;
int in_gmpympfrcache;
MPC_Object **gmpympccache;
int in_gmpympccache;
};
static struct gmpy_global global;
/* Support for context manager. */
#ifdef WITHOUT_THREADS
/* Use a module-level context. */
static CTXT_Object *module_context = NULL;
#else
/* Key for thread state dictionary */
static PyObject *tls_context_key = NULL;
/* Invariant: NULL or the most recently accessed thread local context */
static CTXT_Object *cached_context = NULL;
#endif
/* Define gmpy2 specific errors for mpfr and mpc data types. No change will
* be made the exceptions raised by mpz, xmpz, and mpq.
*/
static PyObject *GMPyExc_GmpyError = NULL;
static PyObject *GMPyExc_DivZero = NULL;
static PyObject *GMPyExc_Inexact = NULL;
static PyObject *GMPyExc_Invalid = NULL;
static PyObject *GMPyExc_Overflow = NULL;
static PyObject *GMPyExc_Underflow = NULL;
static PyObject *GMPyExc_Erange = NULL;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* End of global data declarations. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* The code for object creation, deletion, and caching is in gmpy_cache.c. */
#include "gmpy2_cache.c"
/* Miscellaneous helper functions and simple methods are in gmpy_misc.c. */
#include "gmpy2_misc.c"
/* Support for conversion to/from binary representation. */
#include "gmpy2_binary.c"
/* Support for conversions to/from numeric types. */
#include "gmpy2_convert.c"
#include "gmpy2_convert_utils.c"
#include "gmpy2_convert_gmp.c"
#include "gmpy2_convert_mpfr.c"
#include "gmpy2_convert_mpc.c"
/* Support for random numbers. */
#include "gmpy2_random.c"
/* Support for Lucas sequences. */
#include "gmpy_mpz_lucas.c"
/* Support for probable-prime tests. */
#include "gmpy_mpz_prp.c"
/* Include helper functions for mpmath. */
#include "gmpy2_mpmath.c"
#include "gmpy2_mpz_divmod.c"
#include "gmpy2_mpz_divmod2exp.c"
#include "gmpy2_mpz_pack.c"
#include "gmpy2_mpz_bitops.c"
#include "gmpy2_mpz_inplace.c"
#include "gmpy2_xmpz_inplace.c"
/* Begin includes of refactored code. */
#include "gmpy2_abs.c"
#include "gmpy2_add.c"
#include "gmpy2_divmod.c"
#include "gmpy2_floordiv.c"
#include "gmpy2_minus.c"
#include "gmpy2_mod.c"
#include "gmpy2_mul.c"
#include "gmpy2_plus.c"
#include "gmpy2_pow.c"
#include "gmpy2_sub.c"
#include "gmpy2_truediv.c"
#include "gmpy2_math.c"
#include "gmpy2_const.c"
#include "gmpy2_square.c"
#include "gmpy2_format.c"
#include "gmpy2_hash.c"
#include "gmpy2_fused.c"
#include "gmpy2_muldiv_2exp.c"
#include "gmpy2_predicate.c"
#include "gmpy2_sign.c"
#include "gmpy2_richcompare.c"
#include "gmpy2_cmp.c"
#include "gmpy2_mpc_misc.c"
#include "gmpy2_mpfr_misc.c"
#include "gmpy2_mpq_misc.c"
#include "gmpy2_mpz_misc.c"
#include "gmpy2_xmpz_misc.c"
#ifdef VECTOR
#include "gmpy2_vector.c"
#endif
/* Include gmpy_context last to avoid adding doc names to .h files. */
#include "gmpy2_mpz.c"
#include "gmpy2_xmpz.c"
#include "gmpy2_mpq.c"
#include "gmpy2_mpfr.c"
#include "gmpy2_mpc.c"
#include "gmpy2_context.c"
static PyMethodDef Pygmpy_methods [] =
{
{ "_printf", GMPy_printf, METH_VARARGS, GMPy_doc_function_printf },
{ "add", GMPy_Context_Add, METH_VARARGS, GMPy_doc_function_add },
{ "bit_clear", GMPy_MPZ_bit_clear_function, METH_VARARGS, doc_bit_clear_function },
{ "bit_flip", GMPy_MPZ_bit_flip_function, METH_VARARGS, doc_bit_flip_function },
{ "bit_length", GMPy_MPZ_bit_length_function, METH_O, doc_bit_length_function },
{ "bit_mask", GMPy_MPZ_bit_mask, METH_O, doc_bit_mask },
{ "bit_scan0", GMPy_MPZ_bit_scan0_function, METH_VARARGS, doc_bit_scan0_function },
{ "bit_scan1", GMPy_MPZ_bit_scan1_function, METH_VARARGS, doc_bit_scan1_function },
{ "bit_set", GMPy_MPZ_bit_set_function, METH_VARARGS, doc_bit_set_function },
{ "bit_test", GMPy_MPZ_bit_test_function, METH_VARARGS, doc_bit_test_function },
{ "bincoef", GMPy_MPZ_Function_Bincoef, METH_VARARGS, GMPy_doc_mpz_function_bincoef },
{ "cmp", GMPy_MPANY_cmp, METH_VARARGS, GMPy_doc_mpany_cmp },
{ "cmp_abs", GMPy_MPANY_cmp_abs, METH_VARARGS, GMPy_doc_mpany_cmp_abs },
{ "comb", GMPy_MPZ_Function_Bincoef, METH_VARARGS, GMPy_doc_mpz_function_comb },
{ "c_div", GMPy_MPZ_c_div, METH_VARARGS, doc_c_div },
{ "c_div_2exp", GMPy_MPZ_c_div_2exp, METH_VARARGS, doc_c_div_2exp },
{ "c_divmod", GMPy_MPZ_c_divmod, METH_VARARGS, doc_c_divmod },
{ "c_divmod_2exp", GMPy_MPZ_c_divmod_2exp, METH_VARARGS, doc_c_divmod_2exp },
{ "c_mod", GMPy_MPZ_c_mod, METH_VARARGS, doc_c_mod },
{ "c_mod_2exp", GMPy_MPZ_c_mod_2exp, METH_VARARGS, doc_c_mod_2exp },
{ "denom", GMPy_MPQ_Function_Denom, METH_O, GMPy_doc_mpq_function_denom },
{ "digits", GMPy_Context_Digits, METH_VARARGS, GMPy_doc_context_digits },
{ "div", GMPy_Context_TrueDiv, METH_VARARGS, GMPy_doc_truediv },
{ "divexact", GMPy_MPZ_Function_Divexact, METH_VARARGS, GMPy_doc_mpz_function_divexact },
{ "divm", GMPy_MPZ_Function_Divm, METH_VARARGS, GMPy_doc_mpz_function_divm },
{ "double_fac", GMPy_MPZ_Function_DoubleFac, METH_O, GMPy_doc_mpz_function_double_fac },
{ "fac", GMPy_MPZ_Function_Fac, METH_O, GMPy_doc_mpz_function_fac },
{ "fib", GMPy_MPZ_Function_Fib, METH_O, GMPy_doc_mpz_function_fib },
{ "fib2", GMPy_MPZ_Function_Fib2, METH_O, GMPy_doc_mpz_function_fib2 },
{ "floor_div", GMPy_Context_FloorDiv, METH_VARARGS, GMPy_doc_floordiv },
{ "from_binary", GMPy_MPANY_From_Binary, METH_O, doc_from_binary },
{ "f_div", GMPy_MPZ_f_div, METH_VARARGS, doc_f_div },
{ "f_div_2exp", GMPy_MPZ_f_div_2exp, METH_VARARGS, doc_f_div_2exp },
{ "f_divmod", GMPy_MPZ_f_divmod, METH_VARARGS, doc_f_divmod },
{ "f_divmod_2exp", GMPy_MPZ_f_divmod_2exp, METH_VARARGS, doc_f_divmod_2exp },
{ "f_mod", GMPy_MPZ_f_mod, METH_VARARGS, doc_f_mod },
{ "f_mod_2exp", GMPy_MPZ_f_mod_2exp, METH_VARARGS, doc_f_mod_2exp },
{ "gcd", GMPy_MPZ_Function_GCD, METH_VARARGS, GMPy_doc_mpz_function_gcd },
{ "gcdext", GMPy_MPZ_Function_GCDext, METH_VARARGS, GMPy_doc_mpz_function_gcdext },
{ "get_cache", GMPy_get_cache, METH_NOARGS, GMPy_doc_get_cache },
{ "hamdist", GMPy_MPZ_hamdist, METH_VARARGS, doc_hamdist },
{ "invert", GMPy_MPZ_Function_Invert, METH_VARARGS, GMPy_doc_mpz_function_invert },
{ "iroot", GMPy_MPZ_Function_Iroot, METH_VARARGS, GMPy_doc_mpz_function_iroot },
{ "iroot_rem", GMPy_MPZ_Function_IrootRem, METH_VARARGS, GMPy_doc_mpz_function_iroot_rem },
{ "isqrt", GMPy_MPZ_Function_Isqrt, METH_O, GMPy_doc_mpz_function_isqrt },
{ "isqrt_rem", GMPy_MPZ_Function_IsqrtRem, METH_O, GMPy_doc_mpz_function_isqrt_rem },
{ "is_bpsw_prp", GMPY_mpz_is_bpsw_prp, METH_VARARGS, doc_mpz_is_bpsw_prp },
{ "is_congruent", GMPy_MPZ_Function_IsCongruent, METH_VARARGS, GMPy_doc_mpz_function_is_congruent },
{ "is_divisible", GMPy_MPZ_Function_IsDivisible, METH_VARARGS, GMPy_doc_mpz_function_is_divisible },
{ "is_even", GMPy_MPZ_Function_IsEven, METH_O, GMPy_doc_mpz_function_is_even },
{ "is_euler_prp", GMPY_mpz_is_euler_prp, METH_VARARGS, doc_mpz_is_euler_prp },
{ "is_extra_strong_lucas_prp", GMPY_mpz_is_extrastronglucas_prp, METH_VARARGS, doc_mpz_is_extrastronglucas_prp },
{ "is_fermat_prp", GMPY_mpz_is_fermat_prp, METH_VARARGS, doc_mpz_is_fermat_prp },
{ "is_fibonacci_prp", GMPY_mpz_is_fibonacci_prp, METH_VARARGS, doc_mpz_is_fibonacci_prp },
{ "is_lucas_prp", GMPY_mpz_is_lucas_prp, METH_VARARGS, doc_mpz_is_lucas_prp },
{ "is_odd", GMPy_MPZ_Function_IsOdd, METH_O, GMPy_doc_mpz_function_is_odd },
{ "is_power", GMPy_MPZ_Function_IsPower, METH_O, GMPy_doc_mpz_function_is_power },
{ "is_prime", GMPy_MPZ_Function_IsPrime, METH_VARARGS, GMPy_doc_mpz_function_is_prime },
{ "is_selfridge_prp", GMPY_mpz_is_selfridge_prp, METH_VARARGS, doc_mpz_is_selfridge_prp },
{ "is_square", GMPy_MPZ_Function_IsSquare, METH_O, GMPy_doc_mpz_function_is_square },
{ "is_strong_prp", GMPY_mpz_is_strong_prp, METH_VARARGS, doc_mpz_is_strong_prp },
{ "is_strong_bpsw_prp", GMPY_mpz_is_strongbpsw_prp, METH_VARARGS, doc_mpz_is_strongbpsw_prp },
{ "is_strong_lucas_prp", GMPY_mpz_is_stronglucas_prp, METH_VARARGS, doc_mpz_is_stronglucas_prp },
{ "is_strong_selfridge_prp", GMPY_mpz_is_strongselfridge_prp, METH_VARARGS, doc_mpz_is_strongselfridge_prp },
{ "jacobi", GMPy_MPZ_Function_Jacobi, METH_VARARGS, GMPy_doc_mpz_function_jacobi },
{ "kronecker", GMPy_MPZ_Function_Kronecker, METH_VARARGS, GMPy_doc_mpz_function_kronecker },
{ "lcm", GMPy_MPZ_Function_LCM, METH_VARARGS, GMPy_doc_mpz_function_lcm },
{ "legendre", GMPy_MPZ_Function_Legendre, METH_VARARGS, GMPy_doc_mpz_function_legendre },
{ "license", GMPy_get_license, METH_NOARGS, GMPy_doc_license },
{ "lucas", GMPy_MPZ_Function_Lucas, METH_O, GMPy_doc_mpz_function_lucas },
{ "lucasu", GMPY_mpz_lucasu, METH_VARARGS, doc_mpz_lucasu },
{ "lucasu_mod", GMPY_mpz_lucasu_mod, METH_VARARGS, doc_mpz_lucasu_mod },
{ "lucasv", GMPY_mpz_lucasv, METH_VARARGS, doc_mpz_lucasv },
{ "lucasv_mod", GMPY_mpz_lucasv_mod, METH_VARARGS, doc_mpz_lucasv_mod },
{ "lucas2", GMPy_MPZ_Function_Lucas2, METH_O, GMPy_doc_mpz_function_lucas2 },
{ "mod", GMPy_Context_Mod, METH_VARARGS, GMPy_doc_mod },
{ "mp_version", GMPy_get_mp_version, METH_NOARGS, GMPy_doc_mp_version },
{ "mp_limbsize", GMPy_get_mp_limbsize, METH_NOARGS, GMPy_doc_mp_limbsize },
{ "mpc_version", GMPy_get_mpc_version, METH_NOARGS, GMPy_doc_mpc_version },
{ "mpfr_version", GMPy_get_mpfr_version, METH_NOARGS, GMPy_doc_mpfr_version },
{ "mpq_from_old_binary", GMPy_MPQ_From_Old_Binary, METH_O, doc_mpq_from_old_binary },
{ "mpz_from_old_binary", GMPy_MPZ_From_Old_Binary, METH_O, doc_mpz_from_old_binary },
{ "mpz_random", GMPy_MPZ_random_Function, METH_VARARGS, GMPy_doc_mpz_random_function },
{ "mpz_rrandomb", GMPy_MPZ_rrandomb_Function, METH_VARARGS, GMPy_doc_mpz_rrandomb_function },
{ "mpz_urandomb", GMPy_MPZ_urandomb_Function, METH_VARARGS, GMPy_doc_mpz_urandomb_function },
{ "mul", GMPy_Context_Mul, METH_VARARGS, GMPy_doc_function_mul },
{ "multi_fac", GMPy_MPZ_Function_MultiFac, METH_VARARGS, GMPy_doc_mpz_function_multi_fac },
{ "next_prime", GMPy_MPZ_Function_NextPrime, METH_O, GMPy_doc_mpz_function_next_prime },
{ "numer", GMPy_MPQ_Function_Numer, METH_O, GMPy_doc_mpq_function_numer },
{ "num_digits", GMPy_MPZ_Function_NumDigits, METH_VARARGS, GMPy_doc_mpz_function_num_digits },
{ "pack", GMPy_MPZ_pack, METH_VARARGS, doc_pack },
{ "popcount", GMPy_MPZ_popcount, METH_O, doc_popcount },
{ "powmod", GMPy_Integer_PowMod, METH_VARARGS, GMPy_doc_integer_powmod },
{ "primorial", GMPy_MPZ_Function_Primorial, METH_O, GMPy_doc_mpz_function_primorial },
{ "qdiv", GMPy_MPQ_Function_Qdiv, METH_VARARGS, GMPy_doc_function_qdiv },
{ "remove", GMPy_MPZ_Function_Remove, METH_VARARGS, GMPy_doc_mpz_function_remove },
{ "random_state", GMPy_RandomState_Factory, METH_VARARGS, GMPy_doc_random_state_factory },
{ "set_cache", GMPy_set_cache, METH_VARARGS, GMPy_doc_set_cache },
{ "sign", GMPy_Context_Sign, METH_O, GMPy_doc_function_sign },
{ "square", GMPy_Context_Square, METH_O, GMPy_doc_function_square },
{ "sub", GMPy_Context_Sub, METH_VARARGS, GMPy_doc_sub },
{ "to_binary", GMPy_MPANY_To_Binary, METH_O, doc_to_binary },
{ "t_div", GMPy_MPZ_t_div, METH_VARARGS, doc_t_div },
{ "t_div_2exp", GMPy_MPZ_t_div_2exp, METH_VARARGS, doc_t_div_2exp },
{ "t_divmod", GMPy_MPZ_t_divmod, METH_VARARGS, doc_t_divmod },
{ "t_divmod_2exp", GMPy_MPZ_t_divmod_2exp, METH_VARARGS, doc_t_divmod_2exp },
{ "t_mod", GMPy_MPZ_t_mod, METH_VARARGS, doc_t_mod },
{ "t_mod_2exp", GMPy_MPZ_t_mod_2exp, METH_VARARGS, doc_t_mod_2exp },
{ "unpack", GMPy_MPZ_unpack, METH_VARARGS, doc_unpack },
{ "version", GMPy_get_version, METH_NOARGS, GMPy_doc_version },
{ "xbit_mask", GMPy_XMPZ_Function_XbitMask, METH_O, GMPy_doc_xmpz_function_xbit_mask },
{ "_mpmath_normalize", Pympz_mpmath_normalize, METH_VARARGS, doc_mpmath_normalizeg },
{ "_mpmath_create", Pympz_mpmath_create, METH_VARARGS, doc_mpmath_createg },
{ "acos", GMPy_Context_Acos, METH_O, GMPy_doc_function_acos },
{ "acosh", GMPy_Context_Acosh, METH_O, GMPy_doc_function_acosh },
{ "ai", GMPy_Context_Ai, METH_O, GMPy_doc_function_ai },
{ "agm", GMPy_Context_AGM, METH_VARARGS, GMPy_doc_function_agm },
{ "asin", GMPy_Context_Asin, METH_O, GMPy_doc_function_asin },
{ "asinh", GMPy_Context_Asinh, METH_O, GMPy_doc_function_asinh },
{ "atan", GMPy_Context_Atan, METH_O, GMPy_doc_function_atan },
{ "atanh", GMPy_Context_Atanh, METH_O, GMPy_doc_function_atanh },
{ "atan2", GMPy_Context_Atan2, METH_VARARGS, GMPy_doc_function_atan2 },
{ "can_round", GMPy_MPFR_Can_Round, METH_VARARGS, GMPy_doc_mpfr_can_round },
{ "cbrt", GMPy_Context_Cbrt, METH_O, GMPy_doc_function_cbrt },
{ "ceil", GMPy_Context_Ceil, METH_O, GMPy_doc_function_ceil },
{ "check_range", GMPy_Context_CheckRange, METH_O, GMPy_doc_function_check_range },
{ "const_catalan", (PyCFunction)GMPy_Function_Const_Catalan, METH_VARARGS | METH_KEYWORDS, GMPy_doc_function_const_catalan },
{ "const_euler", (PyCFunction)GMPy_Function_Const_Euler, METH_VARARGS | METH_KEYWORDS, GMPy_doc_function_const_euler },
{ "const_log2", (PyCFunction)GMPy_Function_Const_Log2, METH_VARARGS | METH_KEYWORDS, GMPy_doc_function_const_log2 },
{ "const_pi", (PyCFunction)GMPy_Function_Const_Pi, METH_VARARGS | METH_KEYWORDS, GMPy_doc_function_const_pi },
{ "context", (PyCFunction)GMPy_CTXT_Context, METH_VARARGS | METH_KEYWORDS, GMPy_doc_context },
{ "copy_sign", GMPy_MPFR_copy_sign, METH_VARARGS, GMPy_doc_mpfr_copy_sign },
{ "cos", GMPy_Context_Cos, METH_O, GMPy_doc_function_cos },
{ "cosh", GMPy_Context_Cosh, METH_O, GMPy_doc_function_cosh },
{ "cot", GMPy_Context_Cot, METH_O, GMPy_doc_function_cot },
{ "coth", GMPy_Context_Coth, METH_O, GMPy_doc_function_coth },
{ "csc", GMPy_Context_Csc, METH_O, GMPy_doc_function_csc },
{ "csch", GMPy_Context_Csch, METH_O, GMPy_doc_function_csch },
{ "degrees", GMPy_Context_Degrees, METH_O, GMPy_doc_function_degrees },
{ "digamma", GMPy_Context_Digamma, METH_O, GMPy_doc_function_digamma },
{ "div_2exp", GMPy_Context_Div_2exp, METH_VARARGS, GMPy_doc_function_div_2exp },
{ "eint", GMPy_Context_Eint, METH_O, GMPy_doc_function_eint },
{ "erf", GMPy_Context_Erf, METH_O, GMPy_doc_function_erf },
{ "erfc", GMPy_Context_Erfc, METH_O, GMPy_doc_function_erfc },
{ "exp", GMPy_Context_Exp, METH_O, GMPy_doc_function_exp },
{ "expm1", GMPy_Context_Expm1, METH_O, GMPy_doc_function_expm1 },
{ "exp10", GMPy_Context_Exp10, METH_O, GMPy_doc_function_exp10 },
{ "exp2", GMPy_Context_Exp2, METH_O, GMPy_doc_function_exp2 },
{ "f2q", GMPy_Context_F2Q, METH_VARARGS, GMPy_doc_function_f2q },
{ "factorial", GMPy_Context_Factorial, METH_O, GMPy_doc_function_factorial },
{ "floor", GMPy_Context_Floor, METH_O, GMPy_doc_function_floor },
{ "fma", GMPy_Context_FMA, METH_VARARGS, GMPy_doc_function_fma },
{ "fms", GMPy_Context_FMS, METH_VARARGS, GMPy_doc_function_fms },
#if MPFR_VERSION_MAJOR > 3
{ "fmma", GMPy_Context_FMMA, METH_VARARGS, GMPy_doc_function_fmma },
{ "fmms", GMPy_Context_FMMS, METH_VARARGS, GMPy_doc_function_fmms },
#endif
{ "fmod", GMPy_Context_Fmod, METH_VARARGS, GMPy_doc_function_fmod },
{ "frac", GMPy_Context_Frac, METH_O, GMPy_doc_function_frac },
{ "free_cache", GMPy_MPFR_Free_Cache, METH_NOARGS, GMPy_doc_mpfr_free_cache },
{ "frexp", GMPy_Context_Frexp, METH_O, GMPy_doc_function_frexp },
{ "fsum", GMPy_Context_Fsum, METH_O, GMPy_doc_function_fsum },
{ "gamma", GMPy_Context_Gamma, METH_O, GMPy_doc_function_gamma },
{ "get_context", GMPy_CTXT_Get, METH_NOARGS, GMPy_doc_get_context },
{ "get_emax_max", GMPy_MPFR_get_emax_max, METH_NOARGS, GMPy_doc_mpfr_get_emax_max },
{ "get_emin_min", GMPy_MPFR_get_emin_min, METH_NOARGS, GMPy_doc_mpfr_get_emin_min },
{ "get_exp", GMPy_MPFR_get_exp, METH_O, GMPy_doc_mpfr_get_exp },
{ "get_max_precision", GMPy_MPFR_get_max_precision, METH_NOARGS, GMPy_doc_mpfr_get_max_precision },
{ "hypot", GMPy_Context_Hypot, METH_VARARGS, GMPy_doc_function_hypot },
{ "ieee", (PyCFunction)GMPy_CTXT_ieee, METH_VARARGS | METH_KEYWORDS, GMPy_doc_context_ieee },
{ "inf", GMPy_MPFR_set_inf, METH_VARARGS, GMPy_doc_mpfr_set_inf },
{ "is_finite", GMPy_Context_Is_Finite, METH_O, GMPy_doc_function_is_finite },
{ "is_infinite", GMPy_Context_Is_Infinite, METH_O, GMPy_doc_function_is_infinite },
{ "is_integer", GMPy_Context_Is_Integer, METH_O, GMPy_doc_function_is_integer },
{ "is_lessgreater", GMPy_Context_Is_LessGreater, METH_VARARGS, GMPy_doc_function_is_lessgreater },
{ "is_nan", GMPy_Context_Is_NAN, METH_O, GMPy_doc_function_is_nan },
{ "is_regular", GMPy_Context_Is_Regular, METH_O, GMPy_doc_function_is_regular },
{ "is_signed", GMPy_Context_Is_Signed, METH_O, GMPy_doc_function_is_signed },
{ "is_unordered", GMPy_Context_Is_Unordered, METH_VARARGS, GMPy_doc_function_is_unordered },
{ "is_zero", GMPy_Context_Is_Zero, METH_O, GMPy_doc_function_is_zero },
{ "jn", GMPy_Context_Jn, METH_VARARGS, GMPy_doc_function_jn },
{ "j0", GMPy_Context_J0, METH_O, GMPy_doc_function_j0 },
{ "j1", GMPy_Context_J1, METH_O, GMPy_doc_function_j1 },
{ "lgamma", GMPy_Context_Lgamma, METH_O, GMPy_doc_function_lgamma },
{ "li2", GMPy_Context_Li2, METH_O, GMPy_doc_function_li2 },
{ "lngamma", GMPy_Context_Lngamma, METH_O, GMPy_doc_function_lngamma },
{ "local_context", (PyCFunction)GMPy_CTXT_Local, METH_VARARGS | METH_KEYWORDS, GMPy_doc_local_context },
{ "log", GMPy_Context_Log, METH_O, GMPy_doc_function_log },
{ "log1p", GMPy_Context_Log1p, METH_O, GMPy_doc_function_log1p },
{ "log10", GMPy_Context_Log10, METH_O, GMPy_doc_function_log10 },
{ "log2", GMPy_Context_Log2, METH_O, GMPy_doc_function_log2 },
{ "maxnum", GMPy_Context_Maxnum, METH_VARARGS, GMPy_doc_function_maxnum },
{ "minnum", GMPy_Context_Minnum, METH_VARARGS, GMPy_doc_function_minnum },
{ "modf", GMPy_Context_Modf, METH_O, GMPy_doc_function_modf },
{ "mpfr_from_old_binary", GMPy_MPFR_From_Old_Binary, METH_O, doc_mpfr_from_old_binary },
{ "mpfr_random", GMPy_MPFR_random_Function, METH_VARARGS, GMPy_doc_mpfr_random_function },
{ "mpfr_grandom", GMPy_MPFR_grandom_Function, METH_VARARGS, GMPy_doc_mpfr_grandom_function },
#if MPFR_VERSION_MAJOR > 3
{ "mpfr_nrandom", GMPy_MPFR_nrandom_Function, METH_VARARGS, GMPy_doc_mpfr_nrandom_function },
#endif
{ "mul_2exp", GMPy_Context_Mul_2exp, METH_VARARGS, GMPy_doc_function_mul_2exp },
{ "nan", GMPy_MPFR_set_nan, METH_NOARGS, GMPy_doc_mpfr_set_nan },
{ "next_above", GMPy_Context_NextAbove, METH_O, GMPy_doc_function_next_above },
{ "next_below", GMPy_Context_NextBelow, METH_O, GMPy_doc_function_next_below },
{ "next_toward", GMPy_Context_NextToward, METH_VARARGS, GMPy_doc_function_next_toward },
{ "radians", GMPy_Context_Radians, METH_O, GMPy_doc_function_radians },
{ "rec_sqrt", GMPy_Context_RecSqrt, METH_O, GMPy_doc_function_rec_sqrt },
{ "reldiff", GMPy_Context_RelDiff, METH_VARARGS, GMPy_doc_function_reldiff },
{ "remainder", GMPy_Context_Remainder, METH_VARARGS, GMPy_doc_function_remainder },
{ "remquo", GMPy_Context_RemQuo, METH_VARARGS, GMPy_doc_function_remquo },
{ "rint", GMPy_Context_Rint, METH_O, GMPy_doc_function_rint },
{ "rint_ceil", GMPy_Context_RintCeil, METH_O, GMPy_doc_function_rint_ceil },
{ "rint_floor", GMPy_Context_RintFloor, METH_O, GMPy_doc_function_rint_floor },
{ "rint_round", GMPy_Context_RintRound, METH_O, GMPy_doc_function_rint_round },
{ "rint_trunc", GMPy_Context_RintTrunc, METH_O, GMPy_doc_function_rint_trunc },
{ "root", GMPy_Context_Root, METH_VARARGS, GMPy_doc_function_root },
{ "rootn", GMPy_Context_Rootn, METH_VARARGS, GMPy_doc_function_rootn },
{ "round_away", GMPy_Context_RoundAway, METH_O, GMPy_doc_function_round_away },
{ "round2", GMPy_Context_Round2, METH_VARARGS, GMPy_doc_function_round2 },
{ "sec", GMPy_Context_Sec, METH_O, GMPy_doc_function_sec },
{ "sech", GMPy_Context_Sech, METH_O, GMPy_doc_function_sech },
{ "set_context", GMPy_CTXT_Set, METH_O, GMPy_doc_set_context },
{ "set_exp", GMPy_MPFR_set_exp, METH_VARARGS, GMPy_doc_mpfr_set_exp },
{ "set_sign", GMPy_MPFR_set_sign, METH_VARARGS, GMPy_doc_mpfr_set_sign },
{ "sin", GMPy_Context_Sin, METH_O, GMPy_doc_function_sin },
{ "sin_cos", GMPy_Context_Sin_Cos, METH_O, GMPy_doc_function_sin_cos },
{ "sinh", GMPy_Context_Sinh, METH_O, GMPy_doc_function_sinh },
{ "sinh_cosh", GMPy_Context_Sinh_Cosh, METH_O, GMPy_doc_function_sinh_cosh },
{ "sqrt", GMPy_Context_Sqrt, METH_O, GMPy_doc_function_sqrt },
{ "tan", GMPy_Context_Tan, METH_O, GMPy_doc_function_tan },
{ "tanh", GMPy_Context_Tanh, METH_O, GMPy_doc_function_tanh },
{ "trunc", GMPy_Context_Trunc, METH_O, GMPy_doc_function_trunc},
#ifdef VECTOR
{ "vector", GMPy_Context_Vector, METH_O, GMPy_doc_function_vector},
{ "vector2", GMPy_Context_Vector2, METH_VARARGS, GMPy_doc_function_vector2},
#endif
{ "yn", GMPy_Context_Yn, METH_VARARGS, GMPy_doc_function_yn },
{ "y0", GMPy_Context_Y0, METH_O, GMPy_doc_function_y0 },
{ "y1", GMPy_Context_Y1, METH_O, GMPy_doc_function_y1 },
{ "zero", GMPy_MPFR_set_zero, METH_VARARGS, GMPy_doc_mpfr_set_zero },
{ "zeta", GMPy_Context_Zeta, METH_O, GMPy_doc_function_zeta },
{ "mpc_random", GMPy_MPC_random_Function, METH_VARARGS, GMPy_doc_mpc_random_function },
{ "norm", GMPy_Context_Norm, METH_O, GMPy_doc_function_norm },
{ "polar", GMPy_Context_Polar, METH_O, GMPy_doc_function_polar },
{ "phase", GMPy_Context_Phase, METH_O, GMPy_doc_function_phase },
{ "proj", GMPy_Context_Proj, METH_O, GMPy_doc_function_proj },
#ifdef MPC_110
{ "root_of_unity", GMPy_Context_Root_Of_Unity, METH_VARARGS, GMPy_doc_function_root_of_unity },
#endif
{ "rect", GMPy_Context_Rect, METH_VARARGS, GMPy_doc_function_rect },
{ NULL, NULL, 1}
};
static char _gmpy_docs[] =
"gmpy2 2.1.0b2 - General Multiple-precision arithmetic for Python\n"
"\n"
"gmpy2 supports several multiple-precision libraries. Integer and\n"
"rational arithmetic is provided by the GMP library. Real floating-\n"
"point arithmetic is provided by the MPFR library. Complex floating-\n"
"point arithmetic is provided by the MPC library.\n"
"\n"
"The integer type 'mpz' has comparable functionality to Python's\n"
"builtin integers, but is faster for operations on large numbers.\n"
"A wide variety of additional functions are provided:\n"
" - bit manipulations\n"
" - GCD, Extended GCD, LCM\n"
" - Fibonacci and Lucas sequences\n"
" - primality testing\n"
" - powers and integer Nth roots\n"
"\n"
"The rational type 'mpq' is equivalent to Python's fractions\n"
"module, but is faster.\n"
"\n"
"The real type 'mpfr' and complex type 'mpc' provide multiple-\n"
"precision real and complex numbers with user-definable precision,\n"
"rounding, and exponent range. All the advanced functions from the\n"
"MPFR and MPC libraries are available.\n\
";
/* Notes on Python 3.x support: Full support for PEP-3121 has not been
* implemented. No per-module state has been defined.
*/
#ifdef PY3
#define INITERROR return NULL
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"gmpy2",
_gmpy_docs,
-1, /*sizeof(struct module_state) */
Pygmpy_methods,
NULL,
NULL, /* gmpy_traverse */
NULL, /* gmpy_clear */
NULL
};
#else
#define INITERROR return
#endif
#ifdef PY3
PyMODINIT_FUNC PyInit_gmpy2(void)
#else
PyMODINIT_FUNC initgmpy2(void)
#endif
{
PyObject *result = NULL;
PyObject *namespace = NULL;
PyObject *gmpy_module = NULL;
PyObject *copy_reg_module = NULL;
PyObject *temp = NULL;
PyObject *numbers_module = NULL;
#ifndef STATIC
static void *GMPy_C_API[GMPy_API_pointers];
PyObject *c_api_object;
#endif
/* Validate the sizes of the various typedef'ed integer types. */
#if defined _WIN64 && (MPIR || MSYS2)
if (sizeof(mp_bitcnt_t) != sizeof(PY_LONG_LONG)) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("Size of PY_LONG_LONG and mp_bitcnt_t not compatible (_WIN64 && MPIR)");
INITERROR;
/* LCOV_EXCL_STOP */
}
#else
if (sizeof(mp_bitcnt_t) != sizeof(long)) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("Size of long and mp_bitcnt_t not compatible");
INITERROR;
/* LCOV_EXCL_STOP */
}
#endif
if (sizeof(mp_bitcnt_t) > sizeof(size_t)) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("Size of size_t and mp_bitcnt_t not compatible");
INITERROR;
/* LCOV_EXCL_STOP */
}
if (sizeof(mpfr_prec_t) != sizeof(long)) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("Size of mpfr_prec_t and long not compatible");
INITERROR;
/* LCOV_EXCL_STOP */
}
if (sizeof(mpfr_exp_t) != sizeof(long)) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("Size of mpfr_exp_t and long not compatible");
INITERROR;
/* LCOV_EXCL_STOP */
}
/* Configure MPFR to use the maximum possible exponent range. */
mpfr_set_emax(mpfr_get_emax_max());
mpfr_set_emin(mpfr_get_emin_min());
/* Initialize the types. */
if (PyType_Ready(&MPZ_Type) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&MPQ_Type) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&XMPZ_Type) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&GMPy_Iter_Type) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&MPFR_Type) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&CTXT_Type) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&CTXT_Manager_Type) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&MPC_Type) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&RandomState_Type) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
/* Initialize the global structure. Eventually this should be module local. */
global.cache_size = 100;
global.cache_obsize = 128;
mpz_init(global.tempz);
/* Initialize object caching. */
set_gmpympzcache();
set_gmpympqcache();
set_gmpyxmpzcache();
set_gmpympfrcache();
set_gmpympccache();
/* Initialize exceptions. */
GMPyExc_GmpyError = PyErr_NewException("gmpy2.gmpy2Error", PyExc_ArithmeticError, NULL);
if (!GMPyExc_GmpyError) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
GMPyExc_Erange = PyErr_NewException("gmpy2.RangeError", GMPyExc_GmpyError, NULL);
if (!GMPyExc_Erange) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
GMPyExc_Inexact = PyErr_NewException("gmpy2.InexactResultError", GMPyExc_GmpyError, NULL);
if (!GMPyExc_Inexact) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
GMPyExc_Overflow = PyErr_NewException("gmpy2.OverflowResultError", GMPyExc_Inexact, NULL);
if (!GMPyExc_Overflow) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
GMPyExc_Underflow = PyErr_NewException("gmpy2.UnderflowResultError", GMPyExc_Inexact, NULL);
if (!GMPyExc_Underflow) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
temp = PyTuple_Pack(2, GMPyExc_GmpyError, PyExc_ValueError);
if (!temp) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
GMPyExc_Invalid = PyErr_NewException("gmpy2.InvalidOperationError", temp, NULL);
Py_DECREF(temp);
if (!GMPyExc_Invalid) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
temp = PyTuple_Pack(2, GMPyExc_GmpyError, PyExc_ZeroDivisionError);
if (!temp) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
GMPyExc_DivZero = PyErr_NewException("gmpy2.DivisionByZeroError", temp, NULL);
Py_DECREF(temp);
if (!GMPyExc_DivZero) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
#ifdef PY3
gmpy_module = PyModule_Create(&moduledef);
#else
gmpy_module = Py_InitModule3("gmpy2", Pygmpy_methods, _gmpy_docs);
#endif
if (gmpy_module == NULL) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
/* Add the mpz type to the module namespace. */
Py_INCREF(&MPZ_Type);
PyModule_AddObject(gmpy_module, "mpz", (PyObject*)&MPZ_Type);
/* Add the xmpz type to the module namespace. */
Py_INCREF(&XMPZ_Type);
PyModule_AddObject(gmpy_module, "xmpz", (PyObject*)&XMPZ_Type);
/* Add the MPQ type to the module namespace. */
Py_INCREF(&MPQ_Type);
PyModule_AddObject(gmpy_module, "mpq", (PyObject*)&MPQ_Type);
/* Add the MPFR type to the module namespace. */
Py_INCREF(&MPFR_Type);
PyModule_AddObject(gmpy_module, "mpfr", (PyObject*)&MPFR_Type);
/* Add the MPC type to the module namespace. */
Py_INCREF(&MPC_Type);
PyModule_AddObject(gmpy_module, "mpc", (PyObject*)&MPC_Type);
/* Initialize thread local contexts. */
#ifdef WITHOUT_THREADS
module_context = (CTXT_Object*)GMPy_CTXT_New();
if (!module_context) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
Py_INCREF(Py_False);
if (PyModule_AddObject(gmpy_module, "HAVE_THREADS", Py_False) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(Py_False);
INITERROR;
/* LCOV_EXCL_STOP */
}
#else
tls_context_key = PyUnicode_FromString("__GMPY2_CTX__");
Py_INCREF(Py_True);
if (PyModule_AddObject(gmpy_module, "HAVE_THREADS", Py_True) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(Py_True);
INITERROR;
/* LCOV_EXCL_STOP */
}
#endif
/* Add the constants for defining rounding modes. */
if (PyModule_AddIntConstant(gmpy_module, "RoundToNearest", MPFR_RNDN) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "RoundToZero", MPFR_RNDZ) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "RoundUp", MPFR_RNDU) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "RoundDown", MPFR_RNDD) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "RoundAwayZero", MPFR_RNDA) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "Default", GMPY_DEFAULT) < 0) {
/* LCOV_EXCL_START */
INITERROR;
/* LCOV_EXCL_STOP */
}
/* Add the exceptions. */
Py_INCREF(GMPyExc_DivZero);
if (PyModule_AddObject(gmpy_module, "DivisionByZeroError", GMPyExc_DivZero) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_DivZero);
INITERROR;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Inexact);
if (PyModule_AddObject(gmpy_module, "InexactResultError", GMPyExc_Inexact) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Inexact);
INITERROR;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Invalid);
if (PyModule_AddObject(gmpy_module, "InvalidOperationError", GMPyExc_Invalid) < 0 ) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Invalid);
INITERROR;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Overflow);
if (PyModule_AddObject(gmpy_module, "OverflowResultError", GMPyExc_Overflow) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Overflow);
INITERROR;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Underflow);
if (PyModule_AddObject(gmpy_module, "UnderflowResultError", GMPyExc_Underflow) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Underflow);
INITERROR;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Erange);
if (PyModule_AddObject(gmpy_module, "RangeError", GMPyExc_Erange) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Erange);
INITERROR;
/* LCOV_EXCL_STOP */
}
#ifdef SHARED
/* Create the Capsule for the C-API. */
GMPy_C_API[MPZ_Type_NUM] = (void*)&MPZ_Type;
GMPy_C_API[XMPZ_Type_NUM] = (void*)&XMPZ_Type;
GMPy_C_API[MPQ_Type_NUM] = (void*)&MPQ_Type;
GMPy_C_API[XMPQ_Type_NUM] = (void*)&MPQ_Type;
GMPy_C_API[MPFR_Type_NUM] = (void*)&MPFR_Type;
GMPy_C_API[XMPFR_Type_NUM] = (void*)&MPFR_Type;
GMPy_C_API[MPC_Type_NUM] = (void*)&MPC_Type;
GMPy_C_API[XMPC_Type_NUM] = (void*)&MPC_Type;
GMPy_C_API[CTXT_Type_NUM] = (void*)&CTXT_Type;
GMPy_C_API[CTXT_Manager_Type_NUM] = (void*)&CTXT_Manager_Type;
GMPy_C_API[RandomState_Type_NUM] = (void*)&RandomState_Type;
GMPy_C_API[GMPy_MPZ_New_NUM] = (void*)GMPy_MPZ_New;
GMPy_C_API[GMPy_MPZ_NewInit_NUM] = (void*)GMPy_MPZ_NewInit;
GMPy_C_API[GMPy_MPZ_Dealloc_NUM] = (void*)GMPy_MPZ_Dealloc;
GMPy_C_API[GMPy_MPZ_ConvertArg_NUM] = (void*)GMPy_MPZ_ConvertArg;
GMPy_C_API[GMPy_XMPZ_New_NUM] = (void*)GMPy_XMPZ_New;
GMPy_C_API[GMPy_XMPZ_NewInit_NUM] = (void*)GMPy_XMPZ_NewInit;
GMPy_C_API[GMPy_XMPZ_Dealloc_NUM] = (void*)GMPy_XMPZ_Dealloc;
GMPy_C_API[GMPy_MPQ_New_NUM] = (void*)GMPy_MPQ_New;
GMPy_C_API[GMPy_MPQ_NewInit_NUM] = (void*)GMPy_MPQ_NewInit;
GMPy_C_API[GMPy_MPQ_Dealloc_NUM] = (void*)GMPy_MPQ_Dealloc;
GMPy_C_API[GMPy_MPQ_ConvertArg_NUM] = (void*)GMPy_MPQ_ConvertArg;
GMPy_C_API[GMPy_MPFR_New_NUM] = (void*)GMPy_MPFR_New;
GMPy_C_API[GMPy_MPFR_NewInit_NUM] = (void*)GMPy_MPFR_NewInit;
GMPy_C_API[GMPy_MPFR_Dealloc_NUM] = (void*)GMPy_MPFR_Dealloc;
GMPy_C_API[GMPy_MPFR_ConvertArg_NUM] = (void*)GMPy_MPFR_ConvertArg;
GMPy_C_API[GMPy_MPC_New_NUM] = (void*)GMPy_MPC_New;
GMPy_C_API[GMPy_MPC_NewInit_NUM] = (void*)GMPy_MPC_NewInit;
GMPy_C_API[GMPy_MPC_Dealloc_NUM] = (void*)GMPy_MPC_Dealloc;
GMPy_C_API[GMPy_MPC_ConvertArg_NUM] = (void*)GMPy_MPC_ConvertArg;
c_api_object = PyCapsule_New((void *)GMPy_C_API, "gmpy2._C_API", NULL);
if (c_api_object != NULL) {
PyModule_AddObject(gmpy_module, "_C_API", c_api_object);
}
#endif
/* Add support for pickling. */
#ifdef PY3
copy_reg_module = PyImport_ImportModule("copyreg");
if (copy_reg_module) {
char* enable_pickle =
"def gmpy2_reducer(x): return (gmpy2.from_binary, (gmpy2.to_binary(x),))\n"
"copyreg.pickle(type(gmpy2.mpz(0)), gmpy2_reducer)\n"
"copyreg.pickle(type(gmpy2.xmpz(0)), gmpy2_reducer)\n"
"copyreg.pickle(type(gmpy2.mpq(0)), gmpy2_reducer)\n"
"copyreg.pickle(type(gmpy2.mpfr(0)), gmpy2_reducer)\n"
"copyreg.pickle(type(gmpy2.mpc(0,0)), gmpy2_reducer)\n";
namespace = PyDict_New();
result = NULL;
PyDict_SetItemString(namespace, "copyreg", copy_reg_module);
PyDict_SetItemString(namespace, "gmpy2", gmpy_module);
PyDict_SetItemString(namespace, "type", (PyObject*)&PyType_Type);
result = PyRun_String(enable_pickle, Py_file_input, namespace, namespace);
if (!result) {
/* LCOV_EXCL_START */
PyErr_Clear();
/* LCOV_EXCL_STOP */
}
Py_DECREF(namespace);
Py_DECREF(copy_reg_module);
Py_XDECREF(result);
}
else {
/* LCOV_EXCL_START */
PyErr_Clear();
/* LCOV_EXCL_STOP */
}
#else
copy_reg_module = PyImport_ImportModule("copy_reg");
if (copy_reg_module) {
char* enable_pickle =
"def gmpy2_reducer(x): return (gmpy2.from_binary, (gmpy2.to_binary(x),))\n"
"copy_reg.pickle(type(gmpy2.mpz(0)), gmpy2_reducer)\n"
"copy_reg.pickle(type(gmpy2.xmpz(0)), gmpy2_reducer)\n"
"copy_reg.pickle(type(gmpy2.mpq(0)), gmpy2_reducer)\n"
"copy_reg.pickle(type(gmpy2.mpfr(0)), gmpy2_reducer)\n"
"copy_reg.pickle(type(gmpy2.mpc(0,0)), gmpy2_reducer)\n";
PyObject* namespace = PyDict_New();
PyObject* result = NULL;
PyDict_SetItemString(namespace, "copy_reg", copy_reg_module);
PyDict_SetItemString(namespace, "gmpy2", gmpy_module);
PyDict_SetItemString(namespace, "type", (PyObject*)&PyType_Type);
result = PyRun_String(enable_pickle, Py_file_input, namespace, namespace);
if (!result) {
/* LCOV_EXCL_START */
PyErr_Clear();
/* LCOV_EXCL_STOP */
}
Py_DECREF(namespace);
Py_DECREF(copy_reg_module);
Py_XDECREF(result);
}
else {
/* LCOV_EXCL_START */
PyErr_Clear();
/* LCOV_EXCL_STOP */
}
#endif
/* Register the gmpy2 types with the numeric tower. */
numbers_module = PyImport_ImportModule("numbers");
if (numbers_module) {
char* register_numbers =
"numbers.Integral.register(type(gmpy2.mpz()))\n"
"numbers.Rational.register(type(gmpy2.mpq()))\n"
"numbers.Real.register(type(gmpy2.mpfr()))\n"
"numbers.Complex.register(type(gmpy2.mpc()))\n"
;
namespace = PyDict_New();
result = NULL;
PyDict_SetItemString(namespace, "numbers", numbers_module);
PyDict_SetItemString(namespace, "gmpy2", gmpy_module);
PyDict_SetItemString(namespace, "type", (PyObject*)&PyType_Type);
result = PyRun_String(register_numbers, Py_file_input,
namespace, namespace);
if (!result) {
PyErr_Clear();
}
Py_DECREF(namespace);
Py_DECREF(numbers_module);
Py_XDECREF(result);
}
else {
PyErr_Clear();
}
#ifdef PY3
return gmpy_module;
#endif
}
gmpy2-2.1.0b3/src/gmpy2.h 0000664 0001750 0001750 00000051007 13525427233 014656 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
gmpy C API extension header file.
Part of Python's gmpy module since version 0.4
Created by Pearu Peterson , November 2000.
Edited by A. Martelli , December 2000.
Edited by Case Van Horsen , 2009, 2010, 2011.
Version 1.02, February 2007.
Version 1.03, June 2008
Version 1.04, June 2008 (no changes)
Version 1.05, February 2009 (support MPIR)
Version 1.20, January 2010 (remove obsolete MS hacks) casevh
Version 2.00, April 2010 (change to gmpy2) casevh
October 2010 (added Py_hash_t) casevh
December 2010 (added mpfr, mpc) casevh
January 2011 (add Pygmpy_context) casevh
April 2011 (split into multiple files) casevh
Version 2.10 August 2014 (reflect major rewrite during 2013/2014) casevh
*/
#ifndef Py_GMPYMODULE_H
#define Py_GMPYMODULE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Structure of gmpy2.h
*
* Revised 17-APR-2017 casevh
*
* 1. Checks for specific Python versions.
* 2. Include headers for GMP/MPIR, MPFR, and MPC.
* 3. Define public C-API.
* 1. Define gmpy2 types.
* 2. Define the public API.
*
*/
/* Check for minimum Python version requirements. */
#if PY_VERSION_HEX < 0x02060000
# error "GMPY2 requires Python 2.6 or later."
#endif
/* Include headers for GMP/MPIR, MPFR, and MPC. */
#ifdef MPIR
# include
#else
# include
#endif
#include
#include
/* Check MPFR and MPC versions. */
#if (!defined(MPC_VERSION) || (MPC_VERSION < MPC_VERSION_NUM(1,0,3)))
# error "GMPY2 requires MPC 1.0.3 or later."
#endif
#if (defined(MPC_VERSION) && (MPC_VERSION >= MPC_VERSION_NUM(1,1,0)))
# define MPC_110
#endif
#if PY_VERSION_HEX < 0x030200A4
typedef long Py_hash_t;
typedef unsigned long Py_uhash_t;
# define _PyHASH_IMAG 1000003
#endif
/* The native_si and native_ui types correspond to long long on Windows 64. They
* should only be used with the MPIR library (not MPFR/MPC).
*/
#if defined(MPIR) && defined(_WIN64)
typedef long long native_si;
typedef unsigned long long native_ui;
#define GMPy_Integer_AsNative_siAndError GMPy_Integer_AsLongLongAndError
#define GMPy_Integer_AsNative_uiAndError GMPy_Integer_AsUnsignedLongLongAndError
#else
typedef long native_si;
typedef unsigned long native_ui;
#define GMPy_Integer_AsNative_siAndError GMPy_Integer_AsLongAndError
#define GMPy_Integer_AsNative_uiAndError GMPy_Integer_AsUnsignedLongAndError
#endif
/* GMPY2 Public API */
/* Types
* MPZ_Object
* XMPZ_Object (mutable version of MPZ_Object)
* MPQ_Object
* XMPQ_Object (mutable version of MPQ_Object)
* MPFR_Object
* XMPFR_Object (mutable version of MPFR_Object)
* MPC_Object
* XMPC_Object (mutable version of MPC_Object)
* CTXT_Object
* CTXT_Manager_Object
* RandomState_Object
*/
typedef struct {
PyObject_HEAD
mpz_t z;
Py_hash_t hash_cache;
} MPZ_Object;
typedef struct {
PyObject_HEAD
mpz_t z;
} XMPZ_Object;
typedef struct {
PyObject_HEAD
mpq_t q;
Py_hash_t hash_cache;
} MPQ_Object;
typedef struct {
PyObject_HEAD
mpfr_t f;
Py_hash_t hash_cache;
int rc;
} MPFR_Object;
typedef struct {
PyObject_HEAD
mpc_t c;
Py_hash_t hash_cache;
int rc;
} MPC_Object;
typedef struct {
PyObject_HEAD
gmp_randstate_t state;
} RandomState_Object;
typedef struct {
mpfr_prec_t mpfr_prec; /* current precision in bits, for MPFR */
mpfr_rnd_t mpfr_round; /* current rounding mode for float (MPFR) */
mpfr_exp_t emax; /* maximum exponent */
mpfr_exp_t emin; /* minimum exponent */
int subnormalize; /* if 1, subnormalization is performed */
int underflow; /* did an underflow occur? */
int overflow; /* did an overflow occur? */
int inexact; /* was the result inexact? */
int invalid; /* invalid operation (i.e. NaN)? */
int erange; /* did a range error occur? */
int divzero; /* divided by zero? */
int traps; /* if 0, do not trap any exceptions */
/* if not 0, then raise traps per bits above */
mpfr_prec_t real_prec; /* current precision in bits, for Re(MPC) */
mpfr_prec_t imag_prec; /* current precision in bits, for Im(MPC) */
mpfr_rnd_t real_round; /* current rounding mode for Re(MPC) */
mpfr_rnd_t imag_round; /* current rounding mode for Im(MPC) */
int allow_complex; /* if 1, allow mpfr functions to return an mpc */
int rational_division; /* if 1, mpz/mpz returns an mpq result */
} gmpy_context;
typedef struct {
PyObject_HEAD
gmpy_context ctx;
#ifndef WITHOUT_THREADS
PyThreadState *tstate;
#endif
} CTXT_Object;
typedef struct {
PyObject_HEAD
CTXT_Object *new_context; /* Context that will be returned when
* __enter__ is called. */
CTXT_Object *old_context; /* Context that will restored when
* __exit__ is called. */
} CTXT_Manager_Object;
#define MPZ(obj) (((MPZ_Object*)(obj))->z)
#define MPQ(obj) (((MPQ_Object*)(obj))->q)
#define MPFR(obj) (((MPFR_Object*)(obj))->f)
#define MPC(obj) (((MPC_Object*)(obj))->c)
/* Start of the C-API definitions */
#define MPZ_Type_NUM 0
#define XMPZ_Type_NUM 1
#define MPQ_Type_NUM 2
#define XMPQ_Type_NUM 3
#define MPFR_Type_NUM 4
#define XMPFR_Type_NUM 5
#define MPC_Type_NUM 6
#define XMPC_Type_NUM 7
#define CTXT_Type_NUM 8
#define CTXT_Manager_Type_NUM 9
#define RandomState_Type_NUM 10
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPZ_New_NUM 11
#define GMPy_MPZ_New_RETURN MPZ_Object *
#define GMPy_MPZ_New_PROTO (CTXT_Object *context)
#define GMPy_MPZ_NewInit_NUM 12
#define GMPy_MPZ_NewInit_RETURN PyObject *
#define GMPy_MPZ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPZ_Dealloc_NUM 13
#define GMPy_MPZ_Dealloc_RETURN void
#define GMPy_MPZ_Dealloc_PROTO (MPZ_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPZ_ConvertArg_NUM 14
#define GMPy_MPZ_ConvertArg_RETURN int
#define GMPy_MPZ_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_XMPZ_New_NUM 15
#define GMPy_XMPZ_New_RETURN XMPZ_Object *
#define GMPy_XMPZ_New_PROTO (CTXT_Object *context)
#define GMPy_XMPZ_NewInit_NUM 16
#define GMPy_XMPZ_NewInit_RETURN PyObject *
#define GMPy_XMPZ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_XMPZ_Dealloc_NUM 17
#define GMPy_XMPZ_Dealloc_RETURN void
#define GMPy_XMPZ_Dealloc_PROTO (XMPZ_Object *self)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPQ_New_NUM 18
#define GMPy_MPQ_New_RETURN MPQ_Object *
#define GMPy_MPQ_New_PROTO (CTXT_Object *context)
#define GMPy_MPQ_NewInit_NUM 19
#define GMPy_MPQ_NewInit_RETURN PyObject *
#define GMPy_MPQ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPQ_Dealloc_NUM 20
#define GMPy_MPQ_Dealloc_RETURN void
#define GMPy_MPQ_Dealloc_PROTO (MPQ_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPQ_ConvertArg_NUM 21
#define GMPy_MPQ_ConvertArg_RETURN int
#define GMPy_MPQ_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPFR_New_NUM 22
#define GMPy_MPFR_New_RETURN MPFR_Object *
#define GMPy_MPFR_New_PROTO (mpfr_prec_t bits, CTXT_Object *context)
#define GMPy_MPFR_NewInit_NUM 23
#define GMPy_MPFR_NewInit_RETURN PyObject *
#define GMPy_MPFR_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPFR_Dealloc_NUM 24
#define GMPy_MPFR_Dealloc_RETURN void
#define GMPy_MPFR_Dealloc_PROTO (MPFR_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPFR_ConvertArg_NUM 25
#define GMPy_MPFR_ConvertArg_RETURN int
#define GMPy_MPFR_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPC_New_NUM 26
#define GMPy_MPC_New_RETURN MPC_Object *
#define GMPy_MPC_New_PROTO (mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context)
#define GMPy_MPC_NewInit_NUM 27
#define GMPy_MPC_NewInit_RETURN PyObject *
#define GMPy_MPC_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPC_Dealloc_NUM 28
#define GMPy_MPC_Dealloc_RETURN void
#define GMPy_MPC_Dealloc_PROTO (MPC_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPC_ConvertArg_NUM 29
#define GMPy_MPC_ConvertArg_RETURN int
#define GMPy_MPC_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* Total number of C-API pointers. */
#define GMPy_API_pointers 30
/* End of C-API definitions. */
#ifdef GMPY2_MODULE
/* Define various macros to deal with differences between Python 2 and 3. */
#if (PY_MAJOR_VERSION == 3)
#define PY3
#define Py2or3String_FromString PyUnicode_FromString
#define Py2or3String_FromFormat PyUnicode_FromFormat
#define Py2or3String_Check PyUnicode_Check
#define Py2or3String_Format PyUnicode_Format
#define Py2or3String_AsString PyUnicode_AS_DATA
#define PyStrOrUnicode_Check(op) (PyBytes_Check(op) || PyUnicode_Check(op))
#define PyIntOrLong_FromLong PyLong_FromLong
#define PyIntOrLong_Check(op) PyLong_Check(op)
#define PyIntOrLong_FromSize_t PyLong_FromSize_t
#define PyIntOrLong_FromSsize_t PyLong_FromSsize_t
#define PyIntOrLong_AsSsize_t PyLong_AsSsize_t
#define PyIntOrLong_AsLong PyLong_AsLong
#else
#define PY2
#define Py2or3String_FromString PyString_FromString
#define Py2or3String_FromFormat PyString_FromFormat
#define Py2or3String_Check PyString_Check
#define Py2or3String_Format PyString_Format
#define Py2or3String_AsString PyString_AsString
#define PyStrOrUnicode_Check(op) (PyString_Check(op) || PyUnicode_Check(op))
#define PyIntOrLong_FromLong PyInt_FromLong
#define PyIntOrLong_Check(op) (PyInt_Check(op) || PyLong_Check(op))
#define PyIntOrLong_FromSize_t PyInt_FromSize_t
#define PyIntOrLong_FromSsize_t PyInt_FromSsize_t
#define PyIntOrLong_AsSsize_t PyInt_AsSsize_t
#define PyIntOrLong_AsLong PyInt_AsLong
#endif
#ifndef ABS
# define ABS(a) (((a) < 0) ? -(a) : (a))
#endif
#if defined(MS_WIN32) && defined(_MSC_VER)
/* so one won't need to link explicitly to gmp.lib...: */
# if defined(MPIR)
# pragma comment(lib,"mpir.lib")
# else
# pragma comment(lib,"gmp.lib")
# endif
# define USE_ALLOCA 1
# define inline __inline
#endif
#ifdef __GNUC__
# define USE_ALLOCA 1
#endif
#ifndef alloca
# ifdef __GNUC__
# define alloca __builtin_alloca
# else
# ifdef _MSC_VER
# include
# define alloca _alloca
# else
# if HAVE_ALLOCA_H
# include
# else
char *alloca ();
# endif
# endif
# endif
#endif
#define ALLOC_THRESHOLD 8192
#define INDEX_ERROR(msg) PyErr_SetString(PyExc_IndexError, msg)
#define TYPE_ERROR(msg) PyErr_SetString(PyExc_TypeError, msg)
#define VALUE_ERROR(msg) PyErr_SetString(PyExc_ValueError, msg)
#define ZERO_ERROR(msg) PyErr_SetString(PyExc_ZeroDivisionError, msg)
#define SYSTEM_ERROR(msg) PyErr_SetString(PyExc_SystemError, msg)
#define OVERFLOW_ERROR(msg) PyErr_SetString(PyExc_OverflowError, msg)
#define RUNTIME_ERROR(msg) PyErr_SetString(PyExc_RuntimeError, msg)
#define GMPY_DEFAULT -1
/* To prevent excessive memory usage, we don't want to save very large
* numbers in the cache. The default value specified in the options
* structure is 128 words (512 bytes on 32-bit platforms, 1024 bytes on
* 64-bit platforms).
*/
#define MAX_CACHE_LIMBS 16384
/* The maximum number of objects that can be saved in a cache is specified
* here. The default value is 100.*/
#define MAX_CACHE 1000
#ifdef USE_ALLOCA
# define TEMP_ALLOC(B, S) \
if(S < ALLOC_THRESHOLD) { \
B = alloca(S); \
} else { \
if(!(B = malloc(S))) { \
PyErr_NoMemory(); \
return NULL; \
} \
}
# define TEMP_FREE(B, S) if(S >= ALLOC_THRESHOLD) free(B)
#else
# define TEMP_ALLOC(B, S) \
if(!(B = malloc(S))) { \
PyErr_NoMemory(); \
return NULL; \
}
# define TEMP_FREE(B, S) free(B)
#endif
/* Various defs to mask differences between Python versions. */
#define Py_RETURN_NOTIMPLEMENTED \
return Py_INCREF(Py_NotImplemented), Py_NotImplemented
#ifndef Py_SIZE
# define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
#endif
#ifndef Py_TYPE
# define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#endif
/* Import a collection of general purpose macros. */
#include "gmpy2_macros.h"
/* Import the files that complete the definition of the types defined above. */
#include "gmpy2_mpz.h"
#include "gmpy2_xmpz.h"
#include "gmpy2_mpq.h"
#include "gmpy2_mpfr.h"
#include "gmpy2_mpc.h"
#include "gmpy2_context.h"
#include "gmpy2_random.h"
/* Import the header files that provide the various functions. */
/* Support object caching, creation, and deletion. */
#include "gmpy2_cache.h"
/* Suport for miscellaneous functions (ie. version, license, etc.). */
#include "gmpy2_misc.h"
/* Support conversion to/from binary format. */
#include "gmpy2_binary.h"
/* Support for mpz/xmpz specific functions. */
#include "gmpy2_convert.h"
#include "gmpy2_convert_utils.h"
#include "gmpy2_convert_gmp.h"
#include "gmpy2_convert_mpfr.h"
#include "gmpy2_convert_mpc.h"
#include "gmpy2_mpz_divmod.h"
#include "gmpy2_mpz_divmod2exp.h"
#include "gmpy2_mpz_pack.h"
#include "gmpy2_mpz_bitops.h"
#include "gmpy2_mpz_inplace.h"
#include "gmpy2_mpz_misc.h"
#include "gmpy2_xmpz_inplace.h"
#include "gmpy2_xmpz_misc.h"
/* Support for mpq specific functions. */
#include "gmpy2_mpq_misc.h"
/* Support for mpfr specific functions. */
#include "gmpy2_mpfr_misc.h"
/* Support for mpc specific functions. */
#include "gmpy2_mpc_misc.h"
/* Support Lucas sequences. */
#include "gmpy_mpz_lucas.h"
/* Support probable-prime tests. */
#include "gmpy_mpz_prp.h"
/* Support higher-level Python methods and functions; generally not
* specific to a single type.
*/
#include "gmpy2_abs.h"
#include "gmpy2_add.h"
#include "gmpy2_divmod.h"
#include "gmpy2_floordiv.h"
#include "gmpy2_minus.h"
#include "gmpy2_mod.h"
#include "gmpy2_mul.h"
#include "gmpy2_plus.h"
#include "gmpy2_pow.h"
#include "gmpy2_sub.h"
#include "gmpy2_truediv.h"
#include "gmpy2_math.h"
#include "gmpy2_const.h"
#include "gmpy2_square.h"
#include "gmpy2_format.h"
#include "gmpy2_hash.h"
#include "gmpy2_fused.h"
#include "gmpy2_muldiv_2exp.h"
#include "gmpy2_predicate.h"
#include "gmpy2_sign.h"
#include "gmpy2_richcompare.h"
#include "gmpy2_cmp.h"
#ifdef VECTOR
# include "gmpy2_vector.h"
#endif /* defined(VECTOR) */
#else /* defined(GMPY2_MODULE) */
/* This section is used for other C-coded modules that use gmpy2's API. */
static void **GMPy_C_API;
#define MPZ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPZ_Type_NUM])
#define XMPZ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPZ_Type_NUM])
#define MPQ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPQ_Type_NUM])
#define XMPQ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPQ_Type_NUM])
#define MPFR_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPFR_Type_NUM])
#define XMPFR_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPFR_Type_NUM])
#define MPC_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPC_Type_NUM])
#define XMPC_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPC_Type_NUM])
#define GMPy_MPZ_New (*(GMPy_MPZ_New_RETURN (*)GMPy_MPZ_New_PROTO) GMPy_C_API[GMPy_MPZ_New_NUM])
#define GMPy_MPZ_NewInit (*(GMPy_MPZ_NewInit_RETURN (*)GMPy_MPZ_NewInit_PROTO) GMPy_C_API[GMPy_MPZ_NewInit_NUM])
#define GMPy_MPZ_Dealloc (*(GMPy_MPZ_Dealloc_RETURN (*)GMPy_MPZ_Dealloc_PROTO) GMPy_C_API[GMPy_MPZ_Dealloc_NUM])
#define GMPy_MPZ_ConvertArg (*(GMPy_MPZ_ConvertArg_RETURN (*)GMPy_MPZ_ConvertArg_PROTO) GMPy_C_API[GMPy_MPZ_ConvertArg_NUM])
#define GMPy_XMPZ_New (*(GMPy_XMPZ_New_RETURN (*)GMPy_XMPZ_New_PROTO) GMPy_C_API[GMPy_XMPZ_New_NUM])
#define GMPy_XMPZ_NewInit (*(GMPy_XMPZ_NewInit_RETURN (*)GMPy_XMPZ_NewInit_PROTO) GMPy_C_API[GMPy_XMPZ_NewInit_NUM])
#define GMPy_XMPZ_Dealloc (*(GMPy_XMPZ_Dealloc_RETURN (*)GMPy_XMPZ_Dealloc_PROTO) GMPy_C_API[GMPy_XMPZ_Dealloc_NUM])
#define GMPy_MPQ_New (*(GMPy_MPQ_New_RETURN (*)GMPy_MPQ_New_PROTO) GMPy_C_API[GMPy_MPQ_New_NUM])
#define GMPy_MPQ_NewInit (*(GMPy_MPQ_NewInit_RETURN (*)GMPy_MPQ_NewInit_PROTO) GMPy_C_API[GMPy_MPQ_NewInit_NUM])
#define GMPy_MPQ_Dealloc (*(GMPy_MPQ_Dealloc_RETURN (*)GMPy_MPQ_Dealloc_PROTO) GMPy_C_API[GMPy_MPQ_Dealloc_NUM])
#define GMPy_MPQ_ConvertArg (*(GMPy_MPQ_ConvertArg_RETURN (*)GMPy_MPQ_ConvertArg_PROTO) GMPy_C_API[GMPy_MPQ_ConvertArg_NUM])
#define GMPy_MPFR_New (*(GMPy_MPFR_New_RETURN (*)GMPy_MPFR_New_PROTO) GMPy_C_API[GMPy_MPFR_New_NUM])
#define GMPy_MPFR_NewInit (*(GMPy_MPFR_NewInit_RETURN (*)GMPy_MPFR_NewInit_PROTO) GMPy_C_API[GMPy_MPFR_NewInit_NUM])
#define GMPy_MPFR_Dealloc (*(GMPy_MPFR_Dealloc_RETURN (*)GMPy_MPFR_Dealloc_PROTO) GMPy_C_API[GMPy_MPFR_Dealloc_NUM])
#define GMPy_MPFR_ConvertArg (*(GMPy_MPFR_ConvertArg_RETURN (*)GMPy_MPFR_ConvertArg_PROTO) GMPy_C_API[GMPy_MPFR_ConvertArg_NUM])
#define GMPy_MPC_New (*(GMPy_MPC_New_RETURN (*)GMPy_MPC_New_PROTO) GMPy_C_API[GMPy_MPC_New_NUM])
#define GMPy_MPC_NewInit (*(GMPy_MPC_NewInit_RETURN (*)GMPy_MPC_NewInit_PROTO) GMPy_C_API[GMPy_MPC_NewInit_NUM])
#define GMPy_MPC_Dealloc (*(GMPy_MPC_Dealloc_RETURN (*)GMPy_MPC_Dealloc_PROTO) GMPy_C_API[GMPy_MPC_Dealloc_NUM])
#define GMPy_MPC_ConvertArg (*(GMPy_MPC_ConvertArg_RETURN (*)GMPy_MPC_ConvertArg_PROTO) GMPy_C_API[GMPy_MPC_ConvertArg_NUM])
static int
import_gmpy2(void)
{
GMPy_C_API = (void **)PyCapsule_Import("gmpy2._C_API", 0);
return (GMPy_C_API != NULL) ? 0 : -1;
}
#endif /* defined(GMPY2_MODULE) */
#ifdef __cplusplus
}
#endif /* defined(__cplusplus */
#endif /* !defined(Py_GMPYMODULE_H */
gmpy2-2.1.0b3/src/gmpy2.pxd 0000664 0001750 0001750 00000011111 13356026702 015210 0 ustar case case 0000000 0000000 cdef extern from "gmp.h":
# gmp integers
ctypedef long mp_limb_t
ctypedef struct __mpz_struct:
int _mp_alloc
int _mp_size
mp_limb_t* _mp_d
ctypedef __mpz_struct mpz_t[1]
ctypedef __mpz_struct *mpz_ptr
ctypedef const __mpz_struct *mpz_srcptr
# gmp rationals
ctypedef struct __mpq_struct:
__mpz_struct _mp_num
__mpz_struct _mp_den
ctypedef __mpq_struct mpq_t[1]
ctypedef __mpq_struct *mpq_ptr
ctypedef const __mpq_struct *mpq_srcptr
void mpz_set(mpz_t rop, mpz_t op)
void mpq_set(mpq_ptr rop, mpq_srcptr op)
void mpq_set_num(mpq_t rational, mpz_t numerator)
void mpq_set_den(mpq_t rational, mpz_t denominator)
cdef extern from "mpfr.h":
# mpfr reals
ctypedef int mpfr_sign_t
ctypedef long mpfr_prec_t
ctypedef long mpfr_exp_t
ctypedef struct __mpfr_struct:
mpfr_prec_t _mpfr_prec
mpfr_sign_t _mpfr_sign
mpfr_exp_t _mpfr_exp
mp_limb_t* _mpfr_d
ctypedef __mpfr_struct mpfr_t[1]
ctypedef __mpfr_struct *mpfr_ptr
ctypedef const __mpfr_struct *mpfr_srcptr
ctypedef enum mpfr_rnd_t:
MPFR_RNDN
MPFR_RNDZ
MPFR_RNDU
MPFR_RNDD
MPFR_RNDA
MPFR_RNDF
MPFR_RNDNA
mpfr_prec_t mpfr_get_prec(mpfr_t x)
int mpfr_set(mpfr_t rop, mpfr_t op, mpfr_rnd_t rnd)
cdef extern from "mpc.h":
# mpc complexes
ctypedef struct __mpc_struct:
mpfr_t re
mpfr_t im
ctypedef __mpc_struct mpc_t[1];
ctypedef __mpc_struct *mpc_ptr;
ctypedef const __mpc_struct *mpc_srcptr;
ctypedef enum mpc_rnd_t:
MPC_RNDNN
MPC_RNDNZ
MPC_RNDNU
MPC_RNDND
MPC_RNDZN
MPC_RNDZZ
MPC_RNDZU
MPC_RNDZD
MPC_RNDUN
MPC_RNDUZ
MPC_RNDUU
MPC_RNDUD
MPC_RNDDN
MPC_RNDDZ
MPC_RNDDU
MPC_RNDDD
mpfr_prec_t mpc_get_prec(mpc_srcptr x)
void mpc_get_prec2(mpfr_prec_t *pr, mpfr_prec_t *pi, mpc_srcptr x)
int mpc_set(mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
int mpc_set_fr_fr(mpc_ptr rop, mpfr_srcptr rp, mpfr_srcptr ip, mpc_rnd_t rnd)
cdef extern from "gmpy2.h":
# Initialize the C-API
# This must be called before any other functions, but not to access
# the types.
cdef int import_gmpy2() except -1
# Object types
ctypedef class gmpy2.mpz [object MPZ_Object]:
cdef mpz_t z
ctypedef class gmpy2.mpq [object MPQ_Object]:
cdef mpq_t q
ctypedef class gmpy2.mpfr [object MPFR_Object]:
cdef mpfr_t f
cdef int rc
ctypedef class gmpy2.mpc [object MPC_Object]:
cdef mpc_t c
cdef int rc
# Object creation
cdef mpz GMPy_MPZ_New(void *)
cdef mpq GMPy_MPQ_New(void *)
cdef mpfr GMPy_MPFR_New(mpfr_prec_t prec, void *)
cdef mpc GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, void *)
# C field access
cdef mpz_t MPZ(mpz)
cdef mpq_t MPQ(mpq)
cdef mpfr_t MPFR(mpfr)
cdef mpc_t MPC(mpc)
# Type check
cdef bint MPZ_Check(object)
cdef bint MPQ_Check(object)
cdef bint MPFR_Check(object)
cdef bint MPC_Check(object)
# Build a gmpy2 mpz from a gmp mpz
cdef inline mpz GMPy_MPZ_From_mpz(mpz_srcptr z):
cdef mpz res = GMPy_MPZ_New(NULL)
mpz_set(res.z, z)
return res
# Build a gmpy2 mpq from a gmp mpq
cdef inline mpq GMPy_MPQ_From_mpq(mpq_srcptr q):
cdef mpq res = GMPy_MPQ_New(NULL)
mpq_set(res.q, q)
return res
# Build a gmpy2 mpq from gmp mpz numerator and denominator
cdef inline mpq GMPy_MPQ_From_mpz(mpz_srcptr num, mpz_srcptr den):
cdef mpq res = GMPy_MPQ_New(NULL)
mpq_set_num(res.q, num)
mpq_set_den(res.q, den)
return res
# Build a gmpy2 mpfr from a mpfr
cdef inline mpfr GMPy_MPFR_From_mpfr(mpfr_srcptr x):
cdef mpfr res = GMPy_MPFR_New(mpfr_get_prec(x), NULL)
mpfr_set(res.f, x, MPFR_RNDN)
return res
# Build a gmpy2 mpc from a mpc
cdef inline mpc GMPy_MPC_From_mpc(mpc_srcptr c):
cdef mpfr_prec_t pr
cdef mpfr_prec_t pi
mpc_get_prec2(&pr, &pi, c)
cdef mpc res = GMPy_MPC_New(pr, pi, NULL)
mpc_set(res.c, c, MPC_RNDNN)
return res
# Build a gmpy2 mpc from a real part mpfr and an imaginary part mpfr
cdef inline mpc GMPy_MPC_From_mpfr(mpfr_srcptr re, mpfr_srcptr im):
cdef mpc res = GMPy_MPC_New(mpfr_get_prec(re), mpfr_get_prec(im), NULL)
# We intentionally use MPFR funtions instead of MPC functions here
# in order not to add an unneeded dependency on MPC. It's probably
# faster too this way.
mpfr_set(res.c.re, re, MPFR_RNDN)
mpfr_set(res.c.im, im, MPFR_RNDN)
return res
gmpy2-2.1.0b3/src/gmpy2_abs.c 0000664 0001750 0001750 00000015507 13425751027 015503 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_abs.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __abs__, gmpy2.abs(), and context.abs().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. If the value
* of context is NULL, then the function should use the currently active
* context.
*
* GMPy_Number_Abs(Number, context)
*
* Private API
* ===========
* GMPy_MPZ_Abs_Slot
* GMPy_MPQ_Abs_Slot
* GMPy_MPFR_Abs_Slot
* GMPy_MPC_Abs_Slot
*
* GMPy_Integer_Abs(Integer, context|NULL)
* GMPy_Rational_Abs(Rational, context|NULL)
* GMPy_Real_Abs(Real, context|NULL)
* GMPy_Complex_Abs(Complex, context|NULL)
*
* GMPy_Context_Abs(context, obj)
*/
static PyObject *
GMPy_Integer_Abs(PyObject *x, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (MPZ_Check(x)) {
if (mpz_sgn(MPZ(x)) >= 0) {
Py_INCREF(x);
return x;
}
else {
if ((result = GMPy_MPZ_New(context)))
mpz_abs(result->z, MPZ(x));
return (PyObject*)result;
}
}
/* This is safe because result is not an incremented reference to an
* existing value. Why?
* 1) No values are interned like Python's integers.
* 2) MPZ is already handled so GMPy_MPZ_From_Integer() can't return
* an incremented reference to an existing value (which it would do
* if passed an MPZ).
*/
if ((result = GMPy_MPZ_From_Integer(x, context))) {
mpz_abs(result->z, result->z);
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Abs_Slot(MPZ_Object *x)
{
return GMPy_Integer_Abs((PyObject*)x, NULL);
}
static PyObject *
GMPy_Rational_Abs(PyObject *x, CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (MPQ_Check(x)) {
if (mpz_sgn(mpq_numref(MPQ(x))) >= 0) {
Py_INCREF(x);
return x;
}
else {
if ((result = GMPy_MPQ_New(context))) {
mpq_set(result->q, MPQ(x));
mpz_abs(mpq_numref(result->q), mpq_numref(result->q));
}
return (PyObject*)result;
}
}
/* This is safe because result is not an incremented reference to an
* existing value. MPQ is already handled so GMPy_MPQ_From_Rational()
* can't return an incremented reference to an existing value (which it
* would do if passed an MPQ).
*/
if ((result = GMPy_MPQ_From_Rational(x, context))) {
mpz_abs(mpq_numref(result->q), mpq_numref(result->q));
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPQ_Abs_Slot(MPQ_Object *x)
{
return GMPy_Rational_Abs((PyObject*)x, NULL);
}
static PyObject *
GMPy_Real_Abs(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context)) ||
!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_abs(result->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_MPFR_Abs_Slot(MPFR_Object *x)
{
return GMPy_Real_Abs((PyObject*)x, NULL);
}
static PyObject *
GMPy_Complex_Abs(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPC_Object *tempx = NULL;
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context)) ||
!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpc_abs(result->f, tempx->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_MPC_Abs_Slot(MPC_Object *x)
{
return GMPy_Complex_Abs((PyObject*)x, NULL);
}
static PyObject *
GMPy_Number_Abs(PyObject *x, CTXT_Object *context)
{
if (IS_INTEGER(x))
return GMPy_Integer_Abs(x, context);
if (IS_RATIONAL_ONLY(x))
return GMPy_Rational_Abs(x, context);
if (IS_REAL_ONLY(x))
return GMPy_Real_Abs(x, context);
if (IS_COMPLEX_ONLY(x))
return GMPy_Complex_Abs(x, context);
TYPE_ERROR("abs() argument type not supported");
return NULL;
}
/* Implement context.abs(). The following code assumes it used a as method of
* a context. */
PyDoc_STRVAR(GMPy_doc_context_abs,
"context.abs(x) -> number\n\n"
"Return abs(x), the context is applied to the result.");
static PyObject *
GMPy_Context_Abs(PyObject *self, PyObject *other)
{
return GMPy_Number_Abs(other, (CTXT_Object*)self);
}
gmpy2-2.1.0b3/src/gmpy2_abs.h 0000664 0001750 0001750 00000005464 13425751631 015512 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_abs.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_ABS_H
#define GMPY2_ABS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Abs(PyObject *x, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_Abs(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Rational_Abs(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Real_Abs(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Abs(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPZ_Abs_Slot(MPZ_Object *x);
static PyObject * GMPy_MPQ_Abs_Slot(MPQ_Object *x);
static PyObject * GMPy_MPFR_Abs_Slot(MPFR_Object *x);
static PyObject * GMPy_MPC_Abs_Slot(MPC_Object *x);
static PyObject * GMPy_Context_Abs(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_add.c 0000664 0001750 0001750 00000042445 13425751130 015462 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_add.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the + operator, gmpy2.add(), and context.add().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL
* value for context implies the function should use the currently active
* context.
*
* GMPy_Number_Add(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_MPZ_Add_Slot
* GMPy_MPQ_Add_Slot
* GMPy_MPFR_Add_Slot
* GMPy_MPC_Add_Slot
*
* GMPy_Integer_Add(Integer, Integer, context|NULL)
* GMPy_Rational_Add(Rational, Rational, context|NULL)
* GMPy_Real_Add(Real, Real, context|NULL)
* GMPy_Complex_Add(Complex, Complex, context|NULL)
*
* GMPy_Context_Add(context, args)
*
*/
/* Add two Integer objects (see gmpy2_convert.h). If an error occurs, NULL
* is returned and an exception is set. If either x or y can't be converted
* into an mpz, Py_NotImplemented is returned.
*/
static PyObject *
GMPy_Integer_Add(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPZ_Check(x)) {
if (PyIntOrLong_Check(y)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(y, &error);
if (!error) {
if (temp >= 0) {
mpz_add_ui(result->z, MPZ(x), temp);
}
else {
mpz_sub_ui(result->z, MPZ(x), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpz_add(result->z, MPZ(x), global.tempz);
}
return (PyObject*)result;
}
if (MPZ_Check(y)) {
mpz_add(result->z, MPZ(x), MPZ(y));
return (PyObject*)result;
}
}
if (MPZ_Check(y)) {
if (PyIntOrLong_Check(x)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(x, &error);
if (!error) {
if (temp >= 0) {
mpz_add_ui(result->z, MPZ(y), temp);
}
else {
mpz_sub_ui(result->z, MPZ(y), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, x);
mpz_add(result->z, MPZ(y), global.tempz);
}
return (PyObject*)result;
}
}
if (IS_INTEGER(x) && IS_INTEGER(y)) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_Integer(x, context)) ||
!(tempy = GMPy_MPZ_From_Integer(y, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_add(result->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
SYSTEM_ERROR("Internal error in GMPy_Integer_Add().");
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Implement __add__ for MPZ_Object. On entry, one of the two arguments must
* be an MPZ_Object. If the other object is an Integer, add and return an
* MPZ_Object. If the other object isn't an MPZ_Object, call the appropriate
* function. If no appropriate function can be found, return NotImplemented.
*/
static PyObject *
GMPy_MPZ_Add_Slot(PyObject *x, PyObject *y)
{
if (MPZ_Check(x) && MPZ_Check(y)) {
MPZ_Object *result = NULL;
if ((result = GMPy_MPZ_New(NULL))) {
mpz_add(result->z, MPZ(x), MPZ(y));
}
return (PyObject*)result;
}
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_Add(x, y, NULL);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Add(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Add(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Add(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* Add two Rational objects (see gmpy2_convert.h). Returns None and
* raises TypeError if both objects are not valid rationals. GMPy_Rational_Add
* is intended to be called from GMPy_Number_Add(). */
static PyObject *
GMPy_Rational_Add(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPQ_Check(x) && MPQ_Check(y)) {
mpq_add(result->q, MPQ(x), MPQ(y));
return (PyObject*)result;
}
if (IS_RATIONAL(x) && IS_RATIONAL(y)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_Number(x, context)) ||
!(tempy = GMPy_MPQ_From_Number(y, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_add(result->q, tempx->q, tempy->q);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
SYSTEM_ERROR("Internal error in GMPy_Rational_Add().");
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Implement __add__ for Pympq. On entry, one of the two arguments must
* be a Pympq. If the other object is a Rational, add and return a Pympq.
* If the other object isn't a Pympq, call the appropriate function. If
* no appropriate function can be found, return NotImplemented. */
static PyObject *
GMPy_MPQ_Add_Slot(PyObject *x, PyObject *y)
{
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Add(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Add(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Add(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* Addition can be performed by the equivalent of mpfr.__add__ or by
* gmpy2.add().
*
* GMPy_Real_Add(x, y, context) returns x+y using the provided context. If
* provided context is NULL, then the current context is used. If an error
* occurs, NULL is returned and an exception is set. If either x or y can't
* be converted to an mpfr, then Py_NotImplemented is returned.
* GMPy_Real_Add() will not try to promote the result to a different type
* (i.e. mpc).
*
* GMPy_mpfr_add_fast(x, y) is the entry point for mpfr.__add__.
*/
/* Attempt to add two numbers and return an mpfr. The code path is optimized by
* checking for mpfr objects first. Returns Py_NotImplemented if both objects
* are not valid reals. */
static PyObject *
GMPy_Real_Add(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPFR_Check(x)) {
if (MPFR_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_add(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
goto done;
}
if (PyIntOrLong_Check(y)) {
int error;
long temp = GMPy_Integer_AsLongAndError(y, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_add_si(result->f, MPFR(x), temp, GET_MPFR_ROUND(context));
goto done;
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpfr_clear_flags();
result->rc = mpfr_add_z(result->f, MPFR(x), global.tempz, GET_MPFR_ROUND(context));
goto done;
}
}
if (CHECK_MPZANY(y)) {
mpfr_clear_flags();
result->rc = mpfr_add_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context));
goto done;
}
if (IS_RATIONAL(y)) {
MPQ_Object *tempy = NULL;
if (!(tempy = GMPy_MPQ_From_Number(y, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_add_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempy);
goto done;
}
if (PyFloat_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_add_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context));
goto done;
}
}
if (MPFR_Check(y)) {
if (PyIntOrLong_Check(x)) {
int error;
long temp = GMPy_Integer_AsLongAndError(x, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_add_si(result->f, MPFR(y), temp, GET_MPFR_ROUND(context));
goto done;
}
else {
mpz_set_PyIntOrLong(global.tempz, x);
mpfr_clear_flags();
result->rc = mpfr_add_z(result->f, MPFR(y), global.tempz, GET_MPFR_ROUND(context));
goto done;
}
}
if (CHECK_MPZANY(x)) {
mpfr_clear_flags();
result->rc = mpfr_add_z(result->f, MPFR(y), MPZ(x), GET_MPFR_ROUND(context));
goto done;
}
if (IS_RATIONAL(x)) {
MPQ_Object *tempx = NULL;
if (!(tempx = GMPy_MPQ_From_Number(x, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_add_q(result->f, MPFR(y), tempx->q, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
goto done;
}
if (PyFloat_Check(x)) {
mpfr_clear_flags();
result->rc = mpfr_add_d(result->f, MPFR(y), PyFloat_AS_DOUBLE(x), GET_MPFR_ROUND(context));
goto done;
}
}
if (IS_REAL(x) && IS_REAL(y)) {
MPFR_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context)) ||
!(tempy = GMPy_MPFR_From_Real(y, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_add(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
goto done;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
SYSTEM_ERROR("Internal error in GMPy_Real_Add().");
return NULL;
/* LCOV_EXCL_STOP */
done:
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* Implement __add__ for Pympfr. On entry, one of the two arguments must
* be a Pympfr. If the other object is a Real, add and return a Pympfr.
* If the other object isn't a Pympfr, call the appropriate function. If
* no appropriate function can be found, return NotImplemented. */
static PyObject *
GMPy_MPFR_Add_Slot(PyObject *x, PyObject *y)
{
if ((MPFR_Check(x)) && MPFR_Check(y)) {
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_add(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Add(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Add(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* GMPy_Complex_Add(x, y, context) returns x+y using the provided context. If
* context is NULL, then the current context is used. If an error occurs, NULL
* is returned and an exception is set. If either x or y can't be converted to
* an mpc, then Py_NotImplemented is returned. */
static PyObject *
GMPy_Complex_Add(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPC_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPC_Check(x) && MPC_Check(y)) {
result->rc = mpc_add(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_COMPLEX(x) && IS_COMPLEX(y)) {
MPC_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context)) ||
!(tempy = GMPy_MPC_From_Complex(y, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpc_add(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
SYSTEM_ERROR("Internal error in GMPy_Complex_Add().");
return NULL;
/* LCOV_EXCL_STOP */
}
/* GMPy_MPC_Add_Slot() is called by mpc.__add__. It just gets a borrowed reference
* to the current context and call Pympc_Add_Complex(). Since mpc is the last
* step of the numeric ladder, the NotImplemented return value from
* Pympc_Add_Complex() is correct and is just passed on. */
static PyObject *
GMPy_MPC_Add_Slot(PyObject *x, PyObject *y)
{
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Add(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Number_Add(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_Add(x, y, context);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Add(x, y, context);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Add(x, y, context);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Add(x, y, context);
TYPE_ERROR("add() argument type not supported");
return NULL;
}
/* Implement context.add() and gmpy2.add(). */
PyDoc_STRVAR(GMPy_doc_function_add,
"add(x, y) -> number\n\n"
"Return x + y.");
PyDoc_STRVAR(GMPy_doc_context_add,
"context.add(x, y) -> number\n\n"
"Return x + y.");
static PyObject *
GMPy_Context_Add(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("add() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Add(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
gmpy2-2.1.0b3/src/gmpy2_add.h 0000664 0001750 0001750 00000005640 13425751160 015466 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_add.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_ADD_H
#define GMPY2_ADD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Add(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_Add(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Rational_Add(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Real_Add(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_Add(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_MPZ_Add_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPQ_Add_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPFR_Add_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPC_Add_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_Add(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_binary.c 0000664 0001750 0001750 00000122341 13425751237 016220 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_binary.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Conversion routines between GMPY2 objects and a compact, portable
* binary representation. The binary format of GMPY2 is not compatible
* with GMPY 1.x. Methods to read the old format are provided.
*/
/* Provide functions to access the old binary formats. */
PyDoc_STRVAR(doc_mpz_from_old_binary,
"mpz_from_old_binary(string) -> mpz\n\n"
"Return an 'mpz' from a GMPY 1.x binary format.");
static PyObject *
GMPy_MPZ_From_Old_Binary(PyObject *self, PyObject *other)
{
unsigned char *cp;
Py_ssize_t len;
int negative = 0;
MPZ_Object *result;
if (!(PyBytes_Check(other))) {
TYPE_ERROR("mpz_from_old_binary() requires bytes argument");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
len = PyBytes_Size(other);
cp = (unsigned char*)PyBytes_AsString(other);
if (cp[len-1] == 0xFF) {
negative = 1;
--len;
}
mpz_import(result->z, len, -1, sizeof(char), 0, 0, cp);
if (negative)
mpz_neg(result->z, result->z);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpq_from_old_binary,
"mpq_from_old_binary(string) -> mpq\n\n"
"Return an 'mpq' from a GMPY 1.x binary format.");
static PyObject *
GMPy_MPQ_From_Old_Binary(PyObject *self, PyObject *other)
{
unsigned char *cp;
Py_ssize_t len;
int topper, negative, numlen;
mpz_t numerator, denominator;
MPQ_Object *result;
if (!(PyBytes_Check(other))) {
TYPE_ERROR("mpq_from_old_binary() requires bytes argument");
return NULL;
}
if (!(result = GMPy_MPQ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
len = PyBytes_Size(other);
cp = (unsigned char*)PyBytes_AsString(other);
if (len < 6) {
VALUE_ERROR("invalid mpq binary (too short)");
Py_DECREF((PyObject*)result);
return NULL;
}
topper = cp[3] & 0x7f;
negative = cp[3] & 0x80;
numlen = cp[0] + 256 * (cp[1] + 256 * (cp[2] + 256 * topper));
if (len < (4 + numlen + 1)) {
VALUE_ERROR("invalid mpq binary (num len)");
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_init(numerator);
mpz_init(denominator);
mpz_import(numerator, numlen, -1, sizeof(char), 0, 0, cp+4);
mpz_import(denominator, len-4-numlen, -1, sizeof(char), 0, 0, cp+4+numlen);
if (negative)
mpz_neg(numerator, numerator);
mpq_set_num(result->q, numerator);
mpq_set_den(result->q, denominator);
mpq_canonicalize(result->q);
mpz_clear(numerator);
mpz_clear(denominator);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpfr_from_old_binary,
"mpfr_from_old_binary(string) -> mpfr\n\n"
"Return an 'mpfr' from a GMPY 1.x binary mpf format.");
static PyObject *
GMPy_MPFR_From_Old_Binary(PyObject *self, PyObject *other)
{
unsigned char *cp;
Py_ssize_t len;
MPFR_Object *result;
mpfr_t digit;
mpfr_prec_t prec;
int i, codebyte, resusign, exposign, resuzero, precilen;
unsigned int expomag = 0;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(PyBytes_Check(other))) {
TYPE_ERROR("mpfr_from_old_binary() requires bytes argument");
return NULL;
}
len = PyBytes_Size(other);
cp = (unsigned char*)PyBytes_AsString(other);
if (len == 1) {
prec = 0;
}
else {
prec = (mpfr_prec_t)(8 * (len - 5));
if ((len>=5) && (cp[0]&8)) {
prec = 0;
for (i=4; i>0; --i) {
prec = (prec << 8) | cp[i];
}
}
}
/*
* binary format for MP floats: first, a code-byte, then, a LSB
* 4-byte unsigned int (exponent magnitude), then the "mantissa"
* (actually, "significand", but "mantissa" is the usual term...)
* in MSB form.
*
* The codebyte encodes both the signs, exponent and result, or
* also the zeroness of the result (in which case, nothing more).
*/
codebyte = cp[0];
resusign = codebyte & 1;
exposign = codebyte & 2;
resuzero = codebyte & 4;
precilen = (codebyte & 8)?4:0;
/* mpfr zero has a very compact (1-byte) binary encoding!-) */
if (resuzero) {
if (!(result = GMPy_MPFR_New(prec, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpfr_set_ui(result->f, 0, MPFR_RNDN);
return (PyObject*)result;
}
/* all other numbers are 6+ bytes: codebyte, 4-byte exp, 1+
* bytes for the mantissa; check this string is 6+ bytes
*/
if (len < 6 + precilen) {
VALUE_ERROR("invalid mpf binary encoding (too short)");
return NULL;
}
if (!(result = GMPy_MPFR_New(prec, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* reconstruct exponent */
for (i = 4 + precilen; i > precilen; --i) {
expomag = (expomag<<8) | cp[i];
}
/* reconstruct 'mantissa' (significand) */
mpfr_set_si(result->f, 0, MPFR_RNDN);
mpfr_init2(digit, prec);
for (i = 5 + precilen; ictx.mpfr_round);
mpfr_add(result->f, result->f, digit, MPFR_RNDN);
}
mpfr_clear(digit);
/* apply exponent, with its appropriate sign */
if (exposign)
mpfr_div_2ui(result->f, result->f, 8*expomag, MPFR_RNDN);
else
mpfr_mul_2ui(result->f, result->f, 8*expomag, MPFR_RNDN);
/* apply significand-sign (sign of the overall number) */
if (resusign)
mpfr_neg(result->f, result->f, MPFR_RNDN);
return (PyObject*)result;
}
/* Format of the binary representation of an mpz/xmpz.
*
* byte[0]: 1 => mpz
* 2 => xmpz
* 3 => mpq (see Pympq_To_Binary)
* 4 => mpfr (see Pympfr_To_Binary)
* 5 => mpc (see Pympc_To_Binary)
* byte[1:0-1]: 0 => value is 0
* 1 => value is > 0
* 2 => value is < 0
* 3 => unassigned
* byte[2]+: value
*/
static PyObject *
GMPy_MPZ_To_Binary(MPZ_Object *self)
{
size_t size = 2;
int sgn;
char *buffer;
PyObject *result;
sgn = mpz_sgn(self->z);
if (sgn == 0) {
TEMP_ALLOC(buffer, size);
buffer[0] = 0x01;
buffer[1] = 0x00;
goto done;
}
size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2;
TEMP_ALLOC(buffer, size);
buffer[0] = 0x01;
if (sgn > 0)
buffer[1] = 0x01;
else
buffer[1] = 0x02;
mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z);
done:
result = PyBytes_FromStringAndSize(buffer, size);
TEMP_FREE(buffer, size);
return result;
}
static PyObject *
GMPy_XMPZ_To_Binary(XMPZ_Object *self)
{
size_t size = 2;
int sgn;
char *buffer;
PyObject *result;
sgn = mpz_sgn(self->z);
if (sgn == 0) {
TEMP_ALLOC(buffer, size);
buffer[0] = 0x02;
buffer[1] = 0x00;
goto done;
}
size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2;
TEMP_ALLOC(buffer, size);
buffer[0] = 0x02;
if (sgn > 0)
buffer[1] = 0x01;
else
buffer[1] = 0x02;
mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z);
done:
result = PyBytes_FromStringAndSize(buffer, size);
TEMP_FREE(buffer, size);
return result;
}
/* Format of the binary representation of an mpq.
*
* byte[0]: 1 => mpz (see Pympz_To_Binary)
* 2 => xmpz (see Pyxmpz_To_Binary)
* 3 => mpq
* 4 => mpfr (see Pympfr_To_Binary)
* 5 => mpc (see Pympc_To_Binary)
* byte[1:0-1]: 0 => value is 0
* 1 => value is > 0
* 2 => value is < 0
* 3 => unassigned
* byte[1:2-2]: 0 => 32-bit length (n=4)
* 1 => 64-bit length (n=8)
* byte[2+]: numerator length, using either 4 or 8 bytes
* byte[2+n]+: numerator, followed by denominator
*/
static PyObject *
GMPy_MPQ_To_Binary(MPQ_Object *self)
{
size_t sizenum, sizeden, sizesize = 4, size = 2, sizetemp, i;
size_t count = 0;
int sgn;
char *buffer, large = 0x00;
PyObject *result = 0;
sgn = mpq_sgn(self->q);
if (sgn == 0) {
TEMP_ALLOC(buffer, size);
buffer[0] = 0x03;
buffer[1] = 0x00;
goto done;
}
sizenum = (mpz_sizeinbase(mpq_numref(self->q), 2) + 7) / 8;
sizeden = (mpz_sizeinbase(mpq_denref(self->q), 2) + 7) / 8;
size = sizenum + sizeden + 2;
/* Check if sizenum larger than 32 bits. */
if ((sizenum >> 16) >> 16) {
/* Current versions of GMP do not allow values to be this large. The
* test is left to (possibly) support future versions that support
* larger values.
*/
/* LCOV_EXCL_START */
large = 0x04;
sizesize = 8;
/* LCOV_EXCL_STOP */
}
size += sizesize;
TEMP_ALLOC(buffer, size);
buffer[0] = 0x03;
if (sgn > 0)
buffer[1] = 0x01 | large;
else
buffer[1] = 0x02 | large;
/* Copy sizenum to the buffer. */
sizetemp = sizenum;
for (i=0; i>= 8;
}
mpz_export(buffer+sizesize+2, &count, -1,
sizeof(char), 0, 0, mpq_numref(self->q));
if (count != sizenum) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("internal error in Pympq_To_Binary");
TEMP_FREE(buffer, size);
return NULL;
/* LCOV_EXCL_STOP */
}
count = 0;
mpz_export(buffer+sizenum+sizesize+2, &count, -1,
sizeof(char), 0, 0, mpq_denref(self->q));
if (count != sizeden) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("internal error in Pympq_To_Binary");
TEMP_FREE(buffer, size);
return NULL;
/* LCOV_EXCL_STOP */
}
done:
result = PyBytes_FromStringAndSize(buffer, size);
TEMP_FREE(buffer, size);
return result;
}
/* Format of the binary representation of an mpfr.
*
* byte[0]: 1 => mpz (see Pympz_To_Binary)
* 2 => xmpz (see Pyxmpz_To_Binary)
* 3 => mpq (see Pympq_To_Binary)
* 4 => mpfr
* 5 => mpc (see Pympc_To_Binary)
* byte[1:0]: 0 => value is "special"
* 1 => value is an actual number
* byte[1:1]: 0 => signbit is clear
* 1 => signbit is set
* byte[1:2-2]: 0 => 32-bit lengths (n=4)
* 1 => 64-bit lengths (n=8)
* byte[1:3-4]: 0 => 0 (see signbit)
* 1 => value is NaN
* 2 => value is Inf (see signbit)
* 3 => unassigned
* byte[1:5]: 0 => exponent is positive
* 1 => exponent is negative
* byte[1:6]: 0 => 4 byte limbs
* 1 => 8 byte limbs
* byte[2]: 0 => rc = 0
* 1 => rc > 0
* 2 => rc < 0
* byte[3]: mpfr.round_mode
* byte[4]+: precision, saved in 4 or 8 bytes
* byte[4+n]+: exponent, saved in 4 or 8 bytes
* byte[4+2n]+: mantissa
*/
static PyObject *
GMPy_MPFR_To_Binary(MPFR_Object *self)
{
size_t sizemant = 0, sizesize = 4, size = 4, sizetemp, i;
mp_limb_t templimb;
mpfr_prec_t precision;
mpfr_exp_t exponent = 0;
int sgn;
char *buffer, *cp, large = 0x00, expsgn = 0x00;
PyObject *result = 0;
/* Check if the precision, exponent and mantissa length can fit in
* 32 bits.
*/
sgn = mpfr_signbit(self->f);
precision = mpfr_get_prec(self->f);
/* Exponent and mantiss are only valid for regular numbers
* (not 0, Nan, Inf, -Inf).
*/
if (mpfr_regular_p(self->f)) {
exponent = self->f->_mpfr_exp;
if (exponent < 0) {
exponent = -exponent;
expsgn = 0x20;
}
/* Calculate the size of mantissa in limbs */
sizemant = (self->f->_mpfr_prec + mp_bits_per_limb - 1)/mp_bits_per_limb;
}
if (((exponent >> 16) >> 16) ||
((precision >> 16) >> 16) ||
((sizemant >> 16) >> 16)) {
/* This can only be tested on 64-bit platforms. lcov will report the
* code as not tested until 64-bit specific tests are created.
*/
sizesize = 8;
large = 0x04;
}
if (!mpfr_regular_p(self->f)) {
/* Only need to save the precision. */
size += sizesize;
TEMP_ALLOC(buffer, size);
buffer[0] = 0x04;
/* Set to all 0 since we are special. */
buffer[1] = 0x00;
/* Set the sign bit. */
if (sgn) buffer[1] |= 0x02;
/* 4 or 8 byte values. */
buffer[1] |= large;
/* Check if NaN. */
if (mpfr_nan_p(self->f)) buffer[1] |= 0x08;
/* Check if Infinity. */
if (mpfr_inf_p(self->f)) buffer[1] |= 0x10;
/* Save the result code */
if (self->rc == 0) buffer[2] = 0x00;
else if (self->rc > 0) buffer[2] = 0x01;
else buffer[2] = 0x02;
/* Save the precision */
sizetemp = precision;
for (i=0; i>= 8;
}
goto done;
}
/* Now process all actual numbers. */
size += (2 * sizesize) + (sizemant * (mp_bits_per_limb >> 3));
TEMP_ALLOC(buffer, size);
buffer[0] = 0x04;
/* Set bit 0 to 1 since we are an actual number. */
buffer[1] = 0x01;
/* Save the sign bit. */
if (sgn) buffer[1] |= 0x02;
/* Save the size of the values. */
buffer[1] |= large;
/* Save the exponent sign. */
buffer[1] |= expsgn;
/* Save the limb size. */
if ((mp_bits_per_limb >> 3) == 8)
buffer[1] |= 0x40;
/* This branch can only be reached on 32-bit platforms. */
else if ((mp_bits_per_limb >> 3) != 4) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("cannot support current limb size");
TEMP_FREE(buffer, size);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Save the result code. */
if (self->rc == 0) buffer[2] = 0x00;
else if (self->rc > 0) buffer[2] = 0x01;
else buffer[2] = 0x02;
/* Rounding mode is no longer used, so just store a null byte. */
buffer[3] = 0x00;
/* Save the precision */
cp = buffer + 4;
sizetemp = precision;
for (i=0; i>= 8;
}
/* Save the exponenet */
cp += sizesize;
sizetemp = exponent;
for (i=0; i>= 8;
}
/* Save the actual mantissa */
cp += sizesize;
for (i=0; if->_mpfr_d[i];
#if GMP_LIMB_BITS == 64
cp[0] = (char)(templimb & 0xff);
templimb >>= 8;
cp[1] = (char)(templimb & 0xff);
templimb >>= 8;
cp[2] = (char)(templimb & 0xff);
templimb >>= 8;
cp[3] = (char)(templimb & 0xff);
templimb >>= 8;
cp[4] = (char)(templimb & 0xff);
templimb >>= 8;
cp[5] = (char)(templimb & 0xff);
templimb >>= 8;
cp[6] = (char)(templimb & 0xff);
templimb >>= 8;
cp[7] = (char)(templimb & 0xff);
cp += 8;
#endif
#if GMP_LIMB_BITS == 32
cp[0] = (char)(templimb & 0xff);
templimb >>= 8;
cp[1] = (char)(templimb & 0xff);
templimb >>= 8;
cp[2] = (char)(templimb & 0xff);
templimb >>= 8;
cp[3] = (char)(templimb & 0xff);
cp += 4;
#endif
}
done:
result = PyBytes_FromStringAndSize(buffer, size);
TEMP_FREE(buffer, size);
return result;
}
/* Format of the binary representation of an mpc.
*
* The format consists of the concatenation of mpfrs (real and imaginary)
* converted to binary format. The 0x04 leading byte of each binary string
* is replaced by 0x05.
*/
static PyObject *
GMPy_MPC_To_Binary(MPC_Object *obj)
{
MPFR_Object *real = NULL, *imag = NULL;
PyObject *result = NULL, *temp = NULL;
mpfr_prec_t rprec = 0, iprec = 0;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
mpc_get_prec2(&rprec, &iprec, obj->c);
if (!(real = GMPy_MPFR_New(rprec, context)) ||
!(imag = GMPy_MPFR_New(iprec, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)real);
Py_XDECREF((PyObject*)imag);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_set(real->f, mpc_realref(obj->c), MPFR_RNDN);
mpfr_set(imag->f, mpc_imagref(obj->c), MPFR_RNDN);
real->rc = obj->rc;
if (!(result = GMPy_MPFR_To_Binary(real)) ||
!(temp = GMPy_MPFR_To_Binary(imag))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)temp);
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
PyBytes_AS_STRING(result)[0] = 0x05;
PyBytes_AS_STRING(temp)[0] = 0x05;
PyBytes_ConcatAndDel(&result, temp);
return result;
}
PyDoc_STRVAR(doc_from_binary,
"from_binary(bytes) -> gmpy2 object\n"
"Return a Python object from a byte sequence created by\n"
"gmpy2.to_binary().");
static PyObject *
GMPy_MPANY_From_Binary(PyObject *self, PyObject *other)
{
unsigned char *buffer, *cp;
Py_ssize_t len;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(PyBytes_Check(other))) {
TYPE_ERROR("from_binary() requires bytes argument");
return NULL;
}
len = PyBytes_Size(other);
if (len < 2) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
buffer = (unsigned char*)PyBytes_AsString(other);
cp = buffer;
switch (cp[0]) {
case 0x01: {
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[1] == 0x00) {
mpz_set_ui(result->z, 0);
return (PyObject*)result;
}
mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2);
if (cp[1] == 0x02)
mpz_neg(result->z, result->z);
return (PyObject*)result;
break;
}
case 0x02: {
XMPZ_Object *result;
if (!(result = GMPy_XMPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[1] == 0x00) {
mpz_set_ui(result->z, 0);
return (PyObject*)result;
}
mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2);
if (cp[1] == 0x02)
mpz_neg(result->z, result->z);
return (PyObject*)result;
break;
}
case 0x03: {
MPQ_Object *result;
Py_ssize_t numlen = 0, sizesize = 4, i;
mpz_t num, den;
if (!(result = GMPy_MPQ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[1] == 0x00) {
mpq_set_ui(result->q, 0, 1);
return (PyObject*)result;
}
if (cp[1] & 0x04)
sizesize = 8;
if (len < 2 + sizesize) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
for (i=sizesize; i>0; --i) {
numlen = (numlen << 8) + cp[i+1];
}
if (len < 2 + sizesize + numlen + 1) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
mpz_init(num);
mpz_init(den);
mpz_import(num, numlen, -1,
sizeof(char), 0, 0, cp+sizesize+2);
mpz_import(den, len-numlen-sizesize-2, -1,
sizeof(char), 0, 0, cp+sizesize+numlen+2);
mpq_set_num(result->q, num);
mpq_set_den(result->q, den);
mpq_canonicalize(result->q);
mpz_clear(num);
mpz_clear(den);
if (cp[1] == 0x02)
mpq_neg(result->q, result->q);
return (PyObject*)result;
break;
}
case 0x04: {
MPFR_Object *result;
Py_ssize_t sizemant = 0, sizesize = 4, i, newmant;
mpfr_prec_t precision = 0;
mpfr_exp_t exponent = 0;
mp_limb_t templimb;
int sgn = 1, expsgn = 1, limbsize = 4;
int newlimbsize = (mp_bits_per_limb >> 3);
if (len < 4) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
/* Get size of values. */
if (cp[1] & 0x04) sizesize = 8;
/* Get the original precision. */
for (i=sizesize; i>0; --i) {
precision = (precision << 8) + cp[i+3];
}
/* Get the original sign bit. */
if (cp[1] & 0x02) sgn = -1;
/* Get the original exponent sign. */
if (cp[1] & 0x20) expsgn = -1;
/* Get the limb size of the originating system. */
if (cp[1] & 0x40) limbsize = 8;
if (!(result = GMPy_MPFR_New(precision, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* Restore the original result code and rounding mode. */
/* Get the original result code. */
if (cp[2] == 0) result->rc = 0;
else if (cp[2] == 1) result->rc = 1;
else result->rc = -1;
if (!(cp[1] & 0x01)) {
/* Process special numbers. */
if ((cp[1] & 0x18) == 0x00)
mpfr_set_zero(result->f, sgn);
else if ((cp[1] & 0x18) == 0x08)
mpfr_set_nan(result->f);
else
mpfr_set_inf(result->f, sgn);
return (PyObject*)result;
}
/* Process actual numbers. */
/* Calculate the number of limbs on the original system. */
if (limbsize == 8) sizemant = ((precision + 63) / 64);
else sizemant = ((precision + 31) / 32);
/* Calculate the number of limbs on the current system. */
newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb;
/* Get the original exponent. */
cp = buffer + 4 + sizesize - 1;
for (i=sizesize; i>0; --i) {
exponent = (exponent << 8) + cp[i];
}
if (len < 2 + sizesize) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
/* Check if the mantissa occupies the same number of bytes
* on both the source and target system. */
if (limbsize * sizemant == newmant * newlimbsize) {
mpfr_set_ui(result->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize);
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
result->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(result->f, result->f, MPFR_RNDN);
return (PyObject*)result;
}
else if (limbsize * sizemant > newmant * newlimbsize) {
/* Since the amount of saved data is greater than the amount of
* data needed on the new system, we skip the first 32 bits
* since they must be 0.
*/
/* Verify we are on a 32-bit system and the source was 64-bit. */
if ((limbsize == 8) && (newlimbsize == 4)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
return NULL;
}
mpfr_set_ui(result->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize) + 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
result->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(result->f, result->f, MPFR_RNDN);
return (PyObject*)result;
}
else {
/* Since the amount of saved data is less than the amount of
* data needed on the new system, we must "add" 32 0-bits at
* the low end.
*/
/* Verify we are on a 64-bit system and the source was 32-bit. */
if ((limbsize == 4) && (newlimbsize == 8)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
return NULL;
}
mpfr_set_ui(result->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize);
templimb = cp[3];
templimb = (templimb << 8) + cp[2];
templimb = (templimb << 8) + cp[1];
templimb = (templimb << 8) + cp[0];
result->f->_mpfr_d[i] = ((templimb << 16) << 16);
cp += 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
result->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(result->f, result->f, MPFR_RNDN);
return (PyObject*)result;
}
}
case 0x05: {
MPC_Object *result;
MPFR_Object *real = 0, *imag = 0;
Py_ssize_t sizemant = 0, sizesize = 4, i, newmant;
mpfr_prec_t precision = 0;
mpfr_exp_t exponent = 0;
mp_limb_t templimb;
int sgn = 1, expsgn = 1, limbsize = 4;
int newlimbsize = (mp_bits_per_limb >> 3);
unsigned char *tempbuf;
if (len < 4) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
/* read the real part first */
if (cp[1] & 0x04) sizesize = 8;
for (i=sizesize; i>0; --i) {
precision = (precision << 8) + cp[i+3];
}
if (cp[1] & 0x02) sgn = -1;
if (cp[1] & 0x20) expsgn = -1;
if (cp[1] & 0x40) limbsize = 8;
if (!(real = GMPy_MPFR_New(precision, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[2] == 0) real->rc = 0;
else if (cp[2] == 1) real->rc = 1;
else real->rc = -1;
if (!(cp[1] & 0x01)) {
if ((cp[1] & 0x18) == 0x00)
mpfr_set_zero(real->f, sgn);
else if ((cp[1] & 0x18) == 0x08)
mpfr_set_nan(real->f);
else
mpfr_set_inf(real->f, sgn);
cp += 4 + sizesize;
goto readimag;
}
if (limbsize == 8) sizemant = ((precision + 63) / 64);
else sizemant = ((precision + 31) / 32);
newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb;
cp = buffer + 4 + sizesize - 1;
for (i=sizesize; i>0; --i) {
exponent = (exponent << 8) + cp[i];
}
if (limbsize * sizemant == newmant * newlimbsize) {
mpfr_set_ui(real->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize);
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
real->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(real->f, real->f, MPFR_RNDN);
}
else if (limbsize * sizemant > newmant * newlimbsize) {
if ((limbsize == 8) && (newlimbsize == 4)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
return NULL;
}
mpfr_set_ui(real->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize) + 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
real->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(real->f, real->f, MPFR_RNDN);
}
else {
if ((limbsize == 4) && (newlimbsize == 8)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
return NULL;
}
mpfr_set_ui(real->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize);
templimb = cp[3];
templimb = (templimb << 8) + cp[2];
templimb = (templimb << 8) + cp[1];
templimb = (templimb << 8) + cp[0];
real->f->_mpfr_d[i] = ((templimb << 16) << 16);
cp += 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
real->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(real->f, real->f, MPFR_RNDN);
}
readimag:
/* Set all the variables back to default. */
tempbuf = cp;
sizemant = 0;
sizesize = 4;
precision = 0;
exponent = 0;
sgn = 1;
expsgn = 1;
limbsize = 4;
/* Done reading the real part. The next byte should be 0x05. */
if (!(cp[0] == 0x05)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
return NULL;
}
if (cp[1] & 0x04) sizesize = 8;
for (i=sizesize; i>0; --i) {
precision = (precision << 8) + cp[i+3];
}
if (cp[1] & 0x02) sgn = -1;
if (cp[1] & 0x20) expsgn = -1;
if (cp[1] & 0x40) limbsize = 8;
if (!(imag = GMPy_MPFR_New(precision, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)real);
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[2] == 0) imag->rc = 0;
else if (cp[2] == 1) imag->rc = 1;
else imag->rc = -1;
if (!(cp[1] & 0x01)) {
if ((cp[1] & 0x18) == 0x00)
mpfr_set_zero(imag->f, sgn);
else if ((cp[1] & 0x18) == 0x08)
mpfr_set_nan(imag->f);
else
mpfr_set_inf(imag->f, sgn);
goto alldone;
}
if (limbsize == 8) sizemant = ((precision + 63) / 64);
else sizemant = ((precision + 31) / 32);
newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb;
cp = tempbuf + 4 + sizesize - 1;
for (i=sizesize; i>0; --i) {
exponent = (exponent << 8) + cp[i];
}
if (limbsize * sizemant == newmant * newlimbsize) {
mpfr_set_ui(imag->f, 1, MPFR_RNDN);
cp = tempbuf + 4 + (2 * sizesize);
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
imag->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(imag->f, imag->f, MPFR_RNDN);
}
else if (limbsize * sizemant > newmant * newlimbsize) {
if ((limbsize == 8) && (newlimbsize == 4)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return NULL;
}
mpfr_set_ui(imag->f, 1, MPFR_RNDN);
cp = tempbuf + 4 + (2 * sizesize) + 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
imag->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(imag->f, imag->f, MPFR_RNDN);
}
else {
if ((limbsize == 4) && (newlimbsize == 8)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return NULL;
}
mpfr_set_ui(imag->f, 1, MPFR_RNDN);
cp = tempbuf + 4 + (2 * sizesize);
templimb = cp[3];
templimb = (templimb << 8) + cp[2];
templimb = (templimb << 8) + cp[1];
templimb = (templimb << 8) + cp[0];
imag->f->_mpfr_d[i] = ((templimb << 16) << 16);
cp += 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
imag->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(imag->f, imag->f, MPFR_RNDN);
}
alldone:
if (!(result = (MPC_Object*)GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_swap(mpc_realref(result->c), real->f);
mpfr_swap(mpc_imagref(result->c), imag->f);
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return (PyObject*)result;
}
default: {
TYPE_ERROR("from_binary() argument type not supported");
return NULL;
}
}
}
PyDoc_STRVAR(doc_to_binary,
"to_binary(x) -> bytes\n"
"Return a Python byte sequence that is a portable binary\n"
"representation of a gmpy2 object x. The byte sequence can\n"
"be passed to gmpy2.from_binary() to obtain an exact copy of\n"
"x's value. Works with mpz, xmpz, mpq, mpfr, and mpc types. \n"
"Raises TypeError if x is not a gmpy2 object.");
static PyObject *
GMPy_MPANY_To_Binary(PyObject *self, PyObject *other)
{
if(MPZ_Check(other))
return GMPy_MPZ_To_Binary((MPZ_Object*)other);
else if(XMPZ_Check(other))
return GMPy_XMPZ_To_Binary((XMPZ_Object*)other);
else if(MPQ_Check(other))
return GMPy_MPQ_To_Binary((MPQ_Object*)other);
else if(MPFR_Check(other))
return GMPy_MPFR_To_Binary((MPFR_Object*)other);
else if(MPC_Check(other))
return GMPy_MPC_To_Binary((MPC_Object*)other);
TYPE_ERROR("to_binary() argument type not supported");
return NULL;
}
gmpy2-2.1.0b3/src/gmpy2_binary.h 0000664 0001750 0001750 00000006004 13425751304 016215 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_binary.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_BINARY_H
#define GMPY_BINARY_H
#ifdef __cplusplus
extern "C" {
#endif
/* Conversion routines between GMPY2 objects and a compact, portable
* binary representation. The binary format of GMPY2 is not compatible
* with GMPY 1.x. Methods to read the old format are provided.
*/
static PyObject * GMPy_MPZ_From_Old_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_From_Old_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_From_Old_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPANY_From_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPANY_To_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_To_Binary(MPZ_Object *self);
static PyObject * GMPy_XMPZ_To_Binary(XMPZ_Object *self);
static PyObject * GMPy_MPQ_To_Binary(MPQ_Object *self);
static PyObject * GMPy_MPFR_To_Binary(MPFR_Object *self);
static PyObject * GMPy_MPC_To_Binary(MPC_Object *self);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_cache.c 0000664 0001750 0001750 00000073440 13461370120 015770 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_cache.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* gmpy2 caches objects so they can be reused quickly without involving a new
* memory allocation or object construction.
*
* The "py???cache" is used to cache Py??? objects. The cache is accessed
* via Py???_new/Py???_dealloc. The functions set_py???cache and
* set_py???cache are used to change the size of the array used to the store
* the cached objects.
*/
/* Caching logic for Pympz. */
static void
set_gmpympzcache(void)
{
if (global.in_gmpympzcache > global.cache_size) {
int i;
for (i = global.cache_size; i < global.in_gmpympzcache; ++i) {
mpz_clear(global.gmpympzcache[i]->z);
PyObject_Del(global.gmpympzcache[i]);
}
global.in_gmpympzcache = global.cache_size;
}
global.gmpympzcache = realloc(global.gmpympzcache, sizeof(MPZ_Object)*global.cache_size);
}
/* GMPy_MPZ_New returns a reference to a new MPZ_Object. Its value
* is initialized to 0.
*/
static MPZ_Object *
GMPy_MPZ_New(CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (global.in_gmpympzcache) {
result = global.gmpympzcache[--(global.in_gmpympzcache)];
/* Py_INCREF does not set the debugging pointers, so need to use
* _Py_NewReference instead. */
_Py_NewReference((PyObject*)result);
mpz_set_ui(result->z, 0);
result->hash_cache = -1;
}
else {
if ((result = PyObject_New(MPZ_Object, &MPZ_Type))) {
mpz_init(result->z);
result->hash_cache = -1;
}
}
return result;
}
/* GMPy_MPZ_NewInit returns a reference to an initialized MPZ_Object. It is
* used by mpz.__new__ to replace the old mpz() factory function.
*/
static PyObject *
GMPy_MPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
MPZ_Object *result = NULL;
PyObject *n = NULL;
PyObject *temp = NULL;
PyObject *out = NULL;
int base = 0;
Py_ssize_t argc;
static char *kwlist[] = {"s", "base", NULL };
CTXT_Object *context = NULL;
if (type != &MPZ_Type) {
TYPE_ERROR("mpz.__new__() requires mpz type");
return NULL;
}
/* Optimize the most common use cases first; either 0 or 1 argument */
argc = PyTuple_GET_SIZE(args);
if (argc == 0) {
return (PyObject*)GMPy_MPZ_New(context);
}
if (argc == 1 && !keywds) {
n = PyTuple_GET_ITEM(args, 0);
if (MPZ_Check(n)) {
Py_INCREF(n);
return n;
}
if (PyIntOrLong_Check(n)) {
return (PyObject*)GMPy_MPZ_From_PyIntOrLong(n, context);
}
if (MPQ_Check(n)) {
return (PyObject*)GMPy_MPZ_From_MPQ((MPQ_Object*)n, context);
}
if (MPFR_Check(n)) {
return (PyObject*)GMPy_MPZ_From_MPFR((MPFR_Object*)n, context);
}
if (PyFloat_Check(n)) {
return (PyObject*)GMPy_MPZ_From_PyFloat(n, context);
}
if (XMPZ_Check(n)) {
return (PyObject*)GMPy_MPZ_From_XMPZ((XMPZ_Object*)n, context);
}
if (IS_FRACTION(n)) {
MPQ_Object *temp = GMPy_MPQ_From_Fraction(n, context);
if (temp) {
result = GMPy_MPZ_From_MPQ(temp, context);
Py_DECREF((PyObject*)temp);
}
return (PyObject*)result;
}
if (PyStrOrUnicode_Check(n)) {
return (PyObject*)GMPy_MPZ_From_PyStr(n, base, context);
}
if (HAS_MPZ_CONVERSION(n)) {
out = (PyObject *) PyObject_CallMethod(n, "__mpz__", NULL);
if (out == NULL)
return out;
if (!MPZ_Check(out)) {
PyErr_Format(PyExc_TypeError,
"object of type '%.200s' can not be interpreted as mpz",
out->ob_type->tp_name);
Py_DECREF(out);
return NULL;
}
return out;
}
/* Try converting to integer. */
temp = PyNumber_Long(n);
if (temp) {
result = GMPy_MPZ_From_PyIntOrLong(temp, context);
Py_DECREF(temp);
return (PyObject*)result;
}
TYPE_ERROR("mpz() requires numeric or string argument");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) {
return NULL;
}
if ((base != 0) && ((base < 2)|| (base > 62))) {
VALUE_ERROR("base for mpz() must be 0 or in the interval [2, 62]");
return NULL;
}
if (PyStrOrUnicode_Check(n)) {
return (PyObject*)GMPy_MPZ_From_PyStr(n, base, context);
}
if (IS_REAL(n)) {
TYPE_ERROR("mpz() with number argument only takes 1 argument");
}
else {
TYPE_ERROR("mpz() requires numeric or string (and optional base) arguments");
}
return NULL;
}
static void
GMPy_MPZ_Dealloc(MPZ_Object *self)
{
if (global.in_gmpympzcache < global.cache_size &&
self->z->_mp_alloc <= global.cache_obsize) {
global.gmpympzcache[(global.in_gmpympzcache)++] = self;
}
else {
mpz_clear(self->z);
PyObject_Del(self);
}
}
/* Caching logic for Pyxmpz. */
static void
set_gmpyxmpzcache(void)
{
if (global.in_gmpyxmpzcache > global.cache_size) {
int i;
for (i = global.cache_size; i < global.in_gmpyxmpzcache; ++i) {
mpz_clear(global.gmpyxmpzcache[i]->z);
PyObject_Del(global.gmpyxmpzcache[i]);
}
global.in_gmpyxmpzcache = global.cache_size;
}
global.gmpyxmpzcache = realloc(global.gmpyxmpzcache, sizeof(XMPZ_Object)*global.cache_size);
}
static XMPZ_Object *
GMPy_XMPZ_New(CTXT_Object *context)
{
XMPZ_Object *result = NULL;
if (global.in_gmpyxmpzcache) {
result = global.gmpyxmpzcache[--(global.in_gmpyxmpzcache)];
/* Py_INCREF does not set the debugging pointers, so need to use
* _Py_NewReference instead. */
_Py_NewReference((PyObject*)result);
mpz_set_ui(result->z, 0);
}
else {
if ((result = PyObject_New(XMPZ_Object, &XMPZ_Type))) {
mpz_init(result->z);
}
}
return result;
}
static PyObject *
GMPy_XMPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
XMPZ_Object *result = NULL;
PyObject *n = NULL;
PyObject *temp = NULL;
int base = 0;
Py_ssize_t argc;
static char *kwlist[] = {"s", "base", NULL };
CTXT_Object *context = NULL;
if (type != &XMPZ_Type) {
TYPE_ERROR("xmpz.__new__() requires xmpz type");
return NULL;
}
/* Optimize the most common use cases first; either 0 or 1 argument */
argc = PyTuple_GET_SIZE(args);
if (argc == 0) {
return (PyObject*)GMPy_XMPZ_New(context);
}
if (argc == 1 && !keywds) {
n = PyTuple_GET_ITEM(args, 0);
if (XMPZ_Check(n)) {
Py_INCREF(n);
return n;
}
if (PyIntOrLong_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_PyIntOrLong(n, context);
}
if (MPQ_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_MPQ((MPQ_Object*)n, context);
}
if (MPFR_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_MPFR((MPFR_Object*)n, context);
}
if (PyFloat_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_PyFloat(n, context);
}
if (MPZ_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_MPZ((MPZ_Object*)n, context);
}
if (IS_FRACTION(n)) {
MPQ_Object *temp = GMPy_MPQ_From_Fraction(n, context);
if (temp) {
result = GMPy_XMPZ_From_MPQ(temp, context);
Py_DECREF((PyObject*)temp);
}
return (PyObject*)result;
}
if (PyStrOrUnicode_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_PyStr(n, base, context);
}
/* Try converting to integer. */
temp = PyNumber_Long(n);
if (temp) {
result = GMPy_XMPZ_From_PyIntOrLong(temp, context);
Py_DECREF(temp);
return (PyObject*)result;
}
TYPE_ERROR("xmpz() requires numeric or string argument");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) {
return NULL;
}
if ((base != 0) && ((base < 2)|| (base > 62))) {
VALUE_ERROR("base for xmpz() must be 0 or in the interval [2, 62]");
return NULL;
}
if (PyStrOrUnicode_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_PyStr(n, base, context);
}
if (IS_REAL(n)) {
TYPE_ERROR("xmpz() with number argument only takes 1 argument");
}
else {
TYPE_ERROR("xmpz() requires numeric or string (and optional base) arguments");
}
return NULL;
}
static void
GMPy_XMPZ_Dealloc(XMPZ_Object *obj)
{
if (global.in_gmpyxmpzcache < global.cache_size &&
obj->z->_mp_alloc <= global.cache_obsize) {
global.gmpyxmpzcache[(global.in_gmpyxmpzcache)++] = obj;
}
else {
mpz_clear(obj->z);
PyObject_Del((PyObject*)obj);
}
}
/* Caching logic for Pympq. */
static void
set_gmpympqcache(void)
{
if (global.in_gmpympqcache > global.cache_size) {
int i;
for (i = global.cache_size; i < global.in_gmpympqcache; ++i) {
mpq_clear(global.gmpympqcache[i]->q);
PyObject_Del(global.gmpympqcache[i]);
}
global.in_gmpympqcache = global.cache_size;
}
global.gmpympqcache = realloc(global.gmpympqcache, sizeof(MPQ_Object)*global.cache_size);
}
static MPQ_Object *
GMPy_MPQ_New(CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (global.in_gmpympqcache) {
result = global.gmpympqcache[--(global.in_gmpympqcache)];
/* Py_INCREF does not set the debugging pointers, so need to use
_Py_NewReference instead. */
_Py_NewReference((PyObject*)result);
}
else {
if (!(result = PyObject_New(MPQ_Object, &MPQ_Type))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_init(result->q);
}
result->hash_cache = -1;
return result;
}
static PyObject *
GMPy_MPQ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
MPQ_Object *result = NULL, *temp = NULL;
PyObject *n = NULL, *m = NULL;
PyObject *out = NULL;
int base = 10;
Py_ssize_t argc, keywdc = 0;
static char *kwlist[] = {"s", "base", NULL };
CTXT_Object *context = NULL;
if (type != &MPQ_Type) {
TYPE_ERROR("mpq.__new__() requires mpq type");
return NULL;
}
argc = PyTuple_Size(args);
if (keywds) {
keywdc = PyDict_Size(keywds);
}
if (argc + keywdc > 2) {
TYPE_ERROR("mpq() takes at most 2 arguments");
return NULL;
}
if (argc + keywdc == 0) {
if ((result = GMPy_MPQ_New(context))) {
mpq_set_ui(result->q, 0, 1);
}
return (PyObject*)result;
}
if (argc == 0) {
TYPE_ERROR("mpq() requires at least one non-keyword argument");
return NULL;
}
n = PyTuple_GetItem(args, 0);
/* Handle the case where the first argument is a string. */
if (PyStrOrUnicode_Check(n)) {
/* keyword base is legal */
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base))) {
return NULL;
}
}
if ((base != 0) && ((base < 2) || (base > 62))) {
VALUE_ERROR("base for mpq() must be 0 or in the interval [2, 62]");
return NULL;
}
return (PyObject*)GMPy_MPQ_From_PyStr(n, base, context);
}
/* Handle 1 argument. It must be non-complex number or an object with a __mpq__ method. */
if (argc == 1) {
if (IS_REAL(n)) {
return (PyObject *) GMPy_MPQ_From_Number(n, context);
}
if (HAS_MPQ_CONVERSION(n)) {
out = (PyObject *) PyObject_CallMethod(n, "__mpq__", NULL);
if (out == NULL)
return out;
if (!MPQ_Check(out)) {
PyErr_Format(PyExc_TypeError,
"object of type '%.200s' can not be interpreted as mpq",
out->ob_type->tp_name);
Py_DECREF(out);
return NULL;
}
return out;
}
}
/* Handle 2 arguments. Both arguments must be integer or rational. */
if (argc == 2) {
m = PyTuple_GetItem(args, 1);
if (IS_RATIONAL(n) && IS_RATIONAL(m)) {
result = GMPy_MPQ_From_Number(n, context);
temp = GMPy_MPQ_From_Number(m, context);
if (!result || !temp) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)temp);
return NULL;
}
if (mpq_sgn(temp->q) == 0) {
ZERO_ERROR("zero denominator in mpq()");
Py_DECREF((PyObject*)result);
Py_DECREF((PyObject*)temp);
return NULL;
}
mpq_div(result->q, result->q, temp->q);
Py_DECREF((PyObject*)temp);
return (PyObject*)result;
}
}
TYPE_ERROR("mpq() requires numeric or string argument");
return NULL;
}
static void
GMPy_MPQ_Dealloc(MPQ_Object *self)
{
if (global.in_gmpympqcacheq)->_mp_alloc <= global.cache_obsize &&
mpq_denref(self->q)->_mp_alloc <= global.cache_obsize) {
global.gmpympqcache[(global.in_gmpympqcache)++] = self;
}
else {
mpq_clear(self->q);
PyObject_Del(self);
}
}
/* Caching logic for Pympfr. */
static void
set_gmpympfrcache(void)
{
if (global.in_gmpympfrcache > global.cache_size) {
int i;
for (i = global.cache_size; i < global.in_gmpympfrcache; ++i) {
mpfr_clear(global.gmpympfrcache[i]->f);
PyObject_Del(global.gmpympfrcache[i]);
}
global.in_gmpympfrcache = global.cache_size;
}
global.gmpympfrcache = realloc(global.gmpympfrcache, sizeof(MPFR_Object)*global.cache_size);
}
static MPFR_Object *
GMPy_MPFR_New(mpfr_prec_t bits, CTXT_Object *context)
{
MPFR_Object *result;
if (bits < 2) {
CHECK_CONTEXT(context);
bits = GET_MPFR_PREC(context);
}
if (bits < MPFR_PREC_MIN || bits > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return NULL;
}
if (global.in_gmpympfrcache) {
result = global.gmpympfrcache[--(global.in_gmpympfrcache)];
/* Py_INCREF does not set the debugging pointers, so need to use
_Py_NewReference instead. */
_Py_NewReference((PyObject*)result);
mpfr_set_prec(result->f, bits);
}
else {
if (!(result = PyObject_New(MPFR_Object, &MPFR_Type))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_init2(result->f, bits);
}
result->hash_cache = -1;
result->rc = 0;
return result;
}
static PyObject *
GMPy_MPFR_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
CTXT_Object *context = NULL;
Py_ssize_t argc, keywdc = 0;
PyObject *arg0 = NULL;
PyObject *out = NULL;
int base = 0;
/* Assumes mpfr_prec_t is the same as a long. */
mpfr_prec_t prec = 0;
static char *kwlist_s[] = {"s", "precision", "base", "context", NULL};
static char *kwlist_n[] = {"n", "precision", "context", NULL};
if (type != &MPFR_Type) {
TYPE_ERROR("mpfr.__new__() requires mpfr type");
return NULL;
}
CHECK_CONTEXT(context);
argc = PyTuple_Size(args);
if (keywds) {
keywdc = PyDict_Size(keywds);
}
if (argc + keywdc > 4) {
TYPE_ERROR("mpfr() takes at most 4 arguments");
return NULL;
}
if (argc + keywdc == 0) {
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_set_ui(result->f, 0, MPFR_RNDN);
}
return (PyObject*)result;
}
if (argc == 0) {
TYPE_ERROR("mpfr() requires at least one non-keyword argument");
return NULL;
}
arg0 = PyTuple_GET_ITEM(args, 0);
/* A string can have precision, base, and context as additional arguments. */
if (PyStrOrUnicode_Check(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|liO", kwlist_s,
&arg0, &prec, &base, &context)))
return NULL;
}
if (!CTXT_Check(context)) {
TYPE_ERROR("context argument is not a valid context");
return NULL;
}
if (prec < 0) {
VALUE_ERROR("precision for mpfr() must be >= 0");
return NULL;
}
if (base != 0 && (base < 2 || base > 62)) {
VALUE_ERROR("base for mpfr() must be 0 or in the interval [2, 62]");
return NULL;
}
return (PyObject*)GMPy_MPFR_From_PyStr(arg0, base, prec, context);
}
if (HAS_MPFR_CONVERSION(arg0)) {
out = (PyObject *) PyObject_CallMethod(arg0, "__mpfr__", NULL);
if(out == NULL)
return out;
if (!MPFR_Check(out)) {
PyErr_Format(PyExc_TypeError,
"object of type '%.200s' can not be interpreted as mpfr",
out->ob_type->tp_name);
Py_DECREF(out);
return NULL;
}
return out;
}
/* A number can only have precision and context as additional arguments. */
if (IS_REAL(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|lO", kwlist_n,
&arg0, &prec, &context)))
return NULL;
}
if (!CTXT_Check(context)) {
TYPE_ERROR("context argument is not a valid context");
return NULL;
}
if (prec < 0) {
VALUE_ERROR("precision for mpfr() must be >= 0");
return NULL;
}
return (PyObject*)GMPy_MPFR_From_Real(arg0, prec, context);
}
TYPE_ERROR("mpfr() requires numeric or string argument");
return NULL;
}
static void
GMPy_MPFR_Dealloc(MPFR_Object *self)
{
size_t msize;
/* Calculate the number of limbs in the mantissa. */
msize = (self->f->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb;
if (global.in_gmpympfrcache < global.cache_size &&
msize <= (size_t)global.cache_obsize) {
global.gmpympfrcache[(global.in_gmpympfrcache)++] = self;
}
else {
mpfr_clear(self->f);
PyObject_Del(self);
}
}
static void
set_gmpympccache(void)
{
if (global.in_gmpympccache > global.cache_size) {
int i;
for (i = global.cache_size; i < global.in_gmpympccache; ++i) {
mpc_clear(global.gmpympccache[i]->c);
PyObject_Del(global.gmpympccache[i]);
}
global.in_gmpympccache = global.cache_size;
}
global.gmpympccache = realloc(global.gmpympccache, sizeof(MPC_Object)*global.cache_size);
}
static MPC_Object *
GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context)
{
MPC_Object *self;
if (rprec < 2) {
CHECK_CONTEXT(context);
rprec = GET_REAL_PREC(context);
}
if (iprec < 2) {
CHECK_CONTEXT(context);
iprec = GET_IMAG_PREC(context);
}
if (rprec < MPFR_PREC_MIN || rprec > MPFR_PREC_MAX ||
iprec < MPFR_PREC_MIN || iprec > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return NULL;
}
if (global.in_gmpympccache) {
self = global.gmpympccache[--(global.in_gmpympccache)];
/* Py_INCREF does not set the debugging pointers, so need to use
_Py_NewReference instead. */
_Py_NewReference((PyObject*)self);
if (rprec == iprec) {
mpc_set_prec(self->c, rprec);
}
else {
mpc_clear(self->c);
mpc_init3(self->c, rprec, iprec);
}
}
else {
if (!(self = PyObject_New(MPC_Object, &MPC_Type))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpc_init3(self->c, rprec, iprec);
}
self->hash_cache = -1;
self->rc = 0;
return self;
}
static PyObject *
GMPy_MPC_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
MPC_Object *result = NULL;
MPFR_Object *tempreal = NULL, *tempimag = NULL;
PyObject *arg0 = NULL, *arg1 = NULL, *prec = NULL, *out = NULL;
int base = 10;
Py_ssize_t argc = 0, keywdc = 0;
CTXT_Object *context = NULL;
/* Assumes mpfr_prec_t is the same as a long. */
mpfr_prec_t rprec = 0, iprec = 0;
static char *kwlist_c[] = {"c", "precision", "context", NULL};
static char *kwlist_r[] = {"real", "imag", "precision", "context", NULL};
static char *kwlist_s[] = {"s", "precision", "base", "context", NULL};
if (type != &MPC_Type) {
TYPE_ERROR("mpc.__new__() requires mpc type");
return NULL;
}
CHECK_CONTEXT(context);
argc = PyTuple_Size(args);
if (keywds) {
keywdc = PyDict_Size(keywds);
}
if (argc + keywdc > 4) {
TYPE_ERROR("mpc() takes at most 4 arguments");
return NULL;
}
if (argc + keywdc == 0) {
if ((result = GMPy_MPC_New(0, 0, context))) {
mpc_set_ui(result->c, 0, GET_MPC_ROUND(context));
}
return (PyObject*)result;
}
if (argc == 0) {
TYPE_ERROR("mpc() requires at least one non-keyword argument");
return NULL;
}
arg0 = PyTuple_GET_ITEM(args, 0);
/* A string can have precision, base, and context as additional arguments.
*/
if (PyStrOrUnicode_Check(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|OiO", kwlist_s,
&arg0, &prec, &base, &context)))
return NULL;
}
if (!CTXT_Check(context)) {
TYPE_ERROR("context argument is not a valid context");
return NULL;
}
if (prec) {
if (PyIntOrLong_Check(prec)) {
rprec = (mpfr_prec_t)PyIntOrLong_AsLong(prec);
iprec = rprec;
}
else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) {
rprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 0));
iprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 1));
}
else {
TYPE_ERROR("precision for mpc() must be integer or tuple");
return NULL;
}
if (rprec < 0 || iprec < 0) {
if (PyErr_Occurred()) {
VALUE_ERROR("invalid value for precision in mpc()");
}
else {
VALUE_ERROR("precision for mpc() must be >= 0");
}
return NULL;
}
}
if (base < 2 || base > 36) {
VALUE_ERROR("base for mpc() must be in the interval [2,36]");
return NULL;
}
return (PyObject*)GMPy_MPC_From_PyStr(arg0, base, rprec, iprec, context);
}
if (HAS_MPC_CONVERSION(arg0)) {
out = (PyObject*) PyObject_CallMethod(arg0, "__mpc__", NULL);
if(out == NULL)
return out;
if (!MPC_Check(out)) {
PyErr_Format(PyExc_TypeError,
"object of type '%.200s' can not be interpreted as mpc",
out->ob_type->tp_name);
Py_DECREF(out);
return NULL;
}
return out;
}
/* Should special case PyFLoat to avoid double rounding. */
if (IS_REAL(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|OOO", kwlist_r,
&arg0, &arg1, &prec, &context)))
return NULL;
}
if (!CTXT_Check(context)) {
TYPE_ERROR("context argument is not a valid context");
return NULL;
}
if (prec) {
if (PyIntOrLong_Check(prec)) {
rprec = (mpfr_prec_t)PyIntOrLong_AsLong(prec);
iprec = rprec;
}
else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) {
rprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 0));
iprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 1));
}
else {
TYPE_ERROR("precision for mpc() must be integer or tuple");
return NULL;
}
if (rprec < 0 || iprec < 0) {
if (PyErr_Occurred()) {
VALUE_ERROR("invalid value for precision in mpc()");
}
else {
VALUE_ERROR("precision for mpc() must be >= 0");
}
return NULL;
}
}
if (arg1 && !IS_REAL(arg1)) {
TYPE_ERROR("invalid type for imaginary component in mpc()");
return NULL;
}
tempreal = GMPy_MPFR_From_Real(arg0, rprec, context);
if (arg1) {
tempimag = GMPy_MPFR_From_Real(arg1, iprec, context);
}
else {
if ((tempimag = GMPy_MPFR_New(iprec, context))) {
mpfr_set_ui(tempimag->f, 0, MPFR_RNDN);
}
}
result = GMPy_MPC_New(rprec, iprec, context);
if (!tempreal || !tempimag || !result) {
Py_XDECREF(tempreal);
Py_XDECREF(tempimag);
Py_XDECREF(result);
TYPE_ERROR("mpc() requires string or numeric argument.");
return NULL;
}
mpc_set_fr_fr(result->c, tempreal->f, tempimag->f, GET_MPC_ROUND(context));
Py_DECREF(tempreal);
Py_DECREF(tempimag);
return (PyObject*)result;
}
if (IS_COMPLEX_ONLY(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|O", kwlist_c,
&arg0, &prec)))
return NULL;
}
if (prec) {
if (PyIntOrLong_Check(prec)) {
rprec = (mpfr_prec_t)PyIntOrLong_AsLong(prec);
iprec = rprec;
}
else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) {
rprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 0));
iprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 1));
}
else {
TYPE_ERROR("precision for mpc() must be integer or tuple");
return NULL;
}
if (rprec < 0 || iprec < 0) {
if (PyErr_Occurred()) {
VALUE_ERROR("invalid value for precision in mpc()");
}
else {
VALUE_ERROR("precision for mpc() must be >= 0");
}
return NULL;
}
}
if (PyComplex_Check(arg0)) {
result = GMPy_MPC_From_PyComplex(arg0, rprec, iprec, context);
}
else {
result = GMPy_MPC_From_MPC((MPC_Object*)arg0, rprec, iprec, context);
}
return (PyObject*)result;
}
TYPE_ERROR("mpc() requires numeric or string argument");
return NULL;
}
static void
GMPy_MPC_Dealloc(MPC_Object *self)
{
size_t msize;
/* Calculate the number of limbs in the mantissa. */
msize = (mpc_realref(self->c)->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb;
msize += (mpc_imagref(self->c)->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb;
if (global.in_gmpympccache < global.cache_size &&
msize <= (size_t)global.cache_obsize) {
global.gmpympccache[(global.in_gmpympccache)++] = self;
}
else {
mpc_clear(self->c);
PyObject_Del(self);
}
}
gmpy2-2.1.0b3/src/gmpy2_cache.h 0000664 0001750 0001750 00000010672 13425751455 016011 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_cache.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* gmpy2 caches objects so they can be reused quickly without involving a new
* memory allocation or object construction.
*/
#ifndef GMPY_CACHE_H
#define GMPY_CACHE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private functions */
static void set_gmpympzcache(void);
static void set_gmpyxmpzcache(void);
static void set_gmpympqcache(void);
static void set_gmpympfrcache(void);
static void set_gmpympccache(void);
/* C-API functions */
/* static MPZ_Object * GMPy_MPZ_New(CTXT_Object *context); */
/* static PyObject * GMPy_MPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds); */
/* static void GMPy_MPZ_Dealloc(MPZ_Object *self); */
static GMPy_MPZ_New_RETURN GMPy_MPZ_New GMPy_MPZ_New_PROTO;
static GMPy_MPZ_NewInit_RETURN GMPy_MPZ_NewInit GMPy_MPZ_NewInit_PROTO;
static GMPy_MPZ_Dealloc_RETURN GMPy_MPZ_Dealloc GMPy_MPZ_Dealloc_PROTO;
/* static XMPZ_Object * GMPy_XMPZ_New(CTXT_Object *context); */
/* static PyObject * GMPy_XMPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds); */
/* static void GMPy_XMPZ_Dealloc(XMPZ_Object *self); */
static GMPy_XMPZ_New_RETURN GMPy_XMPZ_New GMPy_XMPZ_New_PROTO;
static GMPy_XMPZ_NewInit_RETURN GMPy_XMPZ_NewInit GMPy_XMPZ_NewInit_PROTO;
static GMPy_XMPZ_Dealloc_RETURN GMPy_XMPZ_Dealloc GMPy_XMPZ_Dealloc_PROTO;
/* static MPQ_Object * GMPy_MPQ_New(CTXT_Object *context); */
/* static PyObject * GMPy_MPQ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds); */
/* static void GMPy_MPQ_Dealloc(MPQ_Object *self); */
static GMPy_MPQ_New_RETURN GMPy_MPQ_New GMPy_MPQ_New_PROTO;
static GMPy_MPQ_NewInit_RETURN GMPy_MPQ_NewInit GMPy_MPQ_NewInit_PROTO;
static GMPy_MPQ_Dealloc_RETURN GMPy_MPQ_Dealloc GMPy_MPQ_Dealloc_PROTO;
/* static MPFR_Object * GMPy_MPFR_New(CTXT_Object *context); */
/* static PyObject * GMPy_MPFR_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds); */
/* static void GMPy_MPFR_Dealloc(MPFR_Object *self); */
static GMPy_MPFR_New_RETURN GMPy_MPFR_New GMPy_MPFR_New_PROTO;
static GMPy_MPFR_NewInit_RETURN GMPy_MPFR_NewInit GMPy_MPFR_NewInit_PROTO;
static GMPy_MPFR_Dealloc_RETURN GMPy_MPFR_Dealloc GMPy_MPFR_Dealloc_PROTO;
static MPC_Object * GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static void GMPy_MPC_Dealloc(MPC_Object *self);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_cmp.c 0000664 0001750 0001750 00000041575 13473132314 015514 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_cmp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_mpany_cmp,
"cmp(x, y) -> integer\n\n"
"Return -1 if x < y; 0 if x = y; or 1 if x > y. Both x and y must be\n"
"integer, rational or real. Note: 0 is returned (and exception flag set)\n"
"if either argument is NaN.");
static PyObject * _return_cmp(int c)
{
if (c < 0) return PyIntOrLong_FromLong(-1);
if (c > 0) return PyIntOrLong_FromLong(1);
return PyIntOrLong_FromLong(0);
}
static PyObject * _return_negated_cmp(int c)
{
if (c < 0) return PyIntOrLong_FromLong(1);
if (c > 0) return PyIntOrLong_FromLong(-1);
return PyIntOrLong_FromLong(0);
}
static PyObject *
GMPy_MPANY_cmp(PyObject *self, PyObject *args)
{
PyObject *arg0, *arg1, *result = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("cmp() requires 2 arguments");
return NULL;
}
arg0 = PyTuple_GET_ITEM(args, 0);
arg1 = PyTuple_GET_ITEM(args, 1);
if (IS_INTEGER(arg0) && IS_INTEGER(arg1)) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_Integer(arg0, context)) ||
!(tempy = GMPy_MPZ_From_Integer(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_cmp(mpz_cmp(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_RATIONAL(arg0) && IS_INTEGER(arg1)) {
MPQ_Object *tempx = NULL;
MPZ_Object *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_Rational(arg0, context)) ||
!(tempy = GMPy_MPZ_From_Integer(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_cmp(mpq_cmp_z(tempx->q, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_INTEGER(arg0) && IS_RATIONAL(arg1)) {
MPZ_Object *tempx = NULL;
MPQ_Object *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_Integer(arg0, context)) ||
!(tempy = GMPy_MPQ_From_Rational(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_negated_cmp(mpq_cmp_z(tempy->q, tempx->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_RATIONAL(arg0) && IS_RATIONAL(arg1)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_Rational(arg0, context)) ||
!(tempy = GMPy_MPQ_From_Rational(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_cmp(mpq_cmp(tempx->q, tempy->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
/* We perform exact comparisons between the mpz, mpq, and mpfr types.
*/
if (IS_REAL(arg0) && IS_INTEGER(arg1)) {
MPFR_Object *tempx = NULL;
MPZ_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_Real(arg0, 1, context)) ||
!(tempy = GMPy_MPZ_From_Integer(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpfr_cmp_z(tempx->f, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_REAL(arg0) && IS_RATIONAL(arg1)) {
MPFR_Object *tempx = NULL;
MPQ_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_Real(arg0, 1, context)) ||
!(tempy = GMPy_MPQ_From_Rational(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpfr_cmp_q(tempx->f, tempy->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_REAL(arg0) && IS_REAL(arg1)) {
MPFR_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_Real(arg0, 1, context)) ||
!(tempy = GMPy_MPFR_From_Real(arg1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpfr_cmp(tempx->f, tempy->f));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_INTEGER(arg0) && IS_REAL(arg1)) {
MPZ_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_Integer(arg0, context)) ||
!(tempy = GMPy_MPFR_From_Real(arg1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_negated_cmp(mpfr_cmp_z(tempy->f, tempx->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_RATIONAL(arg0) && IS_REAL(arg1)) {
MPQ_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_Rational(arg0, context)) ||
!(tempy = GMPy_MPFR_From_Real(arg1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_negated_cmp(mpfr_cmp_q(tempy->f, tempx->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
TYPE_ERROR("cmp() requires integer, rational, or real arguments");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_mpany_cmp_abs,
"cmp_abs(x, y) -> integer\n\n"
"Return -1 if |x| < |y|; 0 if |x| = |y|; or 1 if |x| > |y|. Both x and y\n"
"can be integer, rational, real, or complex.");
static PyObject *
GMPy_MPANY_cmp_abs(PyObject *self, PyObject *args)
{
PyObject *arg0, *arg1, *result = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("cmp() requires 2 arguments");
return NULL;
}
arg0 = PyTuple_GET_ITEM(args, 0);
arg1 = PyTuple_GET_ITEM(args, 1);
if (IS_INTEGER(arg0) && IS_INTEGER(arg1)) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_Integer(arg0, context)) ||
!(tempy = GMPy_MPZ_From_Integer(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_cmp(mpz_cmpabs(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_RATIONAL(arg0) && IS_INTEGER(arg1)) {
MPQ_Object *tempx = NULL;
MPZ_Object *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalAndCopy(arg0, context)) ||
!(tempy = GMPy_MPZ_From_IntegerAndCopy(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_abs(tempx->q, tempx->q);
mpz_abs(tempy->z, tempy->z);
result = _return_cmp(mpq_cmp_z(tempx->q, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_INTEGER(arg0) && IS_RATIONAL(arg1)) {
MPZ_Object *tempx = NULL;
MPQ_Object *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerAndCopy(arg0, context)) ||
!(tempy = GMPy_MPQ_From_RationalAndCopy(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_abs(tempx->z, tempx->z);
mpq_abs(tempy->q, tempy->q);
result = _return_negated_cmp(mpq_cmp_z(tempy->q, tempx->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_RATIONAL(arg0) && IS_RATIONAL(arg1)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalAndCopy(arg0, context)) ||
!(tempy = GMPy_MPQ_From_RationalAndCopy(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_abs(tempx->q, tempx->q);
mpq_abs(tempy->q, tempy->q);
result = _return_cmp(mpq_cmp(tempx->q, tempy->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
/* We perform exact comparisons between the mpz, mpq, and mpfr types.
*/
if (IS_REAL(arg0) && IS_INTEGER(arg1)) {
MPFR_Object *tempx = NULL;
MPZ_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealAndCopy(arg0, 1, context)) ||
!(tempy = GMPy_MPZ_From_IntegerAndCopy(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
mpfr_abs(tempx->f, tempx->f, MPFR_RNDN);
mpz_abs(tempy->z, tempy->z);
result =_return_cmp(mpfr_cmp_z(tempx->f, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_REAL(arg0) && IS_RATIONAL(arg1)) {
MPFR_Object *tempx = NULL;
MPQ_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealAndCopy(arg0, 1, context)) ||
!(tempy = GMPy_MPQ_From_RationalAndCopy(arg1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
mpfr_abs(tempx->f, tempx->f, MPFR_RNDN);
mpq_abs(tempy->q, tempy->q);
result =_return_cmp(mpfr_cmp_q(tempx->f, tempy->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_REAL(arg0) && IS_REAL(arg1)) {
MPFR_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_Real(arg0, 1, context)) ||
!(tempy = GMPy_MPFR_From_Real(arg1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpfr_cmpabs(tempx->f, tempy->f));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_INTEGER(arg0) && IS_REAL(arg1)) {
MPZ_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerAndCopy(arg0, context)) ||
!(tempy = GMPy_MPFR_From_RealAndCopy(arg1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
mpz_abs(tempx->z, tempx->z);
mpfr_abs(tempy->f, tempy->f, MPFR_RNDN);
result =_return_negated_cmp(mpfr_cmp_z(tempy->f, tempx->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_RATIONAL(arg0) && IS_REAL(arg1)) {
MPQ_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalAndCopy(arg0, context)) ||
!(tempy = GMPy_MPFR_From_RealAndCopy(arg1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
mpq_abs(tempx->q, tempx->q);
mpfr_abs(tempy->f, tempy->f, MPFR_RNDN);
result =_return_negated_cmp(mpfr_cmp_q(tempy->f, tempx->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
#ifndef MPC_110
TYPE_ERROR("cmp_abs() requires integer, rational, or real arguments");
return NULL;
#else
if (IS_COMPLEX(arg0) && IS_COMPLEX(arg1)) {
MPC_Object *tempx = NULL;
MPC_Object *tempy = NULL;
if (!(tempx = GMPy_MPC_From_Complex(arg0, 1, 1, context)) ||
!(tempy = GMPy_MPC_From_Complex(arg1, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpc_cmp_abs(tempx->c, tempy->c));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
TYPE_ERROR("cmp_abs() requires integer, rational, real, or complex arguments");
return NULL;
#endif
}
gmpy2-2.1.0b3/src/gmpy2_cmp.h 0000664 0001750 0001750 00000004434 13452460010 015504 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_cmp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_CMP_H
#define GMPY_CMP_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPANY_cmp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPANY_cmp_abs(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_const.c 0000664 0001750 0001750 00000016514 13425751653 016070 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_const.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_function_const_pi,
"const_pi([precision=0]) -> number\n\n"
"Return the constant pi using the specified precision. If no\n"
"precision is specified, the default precision is used.");
static PyObject *
GMPy_Function_Const_Pi(PyObject *self, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
mpfr_prec_t bits = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &bits)) {
return NULL;
}
if ((result = GMPy_MPFR_New(bits, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_pi(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_const_pi,
"context.const_pi() -> number\n\n"
"Return the constant pi using the context's precision.");
static PyObject *
GMPy_Context_Const_Pi(PyObject *self, PyObject *args)
{
MPFR_Object *result = NULL;
CTXT_Object *context = (CTXT_Object*)self;
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_pi(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_const_euler,
"const_euler([precision=0]) -> number\n\n"
"Return the euler constant using the specified precision. If no\n"
"precision is specified, the default precision is used.");
static PyObject *
GMPy_Function_Const_Euler(PyObject *self, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
mpfr_prec_t bits = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &bits)) {
return NULL;
}
if ((result = GMPy_MPFR_New(bits, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_euler(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_const_euler,
"context.const_euler() -> number\n\n"
"Return the euler constant using the context's precision.");
static PyObject *
GMPy_Context_Const_Euler(PyObject *self, PyObject *args)
{
MPFR_Object *result = NULL;
CTXT_Object *context = (CTXT_Object*)self;
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_euler(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_const_log2,
"const_log2([precision=0]) -> number\n\n"
"Return the log2 constant using the specified precision. If no\n"
"precision is specified, the default precision is used.");
static PyObject *
GMPy_Function_Const_Log2(PyObject *self, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
mpfr_prec_t bits = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &bits)) {
return NULL;
}
if ((result = GMPy_MPFR_New(bits, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_log2(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_const_log2,
"context.const_log2() -> number\n\n"
"Return the log2 constant using the context's precision.");
static PyObject *
GMPy_Context_Const_Log2(PyObject *self, PyObject *args)
{
MPFR_Object *result = NULL;
CTXT_Object *context = (CTXT_Object*)self;
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_log2(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_const_catalan,
"const_catalan([precision=0]) -> number\n\n"
"Return the catalan constant using the specified precision. If no\n"
"precision is specified, the default precision is used.");
static PyObject *
GMPy_Function_Const_Catalan(PyObject *self, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
mpfr_prec_t bits = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &bits)) {
return NULL;
}
if ((result = GMPy_MPFR_New(bits, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_catalan(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_const_catalan,
"context.const_catalan() -> number\n\n"
"Return the catalan constant using the context's precision.");
static PyObject *
GMPy_Context_Const_Catalan(PyObject *self, PyObject *args)
{
MPFR_Object *result = NULL;
CTXT_Object *context = (CTXT_Object*)self;
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_catalan(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
gmpy2-2.1.0b3/src/gmpy2_const.h 0000664 0001750 0001750 00000005504 13425751673 016074 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_const.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_CONST_H
#define GMPY_CONST_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Function_Const_Pi(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_Context_Const_Pi(PyObject *self, PyObject *args);
static PyObject * GMPy_Function_Const_Euler(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_Context_Const_Euler(PyObject *self, PyObject *args);
static PyObject * GMPy_Function_Const_Log2(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_Context_Const_Log2(PyObject *self, PyObject *args);
static PyObject * GMPy_Function_Const_Catalan(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_Context_Const_Catalan(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_context.c 0000664 0001750 0001750 00000146542 13525427233 016426 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_context.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements contexts and context managers.
*
* Public API
* ==========
* TBD
*
* Private API
* ===========
* GMPy_CTXT_New
* GMPy_CTXT_Dealloc
* GMPy_CTXT_Set
* GMPy_CTXT_Get
* GMPy_CTXT_Copy
* GMPy_CTXT_ieee
* GMPy_CTXT_Local
* GMPy_CTXT_Context
* GMPy_CTXT_Repr_Slot
* GMPy_CTXT_Enter
* GMPy_CTXT_Exit
* GMPy_CTXT_Clear_Flags
* GMPy_CTXT_Manager_New
* GMPy_CTXT_Manager_Dealloc
* GMPy_CTXT_Manager_Repr_Slot
* GMPy_CTXT_Manager_Enter
* GMPy_CTXT_Manager_Exit
* plus getters & setters....
*
* Internal functions
* ==================
* GMPy_current_context
*/
/* Create and delete Context objects. */
static PyObject *
GMPy_CTXT_New(void)
{
CTXT_Object *result;
if ((result = PyObject_New(CTXT_Object, &CTXT_Type))) {
result->ctx.mpfr_prec = DBL_MANT_DIG;
result->ctx.mpfr_round = MPFR_RNDN;
result->ctx.emax = MPFR_EMAX_DEFAULT;
result->ctx.emin = MPFR_EMIN_DEFAULT;
result->ctx.subnormalize = 0;
result->ctx.underflow = 0;
result->ctx.overflow = 0;
result->ctx.inexact = 0;
result->ctx.invalid = 0;
result->ctx.erange = 0;
result->ctx.divzero = 0;
result->ctx.traps = TRAP_NONE;
result->ctx.real_prec = -1;
result->ctx.imag_prec = -1;
result->ctx.real_round = -1;
result->ctx.imag_round = -1;
result->ctx.allow_complex = 0;
result->ctx.rational_division = 0;
#ifndef WITHOUT_THREADS
result->tstate = NULL;
#endif
}
return (PyObject*)result;
};
static void
GMPy_CTXT_Dealloc(CTXT_Object *self)
{
PyObject_Del(self);
};
/* Support for global and thread local contexts. */
/* Doc-string, alternate definitions below. */
PyDoc_STRVAR(GMPy_doc_set_context,
"set_context(context)\n\n"
"Activate a context object controlling gmpy2 arithmetic.\n");
#ifdef WITHOUT_THREADS
static PyObject *
GMPy_CTXT_Set(PyObject *self, PyObject *other)
{
if (!CTXT_Check(other)) {
VALUE_ERROR("set_context() requires a context argument");
return NULL;
}
Py_DECREF((PyObject*)module_context);
Py_INCREF((PyObject*)other);
module_context = (CTXT_Object*)other;
Py_RETURN_NONE;
}
#else
/* Begin support for thread local contexts. */
/* Get the context from the thread state dictionary. */
static CTXT_Object *
current_context_from_dict(void)
{
PyObject *dict;
PyObject *tl_context;
PyThreadState *tstate;
dict = PyThreadState_GetDict();
if (dict == NULL) {
RUNTIME_ERROR("cannot get thread state");
return NULL;
}
#ifdef PY3
tl_context = PyDict_GetItemWithError(dict, tls_context_key);
#else
tl_context = PyDict_GetItem(dict, tls_context_key);
#endif
if (!tl_context) {
#ifdef PY3
if (PyErr_Occurred()) {
return NULL;
}
#endif
/* Set up a new thread local context. */
tl_context = GMPy_CTXT_New();
if (!tl_context) {
return NULL;
}
if (PyDict_SetItem(dict, tls_context_key, tl_context) < 0) {
Py_DECREF(tl_context);
return NULL;
}
Py_DECREF(tl_context);
}
/* Cache the context of the current thread, assuming that it
* will be accessed several times before a thread switch. */
tstate = PyThreadState_GET();
if (tstate) {
cached_context = (CTXT_Object*)tl_context;
cached_context->tstate = tstate;
}
/* Borrowed reference with refcount==1 */
return (CTXT_Object*)tl_context;
}
/* Return borrowed reference to thread local context. */
static CTXT_Object *
GMPy_current_context(void)
{
PyThreadState *tstate = PyThreadState_GET();
if (cached_context && cached_context->tstate == tstate) {
return (CTXT_Object*)cached_context;
}
return current_context_from_dict();
}
/* Set the thread local context to a new context, decrement old reference */
static PyObject *
GMPy_CTXT_Set(PyObject *self, PyObject *other)
{
PyObject *dict;
PyThreadState *tstate;
if (!CTXT_Check(other)) {
VALUE_ERROR("set_context() requires a context argument");
return NULL;
}
dict = PyThreadState_GetDict();
if (dict == NULL) {
RUNTIME_ERROR("cannot get thread state");
return NULL;
}
if (PyDict_SetItem(dict, tls_context_key, other) < 0) {
return NULL;
}
/* Cache the context of the current thread, assuming that it
* will be accessed several times before a thread switch. */
cached_context = NULL;
tstate = PyThreadState_GET();
if (tstate) {
cached_context = (CTXT_Object*)other;
cached_context->tstate = tstate;
}
Py_RETURN_NONE;
}
#endif
PyDoc_STRVAR(GMPy_doc_context_ieee,
"ieee(size[,subnormalize=True]) -> context\n\n"
"Return a new context corresponding to a standard IEEE floating point\n"
"format. The supported sizes are 16, 32, 64, 128, and multiples of\n"
"32 greater than 128.");
static PyObject *
GMPy_CTXT_ieee(PyObject *self, PyObject *args, PyObject *kwargs)
{
long bitwidth;
double bitlog2;
int sub_mode=1;
PyObject *temp;
CTXT_Object *result;
static char *kwlist[] = {"subnormalize", NULL};
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("ieee() requires 'int' argument");
return NULL;
}
bitwidth = PyIntOrLong_AsLong(PyTuple_GET_ITEM(args, 0));
if (bitwidth == -1 && PyErr_Occurred()) {
TYPE_ERROR("ieee() requires 'int' argument");
return NULL;
}
if (bitwidth <= 0) {
VALUE_ERROR("ieee() requires positive value for size");
return NULL;
}
/* Process just the two keyword arguments. */
if (!(temp = PyTuple_New(0))) {
return NULL;
}
if (!(PyArg_ParseTupleAndKeywords(temp, kwargs,
"|ii", kwlist, &sub_mode))) {
VALUE_ERROR("invalid keyword arguments for ieee()");
Py_DECREF(temp);
return NULL;
}
Py_DECREF(temp);
if (sub_mode)
sub_mode = 1;
if (!(result = (CTXT_Object*)GMPy_CTXT_New())) {
return NULL;
}
if (bitwidth == 16) {
result->ctx.mpfr_prec = 11;
result->ctx.emax = 16;
}
else if (bitwidth == 32) {
result->ctx.mpfr_prec = 24;
result->ctx.emax = 128;
}
else if (bitwidth == 64) {
result->ctx.mpfr_prec = 53;
result->ctx.emax = 1024;
}
else if (bitwidth == 128) {
result->ctx.mpfr_prec = 113;
result->ctx.emax = 16384;
}
else {
if ((bitwidth < 128) && (bitwidth & 31)) {
VALUE_ERROR("bitwidth must be 16, 32, 64, 128; or must be greater than 128 and divisible by 32.");
Py_DECREF((PyObject*)result);
return NULL;
}
bitlog2 = floor((4 * log(bitwidth) / log(2.0)) + 0.5);
result->ctx.mpfr_prec = bitwidth - (long)(bitlog2) + 13;
result->ctx.emax = 1 << (bitwidth - result->ctx.mpfr_prec - 1);
}
result->ctx.subnormalize = sub_mode;
result->ctx.emin = 4 - result->ctx.emax - result->ctx.mpfr_prec;
return (PyObject*)result;
}
/* Create and delete ContextManager objects. */
static PyObject *
GMPy_CTXT_Manager_New(void)
{
PyObject *result;
result = (PyObject*)PyObject_New(CTXT_Manager_Object, &CTXT_Manager_Type);
((CTXT_Manager_Object*)(result))->new_context = NULL;
((CTXT_Manager_Object*)(result))->old_context = NULL;
return result;
}
static void
GMPy_CTXT_Manager_Dealloc(CTXT_Manager_Object *self)
{
Py_XDECREF(self->new_context);
Py_XDECREF(self->old_context);
PyObject_Del(self);
}
/* Helper function to convert to convert a rounding mode to a string. */
static PyObject *
_round_to_name(int val)
{
if (val == MPFR_RNDN) return Py2or3String_FromString("RoundToNearest");
if (val == MPFR_RNDZ) return Py2or3String_FromString("RoundToZero");
if (val == MPFR_RNDU) return Py2or3String_FromString("RoundUp");
if (val == MPFR_RNDD) return Py2or3String_FromString("RoundDown");
if (val == MPFR_RNDA) return Py2or3String_FromString("RoundAwayZero");
if (val == GMPY_DEFAULT) return Py2or3String_FromString("Default");
return NULL;
}
static PyObject *
GMPy_CTXT_Repr_Slot(CTXT_Object *self)
{
PyObject *format;
PyObject *tuple;
PyObject *result = NULL;
int i = 0;
tuple = PyTuple_New(23);
if (!tuple)
return NULL;
format = Py2or3String_FromString(
"context(precision=%s, real_prec=%s, imag_prec=%s,\n"
" round=%s, real_round=%s, imag_round=%s,\n"
" emax=%s, emin=%s,\n"
" subnormalize=%s,\n"
" trap_underflow=%s, underflow=%s,\n"
" trap_overflow=%s, overflow=%s,\n"
" trap_inexact=%s, inexact=%s,\n"
" trap_invalid=%s, invalid=%s,\n"
" trap_erange=%s, erange=%s,\n"
" trap_divzero=%s, divzero=%s,\n"
" allow_complex=%s,\n"
" rational_division=%s)"
);
if (!format) {
Py_DECREF(tuple);
return NULL;
}
PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.mpfr_prec));
if (self->ctx.real_prec == GMPY_DEFAULT)
PyTuple_SET_ITEM(tuple, i++, Py2or3String_FromString("Default"));
else
PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.real_prec));
if (self->ctx.imag_prec == GMPY_DEFAULT)
PyTuple_SET_ITEM(tuple, i++, Py2or3String_FromString("Default"));
else
PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.imag_prec));
PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.mpfr_round));
PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.real_round));
PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.imag_round));
PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.emax));
PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.emin));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.subnormalize));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_UNDERFLOW));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.underflow));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_OVERFLOW));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.overflow));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_INEXACT));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.inexact));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_INVALID));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.invalid));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_ERANGE));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.erange));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_DIVZERO));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.divzero));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.allow_complex));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.rational_division));
if (!PyErr_Occurred())
result = Py2or3String_Format(format, tuple);
else
SYSTEM_ERROR("internal error in GMPy_CTXT_Repr");
Py_DECREF(format);
Py_DECREF(tuple);
return result;
}
static PyObject *
GMPy_CTXT_Manager_Repr_Slot(CTXT_Manager_Object *self)
{
return Py_BuildValue("s", "");
}
PyDoc_STRVAR(GMPy_doc_get_context,
"get_context() -> gmpy2 context\n\n"
"Return a reference to the current context.");
static PyObject *
GMPy_CTXT_Get(PyObject *self, PyObject *args)
{
CTXT_Object *context;
CURRENT_CONTEXT(context);
Py_XINCREF((PyObject*)context);
return (PyObject*)context;
}
PyDoc_STRVAR(GMPy_doc_context_copy,
"context.copy() -> gmpy2 context\n\n"
"Return a copy of a context.");
static PyObject *
GMPy_CTXT_Copy(PyObject *self, PyObject *other)
{
CTXT_Object *result;
result = (CTXT_Object*)GMPy_CTXT_New();
result->ctx = ((CTXT_Object*)self)->ctx;
return (PyObject*)result;
}
/* Parse the keyword arguments available to a context. Returns 1 if no
* error occurred; returns 0 is an error occurred.
*/
static int
_parse_context_args(CTXT_Object *ctxt, PyObject *kwargs)
{
PyObject *args;
int x_trap_underflow = 0, x_trap_overflow = 0, x_trap_inexact = 0;
int x_trap_invalid = 0, x_trap_erange = 0, x_trap_divzero = 0;
static char *kwlist[] = {
"precision", "real_prec", "imag_prec", "round",
"real_round", "imag_round", "emax", "emin", "subnormalize",
"trap_underflow", "trap_overflow", "trap_inexact",
"trap_invalid", "trap_erange", "trap_divzero", "allow_complex",
"rational_division", NULL };
/* Create an empty dummy tuple to use for args. */
if (!(args = PyTuple_New(0))) {
return 0;
}
/* Convert the trap bit positions into ints for the benefit of
* PyArg_ParseTupleAndKeywords().
*/
x_trap_underflow = ctxt->ctx.traps & TRAP_UNDERFLOW;
x_trap_overflow = ctxt->ctx.traps & TRAP_OVERFLOW;
x_trap_inexact = ctxt->ctx.traps & TRAP_INEXACT;
x_trap_invalid = ctxt->ctx.traps & TRAP_INVALID;
x_trap_erange = ctxt->ctx.traps & TRAP_ERANGE;
x_trap_divzero = ctxt->ctx.traps & TRAP_DIVZERO;
if (!(PyArg_ParseTupleAndKeywords(args, kwargs,
"|llliiilliiiiiiiii", kwlist,
&ctxt->ctx.mpfr_prec,
&ctxt->ctx.real_prec,
&ctxt->ctx.imag_prec,
&ctxt->ctx.mpfr_round,
&ctxt->ctx.real_round,
&ctxt->ctx.imag_round,
&ctxt->ctx.emax,
&ctxt->ctx.emin,
&ctxt->ctx.subnormalize,
&x_trap_underflow,
&x_trap_overflow,
&x_trap_inexact,
&x_trap_invalid,
&x_trap_erange,
&x_trap_divzero,
&ctxt->ctx.allow_complex,
&ctxt->ctx.rational_division))) {
VALUE_ERROR("invalid keyword arguments for context");
Py_DECREF(args);
return 0;
}
Py_DECREF(args);
ctxt->ctx.traps = TRAP_NONE;
if (x_trap_underflow)
ctxt->ctx.traps |= TRAP_UNDERFLOW;
if (x_trap_overflow)
ctxt->ctx.traps |= TRAP_OVERFLOW;
if (x_trap_inexact)
ctxt->ctx.traps |= TRAP_INEXACT;
if (x_trap_invalid)
ctxt->ctx.traps |= TRAP_INVALID;
if (x_trap_erange)
ctxt->ctx.traps |= TRAP_ERANGE;
if (x_trap_divzero)
ctxt->ctx.traps |= TRAP_DIVZERO;
if (ctxt->ctx.subnormalize)
ctxt->ctx.subnormalize = 1;
/* Sanity check for values. */
if (ctxt->ctx.mpfr_prec < MPFR_PREC_MIN ||
ctxt->ctx.mpfr_prec > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return 0;
}
if (!(ctxt->ctx.real_prec == GMPY_DEFAULT ||
(ctxt->ctx.real_prec >= MPFR_PREC_MIN &&
ctxt->ctx.real_prec <= MPFR_PREC_MAX))) {
VALUE_ERROR("invalid value for real_prec");
return 0;
}
if (!(ctxt->ctx.imag_prec == GMPY_DEFAULT ||
(ctxt->ctx.imag_prec >= MPFR_PREC_MIN &&
ctxt->ctx.imag_prec <= MPFR_PREC_MAX))) {
VALUE_ERROR("invalid value for imag_prec");
return 0;
}
if (!(ctxt->ctx.mpfr_round == MPFR_RNDN ||
ctxt->ctx.mpfr_round == MPFR_RNDZ ||
ctxt->ctx.mpfr_round == MPFR_RNDU ||
ctxt->ctx.mpfr_round == MPFR_RNDD ||
ctxt->ctx.mpfr_round == MPFR_RNDA)) {
VALUE_ERROR("invalid value for round");
return 0;
}
if (ctxt->ctx.mpfr_round == MPFR_RNDA) {
/* Since RNDA is not supported for MPC, set the MPC rounding modes
* to MPFR_RNDN.
*/
ctxt->ctx.real_round = MPFR_RNDN;
ctxt->ctx.imag_round = MPFR_RNDN;
}
if (!(ctxt->ctx.real_round == MPFR_RNDN ||
ctxt->ctx.real_round == MPFR_RNDZ ||
ctxt->ctx.real_round == MPFR_RNDU ||
ctxt->ctx.real_round == MPFR_RNDD ||
ctxt->ctx.real_round == GMPY_DEFAULT)) {
VALUE_ERROR("invalid value for real_round");
return 0;
}
if (!(ctxt->ctx.imag_round == MPFR_RNDN ||
ctxt->ctx.imag_round == MPFR_RNDZ ||
ctxt->ctx.imag_round == MPFR_RNDU ||
ctxt->ctx.imag_round == MPFR_RNDD ||
ctxt->ctx.imag_round == GMPY_DEFAULT)) {
VALUE_ERROR("invalid value for imag_round");
return 0;
}
if (ctxt->ctx.emin < mpfr_get_emin_min() ||
ctxt->ctx.emin > mpfr_get_emin_max()) {
VALUE_ERROR("invalid value for emin");
return 0;
}
if (ctxt->ctx.emax < mpfr_get_emax_min() ||
ctxt->ctx.emax > mpfr_get_emax_max()) {
VALUE_ERROR("invalid value for emax");
return 0;
}
return 1;
}
PyDoc_STRVAR(GMPy_doc_local_context,
"local_context([context[,keywords]]) -> context manager\n\n"
"Create a context manager object that will restore the current context\n"
"when the 'with ...' block terminates. The temporary context for the\n"
"'with ...' block is based on the current context if no context is\n"
"specified. Keyword arguments are supported and will modify the\n"
"temporary new context.");
static PyObject *
GMPy_CTXT_Local(PyObject *self, PyObject *args, PyObject *kwargs)
{
CTXT_Manager_Object *result;
int arg_context = 0;
CTXT_Object *context, *temp;
CURRENT_CONTEXT(context);
if (PyTuple_GET_SIZE(args) == 1 && CTXT_Check(PyTuple_GET_ITEM(args, 0))) {
arg_context = 1;
}
else if (PyTuple_GET_SIZE(args)) {
VALUE_ERROR("local_context() only supports [context[,keyword]] arguments");
return NULL;
}
if (!(result = (CTXT_Manager_Object*)GMPy_CTXT_Manager_New()))
return NULL;
if (arg_context) {
temp = (CTXT_Object*)PyTuple_GET_ITEM(args, 0);
result->new_context = temp;
Py_INCREF((PyObject*)(result->new_context));
}
else {
result->new_context = context;
Py_INCREF((PyObject*)(result->new_context));
}
result->old_context = (CTXT_Object*)GMPy_CTXT_Copy((PyObject*)context, NULL);
if (!(result->old_context)) {
Py_DECREF((PyObject*)result);
return NULL;
}
if (!_parse_context_args(result->new_context, kwargs)) {
/* There was an error parsing the keyword arguments. */
Py_DECREF((PyObject*)result);
return NULL;
}
else {
/* Parsing was successful. */
return (PyObject*)result;
}
}
PyDoc_STRVAR(GMPy_doc_context,
"context() -> context manager\n\n"
"Return a new context for controlling MPFR and MPC arithmetic. To load\n"
"the new context, use set_context(). Options can only be specified as\n"
"keyword arguments. \n"
"\nOptions\n"
" precision: precision, in bits, of an MPFR result\n"
" real_prec: precision, in bits, of Re(MPC)\n"
" -1 implies use mpfr_prec\n"
" imag_prec: precision, in bits, of Im(MPC)\n"
" -1 implies use real_prec\n"
" round: rounding mode for MPFR\n"
" real_round: rounding mode for Re(MPC)\n"
" -1 implies use mpfr_round\n"
" imag_round: rounding mode for Im(MPC)\n"
" -1 implies use real_round\n"
" e_max: maximum allowed exponent\n"
" e_min: minimum allowed exponent\n"
" subnormalize: if True, subnormalized results can be returned\n"
" trap_underflow: if True, raise exception for underflow\n"
" if False, set underflow flag\n"
" trap_overflow: if True, raise exception for overflow\n"
" if False, set overflow flag and return Inf or -Inf\n"
" trap_inexact: if True, raise exception for inexact result\n"
" if False, set inexact flag\n"
" trap_invalid: if True, raise exception for invalid operation\n"
" if False, set invalid flag and return NaN\n"
" trap_erange: if True, raise exception for range error\n"
" if False, set erange flag\n"
" trap_divzero: if True, raise exception for division by zero\n"
" if False, set divzero flag and return Inf or -Inf\n"
" allow_complex: if True, allow mpfr functions to return mpc\n"
" if False, mpfr functions cannot return an mpc\n"
" rational_division: if True, mpz/mpz returns an mpq\n"
" if False, mpz/mpz follows default behavior\n");
#if 0
"\nMethods\n"
" abs(x) return absolute value of x\n"
" acos(x) return inverse cosine of x\n"
" acosh(x) return inverse hyperbolic cosine of x\n"
" add(x,y) return x + y\n"
" agm(x,y) return arthimetic-geometric mean of x and y\n"
" ai(x) return the Airy function of x\n"
" asin(x) return inverse sine of x\n"
" asinh(x) return inverse hyperbolic sine of x\n"
" atan(x) return inverse tangent of x\n"
" atan2(y,x) return inverse tangent of (y / x)\n"
" atanh(x) return inverse hyperbolic tangent of x\n"
" cbrt(x) return cube root of x\n"
" ceil(x) return ceiling of x\n"
" check_range(x) return value with exponents within current range\n"
" clear_flags() clear all exception flags\n"
" const_catalan() return Catalan constant (0.91596559...)\n"
" const_euler() return Euler contstant (0.57721566...)\n"
" const_log() return natural log of 2 (0.69314718...)\n"
" const_pi() return Pi (3.14159265...)\n"
" copy() return a copy of the context\n"
" cos(x) return cosine of x\n"
" cosh(x) return hyperbolic cosine of x\n"
" cot(x) return cotangent of x\n"
" coth(x) return hyperbolic cotangent of x\n"
" csc(x) return cosecant of x\n"
" csch(x) return hyperbolic cosecant of x\n"
" degrees(x) convert value in radians to degrees\n"
" digamma(x) return the digamma of x\n"
" div(x,y) return x / y\n"
" divmod(x,y) return integer quotient and remainder\n"
" div_2exp(x,n) return x / 2**n)\n"
" eint(x) return exponential integral of x\n"
" erf(x) return error function of x\n"
" erfc(x) return complementary error function of x\n"
" exp(x) return e**x\n"
" exp10(x) return 10**x\n"
" exp2(x) return 2**x\n"
" expm1(x) return e**x - 1\n"
" factorial(n) return floating-point approximation to n!\n"
" floor(x) return floor of x\n"
" fma(x,y,z) return correctly rounded (x * y) + z\n"
" fmod(x,y) return x - int(x / y) * y, rounding to 0\n"
" fms(x,y,z) return correctly rounded (x * y) - z\n"
" fsum(i) return accurate sum of iterable i\n"
" gamma(x) return gamma of x\n"
" hypot(y,x) return square root of (x**2 + y**2)\n"
" is_finite(x) return True if x is finite\n"
" is_infinite(x)\n"
" is_nan(x)\n"
" is_zero(x)\n"
" j0(x) return Bessel of first kind of order 0 of x\n"
" j1(x) return Bessel of first kind of order 1 of x\n"
" jn(x,n) return Bessel of first kind of order n of x\n"
" lgamma(x) return tuple (log(abs(gamma(x)), sign(gamma(x)))\n"
" li2(x) return real part of dilogarithm of x\n"
" lngamma(x) return logarithm of gamma of x\n"
" log(x) return natural logarithm of x\n"
" log10(x) return base-10 logarithm of x\n"
" log2(x) return base-2 logarithm of x\n"
" max2(x,y) return maximum of x and y, rounded to context\n"
" mpc(...) create a new instance of an mpc\n"
" mpfr(...) create a new instance of an mpfr\n"
" minus(x) return -x\n"
" min2(x,y) return minimum of x and y, rounded to context\n"
" mul(x,y) return x * y\n"
" mul_2exp(x,n) return x * 2**n\n"
" next_above(x) return next mpfr towards +Infinity\n"
" next_below(x) return next mpfr towards -Infinity\n"
" plus(x) return +x\n"
" pow(x,y) return x ** y\n"
" radians(x) convert value in degrees to radians\n"
" rec_sqrt(x) return 1 / sqrt(x)\n"
" rel_diff(x,y) return abs(x - y) / x\n"
" remainder(x,y) return x - int(x / y) * y, rounding to even\n"
" remquo(x,y) return tuple of remainder(x,y) and low bits of\n"
" the quotient\n"
" rint(x) return x rounded to integer with current rounding\n"
" rint_ceil(x) ...\n"
" rint_floor(x) ...\n"
" rint_round(x) ...\n"
" rint_trunc(x) ...\n"
" root(x,n) return the n-th of x\n"
#ifdef MPC_110
" root_of_unity() return the k-th power of the n-th root of mpc(1)\n"
#endif
" round2(x,n) return x rounded to n bits.\n"
" round_away(x) return x rounded to integer, ties away from 0\n"
" sec(x) return secant of x\n"
" sech(x) return hyperbolic secant of x\n"
" sin(x) return sine of x\n"
" sin_cos(x) return tuple (sin(x), cos(x))\n"
" sinh(x) return hyperbolic sine of x\n"
" sinh_cosh(x) return tuple (sinh(x), cosh(x))\n"
" sqrt(x) return square root of x\n"
" square(x) return x * x\n"
" sub(x) return x - y\n"
" tan(x) return tangent of x\n"
" tanh(x) return hyperbolic tangent of x\n"
" trunc(x) return x rounded towards 0\n"
" y0(x) return Bessel of second kind of order 0 of x\n"
" y1(x) return Bessel of second kind of order 1 of x\n"
" yn(x,n) return Bessel of second kind of order n of x\n"
" zeta(x) return Riemann zeta of x"
#endif
static PyObject *
GMPy_CTXT_Context(PyObject *self, PyObject *args, PyObject *kwargs)
{
CTXT_Object *result;
if (PyTuple_GET_SIZE(args)) {
VALUE_ERROR("context() only supports keyword arguments");
return NULL;
}
if (!(result = (CTXT_Object*)GMPy_CTXT_New()))
return NULL;
if (!_parse_context_args(result, kwargs)) {
/* There was an error parsing the keyword arguments. */
Py_DECREF((PyObject*)result);
return NULL;
}
else {
/* Parsing was successful. */
return (PyObject*)result;
}
}
static PyObject *
GMPy_CTXT_Manager_Enter(PyObject *self, PyObject *args)
{
PyObject *temp;
temp = GMPy_CTXT_Set(NULL, (PyObject*)((CTXT_Manager_Object*)self)->new_context);
if (!temp)
return NULL;
Py_DECREF(temp);
Py_INCREF((PyObject*)(((CTXT_Manager_Object*)self)->new_context));
return (PyObject*)(((CTXT_Manager_Object*)self)->new_context);
}
static PyObject *
GMPy_CTXT_Manager_Exit(PyObject *self, PyObject *args)
{
PyObject *temp;
temp = GMPy_CTXT_Set(NULL, (PyObject*)((CTXT_Manager_Object*)self)->old_context);
if (!temp)
return NULL;
Py_DECREF(temp);
Py_RETURN_NONE;
}
static PyObject *
GMPy_CTXT_Enter(PyObject *self, PyObject *args)
{
PyObject *temp;
PyObject *result;
result = GMPy_CTXT_Copy(self, NULL);
if (!result)
return NULL;
temp = GMPy_CTXT_Set(NULL, result);
if (!temp)
return NULL;
Py_DECREF(temp);
return result;
}
static PyObject *
GMPy_CTXT_Exit(PyObject *self, PyObject *args)
{
PyObject *temp;
temp = GMPy_CTXT_Set(NULL, self);
if (!temp)
return NULL;
Py_DECREF(temp);
Py_RETURN_NONE;
}
PyDoc_STRVAR(GMPy_doc_context_clear_flags,
"clear_flags()\n\n"
"Clear all MPFR exception flags.");
static PyObject *
GMPy_CTXT_Clear_Flags(PyObject *self, PyObject *args)
{
((CTXT_Object*)self)->ctx.underflow = 0;
((CTXT_Object*)self)->ctx.overflow = 0;
((CTXT_Object*)self)->ctx.inexact = 0;
((CTXT_Object*)self)->ctx.invalid = 0;
((CTXT_Object*)self)->ctx.erange = 0;
((CTXT_Object*)self)->ctx.divzero = 0;
Py_RETURN_NONE;
}
/* Define the get/set functions. */
#define GETSET_BOOLEAN(NAME) \
static PyObject * \
GMPy_CTXT_Get_##NAME(CTXT_Object *self, void *closure) \
{ \
return PyBool_FromLong(self->ctx.NAME); \
}; \
static int \
GMPy_CTXT_Set_##NAME(CTXT_Object *self, PyObject *value, void *closure) \
{ \
if (!(PyBool_Check(value))) { \
TYPE_ERROR(#NAME " must be True or False"); \
return -1; \
} \
self->ctx.NAME = (value == Py_True) ? 1 : 0; \
return 0; \
}
/* Define the get/set functions. This version works with the individual
* bits in the traps field.
*/
#define GETSET_BOOLEAN_BIT(NAME, TRAP) \
static PyObject * \
GMPy_CTXT_Get_##NAME(CTXT_Object *self, void *closure) \
{ \
return PyBool_FromLong(self->ctx.traps & TRAP); \
}; \
static int \
GMPy_CTXT_Set_##NAME(CTXT_Object *self, PyObject *value, void *closure) \
{ \
if (!(PyBool_Check(value))) { \
TYPE_ERROR(#NAME " must be True or False"); \
return -1; \
} \
if (value == Py_True) \
self->ctx.traps |= TRAP; \
else \
self->ctx.traps &= ~(TRAP); \
return 0; \
}
GETSET_BOOLEAN(subnormalize);
GETSET_BOOLEAN(underflow);
GETSET_BOOLEAN(overflow);
GETSET_BOOLEAN(inexact);
GETSET_BOOLEAN(invalid);
GETSET_BOOLEAN(erange);
GETSET_BOOLEAN(divzero);
GETSET_BOOLEAN_BIT(trap_underflow, TRAP_UNDERFLOW);
GETSET_BOOLEAN_BIT(trap_overflow, TRAP_OVERFLOW);
GETSET_BOOLEAN_BIT(trap_inexact, TRAP_INEXACT);
GETSET_BOOLEAN_BIT(trap_invalid, TRAP_INVALID);
GETSET_BOOLEAN_BIT(trap_erange, TRAP_ERANGE);
GETSET_BOOLEAN_BIT(trap_divzero, TRAP_DIVZERO);
GETSET_BOOLEAN(allow_complex)
GETSET_BOOLEAN(rational_division)
static PyObject *
GMPy_CTXT_Get_precision(CTXT_Object *self, void *closure)
{
return PyIntOrLong_FromSsize_t((Py_ssize_t)(self->ctx.mpfr_prec));
}
static int
GMPy_CTXT_Set_precision(CTXT_Object *self, PyObject *value, void *closure)
{
Py_ssize_t temp;
if (!(PyIntOrLong_Check(value))) {
TYPE_ERROR("precision must be Python integer");
return -1;
}
temp = PyIntOrLong_AsSsize_t(value);
/* A return value of -1 indicates an error has occurred. Since -1 is not
* a legal value, we don't specifically check for an error condition.
*/
if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return -1;
}
self->ctx.mpfr_prec = (mpfr_prec_t)temp;
return 0;
}
static PyObject *
GMPy_CTXT_Get_real_prec(CTXT_Object *self, void *closure)
{
return PyIntOrLong_FromSsize_t((Py_ssize_t)(GET_REAL_PREC(self)));
}
static int
GMPy_CTXT_Set_real_prec(CTXT_Object *self, PyObject *value, void *closure)
{
Py_ssize_t temp;
if (!(PyIntOrLong_Check(value))) {
TYPE_ERROR("real_prec must be Python integer");
return -1;
}
temp = PyIntOrLong_AsSsize_t(value);
/* A return value of -1 indicates an error has occurred. Since -1 is not
* a legal value, we don't specifically check for an error condition.
*/
if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for real_prec");
return -1;
}
self->ctx.real_prec = (mpfr_prec_t)temp;
return 0;
}
static PyObject *
GMPy_CTXT_Get_imag_prec(CTXT_Object *self, void *closure)
{
return PyIntOrLong_FromSsize_t((Py_ssize_t)(GET_IMAG_PREC(self)));
}
static int
GMPy_CTXT_Set_imag_prec(CTXT_Object *self, PyObject *value, void *closure)
{
Py_ssize_t temp;
if (!(PyIntOrLong_Check(value))) {
TYPE_ERROR("imag_prec must be Python integer");
return -1;
}
temp = PyIntOrLong_AsSsize_t(value);
/* A return value of -1 indicates an error has occurred. Since -1 is not
* a legal value, we don't specifically check for an error condition.
*/
if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for imag_prec");
return -1;
}
self->ctx.imag_prec = (mpfr_prec_t)temp;
return 0;
}
static PyObject *
GMPy_CTXT_Get_round(CTXT_Object *self, void *closure)
{
return PyIntOrLong_FromLong((long)(self->ctx.mpfr_round));
}
static int
GMPy_CTXT_Set_round(CTXT_Object *self, PyObject *value, void *closure)
{
long temp;
if (!(PyIntOrLong_Check(value))) {
TYPE_ERROR("round mode must be Python integer");
return -1;
}
temp = PyIntOrLong_AsLong(value);
if (temp == -1 && PyErr_Occurred()) {
VALUE_ERROR("invalid value for round mode");
return -1;
}
if (temp == MPFR_RNDN)
self->ctx.mpfr_round = MPFR_RNDN;
else if (temp == MPFR_RNDZ)
self->ctx.mpfr_round = MPFR_RNDZ;
else if (temp == MPFR_RNDU)
self->ctx.mpfr_round = MPFR_RNDU;
else if (temp == MPFR_RNDD)
self->ctx.mpfr_round = MPFR_RNDD;
else if (temp == MPFR_RNDA) {
self->ctx.mpfr_round = MPFR_RNDA;
/* Since RNDA is not supported for MPC, set the MPC rounding modes
to MPFR_RNDN. */
self->ctx.real_round = MPFR_RNDN;
self->ctx.imag_round = MPFR_RNDN;
}
else {
VALUE_ERROR("invalid value for round mode");
return -1;
}
return 0;
}
static PyObject *
GMPy_CTXT_Get_real_round(CTXT_Object *self, void *closure)
{
return PyIntOrLong_FromLong((long)GET_REAL_ROUND(self));
}
static int
GMPy_CTXT_Set_real_round(CTXT_Object *self, PyObject *value, void *closure)
{
long temp;
if (!(PyIntOrLong_Check(value))) {
TYPE_ERROR("round mode must be Python integer");
return -1;
}
temp = PyIntOrLong_AsLong(value);
if (temp == -1 && PyErr_Occurred()) {
VALUE_ERROR("invalid value for round mode");
return -1;
}
if (temp == GMPY_DEFAULT || temp == MPFR_RNDN || temp == MPFR_RNDZ ||
temp == MPFR_RNDU || temp == MPFR_RNDD) {
self->ctx.real_round = (int)temp;
}
else {
VALUE_ERROR("invalid value for round mode");
return -1;
}
return 0;
}
static PyObject *
GMPy_CTXT_Get_imag_round(CTXT_Object *self, void *closure)
{
return PyIntOrLong_FromLong((long)GET_IMAG_ROUND(self));
}
static int
GMPy_CTXT_Set_imag_round(CTXT_Object *self, PyObject *value, void *closure)
{
long temp;
if (!(PyIntOrLong_Check(value))) {
TYPE_ERROR("round mode must be Python integer");
return -1;
}
temp = PyIntOrLong_AsLong(value);
if (temp == -1 && PyErr_Occurred()) {
VALUE_ERROR("invalid value for round mode");
return -1;
}
if (temp == GMPY_DEFAULT || temp == MPFR_RNDN || temp == MPFR_RNDZ ||
temp == MPFR_RNDU || temp == MPFR_RNDD) {
self->ctx.imag_round = (int)temp;
}
else {
VALUE_ERROR("invalid value for round mode");
return -1;
}
return 0;
}
static PyObject *
GMPy_CTXT_Get_emin(CTXT_Object *self, void *closure)
{
return PyIntOrLong_FromLong(self->ctx.emin);
}
static int
GMPy_CTXT_Set_emin(CTXT_Object *self, PyObject *value, void *closure)
{
long exp;
if (!(PyIntOrLong_Check(value))) {
TYPE_ERROR("emin must be Python integer");
return -1;
}
exp = PyIntOrLong_AsLong(value);
if (exp == -1 && PyErr_Occurred()) {
VALUE_ERROR("requested minimum exponent is invalid");
return -1;
}
if (!(exp >= MPFR_EMIN_MIN && exp <= MPFR_EMIN_MAX)) {
VALUE_ERROR("requested minimum exponent is invalid");
return -1;
}
self->ctx.emin = exp;
return 0;
}
static PyObject *
GMPy_CTXT_Get_emax(CTXT_Object *self, void *closure)
{
return PyIntOrLong_FromLong(self->ctx.emax);
}
static int
GMPy_CTXT_Set_emax(CTXT_Object *self, PyObject *value, void *closure)
{
long exp;
if (!(PyIntOrLong_Check(value))) {
TYPE_ERROR("emax must be Python integer");
return -1;
}
exp = PyIntOrLong_AsLong(value);
if (exp == -1 && PyErr_Occurred()) {
VALUE_ERROR("requested maximum exponent is invalid");
return -1;
}
if (!(exp >= MPFR_EMAX_MIN && exp <= MPFR_EMAX_MAX)) {
VALUE_ERROR("requested maximum exponent is invalid");
return -1;
}
self->ctx.emax = exp;
return 0;
}
#define ADD_GETSET(NAME) \
{#NAME, \
(getter)GMPy_CTXT_Get_##NAME, \
(setter)GMPy_CTXT_Set_##NAME, NULL, NULL}
static PyGetSetDef GMPyContext_getseters[] = {
ADD_GETSET(precision),
ADD_GETSET(real_prec),
ADD_GETSET(imag_prec),
ADD_GETSET(round),
ADD_GETSET(real_round),
ADD_GETSET(imag_round),
ADD_GETSET(emax),
ADD_GETSET(emin),
ADD_GETSET(subnormalize),
ADD_GETSET(underflow),
ADD_GETSET(overflow),
ADD_GETSET(inexact),
ADD_GETSET(invalid),
ADD_GETSET(erange),
ADD_GETSET(divzero),
ADD_GETSET(trap_underflow),
ADD_GETSET(trap_overflow),
ADD_GETSET(trap_inexact),
ADD_GETSET(trap_invalid),
ADD_GETSET(trap_erange),
ADD_GETSET(trap_divzero),
ADD_GETSET(allow_complex),
ADD_GETSET(rational_division),
{NULL}
};
static PyMethodDef GMPyContext_methods[] =
{
{ "abs", GMPy_Context_Abs, METH_O, GMPy_doc_context_abs },
{ "acos", GMPy_Context_Acos, METH_O, GMPy_doc_context_acos },
{ "acosh", GMPy_Context_Acosh, METH_O, GMPy_doc_context_acosh },
{ "add", GMPy_Context_Add, METH_VARARGS, GMPy_doc_context_add },
{ "agm", GMPy_Context_AGM, METH_VARARGS, GMPy_doc_context_agm },
{ "ai", GMPy_Context_Ai, METH_O, GMPy_doc_context_ai },
{ "asin", GMPy_Context_Asin, METH_O, GMPy_doc_context_asin },
{ "asinh", GMPy_Context_Asinh, METH_O, GMPy_doc_context_asinh },
{ "atan", GMPy_Context_Atan, METH_O, GMPy_doc_context_atan },
{ "atanh", GMPy_Context_Atanh, METH_O, GMPy_doc_context_atanh },
{ "atan2", GMPy_Context_Atan2, METH_VARARGS, GMPy_doc_context_atan2 },
{ "clear_flags", GMPy_CTXT_Clear_Flags, METH_NOARGS, GMPy_doc_context_clear_flags },
{ "cbrt", GMPy_Context_Cbrt, METH_O, GMPy_doc_context_cbrt },
{ "ceil", GMPy_Context_Ceil, METH_O, GMPy_doc_context_ceil },
{ "check_range", GMPy_Context_CheckRange, METH_O, GMPy_doc_context_check_range },
{ "const_catalan", GMPy_Context_Const_Catalan, METH_NOARGS, GMPy_doc_context_const_catalan },
{ "const_euler", GMPy_Context_Const_Euler, METH_NOARGS, GMPy_doc_context_const_euler },
{ "const_log2", GMPy_Context_Const_Log2, METH_NOARGS, GMPy_doc_context_const_log2 },
{ "const_pi", GMPy_Context_Const_Pi, METH_NOARGS, GMPy_doc_context_const_pi },
{ "cos", GMPy_Context_Cos, METH_O, GMPy_doc_context_cos },
{ "cosh", GMPy_Context_Cosh, METH_O, GMPy_doc_context_cosh },
{ "cot", GMPy_Context_Cot, METH_O, GMPy_doc_context_cot },
{ "coth", GMPy_Context_Coth, METH_O, GMPy_doc_context_coth },
{ "copy", GMPy_CTXT_Copy, METH_NOARGS, GMPy_doc_context_copy },
{ "csc", GMPy_Context_Csc, METH_O, GMPy_doc_context_csc },
{ "csch", GMPy_Context_Csch, METH_O, GMPy_doc_context_csch },
{ "degrees", GMPy_Context_Degrees, METH_O, GMPy_doc_context_degrees },
{ "digamma", GMPy_Context_Digamma, METH_O, GMPy_doc_context_digamma },
{ "div", GMPy_Context_TrueDiv, METH_VARARGS, GMPy_doc_context_truediv },
{ "divmod", GMPy_Context_DivMod, METH_VARARGS, GMPy_doc_context_divmod },
{ "div_2exp", GMPy_Context_Div_2exp, METH_VARARGS, GMPy_doc_context_div_2exp },
{ "eint", GMPy_Context_Eint, METH_O, GMPy_doc_context_eint },
{ "erf", GMPy_Context_Erf, METH_O, GMPy_doc_context_erf },
{ "erfc", GMPy_Context_Erfc, METH_O, GMPy_doc_context_erfc },
{ "exp", GMPy_Context_Exp, METH_O, GMPy_doc_context_exp },
{ "expm1", GMPy_Context_Expm1, METH_O, GMPy_doc_context_expm1 },
{ "exp10", GMPy_Context_Exp10, METH_O, GMPy_doc_context_exp10 },
{ "exp2", GMPy_Context_Exp2, METH_O, GMPy_doc_context_exp2 },
{ "factorial", GMPy_Context_Factorial, METH_O, GMPy_doc_context_factorial },
{ "floor", GMPy_Context_Floor, METH_O, GMPy_doc_context_floor },
{ "floor_div", GMPy_Context_FloorDiv, METH_VARARGS, GMPy_doc_context_floordiv },
{ "fma", GMPy_Context_FMA, METH_VARARGS, GMPy_doc_context_fma },
{ "fms", GMPy_Context_FMS, METH_VARARGS, GMPy_doc_context_fms },
#if MPFR_VERSION_MAJOR > 3
{ "fmma", GMPy_Context_FMMA, METH_VARARGS, GMPy_doc_context_fmma },
{ "fmms", GMPy_Context_FMMS, METH_VARARGS, GMPy_doc_context_fmms },
#endif
{ "fmod", GMPy_Context_Fmod, METH_VARARGS, GMPy_doc_context_fmod },
{ "frac", GMPy_Context_Frac, METH_O, GMPy_doc_context_frac },
{ "frexp", GMPy_Context_Frexp, METH_O, GMPy_doc_context_frexp },
{ "fsum", GMPy_Context_Fsum, METH_O, GMPy_doc_context_fsum },
{ "gamma", GMPy_Context_Gamma, METH_O, GMPy_doc_context_gamma },
{ "hypot", GMPy_Context_Hypot, METH_VARARGS, GMPy_doc_context_hypot },
{ "is_finite", GMPy_Context_Is_Finite, METH_O, GMPy_doc_context_is_finite },
{ "is_infinite", GMPy_Context_Is_Infinite, METH_O, GMPy_doc_context_is_infinite },
{ "is_integer", GMPy_Context_Is_Integer, METH_O, GMPy_doc_context_is_integer },
{ "is_nan", GMPy_Context_Is_NAN, METH_O, GMPy_doc_context_is_nan },
{ "is_regular", GMPy_Context_Is_Regular, METH_O, GMPy_doc_context_is_regular },
{ "is_signed", GMPy_Context_Is_Signed, METH_O, GMPy_doc_context_is_signed },
{ "is_zero", GMPy_Context_Is_Zero, METH_O, GMPy_doc_context_is_zero },
{ "jn", GMPy_Context_Jn, METH_VARARGS, GMPy_doc_context_jn },
{ "j0", GMPy_Context_J0, METH_O, GMPy_doc_context_j0 },
{ "j1", GMPy_Context_J1, METH_O, GMPy_doc_context_j1 },
{ "li2", GMPy_Context_Li2, METH_O, GMPy_doc_context_li2 },
{ "lgamma", GMPy_Context_Lgamma, METH_O, GMPy_doc_context_lgamma },
{ "lngamma", GMPy_Context_Lngamma, METH_O, GMPy_doc_context_lngamma },
{ "log", GMPy_Context_Log, METH_O, GMPy_doc_context_log },
{ "log10", GMPy_Context_Log10, METH_O, GMPy_doc_context_log10 },
{ "log1p", GMPy_Context_Log1p, METH_O, GMPy_doc_context_log1p },
{ "log2", GMPy_Context_Log2, METH_O, GMPy_doc_context_log2 },
{ "maxnum", GMPy_Context_Maxnum, METH_VARARGS, GMPy_doc_context_maxnum },
{ "minnum", GMPy_Context_Minnum, METH_VARARGS, GMPy_doc_context_minnum },
{ "minus", GMPy_Context_Minus, METH_VARARGS, GMPy_doc_context_minus },
{ "mod", GMPy_Context_Mod, METH_VARARGS, GMPy_doc_context_mod },
{ "modf", GMPy_Context_Modf, METH_O, GMPy_doc_context_modf },
{ "mul", GMPy_Context_Mul, METH_VARARGS, GMPy_doc_context_mul },
{ "mul_2exp", GMPy_Context_Mul_2exp, METH_VARARGS, GMPy_doc_context_mul_2exp },
{ "next_above", GMPy_Context_NextAbove, METH_O, GMPy_doc_context_next_above },
{ "next_below", GMPy_Context_NextBelow, METH_O, GMPy_doc_context_next_below },
{ "next_toward", GMPy_Context_NextToward, METH_VARARGS, GMPy_doc_context_next_toward },
{ "norm", GMPy_Context_Norm, METH_O, GMPy_doc_context_norm },
{ "phase", GMPy_Context_Phase, METH_O, GMPy_doc_context_phase },
{ "plus", GMPy_Context_Plus, METH_VARARGS, GMPy_doc_context_plus },
{ "polar", GMPy_Context_Polar, METH_O, GMPy_doc_context_polar },
{ "proj", GMPy_Context_Proj, METH_O, GMPy_doc_context_proj },
{ "pow", GMPy_Context_Pow, METH_VARARGS, GMPy_doc_context_pow },
{ "radians", GMPy_Context_Radians, METH_O, GMPy_doc_context_radians },
{ "rect", GMPy_Context_Rect, METH_VARARGS, GMPy_doc_context_rect },
{ "rec_sqrt", GMPy_Context_RecSqrt, METH_O, GMPy_doc_context_rec_sqrt },
{ "reldiff", GMPy_Context_RelDiff, METH_VARARGS, GMPy_doc_context_reldiff },
{ "remainder", GMPy_Context_Remainder, METH_VARARGS, GMPy_doc_context_remainder },
{ "remquo", GMPy_Context_RemQuo, METH_VARARGS, GMPy_doc_context_remquo },
{ "rint", GMPy_Context_Rint, METH_O, GMPy_doc_context_rint },
{ "rint_ceil", GMPy_Context_RintCeil, METH_O, GMPy_doc_context_rint_ceil },
{ "rint_floor", GMPy_Context_RintFloor, METH_O, GMPy_doc_context_rint_floor },
{ "rint_round", GMPy_Context_RintRound, METH_O, GMPy_doc_context_rint_round },
{ "rint_trunc", GMPy_Context_RintTrunc, METH_O, GMPy_doc_context_rint_trunc },
{ "root", GMPy_Context_Root, METH_VARARGS, GMPy_doc_context_root },
{ "rootn", GMPy_Context_Rootn, METH_VARARGS, GMPy_doc_context_rootn },
#ifdef MPC_110
{ "root_of_unity", GMPy_Context_Root_Of_Unity, METH_VARARGS, GMPy_doc_context_root_of_unity },
#endif
{ "round2", GMPy_Context_Round2, METH_VARARGS, GMPy_doc_context_round2 },
{ "round_away", GMPy_Context_RoundAway, METH_O, GMPy_doc_context_round_away },
{ "sec", GMPy_Context_Sec, METH_O, GMPy_doc_context_sec },
{ "sech", GMPy_Context_Sech, METH_O, GMPy_doc_context_sech },
{ "sin", GMPy_Context_Sin, METH_O, GMPy_doc_context_sin },
{ "sin_cos", GMPy_Context_Sin_Cos, METH_O, GMPy_doc_context_sin_cos },
{ "sinh", GMPy_Context_Sinh, METH_O, GMPy_doc_context_sinh },
{ "sinh_cosh", GMPy_Context_Sinh_Cosh, METH_O, GMPy_doc_context_sinh_cosh },
{ "sqrt", GMPy_Context_Sqrt, METH_O, GMPy_doc_context_sqrt },
{ "square", GMPy_Context_Square, METH_O, GMPy_doc_context_square },
{ "sub", GMPy_Context_Sub, METH_VARARGS, GMPy_doc_context_sub },
{ "tan", GMPy_Context_Tan, METH_O, GMPy_doc_context_tan },
{ "tanh", GMPy_Context_Tanh, METH_O, GMPy_doc_context_tanh },
{ "trunc", GMPy_Context_Trunc, METH_O, GMPy_doc_context_trunc },
#ifdef VECTOR
{ "vector", GMPy_Context_Vector, METH_O, GMPy_doc_context_vector },
{ "vector2", GMPy_Context_Vector2, METH_VARARGS, GMPy_doc_context_vector2 },
#endif
{ "yn", GMPy_Context_Yn, METH_VARARGS, GMPy_doc_context_yn },
{ "y0", GMPy_Context_Y0, METH_O, GMPy_doc_context_y0 },
{ "y1", GMPy_Context_Y1, METH_O, GMPy_doc_context_y1 },
{ "zeta", GMPy_Context_Zeta, METH_O, GMPy_doc_context_zeta },
{ "__enter__", GMPy_CTXT_Enter, METH_NOARGS, NULL },
{ "__exit__", GMPy_CTXT_Exit, METH_VARARGS, NULL },
{ NULL, NULL, 1 }
};
static PyTypeObject CTXT_Type =
{
#ifdef PY3
PyVarObject_HEAD_INIT(0, 0)
#else
PyObject_HEAD_INIT(0)
0, /* ob_size */
#endif
"gmpy2 context", /* tp_name */
sizeof(CTXT_Object), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) GMPy_CTXT_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_CTXT_Repr_Slot, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"GMPY2 Context Object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset*/
0, /* tp_iter */
0, /* tp_iternext */
GMPyContext_methods, /* tp_methods */
0, /* tp_members */
GMPyContext_getseters, /* tp_getset */
};
static PyMethodDef GMPyContextManager_methods[] =
{
{ "__enter__", GMPy_CTXT_Manager_Enter, METH_NOARGS, NULL },
{ "__exit__", GMPy_CTXT_Manager_Exit, METH_VARARGS, NULL },
{ NULL, NULL, 1 }
};
static PyTypeObject CTXT_Manager_Type =
{
#ifdef PY3
PyVarObject_HEAD_INIT(0, 0)
#else
PyObject_HEAD_INIT(0)
0, /* ob_size */
#endif
"gmpy2 context", /* tp_name */
sizeof(CTXT_Manager_Object), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) GMPy_CTXT_Manager_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_CTXT_Manager_Repr_Slot, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"GMPY2 Context manager", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset*/
0, /* tp_iter */
0, /* tp_iternext */
GMPyContextManager_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
};
gmpy2-2.1.0b3/src/gmpy2_context.h 0000664 0001750 0001750 00000011242 13525427233 016417 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_context.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_CONTEXT_H
#define GMPY_CONTEXT_H
#ifdef __cplusplus
extern "C" {
#endif
#define TRAP_NONE 0
#define TRAP_UNDERFLOW 1
#define TRAP_OVERFLOW 2
#define TRAP_INEXACT 4
#define TRAP_INVALID 8
#define TRAP_ERANGE 16
#define TRAP_DIVZERO 32
/* The actual typedefs have been moved to gmpy2_types.h. */
static PyTypeObject CTXT_Type;
static PyTypeObject CTXT_Manager_Type;
#ifdef WITHOUT_THREADS
#define CURRENT_CONTEXT(obj) obj = module_context;
#else
#define CURRENT_CONTEXT(obj) obj = GMPy_current_context();
#endif
#define CHECK_CONTEXT(context) \
if (!context) CURRENT_CONTEXT(context);
#define CTXT_Check(v) (((PyObject*)v)->ob_type == &CTXT_Type)
#define CTXT_Manager_Check(v) (((PyObject*)v)->ob_type == &CTXT_Manager_Type)
#define GET_MPFR_PREC(c) (c->ctx.mpfr_prec)
#define GET_REAL_PREC(c) ((c->ctx.real_prec==GMPY_DEFAULT)?GET_MPFR_PREC(c):c->ctx.real_prec)
#define GET_IMAG_PREC(c) ((c->ctx.imag_prec==GMPY_DEFAULT)?GET_REAL_PREC(c):c->ctx.imag_prec)
#define GET_MPFR_ROUND(c) (c->ctx.mpfr_round)
#define GET_REAL_ROUND(c) ((c->ctx.real_round==GMPY_DEFAULT)?GET_MPFR_ROUND(c):c->ctx.real_round)
#define GET_IMAG_ROUND(c) ((c->ctx.imag_round==GMPY_DEFAULT)?GET_REAL_ROUND(c):c->ctx.imag_round)
#define GET_MPC_ROUND(c) (MPC_RND(GET_REAL_ROUND(c), GET_IMAG_ROUND(c)))
#define GET_DIV_MODE(c) (c->ctx.rational_division)
static PyObject * GMPy_CTXT_Manager_New(void);
static void GMPy_CTXT_Manager_Dealloc(CTXT_Manager_Object *self);
static PyObject * GMPy_CTXT_Manager_Repr_Slot(CTXT_Manager_Object *self);
static PyObject * GMPy_CTXT_Manager_Enter(PyObject *self, PyObject *args);
static PyObject * GMPy_CTXT_Manager_Exit(PyObject *self, PyObject *args);
static PyObject * GMPy_CTXT_New(void);
static void GMPy_CTXT_Dealloc(CTXT_Object *self);
static PyObject * GMPy_CTXT_Repr_Slot(CTXT_Object *self);
static PyObject * GMPy_CTXT_Get(PyObject *self, PyObject *args);
static PyObject * GMPy_CTXT_Local(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_CTXT_Context(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_CTXT_Set(PyObject *self, PyObject *other);
static PyObject * GMPy_CTXT_Clear_Flags(PyObject *self, PyObject *args);
static PyObject * GMPy_CTXT_Copy(PyObject *self, PyObject *other);
static PyObject * GMPy_CTXT_ieee(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_CTXT_Enter(PyObject *self, PyObject *args);
static PyObject * GMPy_CTXT_Exit(PyObject *self, PyObject *args);
#ifndef WITHOUT_THREADS
static CTXT_Object * GMPy_current_context(void);
#endif
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_convert.c 0000664 0001750 0001750 00000020200 13452457765 016414 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains all the conversion functions for gmpy2.
*
* Overview
* --------
* gmpy2 tries to optimize the performance and accuracy of conversions from
* other numeric types. gmpy2 uses a LBYL (Look Before You Leap) approach and
* identifies the numeric type before conversion before conversion to a gmpy2
* type. The basic operations (+, -, *, /) are optimized to directly work with
* some basic types such as C longs or doubles.
*/
/* ======================================================================== *
* Miscellaneous helper functions. *
* ======================================================================== */
/* Since macros are used in gmpy2's codebase, these functions are skipped
* until they are needed for the C API in the future.
*/
#if 0
static int GMPy_isInteger(PyObject *obj)
{
return IS_INTEGER(obj) ? 1 : 0;
}
static int GMPy_isFraction(PyObject *obj)
{
return (!strcmp(Py_TYPE(obj)->tp_name, "Fraction")) ? 1 : 0;
}
static int GMPy_isRational(PyObject *obj)
{
return IS_RATIONAL(obj) ? 1 : 0;
}
static int GMPy_isReal(PyObject *obj)
{
return IS_REAL(obj) ? 1 : 0;
}
static int GMPy_isComplex(PyObject *obj)
{
return IS_COMPLEX(obj) ? 1 : 0;
}
#endif
/* mpz_set_PyStr converts a Python "string" into a mpz_t structure. It accepts
* a sequence of bytes (i.e. str in Python 2, bytes in Python 3) or a Unicode
* string (i.e. unicode in Python 3, str in Python 3). Returns -1 on error,
* 1 if successful.
*/
static int
mpz_set_PyStr(mpz_ptr z, PyObject *s, int base)
{
char *cp;
Py_ssize_t len, i;
PyObject *ascii_str = NULL;
if (PyBytes_Check(s)) {
len = PyBytes_Size(s);
cp = PyBytes_AsString(s);
}
else if (PyUnicode_Check(s)) {
ascii_str = PyUnicode_AsASCIIString(s);
if (!ascii_str) {
VALUE_ERROR("string contains non-ASCII characters");
return -1;
}
len = PyBytes_Size(ascii_str);
cp = PyBytes_AsString(ascii_str);
}
else {
TYPE_ERROR("object is not string or Unicode");
return -1;
}
/* Don't allow NULL characters */
for (i = 0; i < len; i++) {
if (cp[i] == '\0') {
VALUE_ERROR("string contains NULL characters");
Py_XDECREF(ascii_str);
return -1;
}
}
/* Check for leading base indicators. */
if (base == 0) {
if (len > 2 && cp[0] == '0') {
if (cp[1] == 'b') { base = 2; cp += 2; }
else if (cp[1] == 'o') { base = 8; cp += 2; }
else if (cp[1] == 'x') { base = 16; cp += 2; }
else { base = 10; }
}
else {
base = 10;
}
}
else if (cp[0] == '0') {
/* If the specified base matches the leading base indicators, then
* we need to skip the base indicators.
*/
if (cp[1] =='b' && base == 2) { cp += 2; }
else if (cp[1] =='o' && base == 8) { cp += 2; }
else if (cp[1] =='x' && base == 16) { cp += 2; }
}
/* delegate rest to GMP's _set_str function */
if (-1 == mpz_set_str(z, cp, base)) {
VALUE_ERROR("invalid digits");
Py_XDECREF(ascii_str);
return -1;
}
Py_XDECREF(ascii_str);
return 1;
}
/* Format an mpz into any base (2 to 62). Bits in the option parameter
* control various behaviors:
* bit 0: if set, output is wrapped with mpz(...) or xmpz(...)
* bit 1: if set, a '+' is included for positive numbers
* bit 2: if set, a ' ' is included for positive nubmers
* bit 3: if set, a '0b', '0o', or '0x' is included for binary, octal, hex
* bit 4: if set, no prefix is included for binary, octal, hex
*
* Note: if neither bit 3 or 4 is set, prefixes that match the platform
* default are included.
*
* If base < 0, capital letters are used.
*
* If which = 0, then mpz formatting is used (if bit 0 set). Otherwise xmpz
* formatting is used (if bit 0 is set).
*/
static char* _ztag = "mpz(";
static char* _xztag = "xmpz(";
static PyObject *
mpz_ascii(mpz_t z, int base, int option, int which)
{
PyObject *result;
char *buffer, *p;
int negative = 0;
size_t size;
if (
!(
((base >= -36) && (base <= -2)) ||
((base >= 2) && (base <= 62))
)
) {
VALUE_ERROR("base must be in the interval 2 ... 62");
return NULL;
}
/* Allocate extra space for:
*
* minus sign and trailing NULL byte (2)
* 'xmpz()' tag (6)
* '0x' prefix (2)
* -----
* 10
*
* And add one more to be sure...
*/
size = mpz_sizeinbase(z, (base < 0 ? -base : base)) + 11;
TEMP_ALLOC(buffer, size);
if (mpz_sgn(z) < 0) {
negative = 1;
mpz_neg(z, z);
}
p = buffer;
if (option & 1) {
if (which)
strcpy(p, _xztag);
else
strcpy(p, _ztag);
p += strlen(p);
}
if (negative) {
*(p++) = '-';
}
else {
if (option & 2)
*(p++) = '+';
else if (option & 4)
*(p++) = ' ';
}
if (option & 8) {
if (base == 2) { *(p++) = '0'; *(p++) = 'b'; }
else if (base == 8) { *(p++) = '0'; *(p++) = 'o'; }
else if (base == 16) { *(p++) = '0'; *(p++) = 'x'; }
else if (base == -16) { *(p++) = '0'; *(p++) = 'X'; }
}
else if (!(option & 24)) {
#ifdef PY2
if (base == 8) { *(p++) = '0'; }
#else
if (base == 2) { *(p++) = '0'; *(p++) = 'b'; }
else if (base == 8) { *(p++) = '0'; *(p++) = 'o'; }
#endif
else if (base == 16) { *(p++) = '0'; *(p++) = 'x'; }
else if (base == -16) { *(p++) = '0'; *(p++) = 'X'; }
}
/* Call GMP. */
mpz_get_str(p, base, z);
p = buffer + strlen(buffer);
if (option & 1)
*(p++) = ')';
*(p++) = '\00';
result = Py_BuildValue("s", buffer);
if (negative == 1) {
mpz_neg(z, z);
}
TEMP_FREE(buffer, size);
return result;
}
gmpy2-2.1.0b3/src/gmpy2_convert.h 0000664 0001750 0001750 00000011507 13512447155 016420 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_H
#define GMPY2_CONVERT_H
#ifdef __cplusplus
extern "C" {
#endif
/* The following macros classify the numeric types that are supported by
* gmpy2.
*/
#define HAS_MPZ_CONVERSION(x) PyObject_HasAttrString(x, "__mpz__")
#define HAS_MPQ_CONVERSION(x) PyObject_HasAttrString(x, "__mpq__")
#define HAS_MPFR_CONVERSION(x) PyObject_HasAttrString(x, "__mpfr__")
#define HAS_MPC_CONVERSION(x) PyObject_HasAttrString(x, "__mpc__")
#define HAS_STRICT_MPZ_CONVERSION(x) (HAS_MPZ_CONVERSION(x) && \
!HAS_MPQ_CONVERSION(x))
#define HAS_STRICT_MPFR_CONVERSION(x) (HAS_MPFR_CONVERSION(x) && \
!HAS_MPC_CONVERSION(x))
#define IS_FRACTION(x) (!strcmp(Py_TYPE(x)->tp_name, "Fraction"))
#define IS_RATIONAL_ONLY(x) (MPQ_Check(x) || IS_FRACTION(x) || HAS_MPQ_CONVERSION(x))
#ifdef PY2
#define IS_INTEGER(x) (MPZ_Check(x) || PyInt_Check(x) || \
PyLong_Check(x) || XMPZ_Check(x) || \
HAS_STRICT_MPZ_CONVERSION(x))
#define IS_RATIONAL(x) (MPQ_Check(x) || IS_FRACTION(x) || \
MPZ_Check(x) || PyInt_Check(x) || PyLong_Check(x) || \
XMPZ_Check(x) || HAS_MPQ_CONVERSION(x) || \
HAS_MPZ_CONVERSION(x))
#else
#define IS_INTEGER(x) (MPZ_Check(x) || PyLong_Check(x) || \
XMPZ_Check(x) || HAS_STRICT_MPZ_CONVERSION(x))
#define IS_RATIONAL(x) (MPQ_Check(x) || IS_FRACTION(x) || \
MPZ_Check(x) || PyLong_Check(x) || \
XMPZ_Check(x) || HAS_MPQ_CONVERSION(x) || \
HAS_MPZ_CONVERSION(x))
#endif
#define IS_REAL_ONLY(x) (MPFR_Check(x) || PyFloat_Check(x) || HAS_STRICT_MPFR_CONVERSION(x))
#define IS_REAL(x) (IS_RATIONAL(x) || IS_REAL_ONLY(x))
#define IS_COMPLEX_ONLY(x) (MPC_Check(x) || PyComplex_Check(x) || HAS_MPC_CONVERSION(x))
#define IS_COMPLEX(x) (IS_REAL(x) || IS_COMPLEX_ONLY(x))
/* Since the macros are used in gmpy2's codebase, these functions are skipped
* until they are needed for the C API in the future.
*/
#if 0
/* Checks for mpz, xmpz, and the integer types included with Python. */
static int GMPy_isInteger(PyObject *obj);
/* Checks for the Fraction type included with Python. */
static int GMPy_isFraction(PyObject *obj);
/* Combined mpq, isInteger() and isFraction() check. */
static int GMPy_isRational(PyObject *obj);
/* Combined mpfr, PyFloat, and isRational() check. */
static int GMPy_isReal(PyObject *obj);
/* Combined mpc, PyComplex, and isReal() check. */
static int GMPy_isComplex(PyObject *obj);
#endif
/* ======== C helper routines ======== */
static int mpz_set_PyStr(mpz_ptr z, PyObject *s, int base);
static PyObject * mpz_ascii(mpz_t z, int base, int option, int which);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_convert_gmp.c 0000664 0001750 0001750 00000071351 13473132013 017247 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_gmp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains all the conversion functions for GMP data types.
*
* Overview
* --------
* gmpy2 tries to optimize the performance and accuracy of conversions from
* other numeric types. gmpy2 uses a LBYL (Look Before You Leap) approach and
* identifies the numeric type before conversion before conversion to a gmpy2
* type. The basic operations (+, -, *, /) are optimized to directly work with
* some basic types such as C longs or doubles.
*/
/* ======================================================================== *
* Conversion between native Python objects and MPZ. *
* ======================================================================== */
static MPZ_Object *
GMPy_MPZ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context)
{
MPZ_Object *result;
int negative;
Py_ssize_t len;
PyLongObject *templong = (PyLongObject*)obj;
assert(PyIntOrLong_Check(obj));
if(!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
#ifdef PY2
if (PyInt_Check(obj)) {
mpz_set_si(result->z, PyInt_AS_LONG(obj));
return result;
}
#endif
switch (Py_SIZE(templong)) {
case -1:
mpz_set_si(result->z, -(sdigit)templong->ob_digit[0]);
break;
case 0:
mpz_set_si(result->z, 0);
break;
case 1:
mpz_set_si(result->z, templong->ob_digit[0]);
break;
default:
mpz_set_si(result->z, 0);
if (Py_SIZE(templong) < 0) {
len = - Py_SIZE(templong);
negative = 1;
} else {
len = Py_SIZE(templong);
negative = 0;
}
mpz_import(result->z, len, -1, sizeof(templong->ob_digit[0]), 0,
sizeof(templong->ob_digit[0])*8 - PyLong_SHIFT, templong->ob_digit);
if (negative) {
mpz_neg(result->z, result->z);
}
}
return result;
}
/* To support creation of temporary mpz objects. */
static void
mpz_set_PyIntOrLong(mpz_t z, PyObject *obj)
{
int negative;
Py_ssize_t len;
PyLongObject *templong = (PyLongObject*)obj;
#ifdef PY2
if (PyInt_Check(obj)) {
mpz_set_si(z, PyInt_AS_LONG(obj));
return;
}
#endif
switch (Py_SIZE(templong)) {
case -1:
mpz_set_si(z, -(sdigit)templong->ob_digit[0]);
break;
case 0:
mpz_set_si(z, 0);
break;
case 1:
mpz_set_si(z, templong->ob_digit[0]);
break;
default:
mpz_set_si(z, 0);
if (Py_SIZE(templong) < 0) {
len = - Py_SIZE(templong);
negative = 1;
} else {
len = Py_SIZE(templong);
negative = 0;
}
mpz_import(z, len, -1, sizeof(templong->ob_digit[0]), 0,
sizeof(templong->ob_digit[0])*8 - PyLong_SHIFT, templong->ob_digit);
if (negative) {
mpz_neg(z, z);
}
}
return;
}
static MPZ_Object *
GMPy_MPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context)
{
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_set_PyStr(result->z, s, base) == -1) {
Py_DECREF((PyObject*)result);
return NULL;
}
return result;
}
static MPZ_Object *
GMPy_MPZ_From_PyFloat(PyObject *obj, CTXT_Object *context)
{
MPZ_Object *result;
assert(PyFloat_Check(obj));
if ((result = GMPy_MPZ_New(context))) {
double d = PyFloat_AsDouble(obj);
if (Py_IS_NAN(d)) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'mpz' does not support NaN");
return NULL;
}
if (Py_IS_INFINITY(d)) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'mpz' does not support Infinity");
return NULL;
}
mpz_set_d(result->z, d);
}
return result;
}
static PyObject *
GMPy_PyLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
{
int negative;
size_t count, size;
PyLongObject *result;
assert(CHECK_MPZANY(obj));
/* Assume gmp uses limbs as least as large as the builtin longs do */
assert(mp_bits_per_limb >= PyLong_SHIFT);
if (mpz_sgn(obj->z) < 0) {
negative = 1;
} else {
negative = 0;
}
size = (mpz_sizeinbase(obj->z, 2) + PyLong_SHIFT - 1) / PyLong_SHIFT;
if (!(result = _PyLong_New(size))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_export(result->ob_digit, &count, -1, sizeof(result->ob_digit[0]), 0,
sizeof(result->ob_digit[0])*8 - PyLong_SHIFT, obj->z);
if (count == 0) {
result->ob_digit[0] = 0;
}
/* long_normalize() is file-static so we must reimplement it */
/* longobjp = long_normalize(longobjp); */
while ((size>0) && (result->ob_digit[size-1] == 0)) {
size--;
}
Py_SIZE(result) = size;
if (negative) {
Py_SIZE(result) = - Py_SIZE(result);
}
return (PyObject*)result;
}
#ifdef PY2
static PyObject *
GMPy_MPZ_Long_Slot(MPZ_Object *self)
{
return GMPy_PyLong_From_MPZ(self, NULL);
}
#endif
/* The PyIntOrLong functions should be used when converting a number back
* to a Python value since is automatically returns an "int" or "long" when
* using Python 2.x. The PyLong_From functions (above) should only be used
* when a PyLong is specifically needed for Python 2.x.
*/
static PyObject *
GMPy_PyIntOrLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
{
assert(CHECK_MPZANY(obj));
#ifdef PY2
if (mpz_fits_slong_p(obj->z)) {
/* cast is safe since we know it fits in a signed long */
return PyInt_FromLong((long)mpz_get_si(obj->z));
}
#endif
return GMPy_PyLong_From_MPZ(obj, context);
}
static PyObject *
GMPy_MPZ_Int_Slot(MPZ_Object *self)
{
return GMPy_PyIntOrLong_From_MPZ(self, NULL);
}
static PyObject *
GMPy_PyFloat_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
{
double res;
assert(CHECK_MPZANY(obj));
res = mpz_get_d(obj->z);
if (Py_IS_INFINITY(res)) {
OVERFLOW_ERROR("'mpz' too large to convert to float");
return NULL;
}
return PyFloat_FromDouble(res);
}
static PyObject *
GMPy_MPZ_Float_Slot(MPZ_Object *self)
{
return GMPy_PyFloat_From_MPZ(self, NULL);
}
static PyObject *
GMPy_PyStr_From_MPZ(MPZ_Object *obj, int base, int option, CTXT_Object *context)
{
assert(CHECK_MPZANY(obj));
return mpz_ascii(obj->z, base, option, 0);
}
static MPZ_Object *
GMPy_MPZ_From_Integer(PyObject *obj, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (MPZ_Check(obj)) {
Py_INCREF(obj);
return (MPZ_Object*)obj;
}
if (PyIntOrLong_Check(obj))
return GMPy_MPZ_From_PyIntOrLong(obj, context);
if (XMPZ_Check(obj))
return GMPy_MPZ_From_XMPZ((XMPZ_Object*)obj, context);
if (HAS_STRICT_MPZ_CONVERSION(obj)) {
result = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (result != NULL && MPZ_Check(result)) {
return result;
}
else {
Py_XDECREF((PyObject*)result);
goto error;
}
}
error:
TYPE_ERROR("cannot convert object to mpz");
return NULL;
}
static MPZ_Object *
GMPy_MPZ_From_IntegerAndCopy(PyObject *obj, CTXT_Object *context)
{
MPZ_Object *result = NULL, *temp = NULL;
result = GMPy_MPZ_From_Integer(obj, context);
if (result == NULL)
return result;
if (Py_REFCNT(result) == 1)
return result;
if (!(temp = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_set(temp->z, result->z);
Py_DECREF((PyObject*)result);
return temp;
}
/* str and repr implementations for mpz */
static PyObject *
GMPy_MPZ_Str_Slot(MPZ_Object *self)
{
/* base-10, no tag */
return GMPy_PyStr_From_MPZ(self, 10, 0, NULL);
}
static PyObject *
GMPy_MPZ_Repr_Slot(MPZ_Object *self)
{
/* base-10, with tag */
return GMPy_PyStr_From_MPZ(self, 10, 1, NULL);
}
#ifdef SHARED
/* Helper function for argument parsing. Not used in static build. */
static int
GMPy_MPZ_ConvertArg(PyObject *arg, PyObject **ptr)
{
MPZ_Object *result = GMPy_MPZ_From_Integer(arg, NULL);
if (result) {
*ptr = (PyObject*)result;
return 1;
}
else {
TYPE_ERROR("argument can not be converted to 'mpz'");
return 0;
}
}
#endif
/* ======================================================================== *
* Conversion between native Python objects/MPZ and XMPZ. *
* ======================================================================== */
static XMPZ_Object *
GMPy_XMPZ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context)
{
XMPZ_Object *result;
int negative;
Py_ssize_t len;
PyLongObject *templong = (PyLongObject*)obj;
assert(PyIntOrLong_Check(obj));
if(!(result = GMPy_XMPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
#ifdef PY2
if (PyInt_Check(obj)) {
mpz_set_si(result->z, PyInt_AS_LONG(obj));
return result;
}
#endif
switch (Py_SIZE(templong)) {
case -1:
mpz_set_si(result->z, -(sdigit)templong->ob_digit[0]);
break;
case 0:
mpz_set_si(result->z, 0);
break;
case 1:
mpz_set_si(result->z, templong->ob_digit[0]);
break;
default:
mpz_set_si(result->z, 0);
if (Py_SIZE(templong) < 0) {
len = - Py_SIZE(templong);
negative = 1;
} else {
len = Py_SIZE(templong);
negative = 0;
}
mpz_import(result->z, len, -1, sizeof(templong->ob_digit[0]), 0,
sizeof(templong->ob_digit[0])*8 - PyLong_SHIFT, templong->ob_digit);
if (negative) {
mpz_neg(result->z, result->z);
}
}
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context)
{
XMPZ_Object *result;
if (!(result = GMPy_XMPZ_New(context)))
return NULL;
if (mpz_set_PyStr(result->z, s, base) == -1) {
Py_DECREF((PyObject*)result);
return NULL;
}
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_PyFloat(PyObject *obj, CTXT_Object *context)
{
XMPZ_Object *result;
assert(PyFloat_Check(obj));
if ((result = GMPy_XMPZ_New(context))) {
double d = PyFloat_AsDouble(obj);
if (Py_IS_NAN(d)) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'xmpz' does not support NaN");
return NULL;
}
if (Py_IS_INFINITY(d)) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'xmpz' does not support Infinity");
return NULL;
}
mpz_set_d(result->z, d);
}
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
{
XMPZ_Object *result;
assert(CHECK_MPZANY(obj));
if ((result = GMPy_XMPZ_New(context)))
mpz_set(result->z, obj->z);
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context)
{
XMPZ_Object *result;
assert(XMPZ_Check(obj));
if ((result = GMPy_XMPZ_New(context)))
mpz_set(result->z, obj->z);
return result;
}
static PyObject *
GMPy_PyStr_From_XMPZ(XMPZ_Object *obj, int base, int option, CTXT_Object *context)
{
assert(XMPZ_Check(obj));
return mpz_ascii(obj->z, base, option, 1);
}
static MPZ_Object *
GMPy_MPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context)
{
MPZ_Object *result;
assert(XMPZ_Check(obj));
if ((result = GMPy_MPZ_New(context)))
mpz_set(result->z, obj->z);
return result;
}
/* str and repr implementations for xmpz */
static PyObject *
GMPy_XMPZ_Str_Slot(XMPZ_Object *self)
{
/* base-10, no tag */
return GMPy_PyStr_From_XMPZ(self, 10, 0, NULL);
}
static PyObject *
GMPy_XMPZ_Repr_Slot(XMPZ_Object *self)
{
/* base-10, with tag */
return GMPy_PyStr_From_XMPZ(self, 10, 1, NULL);
}
/* ======================================================================== *
* Conversion between native Python objects/MPZ/XMPZ and MPQ. *
* ======================================================================== */
static MPQ_Object *
GMPy_MPQ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context)
{
MPQ_Object *result;
MPZ_Object *temp;
assert(PyIntOrLong_Check(obj));
temp = GMPy_MPZ_From_PyIntOrLong(obj, context);
if (!temp)
return NULL;
if ((result = GMPy_MPQ_New(context))) {
mpq_set_z(result->q, temp->z);
Py_DECREF((PyObject*)temp);
}
return result;
}
static MPQ_Object *
GMPy_MPQ_From_PyStr(PyObject *s, int base, CTXT_Object *context)
{
MPQ_Object *result;
char *cp;
char exp_char = 'E';
Py_ssize_t len, i;
PyObject *ascii_str = NULL;
long expt = 0;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (PyBytes_Check(s)) {
len = PyBytes_Size(s);
cp = PyBytes_AsString(s);
}
else if (PyUnicode_Check(s)) {
ascii_str = PyUnicode_AsASCIIString(s);
if (!ascii_str) {
VALUE_ERROR("string contains non-ASCII characters");
goto error;
}
len = PyBytes_Size(ascii_str);
cp = PyBytes_AsString(ascii_str);
}
else {
TYPE_ERROR("object is not string or Unicode");
goto error;
}
/* Don't allow NULL characters */
for (i = 0; i < len; i++) {
if (cp[i] == '\0') {
VALUE_ERROR("string contains NULL characters");
goto error;
}
}
{
char *whereslash = strchr((char*)cp, '/');
char *wheredot = strchr((char*)cp, '.');
char *whereexp = strchr((char*)cp, 'E');
if (!whereexp) {
whereexp = strchr((char*)cp, 'e');
exp_char = 'e';
}
if (whereslash && wheredot) {
VALUE_ERROR("illegal string: both . and / found");
goto error;
}
if (wheredot && (base != 10)) {
VALUE_ERROR("illegal string: embedded . requires base=10");
goto error;
}
/* If base=10, no slash is found, and an exponent symbol is found, then
* assume we have decimal number in scientific format.
*/
if (whereexp && !whereslash && (base == 10)) {
/* Temporarily shorten the string and continue processing as
* normal. We'll deal with the exponent later.
*/
*whereexp = '\0';
expt = atol(whereexp+1);
}
/* Handle the case where an embedded decimal point exists. An optional
* exponent is also allowed. We take advantage of the fact that
* mpz_set_str() ignores embedded space characters. We count the
* number of digits after the decimal point and then replace the '.'
* with a ' '. We've already inserted a NUL byte to terminate the
* string in the case when an exponent was entered. The value for
* the exponent has already been read.
*/
if (wheredot) {
char *counter;
long digits = 0;
counter = wheredot;
digits = 0;
*wheredot = ' ';
while (*++counter != '\0') {
if (isdigit(*counter))
digits++;
}
if (-1 == mpz_set_str(mpq_numref(result->q), (char*)cp, base)) {
if (wheredot)
*wheredot = '.';
/* Restore the exponent! */
if (whereexp && !whereslash && (base == 10))
*whereexp = exp_char;
VALUE_ERROR("invalid digits");
goto error;
}
/* Process the exponent. */
digits = expt - digits;
if (digits < 0) {
mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(-digits));
}
else {
/* Use the denominator instead of a temporary variable. */
mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(digits));
mpz_mul(mpq_numref(result->q), mpq_numref(result->q), mpq_denref(result->q));
mpz_set_ui(mpq_denref(result->q), 1);
}
mpq_canonicalize(result->q);
/* Restore the decimal point. */
*wheredot = '.';
/* Restore the exponent! */
if (whereexp && (base == 10))
*whereexp = exp_char;
goto finish;
}
if (whereslash)
*whereslash = '\0';
/* Read the numerator. */
if (-1 == mpz_set_str(mpq_numref(result->q), (char*)cp, base)) {
if (whereslash)
*whereslash = '/';
VALUE_ERROR("invalid digits");
goto error;
}
/* If a slash was present, read the denominator. */
if (whereslash) {
*whereslash = '/';
if (-1 == mpz_set_str(mpq_denref(result->q), whereslash+1, base)) {
VALUE_ERROR("invalid digits");
goto error;
}
if (0 == mpz_sgn(mpq_denref(result->q))) {
ZERO_ERROR("zero denominator in mpq()");
goto error;
}
mpq_canonicalize(result->q);
}
else {
/* Since no slash was present, either the denominator is 1 or a
* power of 10.
*/
if (expt <= 0) {
mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(-expt));
}
else {
mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(expt));
mpz_mul(mpq_numref(result->q), mpq_numref(result->q), mpq_denref(result->q));
mpz_set_ui(mpq_denref(result->q), 1);
}
mpq_canonicalize(result->q);
if (whereexp && (base == 10))
*whereexp = exp_char;
}
}
finish:
Py_XDECREF(ascii_str);
return result;
error:
Py_DECREF((PyObject*)result);
Py_XDECREF(ascii_str);
return NULL;
}
static MPQ_Object *
GMPy_MPQ_From_PyFloat(PyObject *obj, CTXT_Object *context)
{
MPQ_Object *result;
assert(PyFloat_Check(obj));
if ((result = GMPy_MPQ_New(context))) {
double d = PyFloat_AsDouble(obj);
if (Py_IS_NAN(d)) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'mpq' does not support NaN");
return NULL;
}
if (Py_IS_INFINITY(d)) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'mpq' does not support Infinity");
return NULL;
}
mpq_set_d(result->q, d);
}
return result;
}
static MPQ_Object *
GMPy_MPQ_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
{
MPQ_Object *result;
assert(CHECK_MPZANY(obj));
if ((result = GMPy_MPQ_New(context)))
mpq_set_z(result->q, obj->z);
return result;
}
static MPQ_Object *
GMPy_MPQ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context)
{
MPQ_Object *result;
assert(XMPZ_Check(obj));
if ((result = GMPy_MPQ_New(context)))
mpq_set_z(result->q, obj->z);
return result;
}
static MPZ_Object *
GMPy_MPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
MPZ_Object *result;
assert(MPQ_Check(obj));
if ((result = GMPy_MPZ_New(context)))
mpz_set_q(result->z, obj->q);
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
XMPZ_Object *result;
assert(MPQ_Check(obj));
if ((result = GMPy_XMPZ_New(context)))
mpz_set_q(result->z, obj->q);
return result;
}
#ifdef PY2
static PyObject *
GMPy_PyLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
PyObject *result;
MPZ_Object *temp;
assert(MPQ_Check(obj));
temp = GMPy_MPZ_From_MPQ(obj, context);
if (!temp) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
result = GMPy_PyLong_From_MPZ(temp, context);
Py_DECREF((PyObject*)temp);
return result;
}
static PyObject *
GMPy_MPQ_Long_Slot(MPQ_Object *self)
{
return GMPy_PyLong_From_MPQ(self, NULL);
}
#endif
static PyObject *
GMPy_PyIntOrLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
PyObject *result;
MPZ_Object *temp;
assert(MPQ_Check(obj));
temp = GMPy_MPZ_From_MPQ(obj, context);
if (!temp) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
result = GMPy_PyIntOrLong_From_MPZ(temp, context);
Py_DECREF((PyObject*)temp);
return result;
}
static PyObject *
GMPy_MPQ_Int_Slot(MPQ_Object *self)
{
return GMPy_PyIntOrLong_From_MPQ(self, NULL);
}
static char* _qtag = "mpq(";
static PyObject *
GMPy_PyStr_From_MPQ(MPQ_Object *obj, int base, int option, CTXT_Object *context)
{
PyObject *result = NULL, *numstr = NULL, *denstr = NULL;
char buffer[50], *p;
numstr = mpz_ascii(mpq_numref(obj->q), base, 0, 0);
if (!numstr) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* Check if denominator is 1 and no tag is requested. If so, just
* return the numerator.
*/
if (!(option & 1) && (0 == mpz_cmp_ui(mpq_denref(obj->q),1)))
return numstr;
denstr = mpz_ascii(mpq_denref(obj->q), base, 0, 0);
if (!denstr) {
/* LCOV_EXCL_START */
Py_DECREF(numstr);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Build the format string. */
p = buffer;
if (option & 1) {
strcpy(p, _qtag);
p += strlen(p);
}
#ifdef PY2
*(p++) = '%';
*(p++) = 's';
if (option & 1)
*(p++) = ',';
else
*(p++) = '/';
*(p++) = '%';
*(p++) = 's';
if (option & 1)
*(p++) = ')';
*(p++) = '\00';
result = PyString_FromFormat(buffer, PyString_AS_STRING(numstr),
PyString_AS_STRING(denstr));
#else
*(p++) = '%';
*(p++) = 'U';
if (option & 1)
*(p++) = ',';
else
*(p++) = '/';
*(p++) = '%';
*(p++) = 'U';
if (option & 1)
*(p++) = ')';
*(p++) = '\00';
result = PyUnicode_FromFormat(buffer, numstr, denstr);
#endif
Py_DECREF(numstr);
Py_DECREF(denstr);
return result;
}
static PyObject *
GMPy_PyFloat_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
double res;
assert(MPQ_Check(obj));
res = mpq_get_d(obj->q);
if (Py_IS_INFINITY(res)) {
OVERFLOW_ERROR("'mpq' too large to convert to float");
return NULL;
}
return PyFloat_FromDouble(res);
}
static PyObject *
GMPy_MPQ_Float_Slot(MPQ_Object *self)
{
return GMPy_PyFloat_From_MPQ(self, NULL);
}
static MPQ_Object*
GMPy_MPQ_From_Fraction(PyObject* obj, CTXT_Object *context)
{
MPQ_Object *result;
PyObject *num, *den;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_set_si(result->q, 0, 1);
num = PyObject_GetAttrString(obj, "numerator");
den = PyObject_GetAttrString(obj, "denominator");
if (!num || !PyIntOrLong_Check(num) || !den || !PyIntOrLong_Check(den)) {
SYSTEM_ERROR("Object does not appear to be Fraction");
Py_XDECREF(num);
Py_XDECREF(den);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_set_PyIntOrLong(mpq_numref(result->q), num);
mpz_set_PyIntOrLong(mpq_denref(result->q), den);
Py_DECREF(num);
Py_DECREF(den);
return result;
}
static MPQ_Object*
GMPy_MPQ_From_Number(PyObject *obj, CTXT_Object *context)
{
if (MPQ_Check(obj)) {
Py_INCREF(obj);
return (MPQ_Object*)obj;
}
if (MPZ_Check(obj))
return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context);
if (MPFR_Check(obj))
return GMPy_MPQ_From_MPFR((MPFR_Object*)obj, context);
if (PyFloat_Check(obj))
return GMPy_MPQ_From_PyFloat(obj, context);
if (PyIntOrLong_Check(obj))
return GMPy_MPQ_From_PyIntOrLong(obj, context);
if (XMPZ_Check(obj))
return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context);
if (IS_FRACTION(obj))
return GMPy_MPQ_From_Fraction(obj, context);
if (HAS_MPQ_CONVERSION(obj)) {
MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
if (res != NULL && MPQ_Check(res)) {
return res;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (HAS_MPZ_CONVERSION(obj)) {
MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (res != NULL && MPZ_Check(res)) {
MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
error:
TYPE_ERROR("cannot convert object to mpq");
return NULL;
}
static MPQ_Object*
GMPy_MPQ_From_RationalAndCopy(PyObject *obj, CTXT_Object *context)
{
MPQ_Object *result = NULL, *temp = NULL;
result = GMPy_MPQ_From_Rational(obj, context);
if (result == NULL)
return result;
if (Py_REFCNT(result) == 1)
return result;
if (!(temp = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_set(temp->q, result->q);
Py_DECREF((PyObject*)result);
return temp;
}
static MPQ_Object*
GMPy_MPQ_From_Rational(PyObject *obj, CTXT_Object *context)
{
if (MPQ_Check(obj)) {
Py_INCREF(obj);
return (MPQ_Object*)obj;
}
if (MPZ_Check(obj))
return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context);
if (PyIntOrLong_Check(obj))
return GMPy_MPQ_From_PyIntOrLong(obj, context);
if (XMPZ_Check(obj))
return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context);
if (IS_FRACTION(obj))
return GMPy_MPQ_From_Fraction(obj, context);
TYPE_ERROR("cannot convert object to mpq");
return NULL;
}
/*
* coerce any number to a mpq
*/
#ifdef SHARED
/* Helper function for argument parsing. Not used in static build. */
int
GMPy_MPQ_ConvertArg(PyObject *arg, PyObject **ptr)
{
MPQ_Object* result = GMPy_MPQ_From_Number(arg, NULL);
if (result) {
*ptr = (PyObject*)result;
return 1;
}
else {
if (!PyErr_Occurred()) {
TYPE_ERROR("argument can not be converted to 'mpq'");
}
return 0;
}
}
#endif
/* str and repr implementations for mpq */
static PyObject *
GMPy_MPQ_Str_Slot(MPQ_Object *self)
{
/* base-10, no tag */
return GMPy_PyStr_From_MPQ(self, 10, 0, NULL);
}
static PyObject *
GMPy_MPQ_Repr_Slot(MPQ_Object *self)
{
/* base-10, with tag */
return GMPy_PyStr_From_MPQ(self, 10, 1, NULL);
}
gmpy2-2.1.0b3/src/gmpy2_convert_gmp.h 0000664 0001750 0001750 00000015006 13473132037 017255 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert_gmp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_GMP_H
#define GMPY2_CONVERT_GMP_H
#ifdef __cplusplus
extern "C" {
#endif
/* ======================================================================== *
* Conversion between native Python objects and MPZ. *
* ======================================================================== */
static MPZ_Object * GMPy_MPZ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_PyFloat(PyObject *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_Integer(PyObject *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_IntegerAndCopy(PyObject *obj, CTXT_Object *context);
static PyObject * GMPy_MPZ_Str_Slot(MPZ_Object *self);
static PyObject * GMPy_MPZ_Repr_Slot(MPZ_Object *self);
#ifdef PY2
static PyObject * GMPy_PyLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_MPZ_Long_Slot(MPZ_Object *self);
#endif
static PyObject * GMPy_PyIntOrLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_PyFloat_From_MPZ(MPZ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_PyStr_From_MPZ(MPZ_Object *obj, int base, int option, CTXT_Object *context);
#ifdef SHARED
/* static int GMPy_MPZ_ConvertArg(PyObject *arg, PyObject **ptr); */
static GMPy_MPZ_ConvertArg_RETURN GMPy_MPZ_ConvertArg GMPy_MPZ_ConvertArg_PROTO;
#endif
/* ======================================================================== *
* Conversion between native Python objects/MPZ and XMPZ. *
* ======================================================================== */
static XMPZ_Object * GMPy_XMPZ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_PyFloat(PyObject *self, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_MPZ(MPZ_Object *obj, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_XMPZ_Str_Slot(XMPZ_Object *self);
static PyObject * GMPy_XMPZ_Repr_Slot(XMPZ_Object *self);
static PyObject * GMPy_PyStr_From_XMPZ(XMPZ_Object *self, int base, int option, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context);
/* ======================================================================== *
* Conversion between native Python objects/MPZ/XMPZ and MPQ. *
* ======================================================================== */
static MPQ_Object * GMPy_MPQ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_PyStr(PyObject *s, int base, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_PyFloat(PyObject *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_Fraction(PyObject *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_MPZ(MPZ_Object *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_Rational(PyObject* obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_Number(PyObject* obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_RationalAndCopy(PyObject* obj, CTXT_Object *context);
static PyObject * GMPy_PyIntOrLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_PyStr_From_MPQ(MPQ_Object *obj, int base, int option, CTXT_Object *context);
static PyObject * GMPy_PyFloat_From_MPQ(MPQ_Object *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context);
/* support str() and repr() */
static PyObject * GMPy_MPQ_Str_Slot(MPQ_Object *obj);
static PyObject * GMPy_MPQ_Repr_Slot(MPQ_Object *obj);
static PyObject * GMPy_MPQ_Float_Slot(MPQ_Object *obj);
static PyObject * GMPy_MPQ_Int_Slot(MPQ_Object *obj);
#ifdef PY2
static PyObject * GMPy_PyLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_MPQ_Long_Slot(MPQ_Object *obj);
#endif
#ifdef SHARED
/* int GMPy_MPQ_convert_arg(PyObject *arg, PyObject **ptr); */
static GMPy_MPQ_ConvertArg_RETURN GMPy_MPQ_ConvertArg GMPy_MPQ_ConvertArg_PROTO;
#endif
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_convert_mpc.c 0000664 0001750 0001750 00000045735 13525427233 017263 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_mpc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Please see the documentation for GMPy_MPFR_From_MPFR for detailed
* description of this function.
*/
static MPC_Object *
GMPy_MPC_From_MPC(MPC_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
assert(MPC_Check(obj));
/* Optimize the critical case when prec==1 or obj is NaN or Inf. */
if ((rprec == 1 && iprec == 1) ||
(!mpfr_number_p(mpc_realref(obj->c)) && !mpfr_number_p(mpc_imagref(obj->c)))) {
Py_INCREF((PyObject*)obj);
return obj;
}
CHECK_CONTEXT(context);
if (rprec == 0)
rprec = GET_REAL_PREC(context);
else if (rprec == 1)
rprec = mpfr_get_prec(mpc_realref(obj->c));
if (iprec == 0)
iprec = GET_IMAG_PREC(context);
else if (iprec == 1)
iprec = mpfr_get_prec(mpc_imagref(obj->c));
/* Try to identify when an additional reference to existing instance can
* be returned. It is possible when (1) the precision matches, (2) the
* exponent is valid and not in the range that might require subnormal-
* ization, and (3) subnormalize is not enabled.
*/
if ((rprec == mpfr_get_prec(mpc_realref(obj->c))) &&
(iprec == mpfr_get_prec(mpc_imagref(obj->c))) &&
(!context->ctx.subnormalize) &&
(mpc_realref(obj->c)->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(mpc_realref(obj->c)) - 1)) &&
(mpc_realref(obj->c)->_mpfr_exp <= context->ctx.emax) &&
(mpc_imagref(obj->c)->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(mpc_imagref(obj->c)) - 1)) &&
(mpc_imagref(obj->c)->_mpfr_exp <= context->ctx.emax)
) {
Py_INCREF((PyObject*)obj);
return obj;
}
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set(result->c, obj->c, GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_PyComplex(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result;
assert(PyComplex_Check(obj));
CHECK_CONTEXT(context);
if (rprec == 0)
rprec = GET_REAL_PREC(context);
else if (rprec == 1)
rprec = DBL_MANT_DIG;
if (iprec == 0)
iprec = GET_IMAG_PREC(context);
else if (iprec == 1)
rprec = DBL_MANT_DIG;
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_d_d(result->c, PyComplex_RealAsDouble(obj),
PyComplex_ImagAsDouble(obj), GET_MPC_ROUND(context));
if (rprec != 1 || iprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_MPFR(MPFR_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result;
assert(MPFR_Check(obj));
CHECK_CONTEXT(context);
if (rprec == 0)
rprec = GET_REAL_PREC(context);
else if (rprec == 1)
rprec = mpfr_get_prec(obj->f);
if (iprec == 0)
iprec = GET_IMAG_PREC(context);
else if (iprec == 1)
rprec = mpfr_get_prec(obj->f);
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_fr(result->c, obj->f, GET_MPC_ROUND(context));
if (rprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_PyFloat(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
assert(PyFloat_Check(obj));
if (rprec == 0)
rprec = GET_REAL_PREC(context);
else if (rprec == 1)
rprec = DBL_MANT_DIG;
if (iprec == 0)
iprec = GET_IMAG_PREC(context);
else if (iprec == 1)
rprec = DBL_MANT_DIG;
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_d(result->c, PyFloat_AS_DOUBLE(obj),
GET_MPC_ROUND(context));
if (rprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_MPZ(MPZ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
assert(CHECK_MPZANY(obj));
CHECK_CONTEXT(context);
if (rprec < 2) {
rprec = GET_REAL_PREC(context);
}
if (iprec < 2) {
iprec = GET_IMAG_PREC(context);
}
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_z(result->c, obj->z, GET_MPC_ROUND(context));
if (rprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_MPQ(MPQ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
assert(MPQ_Check(obj));
CHECK_CONTEXT(context);
if (rprec < 2) {
rprec = GET_REAL_PREC(context);
}
if (iprec < 2) {
iprec = GET_IMAG_PREC(context);
}
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_q(result->c, obj->q, GET_MPC_ROUND(context));
if (rprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_Fraction(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
MPQ_Object *tempq;
assert(IS_RATIONAL(obj));
CHECK_CONTEXT(context);
if ((tempq = GMPy_MPQ_From_Fraction(obj, context))) {
result = GMPy_MPC_From_MPQ(tempq, rprec, iprec, context);
Py_DECREF((PyObject*)tempq);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_PyIntOrLong(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
MPZ_Object *tempz;
assert(PyIntOrLong_Check(obj));
CHECK_CONTEXT(context);
if ((tempz = GMPy_MPZ_From_PyIntOrLong(obj, context))) {
result = GMPy_MPC_From_MPZ(tempz, rprec, iprec, context);
Py_DECREF((PyObject*)tempz);
}
return result;
}
/* Python's string representation of a complex number differs from the format
* used by MPC. Both MPC and Python surround the complex number with '(' and
* ')' but Python adds a 'j' after the imaginary component and MPC requires a
* space between the real and imaginery components. GMPy_MPC_From_PyStr tries
* to work around the differences as by reading two MPFR-compatible numbers
* from the string and storing into the real and imaginary components
* respectively.
*/
static MPC_Object *
GMPy_MPC_From_PyStr(PyObject *s, int base, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result;
PyObject *ascii_str = NULL;
Py_ssize_t len;
char *cp, *unwind, *tempchar, *lastchar;
int firstp = 0, lastp = 0, real_rc = 0, imag_rc = 0;
CHECK_CONTEXT(context);
if (PyBytes_Check(s)) {
len = PyBytes_Size(s);
cp = (char*)PyBytes_AsString(s);
}
else if (PyUnicode_Check(s)) {
ascii_str = PyUnicode_AsASCIIString(s);
if (!ascii_str) {
VALUE_ERROR("string contains non-ASCII characters");
return NULL;
}
len = PyBytes_Size(ascii_str);
cp = (char*)PyBytes_AsString(ascii_str);
}
else {
TYPE_ERROR("string required");
return NULL;
}
/* Don't allow NULL characters */
if ((Py_ssize_t)strlen(cp) != len) {
VALUE_ERROR("string without NULL characters expected");
Py_XDECREF(ascii_str);
return NULL;
}
if (!(result = GMPy_MPC_New(rprec, iprec, context))) {
Py_XDECREF(ascii_str);
return NULL;
}
/* Get a pointer to the last valid character (ignoring trailing
* whitespace.) */
lastchar = cp + len - 1;
while (isspace(*lastchar))
lastchar--;
/* Skip trailing ). */
if (*lastchar == ')') {
lastp = 1;
lastchar--;
}
/* Skip trailing j. */
if (*lastchar == 'j')
lastchar--;
/* Skip leading whitespace. */
while (isspace(*cp))
cp++;
/* Skip a leading (. */
if (*cp == '(') {
firstp = 1;
cp++;
}
if (firstp != lastp) goto invalid_string;
/* Read the real component first. */
unwind = cp;
real_rc = mpfr_strtofr(mpc_realref(result->c), cp, &tempchar, base,
GET_REAL_ROUND(context));
/* Verify that at least one valid character was read. */
if (cp == tempchar) goto invalid_string;
/* If the next character is a j, then the real component is 0 and
* we just read the imaginary componenet.
*/
if (*tempchar == 'j') {
mpfr_set_zero(mpc_realref(result->c), MPFR_RNDN);
cp = unwind;
}
else {
/* Read the imaginary component next. */
cp = tempchar;
}
imag_rc = mpfr_strtofr(mpc_imagref(result->c), cp, &tempchar, base,
GET_IMAG_ROUND(context));
if (cp == tempchar && tempchar > lastchar)
goto valid_string;
if (*tempchar != 'j' && *cp != ' ')
goto invalid_string;
if (tempchar <= lastchar)
goto invalid_string;
valid_string:
Py_XDECREF(ascii_str);
result->rc = MPC_INEX(real_rc, imag_rc);
if (rprec != 1 || iprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
return result;
invalid_string:
VALUE_ERROR("invalid string in mpc()");
Py_DECREF((PyObject*)result);
Py_XDECREF(ascii_str);
return NULL;
}
/* See the comments for GMPy_MPFR_From_Real_Temp. */
static MPC_Object *
GMPy_MPC_From_Complex(PyObject* obj, mp_prec_t rprec, mp_prec_t iprec,
CTXT_Object *context)
{
CHECK_CONTEXT(context);
if (MPC_Check(obj))
return GMPy_MPC_From_MPC((MPC_Object*)obj, rprec, iprec, context);
if (MPFR_Check(obj))
return GMPy_MPC_From_MPFR((MPFR_Object*)obj, rprec, iprec, context);
if (PyFloat_Check(obj))
return GMPy_MPC_From_PyFloat(obj, rprec, iprec, context);
if (PyComplex_Check(obj))
return GMPy_MPC_From_PyComplex(obj, rprec, iprec, context);
if (MPQ_Check(obj))
return GMPy_MPC_From_MPQ((MPQ_Object*)obj, rprec, iprec, context);
if (MPZ_Check(obj) || XMPZ_Check(obj))
return GMPy_MPC_From_MPZ((MPZ_Object*)obj, rprec, iprec, context);
if (PyIntOrLong_Check(obj))
return GMPy_MPC_From_PyIntOrLong(obj, rprec, iprec, context);
if (IS_FRACTION(obj))
return GMPy_MPC_From_Fraction(obj, rprec, iprec, context);
if (HAS_MPC_CONVERSION(obj)) {
MPC_Object * res = (MPC_Object *) PyObject_CallMethod(obj, "__mpc__", NULL);
if (res != NULL && MPC_Check(res)) {
return res;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (HAS_MPFR_CONVERSION(obj)) {
MPFR_Object * res = (MPFR_Object *) PyObject_CallMethod(obj, "__mpfr__", NULL);
if (res != NULL && MPFR_Check(res)) {
MPC_Object * temp = GMPy_MPC_From_MPFR(res, rprec, iprec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (HAS_MPQ_CONVERSION(obj)) {
MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
if (res != NULL && MPQ_Check(res)) {
MPC_Object * temp = GMPy_MPC_From_MPQ(res, rprec, iprec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (HAS_MPZ_CONVERSION(obj)) {
MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (res != NULL && MPZ_Check(res)) {
MPC_Object * temp = GMPy_MPC_From_MPZ(res, rprec, iprec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
error:
TYPE_ERROR("object could not be converted to 'mpc'");
return NULL;
}
#if 0
static MPC_Object *
GMPy_MPC_From_ComplexAndCopy(PyObject* obj, mp_prec_t rprec, mp_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL, *temp = NULL;
result = GMPy_MPC_From_Complex(obj, rprec, iprec, context);
if (result == NULL)
return result;
if (Py_REFCNT(result) == 1)
return result;
if (!(temp = GMPy_MPC_New(rprec = mpfr_get_prec(mpc_realref(result->c)),
iprec = mpfr_get_prec(mpc_imagref(result->c)),
context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* Since the precision of temp is the same as the precision of result,
* there shouldn't be any rounding.
*/
mpc_set(temp->c, result->c, MPFR_RNDN);
Py_DECREF((PyObject*)result);
return temp;
}
#endif
static PyObject *
GMPy_PyStr_From_MPC(MPC_Object *self, int base, int digits, CTXT_Object *context)
{
PyObject *tempreal = 0, *tempimag = 0, *result;
CHECK_CONTEXT(context);
if (!((base >= 2) && (base <= 62))) {
VALUE_ERROR("base must be in the interval [2,62]");
return NULL;
}
if ((digits < 0) || (digits == 1)) {
VALUE_ERROR("digits must be 0 or >= 2");
return NULL;
}
tempreal = mpfr_ascii(mpc_realref(self->c), base, digits,
MPC_RND_RE(GET_MPC_ROUND(context)));
tempimag = mpfr_ascii(mpc_imagref(self->c), base, digits,
MPC_RND_IM(GET_MPC_ROUND(context)));
if (!tempreal || !tempimag) {
Py_XDECREF(tempreal);
Py_XDECREF(tempimag);
return NULL;
}
result = Py_BuildValue("(NN)", tempreal, tempimag);
if (!result) {
Py_DECREF(tempreal);
Py_DECREF(tempimag);
}
return result;
}
static PyObject *
GMPy_MPC_Float_Slot(PyObject *self)
{
TYPE_ERROR("can't covert 'mpc' to 'float'");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_mpc_complex, "Convert 'mpc' to 'complex'.");
static PyObject *
GMPy_PyComplex_From_MPC(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
double real, imag;
CHECK_CONTEXT(context);
real = mpfr_get_d(mpc_realref(MPC(self)), GET_REAL_ROUND(context));
imag = mpfr_get_d(mpc_imagref(MPC(self)), GET_IMAG_ROUND(context));
return PyComplex_FromDoubles(real, imag);
}
#ifdef PY2
static PyObject *
GMPy_MPC_Long_Slot(PyObject *self)
{
TYPE_ERROR("can't covert mpc to long");
return NULL;
}
#endif
static PyObject *
GMPy_MPC_Int_Slot(PyObject *self)
{
TYPE_ERROR("can't covert mpc to int");
return NULL;
}
#ifdef SHARED
/*
* coerce any number to a mpc
*/
int
GMPy_MPC_ConvertArg(PyObject *arg, PyObject **ptr)
{
MPC_Object *newob = GMPy_MPC_From_Complex(arg, 0, 0, NULL);
if (newob) {
*ptr = (PyObject*)newob;
return 1;
}
else {
TYPE_ERROR("can't convert argument to 'mpc'");
return 0;
}
}
#endif
/* str and repr implementations for mpc */
static PyObject *
GMPy_MPC_Str_Slot(MPC_Object *self)
{
PyObject *result, *temp;
mpfr_prec_t rbits, ibits;
long rprec, iprec;
char fmtstr[60];
mpc_get_prec2(&rbits, &ibits, MPC(self));
rprec = (long)(log10(2) * (double)rbits) + 2;
iprec = (long)(log10(2) * (double)ibits) + 2;
sprintf(fmtstr, "{0:.%ld.%ldg}", rprec, iprec);
temp = Py_BuildValue("s", fmtstr);
if (!temp)
return NULL;
result = PyObject_CallMethod(temp, "format", "O", self);
Py_DECREF(temp);
return result;
}
static PyObject *
GMPy_MPC_Repr_Slot(MPC_Object *self)
{
PyObject *result, *temp;
mpfr_prec_t rbits, ibits;
long rprec, iprec;
char fmtstr[60];
mpc_get_prec2(&rbits, &ibits, MPC(self));
rprec = (long)(log10(2) * (double)rbits) + 2;
iprec = (long)(log10(2) * (double)ibits) + 2;
if (rbits != DBL_MANT_DIG || ibits !=DBL_MANT_DIG)
sprintf(fmtstr, "mpc('{0:.%ld.%ldg}',(%ld,%ld))",
rprec, iprec, rbits, ibits);
else
sprintf(fmtstr, "mpc('{0:.%ld.%ldg}')", rprec, iprec);
temp = Py_BuildValue("s", fmtstr);
if (!temp)
return NULL;
result = PyObject_CallMethod(temp, "format", "O", self);
Py_DECREF(temp);
return result;
}
gmpy2-2.1.0b3/src/gmpy2_convert_mpc.h 0000664 0001750 0001750 00000010344 13452460010 017241 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_mpc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_MPC_H
#define GMPY2_CONVERT_MPC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Conversions with Pympc */
static MPC_Object * GMPy_MPC_From_MPC(MPC_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_PyComplex(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_MPFR(MPFR_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_PyFloat(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_MPZ(MPZ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_MPQ(MPQ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_Fraction(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_PyIntOrLong(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_PyStr(PyObject *s, int base, mpfr_prec_t rbits, mpfr_prec_t ibits, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_Complex(PyObject* obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
#if 0
static MPC_Object * GMPy_MPC_From_ComplexAndCopy(PyObject* obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
#endif
static PyObject * GMPy_MPC_Float_Slot(PyObject *self);
#ifdef PY2
static PyObject * GMPy_MPC_Long_Slot(PyObject *self);
#endif
static PyObject * GMPy_MPC_Int_Slot(PyObject *self);
static PyObject * GMPy_PyStr_From_MPC(MPC_Object *self, int base, int digits, CTXT_Object *context);
static PyObject * GMPy_PyComplex_From_MPC(PyObject *self, PyObject *other);
/* support str() and repr() */
static PyObject * GMPy_MPC_Str_Slot(MPC_Object *self);
static PyObject * GMPy_MPC_Repr_Slot(MPC_Object *self);
/* Miscellaneous */
#ifdef SHARED
/* static int GMPy_MPC_convert_arg(PyObject *arg, PyObject **ptr); */
static GMPy_MPC_ConvertArg_RETURN GMPy_MPC_ConvertArg GMPy_MPC_ConvertArg_PROTO;
#endif
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_convert_mpfr.c 0000664 0001750 0001750 00000066377 13525427233 017455 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert_mpfr.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains all the conversion functions for MPFR data types.
*
* Overview
* --------
* gmpy2 tries to optimize the performance and accuracy of conversions from
* other numeric types. The basic operations (+, -, *, /) are optimized to
* directly work with the basic types such as C longs or doubles.
*
* gmpy2 supports two different strategies for creating new references to
* an mpfr instance. If bits (or prec) is set to 0, the precison of the
* result exactly matches the precision of the context. The exponent range
* is also limited to the exponents defined in the contest. This is the
* default behavior of the mpfr() function.
*
* If bits (or prec) is set to 1, the precision of the result depends on the
* type of the source.
*
* If the source number is already a radix-2 floating point number,
* the precision is not changed. In practical terms, this only applies
* to sources operands that are either an mpfr or Python double.
*
* In addition, the exponent range is taken from the global emin/emax values
* set in the MPFR library.
*
*/
/* If prec == 0:
* Return an reference to a new mpfr instance. The context argument
* specifies the precision, exponent range, and whether or not subnormals
* are allowed.
*
* This is the default behavior of the mpfr() constructor.
*
* If prec == 1:
* Return an additional reference to an existing mpfr. The precision is not
* changed. The exponent is not checked and may be outside the bounds
* specified in the context argument.
*
* This is used internally for parsing arguments to functions.
*
* If prec >= 2:
* Return a reference to a new mpfr instance. The precision is taken from
* the argument. n instance with the specified precision and the
* exponent is valid in the current context.
*
* This is used by mpfr() with an optional precision keyword.
*
* Since references to existing objects may be returned, the result should not
* modified in-place.
*/
static MPFR_Object *
GMPy_MPFR_From_MPFR(MPFR_Object *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result = NULL;
assert(MPFR_Check(obj));
/* Optimize the critical case when prec==1 or obj is NaN or Inf. */
if (prec == 1 || !mpfr_number_p(obj->f)) {
Py_INCREF((PyObject*)obj);
return obj;
}
CHECK_CONTEXT(context);
if (prec == 0)
prec = GET_MPFR_PREC(context);
/* Try to identify when an additional reference to existing instance can
* be returned. It is possible when (1) the precision matches, (2) the
* exponent is valid and not in the range that might require subnormal-
* ization, and (3) subnormalize is not enabled.
*/
if (prec == mpfr_get_prec(obj->f) &&
!context->ctx.subnormalize &&
obj->f->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(obj->f) - 1) &&
obj->f->_mpfr_exp <= context->ctx.emax
) {
Py_INCREF((PyObject*)obj);
return obj;
}
if ((result = GMPy_MPFR_New(prec, context))) {
mpfr_clear_flags();
result->rc = mpfr_set(result->f, obj->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return result;
}
static MPFR_Object *
GMPy_MPFR_From_PyIntOrLong(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPZ_Object *tempx = NULL;
int error, was_one = 0;
long temp;
assert(PyIntOrLong_Check(obj));
CHECK_CONTEXT(context);
if (prec == 0)
prec = GET_MPFR_PREC(context);
if (prec == 1) {
/* This should be made accurate, but is it worth the overhead? */
/* It is only used if the value fits in a C long. */
prec = 64;
was_one = 1;
}
temp = GMPy_Integer_AsLongAndError(obj, &error);
if (error) {
if (!(tempx = GMPy_MPZ_From_PyIntOrLong(obj, context))) {
return NULL;
}
if (was_one)
prec = 1;
result = GMPy_MPFR_From_MPZ(tempx, prec, context);
Py_DECREF((PyObject*)tempx);
return result;
}
else {
if (!(result = GMPy_MPFR_New(prec, context)))
return NULL;
mpfr_clear_flags();
result->rc = mpfr_set_si(result->f, temp, GET_MPFR_ROUND(context));
if (!was_one) {
GMPY_MPFR_CHECK_RANGE(result, context);
}
GMPY_MPFR_EXCEPTIONS(result, context);
}
return result;
}
/* If prec==0, then the precision of the current context is used.
*
* If prec==1, then the precision of Python float type is used (typically 53).
*
* If prec>=2, then the specified precision is used.
*/
static MPFR_Object *
GMPy_MPFR_From_PyFloat(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result;
assert(PyFloat_Check(obj));
CHECK_CONTEXT(context);
if (prec == 0)
prec = GET_MPFR_PREC(context);
else if (prec == 1)
prec = DBL_MANT_DIG;
if ((result = GMPy_MPFR_New(prec, context))) {
mpfr_clear_flags();
result->rc = mpfr_set_d(result->f, PyFloat_AS_DOUBLE(obj), GET_MPFR_ROUND(context));
if (prec != 1) {
GMPY_MPFR_CHECK_RANGE(result, context);
}
GMPY_MPFR_SUBNORMALIZE(result, context);
GMPY_MPFR_EXCEPTIONS(result, context);
}
return result;
}
/* If prec==0, then the precision of the current context is used.
*
* If prec==1, then an exact conversion is done by using the bit length of the
* argument as the precision.
*
* If prec>=2, then the specified precision is used.
*/
static MPFR_Object *
GMPy_MPFR_From_MPZ(MPZ_Object *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result;
int was_one = 0;
size_t bitlen;
assert(CHECK_MPZANY(obj));
CHECK_CONTEXT(context);
if (prec == 0)
prec = GET_MPFR_PREC(context);
if (prec == 1) {
bitlen = mpz_sizeinbase(obj->z, 2);
if (bitlen < MPFR_PREC_MIN) {
bitlen = MPFR_PREC_MIN;
}
if (bitlen > MPFR_PREC_MAX) {
OVERFLOW_ERROR("'mpz' to large to convert to 'mpfr'\n");
return NULL;
}
prec = (mpfr_prec_t)bitlen;
was_one = 1;
}
if ((result = GMPy_MPFR_New(prec, context))) {
mpfr_clear_flags();
result->rc = mpfr_set_z(result->f, obj->z, GET_MPFR_ROUND(context));
if (!was_one) {
GMPY_MPFR_CHECK_RANGE(result, context);
}
GMPY_MPFR_EXCEPTIONS(result, context);
}
return result;
}
/* If prec<2, then the precision of the current context is used.
*
* If prec>=2, then the specified precision is used.
*/
static MPFR_Object *
GMPy_MPFR_From_MPQ(MPQ_Object *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result;
assert(MPQ_Check(obj));
CHECK_CONTEXT(context);
if (prec < 2)
prec = GET_MPFR_PREC(context);
if ((result = GMPy_MPFR_New(prec, context))) {
mpfr_clear_flags();
result->rc = mpfr_set_q(result->f, obj->q, GET_MPFR_ROUND(context));
GMPY_MPFR_CHECK_RANGE(result, context);
GMPY_MPFR_SUBNORMALIZE(result, context);
GMPY_MPFR_EXCEPTIONS(result, context);
}
return result;
}
/* If prec<2, then the precision of the current context is used.
*
* If prec>=2, then the specified precision is used.
*/
static MPFR_Object *
GMPy_MPFR_From_Fraction(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPQ_Object *tempq;
assert(IS_RATIONAL(obj));
CHECK_CONTEXT(context);
if ((tempq = GMPy_MPQ_From_Fraction(obj, context))) {
result = GMPy_MPFR_From_MPQ(tempq, prec, context);
Py_DECREF((PyObject*)tempq);
}
return result;
}
static MPFR_Object *
GMPy_MPFR_From_PyStr(PyObject *s, int base, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result;
MPQ_Object *tempq;
char *cp, *endptr;
Py_ssize_t len;
PyObject *ascii_str = NULL;
CHECK_CONTEXT(context);
if (prec < 2)
prec = GET_MPFR_PREC(context);
if (PyBytes_Check(s)) {
len = PyBytes_Size(s);
cp = PyBytes_AsString(s);
}
else if (PyUnicode_Check(s)) {
ascii_str = PyUnicode_AsASCIIString(s);
if (!ascii_str) {
VALUE_ERROR("string contains non-ASCII characters");
return NULL;
}
len = PyBytes_Size(ascii_str);
cp = PyBytes_AsString(ascii_str);
}
else {
TYPE_ERROR("object is not string or Unicode");
return NULL;
}
/* Check for leading base indicators. */
if (base == 0) {
if (len > 2 && cp[0] == '0') {
if (cp[1] == 'b') { base = 2; cp += 2; len -= 2; }
else if (cp[1] == 'x') { base = 16; cp += 2; len -= 2; }
else { base = 10; }
}
else {
base = 10;
}
}
else if (cp[0] == '0') {
/* If the specified base matches the leading base indicators, then
* we need to skip the base indicators.
*/
if (cp[1] =='b' && base == 2) { cp += 2; len -= 2; }
else if (cp[1] =='x' && base == 16) { cp += 2; len -= 2; }
}
if (!(result = GMPy_MPFR_New(prec, context))) {
Py_XDECREF(ascii_str);
return NULL;
}
/* delegate the rest to MPFR */
mpfr_clear_flags();
result->rc = mpfr_strtofr(result->f, cp, &endptr, base, GET_MPFR_ROUND(context));
Py_XDECREF(ascii_str);
if (len != (Py_ssize_t)(endptr - cp)) {
VALUE_ERROR("invalid digits");
Py_DECREF((PyObject*)result);
return NULL;
}
/* If the context requests subnormals and the result is in the range for subnormals,
* we use exact conversion via conversion to an mpq.
*
* The sticky bit returned by MPFR's string conversion appears to only reflect the
* portion of the string needed to compute the correctly rounded result. It does not
* accurately reflect whether or not the result is larger or smaller than the entire
* input string. A correct sticky bit is needed by mfpr_subnormalize. Converting the
* string to an mpq and then converting the mpq to an mpfr does properly set the
* sticky bit.
*/
if (base == 10 &&
context->ctx.subnormalize &&
result->f->_mpfr_exp <= context->ctx.emin + mpfr_get_prec(result->f) - 1)
{
if (!(tempq = GMPy_MPQ_From_PyStr(s, base, context))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_set_q(result->f, tempq->q, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempq);
}
GMPY_MPFR_CHECK_RANGE(result, context);
GMPY_MPFR_SUBNORMALIZE(result, context);
GMPY_MPFR_EXCEPTIONS(result, context);
return result;
}
/* GMPy_MPFR_From_Real() converts a real number (see IS_REAL()) to an mpfr.
*
* If prec==0, then the result has the precision of the current context.
*
* If prec==1 and the value can be converted exactly (i.e. the input value is
* a floating-point number using radix-2 representation or an integer), then
* the conversion is done with the maximum possible precision. If the input
* value can't be converted exactly, then the context precision is used.
*
* If prec >=2, then the specified precision is used.
*
* The return value is guaranteed to have a valid exponent.
*/
static MPFR_Object *
GMPy_MPFR_From_Real(PyObject *obj, mp_prec_t prec, CTXT_Object *context)
{
CHECK_CONTEXT(context);
if (MPFR_Check(obj))
return GMPy_MPFR_From_MPFR((MPFR_Object*)obj, prec, context);
if (PyFloat_Check(obj))
return GMPy_MPFR_From_PyFloat(obj, prec, context);
if (MPQ_Check(obj))
return GMPy_MPFR_From_MPQ((MPQ_Object*)obj, prec, context);
if (MPZ_Check(obj) || XMPZ_Check(obj))
return GMPy_MPFR_From_MPZ((MPZ_Object*)obj, prec, context);
if (PyIntOrLong_Check(obj))
return GMPy_MPFR_From_PyIntOrLong(obj, prec, context);
if (IS_FRACTION(obj))
return GMPy_MPFR_From_Fraction(obj, prec, context);
if (HAS_MPFR_CONVERSION(obj)) {
MPFR_Object *res = (MPFR_Object *) PyObject_CallMethod(obj, "__mpfr__", NULL);
if (res != NULL && MPFR_Check(res)) {
return res;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (HAS_MPQ_CONVERSION(obj)) {
MPQ_Object *res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
if (res != NULL && MPQ_Check(res)) {
MPFR_Object * temp = GMPy_MPFR_From_MPQ(res, prec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (HAS_MPZ_CONVERSION(obj)) {
MPZ_Object *res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (res != NULL && MPZ_Check(res)) {
MPFR_Object * temp = GMPy_MPFR_From_MPZ(res, prec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
error:
TYPE_ERROR("object could not be converted to 'mpfr'");
return NULL;
}
static MPFR_Object *
GMPy_MPFR_From_RealAndCopy(PyObject *obj, mp_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result = NULL, *temp = NULL;
result = GMPy_MPFR_From_Real(obj, prec, context);
if (result == NULL)
return result;
if (Py_REFCNT(result) == 1)
return result;
if (!(temp = GMPy_MPFR_New(mpfr_get_prec(result->f), context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* Since the precision of temp is the same as the precision of result,
* there shouldn't be any rounding.
*/
mpfr_set(temp->f, result->f, MPFR_RNDN);
Py_DECREF((PyObject*)result);
return temp;
}
static MPZ_Object *
GMPy_MPZ_From_MPFR(MPFR_Object *obj, CTXT_Object *context)
{
MPZ_Object *result;
assert(MPFR_Check(obj));
CHECK_CONTEXT(context);
if ((result = GMPy_MPZ_New(context))) {
if (mpfr_nan_p(MPFR(obj))) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'mpz' does not support NaN");
return NULL;
}
if (mpfr_inf_p(MPFR(obj))) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'mpz' does not support Infinity");
return NULL;
}
/* return code is ignored */
mpfr_get_z(result->z, MPFR(obj), GET_MPFR_ROUND(context));
}
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_MPFR(MPFR_Object *self, CTXT_Object *context)
{
XMPZ_Object *result;
CHECK_CONTEXT(context);
if ((result = GMPy_XMPZ_New(context))) {
if (mpfr_nan_p(MPFR(self))) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'xmpz' does not support NaN");
return NULL;
}
if (mpfr_inf_p(MPFR(self))) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'xmpz' does not support Infinity");
return NULL;
}
/* return code is ignored */
mpfr_get_z(result->z, MPFR(self), GET_MPFR_ROUND(context));
}
return result;
}
/* Return the simpliest rational number that approximates 'self' to the
* requested precision 'err'. If 'err' is negative, then the requested
* precision is -2**abs(int(err)). If 'err' is NULL, then the requested
* precision is -2**prec. If 'prec' is 0, then the requested precision is
* the precision of 'self'.
*/
static PyObject *
stern_brocot(MPFR_Object* self, MPFR_Object *err, mpfr_prec_t prec, int mayz, CTXT_Object *context)
{
PyObject *result = NULL;
int i, negative, errsign;
mpfr_t f, al, a, r1[3], r2[3], minerr, curerr, newerr, temp;
CHECK_CONTEXT(context);
#define F2Q_PREC 20
if (mpfr_nan_p(self->f)) {
VALUE_ERROR("Cannot convert NaN to a number.");
return NULL;
}
if (mpfr_inf_p(self->f)) {
OVERFLOW_ERROR("Cannot convert Infinity to a number.");
return NULL;
}
if (prec == 0)
prec = mpfr_get_prec(self->f);
errsign = err ? mpfr_sgn(err->f) : 0;
if (errsign < 0)
prec = (mpfr_prec_t)(-mpfr_get_si(err->f, MPFR_RNDN));
if (errsign <= 0 && (prec < 2 || prec > mpfr_get_prec(self->f))) {
VALUE_ERROR("Requested precision out-of-bounds.");
return NULL;
}
if (!(result = (PyObject*)GMPy_MPQ_New(context))) {
return NULL;
}
mpfr_init2(minerr, F2Q_PREC);
if (errsign <= 0) {
mpfr_set_ui(minerr, 1, MPFR_RNDN);
mpfr_div_2si(minerr, minerr, prec, MPFR_RNDN);
}
else {
mpfr_set(minerr, err->f, MPFR_RNDN);
}
mpfr_init2(f, prec);
if (mpfr_sgn(self->f) < 0) {
negative = 1;
mpfr_abs(f, self->f, MPFR_RNDN);
}
else {
negative = 0;
mpfr_set(f, self->f, MPFR_RNDN);
}
mpfr_init2(al, prec);
mpfr_set(al, f, MPFR_RNDN);
mpfr_init2(a, prec);
mpfr_floor(a, al);
mpfr_init2(temp, prec);
for (i=0; i<3; ++i) {
mpfr_init2(r1[i], prec);
mpfr_init2(r2[i], prec);
}
mpfr_set_si(r1[0], 0, MPFR_RNDN);
mpfr_set_si(r1[1], 0, MPFR_RNDN);
mpfr_set_si(r1[2], 1, MPFR_RNDN);
mpfr_set_si(r2[0], 0, MPFR_RNDN);
mpfr_set_si(r2[1], 1, MPFR_RNDN);
mpfr_set(r2[2], a, MPFR_RNDN);
mpfr_init2(curerr, F2Q_PREC);
mpfr_init2(newerr, F2Q_PREC);
mpfr_reldiff(curerr, f, a, MPFR_RNDN);
while (mpfr_cmp(curerr, minerr) > 0) {
mpfr_sub(temp, al, a, MPFR_RNDN);
mpfr_ui_div(al, 1, temp, MPFR_RNDN);
mpfr_floor(a, al);
mpfr_swap(r1[0], r1[1]);
mpfr_swap(r1[1], r1[2]);
mpfr_mul(r1[2], r1[1], a, MPFR_RNDN);
mpfr_add(r1[2], r1[2], r1[0], MPFR_RNDN);
mpfr_swap(r2[0], r2[1]);
mpfr_swap(r2[1], r2[2]);
mpfr_mul(r2[2], r2[1], a, MPFR_RNDN);
mpfr_add(r2[2], r2[2], r2[0], MPFR_RNDN);
mpfr_div(temp, r2[2], r1[2], MPFR_RNDN);
mpfr_reldiff(newerr, f, temp, MPFR_RNDN);
if (mpfr_cmp(curerr, newerr) <= 0) {
mpfr_swap(r1[1],r1[2]);
mpfr_swap(r2[1],r2[2]);
break;
}
mpfr_swap(curerr, newerr);
}
if (mayz && (mpfr_cmp_ui(r1[2],1) == 0)) {
Py_DECREF(result);
result = (PyObject*)GMPy_MPZ_New(context);
mpfr_get_z(MPZ(result), r2[2], MPFR_RNDN);
if (negative)
mpz_neg(MPZ(result), MPZ(result));
}
else {
mpfr_get_z(mpq_numref(MPQ(result)), r2[2], MPFR_RNDN);
mpfr_get_z(mpq_denref(MPQ(result)), r1[2], MPFR_RNDN);
if (negative)
mpz_neg(mpq_numref(MPQ(result)), mpq_numref(MPQ(result)));
}
mpfr_clear(minerr);
mpfr_clear(al);
mpfr_clear(a);
mpfr_clear(f);
for (i=0; i<3; ++i) {
mpfr_clear(r1[i]);
mpfr_clear(r2[i]);
}
mpfr_clear(curerr);
mpfr_clear(newerr);
mpfr_clear(temp);
return result;
}
static MPQ_Object *
GMPy_MPQ_From_MPFR(MPFR_Object *self, CTXT_Object *context)
{
mpfr_exp_t temp, twocount;
MPQ_Object *result;
CHECK_CONTEXT(context);
if (mpfr_nan_p(self->f)) {
VALUE_ERROR("can not convert NaN to MPQ");
return NULL;
}
if (mpfr_inf_p(self->f)) {
OVERFLOW_ERROR("can not convert Infinity to MPQ");
return NULL;
}
if (!(result = GMPy_MPQ_New(context))) {
return NULL;
}
if (mpfr_zero_p(self->f)) {
mpz_set_ui(mpq_numref(result->q), 0);
mpz_set_ui(mpq_denref(result->q), 1);
}
else {
temp = mpfr_get_z_2exp(mpq_numref(result->q), self->f);
twocount = (mpfr_exp_t)mpz_scan1(mpq_numref(result->q), 0);
if (twocount) {
temp += twocount;
mpz_div_2exp(mpq_numref(result->q), mpq_numref(result->q), twocount);
}
mpz_set_ui(mpq_denref(result->q), 1);
if (temp > 0)
mpz_mul_2exp(mpq_numref(result->q), mpq_numref(result->q), temp);
else if (temp < 0)
mpz_mul_2exp(mpq_denref(result->q), mpq_denref(result->q), -temp);
}
return result;
}
static PyObject *
GMPy_PyIntOrLong_From_MPFR(MPFR_Object *obj, CTXT_Object *context)
{
PyObject *result;
MPZ_Object *tempz;
CHECK_CONTEXT(context);
if (!(tempz = GMPy_MPZ_From_MPFR(obj, context)))
return NULL;
result = GMPy_PyIntOrLong_From_MPZ(tempz, context);
Py_DECREF((PyObject*)tempz);
return result;
}
static PyObject *
GMPy_MPFR_Int_Slot(MPFR_Object *self) {
return GMPy_PyIntOrLong_From_MPFR(self, NULL);
}
#ifdef PY2
static PyObject *
GMPy_PyLong_From_MPFR(MPFR_Object *obj, CTXT_Object *context)
{
PyObject *result;
MPZ_Object *tempz;
CHECK_CONTEXT(context);
if (!(tempz = GMPy_MPZ_From_MPFR(obj, context)))
return NULL;
result = GMPy_PyLong_From_MPZ(tempz, context);
Py_DECREF((PyObject*)tempz);
return result;
}
static PyObject *
GMPy_MPFR_Long_Slot(MPFR_Object *self) {
return GMPy_PyLong_From_MPFR(self, NULL);
}
#endif
static PyObject *
GMPy_PyFloat_From_MPFR(MPFR_Object *self, CTXT_Object *context)
{
double res;
CHECK_CONTEXT(context);
res = mpfr_get_d(self->f, GET_MPFR_ROUND(context));
return PyFloat_FromDouble(res);
}
static PyObject *
GMPy_MPFR_Float_Slot(MPFR_Object *self) {
return GMPy_PyFloat_From_MPFR(self, NULL);
}
static PyObject*
GMPy_PyStr_From_MPFR(MPFR_Object *self, int base, int digits, CTXT_Object *context)
{
PyObject *result;
char *buffer;
mpfr_exp_t the_exp;
CHECK_CONTEXT(context);
/* check arguments are valid */
assert(MPFR_Check((PyObject*)self));
if (!((base >= 2) && (base <= 62))) {
VALUE_ERROR("base must be in the interval [2,62]");
return NULL;
}
if ((digits < 0) || (digits == 1)) {
VALUE_ERROR("digits must be 0 or >= 2");
return NULL;
}
/* Process special cases first */
if (!(mpfr_regular_p(self->f))) {
if (mpfr_nan_p(self->f)) {
return Py_BuildValue("(sii)", "nan", 0, 0);
}
else if (mpfr_inf_p(self->f) && !mpfr_signbit(self->f)) {
return Py_BuildValue("(sii)", "inf", 0, 0);
}
else if (mpfr_inf_p(self->f) && mpfr_signbit(self->f)) {
return Py_BuildValue("(sii)", "-inf", 0, 0);
}
/* 0 is not considered a 'regular" number */
else if (mpfr_signbit(self->f)) {
return Py_BuildValue("(sii)", "-0", 0, mpfr_get_prec(self->f));
}
else {
return Py_BuildValue("(sii)", "0", 0, mpfr_get_prec(self->f));
}
}
/* obtain digits-string and exponent */
buffer = mpfr_get_str(0, &the_exp, base, digits, self->f, GET_MPFR_ROUND(context));
if (!*buffer) {
SYSTEM_ERROR("Internal error in Pympfr_To_PyStr");
return NULL;
}
result = Py_BuildValue("(sii)", buffer, the_exp, mpfr_get_prec(self->f));
mpfr_free_str(buffer);
return result;
}
#ifdef SHARED
/*
* coerce any number to a mpf
*/
int
GMPy_MPFR_ConvertArg(PyObject *arg, PyObject **ptr)
{
MPFR_Object* newob = GMPy_MPFR_From_Real(arg, 1, NULL);
if (newob) {
*ptr = (PyObject*)newob;
return 1;
}
else {
TYPE_ERROR("argument can not be converted to 'mpfr'");
return 0;
}
}
#endif
/* str and repr implementations for mpfr */
static PyObject *
GMPy_MPFR_Str_Slot(MPFR_Object *self)
{
PyObject *result, *temp;
long precision;
char fmtstr[60];
precision = (long)(log10(2) * (double)mpfr_get_prec(MPFR(self))) + 2;
sprintf(fmtstr, "{0:.%ldg}", precision);
temp = Py_BuildValue("s", fmtstr);
if (!temp)
return NULL;
result = PyObject_CallMethod(temp, "format", "O", self);
Py_DECREF(temp);
return result;
}
static PyObject *
GMPy_MPFR_Repr_Slot(MPFR_Object *self)
{
PyObject *result, *temp;
long precision, bits;
char fmtstr[60];
bits = mpfr_get_prec(MPFR(self));
precision = (long)(log10(2) * (double)bits) + 2;
if (mpfr_number_p(MPFR(self)) && bits != DBL_MANT_DIG)
sprintf(fmtstr, "mpfr('{0:.%ldg}',%ld)", precision, bits);
else
sprintf(fmtstr, "mpfr('{0:.%ldg}')", precision);
temp = Py_BuildValue("s", fmtstr);
if (!temp)
return NULL;
result = PyObject_CallMethod(temp, "format", "O", self);
Py_DECREF(temp);
return result;
}
static PyObject *
mpfr_ascii(mpfr_t self, int base, int digits, int round)
{
PyObject *result;
char *buffer;
mpfr_exp_t the_exp;
/* Process special cases first */
if (!(mpfr_regular_p(self))) {
if (mpfr_nan_p(self)) {
return Py_BuildValue("(sii)", "nan", 0, 0);
}
else if (mpfr_inf_p(self) && !mpfr_signbit(self)) {
return Py_BuildValue("(sii)", "inf", 0, 0);
}
else if (mpfr_inf_p(self) && mpfr_signbit(self)) {
return Py_BuildValue("(sii)", "-inf", 0, 0);
}
/* 0 is not considered a 'regular" number */
else if (mpfr_signbit(self)) {
return Py_BuildValue("(sii)", "-0", 0, mpfr_get_prec(self));
}
else {
return Py_BuildValue("(sii)", "0", 0, mpfr_get_prec(self));
}
}
/* obtain digits-string and exponent */
buffer = mpfr_get_str(0, &the_exp, base, digits, self, round);
if (!*buffer) {
SYSTEM_ERROR("Internal error in mpfr_ascii");
return NULL;
}
result = Py_BuildValue("(sii)", buffer, the_exp, mpfr_get_prec(self));
mpfr_free_str(buffer);
return result;
}
gmpy2-2.1.0b3/src/gmpy2_convert_mpfr.h 0000664 0001750 0001750 00000011002 13452460010 017416 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_mpfr.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_MPFR_H
#define GMPY2_CONVERT_MPFR_H
#ifdef __cplusplus
extern "C" {
#endif
/********* Pympfr Conversions *********/
/* Conversions with Pympfr */
static MPFR_Object * GMPy_MPFR_From_MPFR(MPFR_Object *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_PyIntOrLong(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_PyFloat(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_MPZ(MPZ_Object *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_MPQ(MPQ_Object *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_Fraction(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_PyStr(PyObject *s, int base, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_Real(PyObject* obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_RealAndCopy(PyObject* obj, mpfr_prec_t prec, CTXT_Object *context);
static PyObject * GMPy_PyIntOrLong_From_MPFR(MPFR_Object *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_MPFR(MPFR_Object *obj, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_MPFR(MPFR_Object *self, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_MPFR(MPFR_Object *self, CTXT_Object *context);
static PyObject * GMPy_PyFloat_From_MPFR(MPFR_Object *self, CTXT_Object *context);
static PyObject * GMPy_PyStr_From_MPFR(MPFR_Object *self, int base, int digits, CTXT_Object *context);
#ifdef PY2
static PyObject * GMPy_PyLong_From_MPFR(MPFR_Object *obj, CTXT_Object *context);
static PyObject * GMPy_MPFR_Long_Slot(MPFR_Object *self);
#endif
static PyObject * GMPy_MPFR_Str_Slot(MPFR_Object *self);
static PyObject * GMPy_MPFR_Repr_Slot(MPFR_Object *self);
static PyObject * GMPy_MPFR_Int_Slot(MPFR_Object *self);
static PyObject * GMPy_MPFR_Float_Slot(MPFR_Object *self);
/* Miscellaneous */
#ifdef SHARED
/* static int GMPy_MPFR_ConvertArg(PyObject *arg, PyObject **ptr); */
static GMPy_MPFR_ConvertArg_RETURN GMPy_MPFR_ConvertArg GMPy_MPFR_ConvertArg_PROTO;
#endif
static PyObject * stern_brocot(MPFR_Object* self, MPFR_Object *err, mpfr_prec_t prec, int mayz, CTXT_Object *context);
static PyObject * mpfr_ascii(mpfr_t self, int base, int digits, int round);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_convert_utils.c 0000664 0001750 0001750 00000030277 13425752152 017637 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_utils.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* ======================================================================== *
* Conversion between Integer objects and C types. *
* ======================================================================== *
*
* Optimized routines for converting an Integer object (Python's integer
* type(s) plus mpz) to various C types.
*
* Note: These functions will not set any exceptions!
*
* Note: These functions assume the input is either a PyInt, PyLong, or an
* mpz. No attempt is made to convert any other type!
*/
#include "longintrepr.h"
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
/* The various ...AndError functions indicate exceptions as follows:
* 1) If error is -1, then the argument is negative and the result could
* not fit into the desired return type.
* 2) If error is 1, then the argument is positive and the result could
* not fit into the desired return type.
* 3) If error is 2, then the argument is not a recognized type.
* 4) If error is 0, then a valid result has been returned.
*
* Note: The original Python functions will accept any object and attempt to
* convert the object to a PyLong. We do not do this. It is assumed that
* the argument is a Python integer or a GMPY2 mpz.
*
* These functions will not set any exceptions. A return value of -1 does
* NOT indicate a possible exception.
*/
/* The following functions are based on PyLong_AsLongAndOverflow(). */
static long
GMPy_Integer_AsLongAndError(PyObject *vv, int *error)
{
register PyLongObject *v;
unsigned long x, prev;
long res;
Py_ssize_t i;
int sign;
*error = 0;
#ifdef PY2
if (PyInt_Check(vv)) {
return PyInt_AS_LONG(vv);
}
#endif
if (PyLong_Check(vv)) {
res = 0;
v = (PyLongObject *)vv;
i = Py_SIZE(v);
switch (i) {
case -1:
res = -(sdigit)v->ob_digit[0];
break;
case 0:
break;
case 1:
res = v->ob_digit[0];
break;
default:
sign = 1;
x = 0;
if (i < 0) {
sign = -1;
i = -(i);
}
while (--i >= 0) {
prev = x;
x = (x << PyLong_SHIFT) + v->ob_digit[i];
if ((x >> PyLong_SHIFT) != prev) {
*error = sign;
return res;
}
}
/* Haven't lost any bits, but casting to long requires extra care.
*/
if (x <= (unsigned long)LONG_MAX) {
res = (long)x * sign;
}
else if (sign < 0 && x == PY_ABS_LONG_MIN) {
res = LONG_MIN;
}
else {
*error = sign;
}
}
return res;
}
if (CHECK_MPZANY(vv)) {
if (mpz_fits_slong_p(MPZ(vv))) {
res = (long) mpz_get_si(MPZ(vv));
}
else {
*error = mpz_sgn(MPZ(vv));
res = 0;
}
return res;
}
*error = 2;
return 0;
}
static unsigned long
GMPy_Integer_AsUnsignedLongAndError(PyObject *vv, int *error)
{
register PyLongObject *v;
unsigned long x, prev, res;
Py_ssize_t i;
*error = 0;
#ifdef PY2
if (PyInt_Check(vv)) {
long temp = PyInt_AS_LONG(vv);
if (temp < 0) {
*error = -1;
return 0;
}
else {
return (unsigned long)temp;
}
}
#endif
if (PyLong_Check(vv)) {
res = 0;
v = (PyLongObject *)vv;
i = Py_SIZE(v);
if (i < 0) {
*error = -1;
return res;
}
switch (i) {
case 0:
break;
case 1:
res = v->ob_digit[0];
break;
default:
x = 0;
while (--i >= 0) {
prev = x;
x = (x << PyLong_SHIFT) + v->ob_digit[i];
if ((x >> PyLong_SHIFT) != prev) {
*error = 1;
return res;
}
}
res = x;
}
return res;
}
if (CHECK_MPZANY(vv)) {
if (mpz_fits_ulong_p(MPZ(vv))) {
res = (unsigned long) mpz_get_ui(MPZ(vv));
}
else {
*error = mpz_sgn(MPZ(vv));
res = 0;
}
return res;
}
*error = 2;
return 0;
}
static long
c_long_From_Integer(PyObject *obj)
{
long result;
int error;
result = GMPy_Integer_AsLongAndError(obj, &error);
if (!error) {
return result;
}
else {
if (error == 2) {
TYPE_ERROR("could not convert object to integer");
}
else {
OVERFLOW_ERROR("value too large to convert to C long");
}
return -1;
}
}
static unsigned long
c_ulong_From_Integer(PyObject *obj)
{
unsigned long result;
int error;
result = GMPy_Integer_AsUnsignedLongAndError(obj, &error);
if (!error) {
return result;
}
else {
if (error == 2) {
TYPE_ERROR("could not convert object to integer");
}
else if (error == 1) {
OVERFLOW_ERROR("value too large to convert to C unsigned long");
}
else if (error < 0) {
VALUE_ERROR("a non-negative value is required");
}
return (unsigned long)(-1);
}
}
/* The follow code is only used on Windows x64 platform. We check for _WIN64
* but we then assume the PY_LONG_LONG is defined.
*/
#ifdef _WIN64
#define PY_ABS_LLONG_MIN (0-(unsigned PY_LONG_LONG)PY_LLONG_MIN)
static PY_LONG_LONG
GMPy_Integer_AsLongLongAndError(PyObject *vv, int *error)
{
register PyLongObject *v;
unsigned PY_LONG_LONG x, prev;
PY_LONG_LONG res;
Py_ssize_t i;
int sign;
*error = 0;
#ifdef PY2
if (PyInt_Check(vv)) {
return (PY_LONG_LONG)PyInt_AS_LONG(vv);
}
#endif
if (PyLong_Check(vv)) {
res = 0;
v = (PyLongObject *)vv;
i = Py_SIZE(v);
switch (i) {
case -1:
res = -(sdigit)v->ob_digit[0];
break;
case 0:
break;
case 1:
res = v->ob_digit[0];
break;
default:
sign = 1;
x = 0;
if (i < 0) {
sign = -1;
i = -(i);
}
while (--i >= 0) {
prev = x;
x = (x << PyLong_SHIFT) + v->ob_digit[i];
if ((x >> PyLong_SHIFT) != prev) {
*error = sign;
return res;
}
}
/* Haven't lost any bits, but casting to long requires extra care.
*/
if (x <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) {
res = (PY_LONG_LONG)x * sign;
}
else if (sign < 0 && x == PY_ABS_LLONG_MIN) {
res = PY_LLONG_MIN;
}
else {
*error = sign;
}
}
return res;
}
if (CHECK_MPZANY(vv)) {
res = 0;
sign = mpz_sgn(MPZ(vv));
if (sign) {
if (mpz_sizeinbase(MPZ(vv), 256) <= sizeof(x)) {
x = 0;
mpz_export(&x, NULL, 1, sizeof(x), 0, 0, MPZ(vv));
}
if (x <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) {
res = (PY_LONG_LONG)x * sign;
}
else if (sign < 0 && x == PY_ABS_LLONG_MIN) {
res = PY_LLONG_MIN;
}
else {
*error = sign;
}
return res;
}
}
*error = 2;
return 0;
}
static unsigned PY_LONG_LONG
GMPy_Integer_AsUnsignedLongLongAndError(PyObject *vv, int *error)
{
register PyLongObject *v;
unsigned PY_LONG_LONG x, prev, res = 0;
Py_ssize_t i;
int sign;
*error = 0;
#ifdef PY2
if (PyInt_Check(vv)) {
long temp = PyInt_AS_LONG(vv);
if (temp < 0) {
*error = -1;
return res;
}
else {
return (unsigned PY_LONG_LONG)temp;
}
}
#endif
if (PyLong_Check(vv)) {
v = (PyLongObject *)vv;
i = Py_SIZE(v);
if (i < 0) {
*error = -1;
return res;
}
switch (i) {
case 0:
break;
case 1:
res = v->ob_digit[0];
break;
default:
x = 0;
while (--i >= 0) {
prev = x;
x = (x << PyLong_SHIFT) + v->ob_digit[i];
if ((x >> PyLong_SHIFT) != prev) {
*error = 1;
return res;
}
}
res = x;
}
return res;
}
if (CHECK_MPZANY(vv)) {
sign = mpz_sgn(MPZ(vv));
if (sign < 0) {
*error = -1;
return res;
}
else if (sign) {
if (mpz_sizeinbase(MPZ(vv), 256) <= sizeof(res)) {
mpz_export(&res, NULL, 1, sizeof(x), 0, 0, MPZ(vv));
}
return res;
}
}
*error = 2;
return 0;
}
static PY_LONG_LONG
c_longlong_From_Integer(PyObject *obj)
{
PY_LONG_LONG result;
int error;
result = GMPy_Integer_AsLongLongAndError(obj, &error);
if (!error) {
return result;
}
else {
if (error == 2) {
TYPE_ERROR("could not convert object to integer");
}
else {
OVERFLOW_ERROR("value too large to convert to C long long");
}
return -1;
}
}
static unsigned PY_LONG_LONG
c_ulonglong_From_Integer(PyObject *obj)
{
unsigned PY_LONG_LONG result;
int error;
result = GMPy_Integer_AsUnsignedLongLongAndError(obj, &error);
if (!error) {
return result;
}
else {
if (error == 2) {
TYPE_ERROR("could not convert object to integer");
}
else if (error == 1) {
OVERFLOW_ERROR("value too large to convert to C unsigned long long");
}
else if (error < 0) {
VALUE_ERROR("a non-negative value is required");
}
return (unsigned PY_LONG_LONG)(-1);
}
}
#endif
gmpy2-2.1.0b3/src/gmpy2_convert_utils.h 0000664 0001750 0001750 00000007347 13425752164 017651 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert_utils.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_UTILS_H
#define GMPY2_CONVERT_UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
/* ======================================================================== *
* Conversion between Integer objects and C types. *
* ======================================================================== */
static long GMPy_Integer_AsLongAndError(PyObject *vv, int *error);
static unsigned long GMPy_Integer_AsUnsignedLongAndError(PyObject *vv, int *error);
static long c_long_From_Integer(PyObject *obj);
static unsigned long c_ulong_From_Integer(PyObject *obj);
#ifdef _WIN64
static PY_LONG_LONG GMPy_Integer_AsLongLongAndError(PyObject *vv, int *error);
static unsigned PY_LONG_LONG GMPy_Integer_AsUnsignedLongLongAndError(PyObject *vv, int *error);
#endif
/* Support conversion to/from mp_bitcnt_t and Py_ssize_t. */
/* The following code assumes that the typedef in gmp.h for mingw64 based
* builds has been changed to unsigned long long int.
*/
#if defined _WIN64 && (MPIR || MSYS2)
# define mp_bitcnt_t_From_Integer c_ulonglong_From_Integer
# define GMPy_Integer_AsMpBitCntAndError GMPy_Integer_AsUnsignedLongLongAndError
#else
# define mp_bitcnt_t_From_Integer c_ulong_From_Integer
# define GMPy_Integer_AsMpBitCntAndError GMPy_Integer_AsUnsignedLongAndError
#endif
/* This just requires that sizeof(mp_bitcnt_t) <= sizeof(size_t) */
#ifdef _WIN64
# define ssize_t_From_Integer c_longlong_From_Integer
#else
# define ssize_t_From_Integer c_long_From_Integer
#endif
#ifdef PY2
# define PyIntOrLong_FromMpBitCnt PyInt_FromSize_t
#else
# define PyIntOrLong_FromMpBitCnt PyLong_FromSize_t
#endif
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_divmod.c 0000664 0001750 0001750 00000033214 13425752202 016207 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_divmod.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __divmod__ and context.divmod().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*
* GMPy_Number_DivMod(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_MPZ_DivMod_Slot
* GMPy_MPQ_DivMod_Slot
* GMPy_MPFR_DivMod_Slot
* GMPy_MPC_DivMod_Slot
*
* GMPy_Integer_DivMod(Integer, Integer, context|NULL)
* GMPy_Rational_DivMod(Rational, Rational, context|NULL)
* GMPy_Real_DivMod(Real, Real, context|NULL)
* GMPy_Complex_DivMod(Complex, Complex, context|NULL)
*
* GMPy_Context_DivMod(context, args)
*
*/
static PyObject *
GMPy_Integer_DivMod(PyObject *x, PyObject *y, CTXT_Object *context)
{
PyObject *result = NULL;
MPZ_Object *tempx = NULL, *tempy = NULL, *rem = NULL, *quo = NULL;
if (!(result = PyTuple_New(2)) ||
!(rem = GMPy_MPZ_New(context)) ||
!(quo = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (CHECK_MPZANY(x)) {
if (PyIntOrLong_Check(y)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(y, &error);
if (error) {
mpz_set_PyIntOrLong(global.tempz, y);
mpz_fdiv_qr(quo->z, rem->z, MPZ(x), global.tempz);
}
else if (temp > 0) {
mpz_fdiv_qr_ui(quo->z, rem->z, MPZ(x), temp);
}
else if (temp == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
else {
mpz_cdiv_qr_ui(quo->z, rem->z, MPZ(x), -temp);
mpz_neg(quo->z, quo->z);
}
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
if (CHECK_MPZANY(y)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
mpz_fdiv_qr(quo->z, rem->z, MPZ(x), MPZ(y));
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
}
if (CHECK_MPZANY(y) && PyIntOrLong_Check(x)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
else {
mpz_set_PyIntOrLong(global.tempz, x);
mpz_fdiv_qr(quo->z, rem->z, global.tempz, MPZ(y));
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return (PyObject*)result;
}
}
if (IS_INTEGER(x) && IS_INTEGER(y)) {
if (!(tempx = GMPy_MPZ_From_Integer(x, context)) ||
!(tempy = GMPy_MPZ_From_Integer(y, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
mpz_fdiv_qr(quo->z, rem->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
/* LCOV_EXCL_START */
SYSTEM_ERROR("Internal error in GMPy_Integer_DivMod().");
/* LCOV_EXCL_STOP */
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)rem);
Py_XDECREF((PyObject*)quo);
Py_XDECREF(result);
return NULL;
}
static PyObject *
GMPy_MPZ_DivMod_Slot(PyObject *x, PyObject *y)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_DivMod(x, y, NULL);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_DivMod(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_DivMod(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_DivMod(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Rational_DivMod(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPQ_Object *tempx = NULL, *tempy = NULL, *rem = NULL;
MPZ_Object *quo = NULL;
PyObject *result = NULL;
if (!(result = PyTuple_New(2)) ||
!(rem = GMPy_MPQ_New(context)) ||
!(quo = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (IS_RATIONAL(x) && IS_RATIONAL(y)) {
if (!(tempx = GMPy_MPQ_From_Number(x, context)) ||
!(tempy = GMPy_MPQ_From_Number(y, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (mpq_sgn(tempy->q) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
mpq_div(rem->q, tempx->q, tempy->q);
mpz_fdiv_q(quo->z, mpq_numref(rem->q), mpq_denref(rem->q));
/* Need to calculate x - quo * y. */
mpq_set_z(rem->q, quo->z);
mpq_mul(rem->q, rem->q, tempy->q);
mpq_sub(rem->q, tempx->q, rem->q);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
/* LCOV_EXCL_START */
SYSTEM_ERROR("Internal error in GMPy_Rational_DivMod().");
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)rem);
Py_XDECREF((PyObject*)quo);
Py_XDECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_MPQ_DivMod_Slot(PyObject *x, PyObject *y)
{
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_DivMod(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_DivMod(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_DivMod(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Real_DivMod(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *tempx = NULL, *tempy = NULL, *quo = NULL, *rem = NULL, *temp;
PyObject *result = NULL;
CHECK_CONTEXT(context);
if (!(result = PyTuple_New(2)) ||
!(rem = GMPy_MPFR_New(0, context)) ||
!(quo = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (IS_REAL(x) && IS_REAL(y)) {
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context)) ||
!(tempy = GMPy_MPFR_From_Real(y, 1, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (mpfr_zero_p(tempy->f)) {
context->ctx.divzero = 1;
if (context->ctx.traps & TRAP_DIVZERO) {
GMPY_DIVZERO("divmod() division by zero");
goto error;
}
mpfr_set_nan(quo->f);
mpfr_set_nan(rem->f);
goto okay;
}
if (mpfr_nan_p(tempx->f) || mpfr_nan_p(tempy->f) || mpfr_inf_p(tempx->f)) {
context->ctx.invalid = 1;
if (context->ctx.traps & TRAP_INVALID) {
GMPY_INVALID("divmod() invalid operation");
goto error;
}
mpfr_set_nan(quo->f);
mpfr_set_nan(rem->f);
goto okay;
}
if (mpfr_inf_p(tempy->f)) {
context->ctx.invalid = 1;
if (context->ctx.traps & TRAP_INVALID) {
GMPY_INVALID("divmod() invalid operation");
goto error;
}
if (mpfr_zero_p(tempx->f)) {
mpfr_set_zero(quo->f, mpfr_sgn(tempy->f));
mpfr_set_zero(rem->f, mpfr_sgn(tempy->f));
}
else if ((mpfr_signbit(tempx->f)) != (mpfr_signbit(tempy->f))) {
mpfr_set_si(quo->f, -1, MPFR_RNDN);
mpfr_set_inf(rem->f, mpfr_sgn(tempy->f));
}
else {
mpfr_set_si(quo->f, 0, MPFR_RNDN);
rem->rc = mpfr_set(rem->f, tempx->f, MPFR_RNDN);
}
goto okay;
}
if (!(temp = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
mpfr_fmod(rem->f, tempx->f, tempy->f, MPFR_RNDN);
mpfr_sub(temp->f, tempx->f, rem->f, MPFR_RNDN);
mpfr_div(quo->f, temp->f, tempy->f, MPFR_RNDN);
if (!mpfr_zero_p(rem->f)) {
if ((mpfr_sgn(tempy->f) < 0) != (mpfr_sgn(rem->f) < 0)) {
mpfr_add(rem->f, rem->f, tempy->f, MPFR_RNDN);
mpfr_sub_ui(quo->f, quo->f, 1, MPFR_RNDN);
}
}
else {
mpfr_copysign(rem->f, rem->f, tempy->f, MPFR_RNDN);
}
if (!mpfr_zero_p(quo->f)) {
mpfr_round(quo->f, quo->f);
}
else {
mpfr_setsign(quo->f, quo->f, mpfr_sgn(tempx->f) * mpfr_sgn(tempy->f) - 1, MPFR_RNDN);
}
Py_DECREF((PyObject*)temp);
GMPY_MPFR_CHECK_RANGE(quo, context);
GMPY_MPFR_CHECK_RANGE(rem, context);
GMPY_MPFR_SUBNORMALIZE(quo, context);
GMPY_MPFR_SUBNORMALIZE(rem, context);
okay:
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
SYSTEM_ERROR("Internal error in GMPy_Real_DivMod_1().");
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)rem);
Py_XDECREF((PyObject*)quo);
Py_XDECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_MPFR_DivMod_Slot(PyObject *x, PyObject *y)
{
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_DivMod(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_DivMod(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Complex_DivMod(PyObject *x, PyObject *y, CTXT_Object *context)
{
TYPE_ERROR("can't take floor or mod of complex number.");
return NULL;
}
static PyObject *
GMPy_MPC_DivMod_Slot(PyObject *x, PyObject *y)
{
return GMPy_Complex_DivMod(x, y, NULL);
}
static PyObject *
GMPy_Number_DivMod(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_DivMod(x, y, context);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_DivMod(x, y, context);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_DivMod(x, y, context);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_DivMod(x, y, context);
TYPE_ERROR("divmod() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_divmod,
"context.div_mod(x, y) -> (quotient, remainder)\n\n"
"Return div_mod(x, y); uses alternate spelling to avoid naming conflicts.\n"
"Note: overflow, underflow, and inexact exceptions are not supported for\n"
"mpfr arguments to context.div_mod().");
static PyObject *
GMPy_Context_DivMod(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("div_mod() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_DivMod(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
gmpy2-2.1.0b3/src/gmpy2_divmod.h 0000664 0001750 0001750 00000005704 13425752217 016225 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_divmod.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_DIVMOD_H
#define GMPY2_DIVMOD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_DivMod(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_DivMod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Rational_DivMod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Real_DivMod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_DivMod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_MPZ_DivMod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPQ_DivMod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPFR_DivMod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPC_DivMod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_DivMod(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_floordiv.c 0000664 0001750 0001750 00000034463 13425752235 016566 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_floordiv.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the // operator, gmpy2.floor_div() and
* context.floor_div().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*
* GMPy_Number_FloorDiv(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_MPZ_FloorDiv_Slot
* GMPy_MPQ_FloorDiv_Slot
* GMPy_MPFR_FloorDiv_Slot
* GMPy_MPC_FloorDiv_Slot
*
* GMPy_Integer_FloorDiv(Integer, Integer, context|NULL)
* GMPy_Rational_FloorDiv(Rational, Rational, context|NULL)
* GMPy_Real_FloorDiv(Real, Real, context|NULL)
* GMPy_Complex_FloorDiv(Complex, Complex, context|NULL)
*
* GMPy_Context_FloorDiv(context, args)
*
*/
static PyObject *
GMPy_Integer_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(context)))
return NULL;
if (CHECK_MPZANY(x)) {
if (PyIntOrLong_Check(y)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(y, &error);
if (!error) {
if (temp > 0) {
mpz_fdiv_q_ui(result->z, MPZ(x), temp);
}
else if (temp == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
else {
mpz_cdiv_q_ui(result->z, MPZ(x), -temp);
mpz_neg(result->z, result->z);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpz_fdiv_q(result->z, MPZ(x), global.tempz);
}
return (PyObject*)result;
}
if (CHECK_MPZANY(y)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_fdiv_q(result->z, MPZ(x), MPZ(y));
return (PyObject*)result;
}
}
if (CHECK_MPZANY(y)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
if (PyIntOrLong_Check(x)) {
mpz_set_PyIntOrLong(global.tempz, x);
mpz_fdiv_q(result->z, global.tempz, MPZ(y));
return (PyObject*)result;
}
}
if (IS_INTEGER(x) && IS_INTEGER(y)) {
MPZ_Object *tempx, *tempy;
tempx = GMPy_MPZ_From_Integer(x, context);
tempy = GMPy_MPZ_From_Integer(y, context);
if (!tempx || !tempy) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_fdiv_q(result->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
}
/* Implement floor division for MPZ_Object. On entry, one of the two arguments
* must be an MPZ_Object. If the other object is an Integer, return an
* MPZ_Object. If the other object isn't an MPZ_Object, call the appropriate
* function. If no appropriate function can be found, return NotImplemented.
*/
static PyObject *
GMPy_MPZ_FloorDiv_Slot(PyObject *x, PyObject *y)
{
if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) {
MPZ_Object *result;
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_fdiv_q(result->z, MPZ(x), MPZ(y));
}
return (PyObject*)result;
}
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_FloorDiv(x, y, NULL);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_FloorDiv(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_FloorDiv(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_FloorDiv(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Rational_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPZ_Object *result;
MPQ_Object *tempq;
CHECK_CONTEXT(context);
result = GMPy_MPZ_New(context);
tempq = GMPy_MPQ_New(context);
if (!result || !tempq) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempq);
return NULL;
}
if (MPQ_Check(x) && MPQ_Check(y)) {
if (mpq_sgn(MPQ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
mpq_div(tempq->q, MPQ(x), MPQ(y));
mpz_fdiv_q(result->z, mpq_numref(tempq->q), mpq_denref(tempq->q));
Py_DECREF((PyObject*)tempq);
return (PyObject*)result;
}
if (IS_RATIONAL(x) && IS_RATIONAL(y)) {
MPQ_Object *tempx, *tempy;
tempx = GMPy_MPQ_From_Number(x, context);
tempy = GMPy_MPQ_From_Number(y, context);
if (!tempx || !tempy) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
goto error;
}
if (mpq_sgn(tempy->q) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
goto error;
}
mpq_div(tempq->q, tempx->q, tempy->q);
mpz_fdiv_q(result->z, mpq_numref(tempq->q), mpq_denref(tempq->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempq);
return (PyObject*)result;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
error:
Py_DECREF((PyObject*)result);
Py_DECREF((PyObject*)tempq);
return NULL;
}
static PyObject *
GMPy_MPQ_FloorDiv_Slot(PyObject *x, PyObject *y)
{
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_FloorDiv(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_FloorDiv(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_FloorDiv(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* Attempt floor division of two numbers and return an mpfr. The code path is
* optimized by checking for mpfr objects first. Returns Py_NotImplemented if
* both objects are not valid reals. */
static PyObject *
GMPy_Real_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPFR_Check(x)) {
if (MPFR_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_div(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
goto done;
}
if (PyIntOrLong_Check(y)) {
int error;
long tempi = GMPy_Integer_AsLongAndError(y, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_div_si(result->f, MPFR(x), tempi, GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
goto done;
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpfr_clear_flags();
result->rc = mpfr_div_z(result->f, MPFR(x), global.tempz, GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
goto done;
}
}
if (CHECK_MPZANY(y)) {
mpfr_clear_flags();
result->rc = mpfr_div_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
goto done;
}
if (IS_RATIONAL(y)) {
MPQ_Object *tempy;
if (!(tempy = GMPy_MPQ_From_Number(y, context))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_div_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
Py_DECREF((PyObject*)tempy);
goto done;
}
if (PyFloat_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_div_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
goto done;
}
}
if (MPFR_Check(y)) {
if (PyIntOrLong_Check(x)) {
int error;
long tempi = GMPy_Integer_AsLongAndError(x, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_si_div(result->f, tempi, MPFR(y), GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
goto done;
}
}
/* Since mpfr_z_div does not exist, this combination is handled at the
* end by converting x to an mpfr. Ditto for rational.*/
if (PyFloat_Check(x)) {
mpfr_clear_flags();
result->rc = mpfr_d_div(result->f, PyFloat_AS_DOUBLE(x), MPFR(y), GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
goto done;
}
}
/* Handle the remaining cases.
* Note: verify that MPZ if converted at full precision! */
if (IS_REAL(x) && IS_REAL(y)) {
MPFR_Object *tempx, *tempy;
tempx = GMPy_MPFR_From_Real(x, 1, context);
tempy = GMPy_MPFR_From_Real(y, 1, context);
if (!tempx || !tempy) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_div(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
goto done;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
done:
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_MPFR_FloorDiv_Slot(PyObject *x, PyObject *y)
{
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_FloorDiv(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_FloorDiv(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Complex_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
TYPE_ERROR("can't take floor of complex number");
return NULL;
}
static PyObject *
GMPy_MPC_FloorDiv_Slot(PyObject *x, PyObject *y)
{
return GMPy_Complex_FloorDiv(x, y, NULL);
}
PyDoc_STRVAR(GMPy_doc_floordiv,
"floor_div(x, y) -> number\n\n"
"Return x // y; uses floor division.");
static PyObject *
GMPy_Number_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_FloorDiv(x, y, context);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_FloorDiv(x, y, context);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_FloorDiv(x, y, context);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_FloorDiv(x, y, context);
TYPE_ERROR("floor_div() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_floordiv,
"context.floor_div(x, y) -> number\n\n"
"Return x // y; uses floor division.");
static PyObject *
GMPy_Context_FloorDiv(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("floor_div() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_FloorDiv(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1),
context);
}
gmpy2-2.1.0b3/src/gmpy2_floordiv.h 0000664 0001750 0001750 00000005734 13425752251 016570 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_floordiv.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_FLOORDIV_H
#define GMPY2_FLOORDIV_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Rational_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Real_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_MPZ_FloorDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPQ_FloorDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPFR_FloorDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPC_FloorDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_FloorDiv(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_format.c 0000664 0001750 0001750 00000057675 13452504734 016243 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_format.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_mpz_format,
"x.__format__(fmt) -> string\n\n"
"Return a Python string by formatting mpz 'x' using the format string\n"
"'fmt'. A valid format string consists of:\n"
" optional alignment code:\n"
" '<' -> left shifted in field\n"
" '>' -> right shifted in field\n"
" '^' -> centered in field\n"
" optional leading sign code:\n"
" '+' -> always display leading sign\n"
" '-' -> only display minus sign\n"
" ' ' -> minus for negative values, space for positive values\n"
" optional base indicator\n"
" '#' -> precede binary, octal, or hex with 0b, 0o or 0x\n"
" optional width\n"
" optional conversion code:\n"
" 'd' -> decimal format\n"
" 'b' -> binary format\n"
" 'o' -> octal format\n"
" 'x' -> hex format\n"
" 'X' -> upper-case hex format\n"
"The default format is 'd'.");
/* Formatting occurs in two phases. Pympz_ascii() is used to create a string
* with the appropriate binary/octal/decimal/hex formatting, including the
* leading sign character (+ , -, or space) and base encoding (0b, 0o, or 0x).
* Left/right/centering using the specified width is done by creating a
* format string and calling the __format__() method of the string object
* returned by Pympz_ascii().
*/
static PyObject *
GMPy_MPZ_Format(PyObject *self, PyObject *args)
{
PyObject *result = NULL, *mpzstr = NULL;
char *fmtcode = 0, *p1, *p2;
char fmt[30];
int base = 10, option = 16;
int seensign = 0, seenindicator = 0, seenalign = 0, seendigits = 0;
if (!CHECK_MPZANY(self)) {
TYPE_ERROR("requires mpz type");
return NULL;
}
if (!PyArg_ParseTuple(args, "s", &fmtcode))
return NULL;
p2 = fmt;
for (p1 = fmtcode; *p1 != '\00'; p1++) {
if (*p1 == '<' || *p1 == '>' || *p1 == '^') {
if (seenalign || seensign || seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p2++) = *p1;
seenalign = 1;
continue;
}
}
if (*p1 == '+') {
if (seensign || seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
option |= 2;
seensign = 1;
continue;
}
}
if (*p1 == '-') {
if (seensign || seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
seensign = 1;
continue;
}
}
if (*p1 == ' ') {
if (seensign || seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
option |= 4;
seensign = 1;
continue;
}
}
if (*p1 == '#') {
if (seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
option |= 8;
seenindicator = 1;
continue;
}
}
if (isdigit(*p1)) {
if (!seenalign) {
*(p2++) = '>';
seenalign = 1;
}
*(p2++) = *p1;
seendigits = 1;
continue;
}
if (*p1 == 'b') {
base = 2;
break;
}
if (*p1 == 'o') {
base = 8;
break;
}
if (*p1 == 'x') {
base = 16;
break;
}
if (*p1 == 'd') {
base = 10;
break;
}
if (*p1 == 'X') {
base = -16;
break;
}
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
*(p2++) = '\00';
if (!(mpzstr = mpz_ascii(MPZ(self), base, option, 0)))
return NULL;
result = PyObject_CallMethod(mpzstr, "__format__", "(s)", fmt);
Py_DECREF(mpzstr);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_format,
"x.__format__(fmt) -> string\n\n"
"Return a Python string by formatting 'x' using the format string\n"
"'fmt'. A valid format string consists of:\n"
" optional alignment code:\n"
" '<' -> left shifted in field\n"
" '>' -> right shifted in field\n"
" '^' -> centered in field\n"
" optional leading sign code\n"
" '+' -> always display leading sign\n"
" '-' -> only display minus for negative values\n"
" ' ' -> minus for negative values, space for positive values\n"
" optional width.precision\n"
" optional rounding mode:\n"
" 'U' -> round toward plus Infinity\n"
" 'D' -> round toward minus Infinity\n"
" 'Y' -> round away from zero\n"
" 'Z' -> round toward zero\n"
" 'N' -> round to nearest\n"
" optional conversion code:\n"
" 'a','A' -> hex format\n"
" 'b' -> binary format\n"
" 'e','E' -> scientific format\n"
" 'f','F' -> fixed point format\n"
" 'g','G' -> fixed or float format\n\n"
"The default format is '.6f'.");
static PyObject *
GMPy_MPFR_Format(PyObject *self, PyObject *args)
{
PyObject *result = NULL, *mpfrstr = NULL;
char *buffer = 0, *newbuf = 0, *fmtcode = 0, *p1, *p2, *p3;
char mpfrfmt[100], fmt[30];
int buflen;
int seensign = 0, seenalign = 0, seendecimal = 0, seendigits = 0;
int seenround = 0, seenconv = 0;
if (!MPFR_Check(self)) {
TYPE_ERROR("requires mpfr type");
return NULL;
}
if (!PyArg_ParseTuple(args, "s", &fmtcode))
return NULL;
p2 = mpfrfmt;
p3 = fmt;
*(p2++) = '%';
for (p1 = fmtcode; *p1 != '\00'; p1++) {
if (*p1 == '<' || *p1 == '>' || *p1 == '^') {
if (seenalign || seensign || seendecimal || seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p3++) = *p1;
seenalign = 1;
continue;
}
}
if (*p1 == '+' || *p1 == ' ') {
if (seensign || seendecimal || seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p2++) = *p1;
seensign = 1;
continue;
}
}
if (*p1 == '-') {
if (seensign || seendecimal || seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
seensign = 1;
continue;
}
}
if (*p1 == '.') {
if (seendecimal || seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p2++) = *p1;
seendecimal = 1;
continue;
}
}
if (isdigit(*p1)) {
if (seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else if (seendecimal) {
*(p2++) = *p1;
continue;
}
else {
if (p3 == fmt) {
*(p3++) = '>';
seenalign = 1;
}
*(p3++) = *p1;
continue;
}
}
if (!seendigits) {
seendigits = 1;
*(p2++) = 'R';
}
if (*p1 == 'U' || *p1 == 'D' || *p1 == 'Y' || *p1 == 'Z' ||
*p1 == 'N' ) {
if (seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p2++) = *p1;
seenround = 1;
continue;
}
}
if (*p1 == 'a' || *p1 == 'A' || *p1 == 'b' || *p1 == 'e' ||
*p1 == 'E' || *p1 == 'f' || *p1 == 'F' || *p1 == 'g' ||
*p1 == 'G' ) {
*(p2++) = *p1;
seenconv = 1;
break;
}
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
if (!seendigits)
*(p2++) = 'R';
if (!seenconv)
*(p2++) = 'f';
*(p2) = '\00';
*(p3) = '\00';
buflen = mpfr_asprintf(&buffer, mpfrfmt, MPFR(self));
/* If there isn't a decimal point in the output and the output
* only consists of digits, then append .0 */
if (strlen(buffer) == strspn(buffer, "+- 0123456789")) {
newbuf = malloc(buflen + 3);
if (!newbuf) {
mpfr_free_str(buffer);
return PyErr_NoMemory();
}
*newbuf = '\0';
strcat(newbuf, buffer);
strcat(newbuf, ".0");
mpfr_free_str(buffer);
mpfrstr = Py_BuildValue("s", newbuf);
free(newbuf);
}
else {
mpfrstr = Py_BuildValue("s", buffer);
mpfr_free_str(buffer);
}
if (!mpfrstr) {
return NULL;
}
result = PyObject_CallMethod(mpfrstr, "__format__", "(s)", fmt);
Py_DECREF(mpfrstr);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpc_format,
"x.__format__(fmt) -> string\n\n"
"Return a Python string by formatting 'x' using the format string\n"
"'fmt'. A valid format string consists of:\n"
" optional alignment code:\n"
" '<' -> left shifted in field\n"
" '>' -> right shifted in field\n"
" '^' -> centered in field\n"
" optional leading sign code\n"
" '+' -> always display leading sign\n"
" '-' -> only display minus for negative values\n"
" ' ' -> minus for negative values, space for positive values\n"
" optional width.real_precision.imag_precision\n"
" optional rounding mode:\n"
" 'U' -> round toward plus infinity\n"
" 'D' -> round toward minus infinity\n"
" 'Z' -> round toward zero\n"
" 'N' -> round to nearest\n"
" optional output style:\n"
" 'P' -> Python style, 1+2j, (default)\n"
" 'M' -> MPC style, (1 2)\n"
" optional conversion code:\n"
" 'a','A' -> hex format\n"
" 'b' -> binary format\n"
" 'e','E' -> scientific format\n"
" 'f','F' -> fixed point format\n"
" 'g','G' -> fixed or scientific format\n\n"
"The default format is 'f'.");
static PyObject *
GMPy_MPC_Format(PyObject *self, PyObject *args)
{
PyObject *result = NULL, *tempstr = NULL;
char *realbuf = 0, *imagbuf = 0, *tempbuf = 0, *fmtcode = 0;
char *p, *rfmtptr, *ifmtptr, *fmtptr;
char rfmt[100], ifmt[100], fmt[30];
int rbuflen, ibuflen;
int seensign = 0, seenalign = 0, seendecimal = 0, seendigits = 0;
int seenround = 0, seenconv = 0, seenstyle = 0, mpcstyle = 0;
if (!MPC_Check(self)) {
TYPE_ERROR("requires 'mpc' object");
return NULL;
}
if (!PyArg_ParseTuple(args, "s", &fmtcode)) {
return NULL;
}
rfmtptr = rfmt;
ifmtptr = ifmt;
fmtptr = fmt;
*(rfmtptr++) = '%';
*(ifmtptr++) = '%';
for (p = fmtcode; *p != '\00'; p++) {
if (*p == '<' || *p == '>' || *p == '^') {
if (seenalign || seensign || seendecimal || seendigits ||
seenround || seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(fmtptr++) = *p;
seenalign = 1;
continue;
}
}
if (*p == '+' || *p == ' ' || *p == '-') {
if (seensign || seendecimal || seendigits || seenround ||
seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
seensign = 1;
continue;
}
}
if (!seensign) {
*(rfmtptr++) = '-';
*(ifmtptr++) = '-';
seensign = 1;
}
if (*p == '.') {
if (seendecimal == 2 || seendigits || seenround || seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
if (!seendecimal) {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
}
seendecimal++;
if (seendecimal == 2) {
while (isdigit(*(ifmtptr-1)))
ifmtptr--;
}
continue;
}
}
if (isdigit(*p)) {
if (seendigits || seenround || seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else if (seendecimal == 1) {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
continue;
}
else if (seendecimal == 2) {
*(ifmtptr++) = *p;
continue;
}
else {
if (fmtptr == fmt) {
*(fmtptr++) = '>';
seenalign = 1;
}
*(fmtptr++) = *p;
continue;
}
}
if (!seendigits) {
seendigits = 1;
*(rfmtptr++) = 'R';
*(ifmtptr++) = 'R';
}
if (*p == 'U' || *p == 'D' || *p == 'Y' || *p == 'Z' ||
*p == 'N' ) {
if (seenround || seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
seenround = 1;
continue;
}
}
if (*p == 'P' || *p == 'M') {
if (seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
if (*p == 'M')
mpcstyle = 1;
seenstyle = 1;
continue;
}
}
if (*p == 'a' || *p == 'A' || *p == 'b' || *p == 'e' ||
*p == 'E' || *p == 'f' || *p == 'F' || *p == 'g' ||
*p == 'G' ) {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
seenconv = 1;
break;
}
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
if (!seensign) {
*(rfmtptr++) = '-';
*(ifmtptr++) = '-';
}
if (!seendigits) {
*(rfmtptr++) = 'R';
*(ifmtptr++) = 'R';
}
if (!seenconv) {
*(rfmtptr++) = 'f';
*(ifmtptr++) = 'f';
}
*(rfmtptr) = '\00';
*(ifmtptr) = '\00';
*(fmtptr) = '\00';
/* Format the real part.... */
rbuflen = mpfr_asprintf(&realbuf, rfmt,
mpc_realref(MPC(self)));
if (rbuflen < 0) {
mpfr_free_str(realbuf);
SYSTEM_ERROR("Internal error in mpfr_asprintf");
return NULL;
}
/* Format the imaginary part. If Python style is wanted, convert the '-'
* or ' ' sign indicator to '+'. */
if (!mpcstyle) {
if (ifmt[1] == ' ' || ifmt[1] == '-' || ifmt[1] == '+') {
ifmt[1] = '+';
}
else {
mpfr_free_str(realbuf);
VALUE_ERROR("Invalid conversion specification for imag");
return NULL;
}
}
ibuflen = mpfr_asprintf(&imagbuf, ifmt,
mpc_imagref(MPC(self)));
if (ibuflen < 0) {
mpfr_free_str(realbuf);
mpfr_free_str(imagbuf);
SYSTEM_ERROR("Internal error in mpfr_asprintf");
return NULL;
}
/* Combine the real and imaginary components into a single buffer.
* Include space for '(', ' ', and 'j)' and possibly appending '.0' twice.
*/
tempbuf = malloc(rbuflen + ibuflen + 10);
if (!tempbuf) {
mpfr_free_str(realbuf);
mpfr_free_str(imagbuf);
return PyErr_NoMemory();
}
tempbuf[0] = '\00';
if (mpcstyle)
strcat(tempbuf, "(");
strcat(tempbuf, realbuf);
/* If there isn't a decimal point in the output and the output
* is short and only consists of digits, then append .0 */
if (strlen(realbuf) < 50 &&
strlen(realbuf) == strspn(realbuf, "+- 0123456789")) {
strcat(tempbuf, ".0");
}
if (mpcstyle)
strcat(tempbuf, " ");
else {
/* Need to insert + if imag is nan or +inf. */
if (mpfr_nan_p(mpc_imagref(MPC(self))) ||
(mpfr_inf_p(mpc_imagref(MPC(self))) &&
mpfr_sgn(mpc_imagref(MPC(self))) > 0)) {
strcat(tempbuf, "+");
}
}
strcat(tempbuf, imagbuf);
if (strlen(imagbuf) < 50 &&
strlen(imagbuf) == strspn(imagbuf, "+- 0123456789")) {
strcat(tempbuf, ".0");
}
if (mpcstyle)
strcat(tempbuf, ")");
else
strcat(tempbuf, "j");
mpfr_free_str(realbuf);
mpfr_free_str(imagbuf);
tempstr = Py_BuildValue("s", tempbuf);
if (!tempstr) {
free(tempbuf);
return NULL;
}
result = PyObject_CallMethod(tempstr, "__format__", "(s)", fmt);
Py_DECREF(tempstr);
return result;
}
/* produce digits for an mpz in requested base, default 10 */
PyDoc_STRVAR(GMPy_doc_mpz_digits_method,
"x.digits([base=10]) -> string\n\n"
"Return Python string representing x in the given base. Values for\n"
"base can range between 2 to 62. A leading '-' is present if x<0\n"
"but no leading '+' is present if x>=0.");
static PyObject *
GMPy_MPZ_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|i", &base)) {
return NULL;
}
return GMPy_PyStr_From_MPZ((MPZ_Object*)self, base, 16, NULL);
}
static PyObject *
GMPy_XMPZ_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|i", &base)) {
return NULL;
}
return GMPy_PyStr_From_XMPZ((XMPZ_Object*)self, base, 0, NULL);
}
PyDoc_STRVAR(GMPy_doc_mpq_digits_method,
"x.digits([base=10]) -> string\n\n"
"Return a Python string representing x in the given base (2 to 62,\n"
"default is 10). A leading '-' is present if x<0, but no leading '+'\n"
"is present if x>=0.\n");
static PyObject *
GMPy_MPQ_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|i", &base)) {
return NULL;
}
return GMPy_PyStr_From_MPQ((MPQ_Object*)self, base, 0, NULL);
}
PyDoc_STRVAR(GMPy_doc_mpfr_digits_method,
"x.digits([base=10[, prec=0]]) -> (mantissa, exponent, bits)\n\n"
"Returns up to 'prec' digits in the given base. If 'prec' is 0, as many\n"
"digits that are available are returned. No more digits than available\n"
"given x's precision are returned. 'base' must be between 2 and 62,\n"
"inclusive. The result is a three element tuple containing the mantissa,\n"
"the exponent, and the number of bits of precision.");
static PyObject *
GMPy_MPFR_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10, prec = 0;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|ii", &base, &prec)) {
return NULL;
}
return GMPy_PyStr_From_MPFR((MPFR_Object*)self, base, prec, NULL);
}
PyDoc_STRVAR(GMPy_doc_mpc_digits_method,
"c.digits(base=10, prec=0) -> ((mant, exp, prec), (mant, exp, prec))\n\n"
"Returns up to 'prec' digits in the given base. If 'prec' is 0, as many\n"
"digits that are available given c's precision are returned. 'base' must\n"
"be between 2 and 62. The result consists of 2 three-element tuples that\n"
"contain the mantissa, exponent, and number of bits of precision of the\n"
"real and imaginary components.");
static PyObject *
GMPy_MPC_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10, prec = 0;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|ii", &base, &prec)) {
return NULL;
}
return GMPy_PyStr_From_MPC((MPC_Object*)self, base, prec, NULL);
}
PyDoc_STRVAR(GMPy_doc_context_digits,
"digits(x[, base[, prec]]) -> string\n\n"
"Return string representing x. Calls mpz.digits, mpq.digits,\n"
"mpfr.digits, or mpc.digits as appropriate.");
static PyObject *
GMPy_Context_Digits(PyObject *self, PyObject *args)
{
PyObject *arg0, *tuple, *temp, *result;
Py_ssize_t argc;
argc = PyTuple_GET_SIZE(args);
if (argc == 0) {
TYPE_ERROR("digits() requires at least one argument");
return NULL;
}
if (argc > 3) {
TYPE_ERROR("digits() accepts at most three arguments");
return NULL;
}
arg0 = PyTuple_GET_ITEM(args, 0);
if (!(tuple = PyTuple_GetSlice(args, 1, argc))) {
return NULL;
}
if (IS_INTEGER(arg0)) {
temp = (PyObject*)GMPy_MPZ_From_Integer(arg0, NULL);
result = GMPy_MPZ_Digits_Method(temp, tuple);
Py_DECREF(temp);
Py_DECREF(tuple);
return result;
}
if (IS_RATIONAL(arg0)) {
temp = (PyObject*)GMPy_MPQ_From_Rational(arg0, NULL);
result = GMPy_MPQ_Digits_Method(temp, tuple);
Py_DECREF(temp);
Py_DECREF(tuple);
return result;
}
if (IS_REAL(arg0)) {
temp = (PyObject*)GMPy_MPFR_From_Real(arg0, 1, NULL);
result = GMPy_MPFR_Digits_Method(temp, tuple);
Py_DECREF(temp);
Py_DECREF(tuple);
return result;
}
if (IS_COMPLEX(arg0)) {
temp = (PyObject*)GMPy_MPC_From_Complex(arg0, 1, 1, NULL);
result = GMPy_MPC_Digits_Method(temp, tuple);
Py_DECREF(temp);
Py_DECREF(tuple);
return result;
}
Py_DECREF(tuple);
TYPE_ERROR("digits() argument type not supported");
return NULL;
}
gmpy2-2.1.0b3/src/gmpy2_format.h 0000664 0001750 0001750 00000005436 13425752314 016233 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_format.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_FORMAT_H
#define GMPY_FORMAT_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_Digits_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Format(PyObject *self, PyObject *args);
static PyObject * GMPy_MPQ_Digits_Method(PyObject *self, PyObject *args);
/* static PyObject * GMPy_MPQ_Format(PyObject *self, PyObject *args); */
static PyObject * GMPy_MPFR_Digits_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Format(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_Digits_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_Format(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Digits(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_fused.c 0000664 0001750 0001750 00000050650 13425752326 016045 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_fused.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *
_GMPy_MPZ_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_mul(result->z, MPZ(x), MPZ(y));
mpz_add(result->z, result->z, MPZ(z));
return (PyObject*)result;
}
static PyObject *
GMPy_Integer_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPZ_From_Integer(x, context)) ||
!(tempy = (PyObject*)GMPy_MPZ_From_Integer(y, context)) ||
!(tempz = (PyObject*)GMPy_MPZ_From_Integer(z, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPZ_FMA(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPQ_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPQ_Object *result;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_mul(result->q, MPQ(x), MPQ(y));
mpq_add(result->q, result->q, MPQ(z));
return (PyObject*)result;
}
static PyObject *
GMPy_Rational_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPQ_From_Rational(x, context)) ||
!(tempy = (PyObject*)GMPy_MPQ_From_Rational(y, context)) ||
!(tempz = (PyObject*)GMPy_MPQ_From_Rational(z, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPQ_FMA(tempx, tempy, tempz, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempz);
return (result);
}
static PyObject *
_GMPy_MPFR_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_fma(result->f, MPFR(x), MPFR(y), MPFR(z), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPFR_From_Real(y, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPFR_From_Real(z, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPFR_FMA(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPC_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpc_fma(result->c, MPC(x), MPC(y), MPC(z), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPC_From_Complex(y, 1, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPC_From_Complex(z, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPC_FMA(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_fma,
"context.fma(x, y, z) -> number\n\n"
"Return correctly rounded result of (x * y) + z.");
PyDoc_STRVAR(GMPy_doc_function_fma,
"fma(x, y, z) -> number\n\n"
"Return correctly rounded result of (x * y) + z.");
GMPY_MPFR_MPC_TRIOP_TEMPLATE(FMA, fma);
static PyObject *
_GMPy_MPZ_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_mul(result->z, MPZ(x), MPZ(y));
mpz_sub(result->z, result->z, MPZ(z));
return (PyObject*)result;
}
static PyObject *
GMPy_Integer_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPZ_From_Integer(x, context)) ||
!(tempy = (PyObject*)GMPy_MPZ_From_Integer(y, context)) ||
!(tempz = (PyObject*)GMPy_MPZ_From_Integer(z, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPZ_FMS(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPQ_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPQ_Object *result;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_mul(result->q, MPQ(x), MPQ(y));
mpq_sub(result->q, result->q, MPQ(z));
return (PyObject*)result;
}
static PyObject *
GMPy_Rational_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPQ_From_Rational(x, context)) ||
!(tempy = (PyObject*)GMPy_MPQ_From_Rational(y, context)) ||
!(tempz = (PyObject*)GMPy_MPQ_From_Rational(z, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPQ_FMS(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPFR_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_fms(result->f, MPFR(x), MPFR(y), MPFR(z), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPFR_From_Real(y, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPFR_From_Real(z, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPFR_FMS(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPC_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* TODO: We shouldn't temporarily mutate an mpc object. */
mpc_neg(MPC(z), MPC(z), GET_MPC_ROUND(context));
result->rc = mpc_fma(result->c, MPC(x), MPC(y), MPC(z), GET_MPC_ROUND(context));
mpc_neg(MPC(z), MPC(z), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPC_From_Complex(y, 1, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPC_From_Complex(z, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPC_FMS(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_fms,
"context.fms(x, y, z) -> number\n\n"
"Return correctly rounded result of (x * y) - z.");
PyDoc_STRVAR(GMPy_doc_function_fms,
"fms(x, y, z) -> number\n\n"
"Return correctly rounded result of (x * y) - z.");
GMPY_MPFR_MPC_TRIOP_TEMPLATE(FMS, fms);
/* Add support for new fmma and fmms functions from MPFr 4. */\
#if MPFR_VERSION_MAJOR > 3
static PyObject *
_GMPy_MPZ_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPZ_Object *result = NULL, *temp = NULL;
if (!(result = GMPy_MPZ_New(context)) ||
!(temp = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF(temp);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_mul(result->z, MPZ(x), MPZ(y));
mpz_mul(temp->z, MPZ(z), MPZ(t));
mpz_add(result->z, result->z, temp->z);
Py_DECREF(temp);
return (PyObject*)result;
}
static PyObject *
GMPy_Integer_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPZ_From_Integer(x, context)) ||
!(tempy = (PyObject*)GMPy_MPZ_From_Integer(y, context)) ||
!(tempz = (PyObject*)GMPy_MPZ_From_Integer(z, context)) ||
!(tempt = (PyObject*)GMPy_MPZ_From_Integer(t, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPZ_FMMA(tempx, tempy, tempz, tempt, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
Py_DECREF(tempt);
return result;
}
static PyObject *
_GMPy_MPQ_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPQ_Object *result = NULL, *temp = NULL;
if (!(result = GMPy_MPQ_New(context)) ||
!(temp = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF(temp);
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_mul(result->q, MPQ(x), MPQ(y));
mpq_mul(temp->q, MPQ(z), MPQ(t));
mpq_add(result->q, result->q, temp->q);
Py_DECREF(temp);
return (PyObject*)result;
}
static PyObject *
GMPy_Rational_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPQ_From_Rational(x, context)) ||
!(tempy = (PyObject*)GMPy_MPQ_From_Rational(y, context)) ||
!(tempz = (PyObject*)GMPy_MPQ_From_Rational(z, context)) ||
!(tempt = (PyObject*)GMPy_MPQ_From_Rational(t, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPQ_FMMA(tempx, tempy, tempz, tempt, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempz);
Py_DECREF((PyObject*)tempt);
return (result);
}
static PyObject *
_GMPy_MPFR_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_fmma(result->f, MPFR(x), MPFR(y), MPFR(z), MPFR(t), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPFR_From_Real(y, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPFR_From_Real(z, 1, context)) ||
!(tempt = (PyObject*)GMPy_MPFR_From_Real(t, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPFR_FMMA(tempx, tempy, tempz, tempt, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
Py_DECREF(tempt);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_fmma,
"context.fmma(x, y, z, t) -> number\n\n"
"Return correctly rounded result of (x * y) + (z * t).");
PyDoc_STRVAR(GMPy_doc_function_fmma,
"fmma(x, y, z, t) -> number\n\n"
"Return correctly rounded result of (x * y) + (z + t).");
GMPY_MPFR_QUADOP_TEMPLATE(FMMA, fmma);
static PyObject *
_GMPy_MPZ_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPZ_Object *result = NULL, *temp = NULL;
if (!(result = GMPy_MPZ_New(context)) ||
!(temp = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF(temp);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_mul(result->z, MPZ(x), MPZ(y));
mpz_mul(temp->z, MPZ(z), MPZ(t));
mpz_sub(result->z, result->z, temp->z);
Py_DECREF(temp);
return (PyObject*)result;
}
static PyObject *
GMPy_Integer_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPZ_From_Integer(x, context)) ||
!(tempy = (PyObject*)GMPy_MPZ_From_Integer(y, context)) ||
!(tempz = (PyObject*)GMPy_MPZ_From_Integer(z, context)) ||
!(tempt = (PyObject*)GMPy_MPZ_From_Integer(t, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPZ_FMMS(tempx, tempy, tempz, tempt, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
Py_DECREF(tempt);
return result;
}
static PyObject *
_GMPy_MPQ_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPQ_Object *result = NULL, *temp = NULL;
if (!(result = GMPy_MPQ_New(context)) ||
!(temp = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF(temp);
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_mul(result->q, MPQ(x), MPQ(y));
mpq_mul(temp->q, MPQ(z), MPQ(t));
mpq_sub(result->q, result->q, temp->q);
Py_DECREF(temp);
return (PyObject*)result;
}
static PyObject *
GMPy_Rational_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPQ_From_Rational(x, context)) ||
!(tempy = (PyObject*)GMPy_MPQ_From_Rational(y, context)) ||
!(tempz = (PyObject*)GMPy_MPQ_From_Rational(z, context)) ||
!(tempt = (PyObject*)GMPy_MPQ_From_Rational(t, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPQ_FMMS(tempx, tempy, tempz, tempt, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempz);
Py_DECREF((PyObject*)tempt);
return (result);
}
static PyObject *
_GMPy_MPFR_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_fmms(result->f, MPFR(x), MPFR(y), MPFR(z), MPFR(t), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPFR_From_Real(y, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPFR_From_Real(z, 1, context)) ||
!(tempt = (PyObject*)GMPy_MPFR_From_Real(t, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPFR_FMMS(tempx, tempy, tempz, tempt, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
Py_DECREF(tempt);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_fmms,
"context.fmms(x, y, z, t) -> number\n\n"
"Return correctly rounded result of (x * y) - (z * t).");
PyDoc_STRVAR(GMPy_doc_function_fmms,
"fmms(x, y, z, t) -> number\n\n"
"Return correctly rounded result of (x * y) - (z + t).");
GMPY_MPFR_QUADOP_TEMPLATE(FMMS, fmms);
#endif
gmpy2-2.1.0b3/src/gmpy2_fused.h 0000664 0001750 0001750 00000006345 13425752341 016051 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_fused.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_FUSED_H
#define GMPY_FUSED_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Integer_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Rational_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Real_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Complex_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Number_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Context_FMA(PyObject *self, PyObject *args);
static PyObject * GMPy_Integer_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Rational_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Real_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Complex_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Number_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Context_FMS(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_hash.c 0000664 0001750 0001750 00000014754 13425752350 015664 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_hash.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static Py_hash_t
GMPy_MPZ_Hash_Slot(MPZ_Object *self)
{
#ifdef _PyHASH_MODULUS
Py_hash_t hash;
if (self->hash_cache != -1) {
return self->hash_cache;
}
hash = (Py_hash_t)mpn_mod_1(self->z->_mp_d, mpz_size(self->z), _PyHASH_MODULUS);
if (mpz_sgn(self->z) < 0) {
hash = -hash;
}
if (hash == -1) {
hash = -2;
}
return (self->hash_cache = hash);
#else
unsigned long x;
if (self->hash_cache != -1) {
return self->hash_cache;
}
x = (unsigned long)mpn_mod_1(self->z->_mp_d, mpz_size(self->z), ULONG_MAX);
if (mpz_sgn(self->z) < 0) {
x = x * -1;
}
if (x == (unsigned long)-1) {
x = (unsigned long)-2;
}
return (self->hash_cache = (long)x);
#endif
}
static Py_hash_t
GMPy_MPQ_Hash_Slot(MPQ_Object *self)
{
#ifdef _PyHASH_MODULUS
Py_hash_t hash = 0;
mpz_t temp, temp1, mask;
if (self->hash_cache != -1) {
return self->hash_cache;
}
mpz_init(temp);
mpz_init(temp1);
mpz_init(mask);
mpz_set_si(mask, 1);
mpz_mul_2exp(mask, mask, _PyHASH_BITS);
mpz_sub_ui(mask, mask, 1);
if (!mpz_invert(temp, mpq_denref(self->q), mask)) {
mpz_clear(temp);
mpz_clear(temp1);
mpz_clear(mask);
hash = _PyHASH_INF;
if (mpz_sgn(mpq_numref(self->q)) < 0) {
hash = -hash;
}
self->hash_cache = hash;
return hash;
}
mpz_set(temp1, mask);
mpz_sub_ui(temp1, temp1, 2);
mpz_powm(temp, mpq_denref(self->q), temp1, mask);
mpz_tdiv_r(temp1, mpq_numref(self->q), mask);
mpz_mul(temp, temp, temp1);
hash = (Py_hash_t)mpn_mod_1(temp->_mp_d, mpz_size(temp), _PyHASH_MODULUS);
if (mpz_sgn(mpq_numref(self->q)) < 0) {
hash = -hash;
}
if (hash == -1) {
hash = -2;
}
mpz_clear(temp);
mpz_clear(temp1);
mpz_clear(mask);
self->hash_cache = hash;
return hash;
#else
PyObject *temp;
if (self->hash_cache != -1) {
return self->hash_cache;
}
if (!(temp = GMPy_PyFloat_From_MPQ(self, NULL))) {
SYSTEM_ERROR("Could not convert 'mpq' to float.");
return -1;
}
self->hash_cache = PyObject_Hash(temp);
Py_DECREF(temp);
return self->hash_cache;
#endif
}
static Py_hash_t
_mpfr_hash(mpfr_t f)
{
#ifdef _PyHASH_MODULUS
Py_uhash_t hash = 0;
Py_ssize_t exp;
size_t msize;
int sign;
/* Handle special cases first */
if (!mpfr_number_p(f)) {
if (mpfr_inf_p(f)) {
if (mpfr_sgn(f) > 0) {
return _PyHASH_INF;
}
else {
return -_PyHASH_INF;
}
}
else {
return _PyHASH_NAN;
}
}
/* Calculate the number of limbs in the mantissa. */
msize = (f->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb;
/* Calculate the hash of the mantissa. */
if (mpfr_sgn(f) > 0) {
hash = mpn_mod_1(f->_mpfr_d, msize, _PyHASH_MODULUS);
sign = 1;
}
else if (mpfr_sgn(f) < 0) {
hash = mpn_mod_1(f->_mpfr_d, msize, _PyHASH_MODULUS);
sign = -1;
}
else {
return 0;
}
/* Calculate the final hash. */
exp = f->_mpfr_exp - (msize * mp_bits_per_limb);
exp = exp >= 0 ? exp % _PyHASH_BITS : _PyHASH_BITS-1-((-1-exp) % _PyHASH_BITS);
hash = ((hash << exp) & _PyHASH_MODULUS) | hash >> (_PyHASH_BITS - exp);
hash *= sign;
if (hash == (Py_uhash_t)(-1)) {
hash = (Py_uhash_t)(-2);
}
return (Py_hash_t)hash;
#else
double temp;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
temp = mpfr_get_d(f, GET_MPFR_ROUND(context));
return _Py_HashDouble(temp);
#endif
}
static Py_hash_t
GMPy_MPFR_Hash_Slot(MPFR_Object *self)
{
if (self->hash_cache == -1) {
self->hash_cache = _mpfr_hash(self->f);
}
return self->hash_cache;
}
static Py_hash_t
GMPy_MPC_Hash_Slot(MPC_Object *self)
{
Py_uhash_t hashreal, hashimag, combined;
if (self->hash_cache != -1) {
return self->hash_cache;
}
hashreal = (Py_uhash_t)_mpfr_hash(mpc_realref(self->c));
if (hashreal == (Py_uhash_t)(-1)) {
return -1;
}
hashimag = (Py_uhash_t)_mpfr_hash(mpc_imagref(self->c));
if (hashimag == (Py_uhash_t)(-1)) {
return -1;
}
combined = hashreal + _PyHASH_IMAG * hashimag;
if (combined == (Py_uhash_t)(-1)) {
combined = (Py_uhash_t)(-2);
}
self->hash_cache = combined;
return (Py_hash_t)combined;
}
gmpy2-2.1.0b3/src/gmpy2_hash.h 0000664 0001750 0001750 00000004565 13425752363 015674 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_hash.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_HASH_H
#define GMPY_HASH_H
#ifdef __cplusplus
extern "C" {
#endif
static Py_hash_t GMPy_MPZ_Hash_Slot(MPZ_Object *self);
static Py_hash_t GMPy_MPQ_Hash_Slot(MPQ_Object *self);
static Py_hash_t GMPy_MPFR_Hash_Slot(MPFR_Object *self);
static Py_hash_t GMPy_MPC_Hash_Slot(MPC_Object *self);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_macros.h 0000664 0001750 0001750 00000063146 13425752400 016225 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_macros.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains a collection of macros that can be used to reduce
* repetitive code. As new macros are written to support of refactoring,
* they should be placed here.
*/
/* NAME is used as part of the GMPy function name. It usually uses an upper-
* case first character.
* FUNC is the component of the actual name used by MPFR and MPC.
*
* GMPY_MPFR_MPC_UNIOP(NAME, FUNC) creates the following functions:
* GMPy_Real_NAME(x, context)
* GMPy_Complex_NAME(x, context)
* GMPy_Number_NAME(x, context)
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_MPC_UNIOP_EX(NAME, FUNC) creates the following functions:
* GMPy_MPFR_NAME(x, context)
* GMPy_Real_NAME(x, context)
* GMPy_MPC_NAME(x, context)
* GMPy_Complex_NAME(x, context)
* GMPy_Number_NAME(x, context)
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_MPC_UNIOP_TEMPLATE(NAME, FUNC) creates the following functions:
* GMPy_Number_NAME(x, context)
* - assumes GMPy_Real_NAME & GMPy_Complex_NAME exist
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_MPC_TRIOP_EX(NAME, FUNC) creates the following functions:
* GMPy_Real_NAME(x, y, Z, context)
* GMPy_Complex_NAME(x, y, Z, context)
* GMPy_Number_NAME(x, y, Z, context)
* - assumes GMPy_Integer_NAME & GMPy_Rational_NAME also exist
* GMPy_Context_NAME(self, args)
* - called with METH_VARARGS
*
* GMPY_MPFR_MPC_UNIOP_TEMPLATE(NAME, FUNC) creates the following functions:
* GMPy_Number_NAME(x, context)
* - assumes GMPy_Real_NAME & GMPy_Complex_NAME exist
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_UNIOP(NAME, FUNC) creates the following functions:
* GMPy_Real_NAME(x, context)
* GMPy_Number_NAME(x, context)
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_UNIOP_TEMPLATE(NAME, FUNC) creates the following functions:
* GMPy_Number_NAME(x, context)
* - assumes GMPy_Real_NAME exists
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_BINOP(NAME, FUNC) creates the following functions:
* GMPy_Real_NAME(x, y, context)
* GMPy_Number_NAME(x, y, context)
* GMPy_Context_NAME(self, args)
* - called with METH_VARARGS
*
*/
#define GMPY_MPFR_MPC_UNIOP(NAME, FUNC) \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL; \
CHECK_CONTEXT(context); \
result = GMPy_MPFR_New(0, context); \
tempx = GMPy_MPFR_From_Real(x, 1, context); \
if (!result || !tempx) { \
Py_XDECREF((PyObject*)result); \
Py_XDECREF((PyObject*)tempx); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f, GET_MPFR_ROUND(context)); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
#define GMPY_MPFR_MPC_UNIOP_EX(NAME, FUNC) \
static PyObject * \
_GMPy_MPFR_##NAME(PyObject *x, CTXT_Object *context) \
{ \
MPFR_Object *result; \
CHECK_CONTEXT(context); \
if (!(result = GMPy_MPFR_New(0, context))) { \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, MPFR(x), GET_MPFR_ROUND(context)); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, CTXT_Object *context) \
{ \
MPFR_Object *tempx; \
PyObject *result; \
CHECK_CONTEXT(context); \
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) { \
return NULL; \
} \
result = _GMPy_MPFR_##NAME((PyObject*)tempx, context); \
Py_DECREF((PyObject*)tempx); \
return (PyObject*)result; \
} \
static PyObject * \
_GMPy_MPC_##NAME(PyObject *x, CTXT_Object *context) \
{ \
MPC_Object *result; \
CHECK_CONTEXT(context); \
if (!(result = GMPy_MPC_New(0, 0, context))) { \
return NULL; \
} \
result->rc = mpc_##FUNC(result->c, MPC(x), GET_MPC_ROUND(context)); \
_GMPy_MPC_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Complex_##NAME(PyObject *x, CTXT_Object *context) \
{ \
MPC_Object *tempx; \
PyObject *result; \
CHECK_CONTEXT(context); \
if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context))) { \
return NULL; \
} \
result = _GMPy_MPC_##NAME((PyObject*)tempx, context); \
Py_DECREF((PyObject*)tempx); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
if (MPFR_Check(x)) \
return _GMPy_MPFR_##NAME(x, context); \
if (MPC_Check(x)) \
return _GMPy_MPC_##NAME(x, context); \
if (IS_REAL(x)) \
return GMPy_Real_##NAME(x, context); \
if (IS_COMPLEX(x)) \
return GMPy_Complex_##NAME(x, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
#define GMPY_MPFR_MPC_UNIOP_TEMPLATE(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
if (IS_REAL(x)) \
return GMPy_Real_##NAME(x, context); \
if (IS_COMPLEX(x)) \
return GMPy_Complex_##NAME(x, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
#define GMPY_MPFR_MPC_UNIOP_TEMPLATE_EX(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
if (MPFR_Check(x)) \
return _GMPy_MPFR_##NAME(x, context); \
if (MPC_Check(x)) \
return _GMPy_MPC_##NAME(x, context); \
if (IS_REAL(x)) \
return GMPy_Real_##NAME(x, context); \
if (IS_COMPLEX(x)) \
return GMPy_Complex_##NAME(x, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
#define GMPY_MPFR_MPC_TRIOP_TEMPLATE(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context) \
{ \
if (MPZ_Check(x) && MPZ_Check(y) && MPZ_Check(z)) \
return _GMPy_MPZ_##NAME(x, y, z, context); \
if (MPQ_Check(x) && MPQ_Check(y) && MPQ_Check(z)) \
return _GMPy_MPQ_##NAME(x, y, z, context); \
if (MPFR_Check(x) && MPFR_Check(y) && MPFR_Check(z)) \
return _GMPy_MPFR_##NAME(x, y, z, context); \
if (MPC_Check(x) && MPC_Check(y) && MPC_Check(z)) \
return _GMPy_MPC_##NAME(x, y, z, context); \
if (IS_INTEGER(x) && IS_INTEGER(y) && IS_INTEGER(z)) \
return GMPy_Integer_##NAME(x, y, z, context); \
if (IS_RATIONAL(x) && IS_RATIONAL(y) && IS_RATIONAL(z)) \
return GMPy_Rational_##NAME(x, y, z, context); \
if (IS_REAL(x) && IS_REAL(y) && IS_REAL(z)) \
return GMPy_Real_##NAME(x, y, z, context); \
if (IS_COMPLEX(x) && IS_COMPLEX(y) && IS_COMPLEX(z)) \
return GMPy_Complex_##NAME(x, y, z, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 3) { \
TYPE_ERROR(#FUNC"() requires 3 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), \
PyTuple_GET_ITEM(args, 1), \
PyTuple_GET_ITEM(args, 2), context); \
}
#define GMPY_MPFR_QUADOP_TEMPLATE(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context) \
{ \
if (MPZ_Check(x) && MPZ_Check(y) && MPZ_Check(z) && MPZ_Check(t)) \
return _GMPy_MPZ_##NAME(x, y, z, t, context); \
if (MPQ_Check(x) && MPQ_Check(y) && MPQ_Check(z) && MPQ_Check(t)) \
return _GMPy_MPQ_##NAME(x, y, z, t, context); \
if (MPFR_Check(x) && MPFR_Check(y) && MPFR_Check(z) && MPFR_Check(t)) \
return _GMPy_MPFR_##NAME(x, y, z, t, context); \
if (IS_INTEGER(x) && IS_INTEGER(y) && IS_INTEGER(z) && IS_INTEGER(t)) \
return GMPy_Integer_##NAME(x, y, z, t, context); \
if (IS_RATIONAL(x) && IS_RATIONAL(y) && IS_RATIONAL(z) && IS_RATIONAL(t)) \
return GMPy_Rational_##NAME(x, y, z, t, context); \
if (IS_REAL(x) && IS_REAL(y) && IS_REAL(z) && IS_REAL(t)) \
return GMPy_Real_##NAME(x, y, z, t, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 4) { \
TYPE_ERROR(#FUNC"() requires 4 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), \
PyTuple_GET_ITEM(args, 1), \
PyTuple_GET_ITEM(args, 2), \
PyTuple_GET_ITEM(args, 3), context); \
}
#define GMPY_MPFR_UNIOP(NAME, FUNC) \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, CTXT_Object *context) \
{ \
MPFR_Object *result, *tempx; \
CHECK_CONTEXT(context); \
result = GMPy_MPFR_New(0, context); \
tempx = GMPy_MPFR_From_Real(x, 1, context); \
if (!result || !tempx) { \
Py_XDECREF((PyObject*)result); \
Py_XDECREF((PyObject*)tempx); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f, GET_MPFR_ROUND(context)); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
if (IS_REAL(x)) \
return GMPy_Real_##NAME(x, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
#define GMPY_MPFR_UNIOP_NOROUND(NAME, FUNC) \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, CTXT_Object *context) \
{ \
MPFR_Object *result, *tempx; \
CHECK_CONTEXT(context); \
result = GMPy_MPFR_New(0, context); \
tempx = GMPy_MPFR_From_Real(x, 1, context); \
if (!result || !tempx) { \
Py_XDECREF((PyObject*)result); \
Py_XDECREF((PyObject*)tempx); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
if (IS_REAL(x)) \
return GMPy_Real_##NAME(x, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_MPFR_Method_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
CHECK_CONTEXT(context); \
return GMPy_Number_##NAME(self, context); \
}\
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
#define GMPY_MPFR_UNIOP_NOROUND_NOMETHOD(NAME, FUNC) \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, CTXT_Object *context) \
{ \
MPFR_Object *result, *tempx; \
CHECK_CONTEXT(context); \
result = GMPy_MPFR_New(0, context); \
tempx = GMPy_MPFR_From_Real(x, 1, context); \
if (!result || !tempx) { \
Py_XDECREF((PyObject*)result); \
Py_XDECREF((PyObject*)tempx); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
if (IS_REAL(x)) \
return GMPy_Real_##NAME(x, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
#define GMPY_MPFR_UNIOP_EX(NAME, FUNC) \
static PyObject * \
_GMPy_MPFR_##NAME(PyObject *x, CTXT_Object *context) \
{ \
MPFR_Object *result; \
CHECK_CONTEXT(context); \
if (!(result = GMPy_MPFR_New(0, context))) { \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, MPFR(x), GET_MPFR_ROUND(context)); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, CTXT_Object *context) \
{ \
PyObject *result, *tempx; \
CHECK_CONTEXT(context); \
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) { \
return NULL; \
} \
result = _GMPy_MPFR_##NAME(tempx, context); \
Py_DECREF(tempx); \
return result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
if (MPFR_Check(x)) \
return _GMPy_MPFR_##NAME(x, context); \
if (IS_REAL(x)) \
return GMPy_Real_##NAME(x, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
#define GMPY_MPFR_UNIOP_TEMPLATE(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
if (IS_REAL(x)) \
return GMPy_Real_##NAME(x, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
#define GMPY_MPFR_UNIOP_TEMPLATE_EX(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
if (MPFR_Check(x)) \
return _GMPy_MPFR_##NAME(x, context); \
if (IS_REAL(x)) \
return GMPy_Real_##NAME(x, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
#define GMPY_MPFR_BINOP(NAME, FUNC) \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL, *tempy = NULL; \
CHECK_CONTEXT(context); \
tempx = GMPy_MPFR_From_Real(x, 1, context); \
tempy = GMPy_MPFR_From_Real(y, 1, context); \
result = GMPy_MPFR_New(0, context); \
if (!result || !tempx || !tempy) { \
Py_XDECREF((PyObject*)tempx); \
Py_XDECREF((PyObject*)tempy); \
Py_XDECREF((PyObject*)result); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context)); \
Py_DECREF((PyObject*)tempx); \
Py_DECREF((PyObject*)tempy); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
if (IS_REAL(x) && IS_REAL(y)) \
return GMPy_Real_##NAME(x, y, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
} \
/* Macro to support functions that require ('mpfr', 'int').
* More precisely, the first argument must pass IS_REAL() and the second
* argument must pass IS_INTEGER(). */
#define GMPY_MPFR_BINOP_REAL_ULONG(NAME, FUNC) \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL; \
unsigned long n; \
CHECK_CONTEXT(context); \
result = GMPy_MPFR_New(0, context); \
tempx = GMPy_MPFR_From_Real(x, 1, context); \
n = c_ulong_From_Integer(y); \
if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) { \
Py_XDECREF((PyObject*)tempx); \
Py_XDECREF((PyObject*)result); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f, n, GET_MPFR_ROUND(context)); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
if (IS_REAL(x) && PyIntOrLong_Check(y)) \
return GMPy_Real_##NAME(x, y, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
} \
/* Macro to support functions that require ('mpfr', 'int').
* More precisely, the first argument must pass IS_REAL() and the second
* argument must pass IS_INTEGER(). The calling sequence passes n first
* to the MPFR library.*/
#define GMPY_MPFR_BINOP_REAL_LONG(NAME, FUNC) \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL; \
long n; \
CHECK_CONTEXT(context); \
result = GMPy_MPFR_New(0, context); \
tempx = GMPy_MPFR_From_Real(x, 1, context); \
n = c_long_From_Integer(y); \
if (!result || !tempx || (n == -1 && PyErr_Occurred())) { \
Py_XDECREF((PyObject*)tempx); \
Py_XDECREF((PyObject*)result); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, n, tempx->f, GET_MPFR_ROUND(context)); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
if (IS_REAL(x) && PyIntOrLong_Check(y)) \
return GMPy_Real_##NAME(x, y, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
} \
#define GMPY_MPFR_BINOP_TEMPLATE(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
if (IS_REAL(x) && IS_REAL(y)) \
return GMPy_Real_##NAME(x, y, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
} \
#define GMPY_MPFR_BINOP_EX(NAME, FUNC) \
static PyObject * \
_GMPy_MPFR_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
MPFR_Object *result; \
CHECK_CONTEXT(context); \
if (!(result = GMPy_MPFR_New(0, context))) { \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context)); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Real_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
PyObject *result, *tempx, *tempy; \
CHECK_CONTEXT(context); \
tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context); \
tempy = (PyObject*)GMPy_MPFR_From_Real(y, 1, context); \
if (!tempx || !tempy) { \
Py_XDECREF(tempx); \
Py_XDECREF(tempy); \
return NULL; \
} \
result = _GMPy_MPFR_##NAME(tempx, tempy, context); \
Py_DECREF(tempx); \
Py_DECREF(tempy); \
return result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
if (MPFR_Check(x) && MPFR_Check(y)) \
return _GMPy_MPFR_##NAME(x, y, context); \
if (IS_REAL(x) && IS_REAL(y)) \
return GMPy_Real_##NAME(x, y, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
}
gmpy2-2.1.0b3/src/gmpy2_math.c 0000664 0001750 0001750 00000155327 13444603111 015663 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_math.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_context_sin,
"context.sin(x) -> number\n\n"
"Return sine of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_sin,
"sin(x) -> number\n\n"
"Return sine of x; x in radians.");
GMPY_MPFR_MPC_UNIOP_EX(Sin, sin)
PyDoc_STRVAR(GMPy_doc_context_cos,
"context.cos(x) -> number\n\n"
"Return cosine of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_cos,
"cos(x) -> number\n\n"
"Return cosine of x; x in radians.");
GMPY_MPFR_MPC_UNIOP_EX(Cos, cos)
PyDoc_STRVAR(GMPy_doc_context_tan,
"context.tan(x) -> number\n\n"
"Return tangent of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_tan,
"tan(x) -> number\n\n"
"Return tangent of x; x in radians.");
GMPY_MPFR_MPC_UNIOP_EX(Tan, tan)
PyDoc_STRVAR(GMPy_doc_context_atan,
"context.atan(x) -> number\n\n"
"Return inverse tangent of x; result in radians.");
PyDoc_STRVAR(GMPy_doc_function_atan,
"atan(x) -> number\n\n"
"Return inverse tangent of x; result in radians.");
GMPY_MPFR_MPC_UNIOP_EX(Atan, atan)
PyDoc_STRVAR(GMPy_doc_context_sinh,
"context.sinh(x) -> number\n\n"
"Return hyperbolic sine of x.");
PyDoc_STRVAR(GMPy_doc_function_sinh,
"sinh(x) -> number\n\n"
"Return hyperbolic sine of x.");
GMPY_MPFR_MPC_UNIOP_EX(Sinh, sinh)
PyDoc_STRVAR(GMPy_doc_context_cosh,
"context.cosh(x) -> number\n\n"
"Return hyperbolic cosine of x.");
PyDoc_STRVAR(GMPy_doc_function_cosh,
"cosh(x) -> number\n\n"
"Return hyperbolic cosine of x.");
GMPY_MPFR_MPC_UNIOP_EX(Cosh, cosh)
PyDoc_STRVAR(GMPy_doc_context_tanh,
"context.tanh(x) -> number\n\n"
"Return hyperbolic tangent of x.");
PyDoc_STRVAR(GMPy_doc_function_tanh,
"tanh(x) -> number\n\n"
"Return hyperbolic tangent of x.");
GMPY_MPFR_MPC_UNIOP_EX(Tanh, tanh)
PyDoc_STRVAR(GMPy_doc_context_asinh,
"context.asinh(x) -> number\n\n"
"Return inverse hyperbolic sine of x.");
PyDoc_STRVAR(GMPy_doc_function_asinh,
"asinh(x) -> number\n\n"
"Return inverse hyperbolic sine of x.");
GMPY_MPFR_MPC_UNIOP_EX(Asinh, asinh)
PyDoc_STRVAR(GMPy_doc_context_acosh,
"context.acosh(x) -> number\n\n"
"Return inverse hyperbolic cosine of x.");
PyDoc_STRVAR(GMPy_doc_function_acosh,
"acosh(x) -> number\n\n"
"Return inverse hyperbolic cosine of x.");
GMPY_MPFR_MPC_UNIOP_EX(Acosh, acosh)
/* Section 2:
* These functions accept a single argument and return an mpfr result.
*
* GMPY_MPFR_UNIOP(NAME, FUNC) creates the following functions:
* GMPy_Real_NAME(x, context)
* GMPy_Number_NAME(x, context)
* GMPy_Context_NAME(self, other)
* - called with METH_O
*/
PyDoc_STRVAR(GMPy_doc_context_sec,
"context.sec(x) -> number\n\n"
"Return secant of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_sec,
"sec(x) -> number\n\n"
"Return secant of x; x in radians.");
GMPY_MPFR_UNIOP_EX(Sec, sec)
PyDoc_STRVAR(GMPy_doc_context_csc,
"context.csc(x) -> number\n\n"
"Return cosecant of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_csc,
"csc(x) -> number\n\n"
"Return cosecant of x; x in radians.");
GMPY_MPFR_UNIOP_EX(Csc, csc)
PyDoc_STRVAR(GMPy_doc_context_cot,
"context.cot(x) -> number\n\n"
"Return cotangent of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_cot,
"cot(x) -> number\n\n"
"Return cotangent of x; x in radians.");
GMPY_MPFR_UNIOP_EX(Cot, cot)
PyDoc_STRVAR(GMPy_doc_context_sech,
"context.sech(x) -> number\n\n"
"Return hyperbolic secant of x.");
PyDoc_STRVAR(GMPy_doc_function_sech,
"sech(x) -> number\n\n"
"Return hyperbolic secant of x.");
GMPY_MPFR_UNIOP_EX(Sech, sech)
PyDoc_STRVAR(GMPy_doc_context_csch,
"context.csch(x) -> number\n\n"
"Return hyperbolic cosecant of x.");
PyDoc_STRVAR(GMPy_doc_function_csch,
"csch(x) -> number\n\n"
"Return hyperbolic cosecant of x.");
GMPY_MPFR_UNIOP_EX(Csch, csch)
PyDoc_STRVAR(GMPy_doc_context_coth,
"context.coth(x) -> number\n\n"
"Return hyperbolic cotangent of x.");
PyDoc_STRVAR(GMPy_doc_function_coth,
"coth(x) -> number\n\n"
"Return hyperbolic cotangent of x.");
GMPY_MPFR_UNIOP_EX(Coth, coth)
PyDoc_STRVAR(GMPy_doc_context_rec_sqrt,
"context.rec_sqrt(x) -> number\n\n"
"Return the reciprocal of the square root of x.");
PyDoc_STRVAR(GMPy_doc_function_rec_sqrt,
"rec_sqrt(x) -> number\n\n"
"Return the reciprocal of the square root of x.");
GMPY_MPFR_UNIOP_EX(RecSqrt, rec_sqrt)
PyDoc_STRVAR(GMPy_doc_context_rint,
"context.rint(x) -> number\n\n"
"Return x rounded to the nearest integer using the context rounding\n"
"mode.");
PyDoc_STRVAR(GMPy_doc_function_rint,
"rint(x) -> number\n\n"
"Return x rounded to the nearest integer using the current rounding\n"
"mode.");
GMPY_MPFR_UNIOP_EX(Rint, rint)
PyDoc_STRVAR(GMPy_doc_context_rint_ceil,
"context.rint_ceil(x) -> number\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"next higher or equal integer and then, if needed, using the context\n"
"rounding mode.");
PyDoc_STRVAR(GMPy_doc_function_rint_ceil,
"rint_ceil(x) -> number\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"next higher or equal integer and then, if needed, using the current\n"
"rounding mode.");
GMPY_MPFR_UNIOP_EX(RintCeil, rint_ceil)
PyDoc_STRVAR(GMPy_doc_context_rint_floor,
"context.rint_floor(x) -> number\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"next lower or equal integer and then, if needed, using the context\n"
"rounding mode.");
PyDoc_STRVAR(GMPy_doc_function_rint_floor,
"rint_floor(x) -> number\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"next lower or equal integer and then, if needed, using the current\n"
"rounding mode.");
GMPY_MPFR_UNIOP_EX(RintFloor, rint_floor)
PyDoc_STRVAR(GMPy_doc_context_rint_round,
"context.rint_round(x) -> number\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"nearest integer (ties away from 0) and then, if needed, using\n"
"the context rounding mode.");
PyDoc_STRVAR(GMPy_doc_function_rint_round,
"rint_round(x) -> number\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"nearest integer (ties away from 0) and then, if needed, using\n"
"the current rounding mode.");
GMPY_MPFR_UNIOP_EX(RintRound, rint_round)
PyDoc_STRVAR(GMPy_doc_context_rint_trunc,
"context.rint_trunc(x) -> number\n\n"
"Return x rounded to the nearest integer by first rounding towards\n"
"zero and then, if needed, using the context rounding mode.");
PyDoc_STRVAR(GMPy_doc_function_rint_trunc,
"rint_trunc(x) -> number\n\n"
"Return x rounded to the nearest integer by first rounding towards\n"
"zero and then, if needed, using the current rounding mode.");
GMPY_MPFR_UNIOP_EX(RintTrunc, rint_trunc)
PyDoc_STRVAR(GMPy_doc_context_frac,
"context.frac(x) -> number\n\n"
"Return fractional part of x.");
PyDoc_STRVAR(GMPy_doc_function_frac,
"frac(x) -> number\n\n"
"Return fractional part of x.");
GMPY_MPFR_UNIOP_EX(Frac, frac)
PyDoc_STRVAR(GMPy_doc_context_cbrt,
"context.cbrt(x) -> number\n\n"
"Return the cube root of x.");
PyDoc_STRVAR(GMPy_doc_function_cbrt,
"cbrt(x) -> number\n\n"
"Return the cube root of x.");
GMPY_MPFR_UNIOP_EX(Cbrt, cbrt)
PyDoc_STRVAR(GMPy_doc_context_log2,
"context.log2(x) -> number\n\n"
"Return base-2 logarithm of x.");
PyDoc_STRVAR(GMPy_doc_function_log2,
"log2(x) -> number\n\n"
"Return base-2 logarithm of x.");
GMPY_MPFR_UNIOP_EX(Log2, log2)
PyDoc_STRVAR(GMPy_doc_context_exp2,
"context.exp2(x) -> number\n\n"
"Return 2**x.");
PyDoc_STRVAR(GMPy_doc_function_exp2,
"exp2(x) -> number\n\n"
"Return 2**x.");
GMPY_MPFR_UNIOP_EX(Exp2, exp2)
PyDoc_STRVAR(GMPy_doc_context_exp10,
"context.exp10(x) -> number\n\n"
"Return 10**x.");
PyDoc_STRVAR(GMPy_doc_function_exp10,
"exp10(x) -> number\n\n"
"Return 10**x.");
GMPY_MPFR_UNIOP_EX(Exp10, exp10)
PyDoc_STRVAR(GMPy_doc_context_log1p,
"context.log1p(x) -> number\n\n"
"Return natural logarithm of (1+x).");
PyDoc_STRVAR(GMPy_doc_function_log1p,
"log1p(x) -> number\n\n"
"Return natural logarithm of (1+x).");
GMPY_MPFR_UNIOP_EX(Log1p, log1p)
PyDoc_STRVAR(GMPy_doc_context_expm1,
"context.expm1(x) -> number\n\n"
"Return exp(x) - 1.");
PyDoc_STRVAR(GMPy_doc_function_expm1,
"expm1(x) -> number\n\n"
"Return exp(x) - 1.");
GMPY_MPFR_UNIOP_EX(Expm1, expm1)
PyDoc_STRVAR(GMPy_doc_context_eint,
"context.eint(x) -> number\n\n"
"Return exponential integral of x.");
PyDoc_STRVAR(GMPy_doc_function_eint,
"eint(x) -> number\n\n"
"Return exponential integral of x.");
GMPY_MPFR_UNIOP_EX(Eint, eint)
PyDoc_STRVAR(GMPy_doc_context_li2,
"context.li2(x) -> number\n\n"
"Return real part of dilogarithm of x.");
PyDoc_STRVAR(GMPy_doc_function_li2,
"li2(x) -> number\n\n"
"Return real part of dilogarithm of x.");
GMPY_MPFR_UNIOP_EX(Li2, li2)
PyDoc_STRVAR(GMPy_doc_context_gamma,
"context.gamma(x) -> number\n\n"
"Return gamma of x.");
PyDoc_STRVAR(GMPy_doc_function_gamma,
"gamma(x) -> number\n\n"
"Return gamma of x.");
GMPY_MPFR_UNIOP_EX(Gamma, gamma)
PyDoc_STRVAR(GMPy_doc_context_lngamma,
"context.lngamma(x) -> number\n\n"
"Return natural logarithm of gamma(x).");
PyDoc_STRVAR(GMPy_doc_function_lngamma,
"lngamma(x) -> number\n\n"
"Return natural logarithm of gamma(x).");
GMPY_MPFR_UNIOP_EX(Lngamma, lngamma)
PyDoc_STRVAR(GMPy_doc_context_digamma,
"context.digamma(x) -> number\n\n"
"Return digamma of x.");
PyDoc_STRVAR(GMPy_doc_function_digamma,
"digamma(x) -> number\n\n"
"Return digamma of x.");
GMPY_MPFR_UNIOP_EX(Digamma, digamma)
PyDoc_STRVAR(GMPy_doc_context_zeta,
"context.zeta(x) -> number\n\n"
"Return Riemann zeta of x.");
PyDoc_STRVAR(GMPy_doc_function_zeta,
"zeta(x) -> number\n\n"
"Return Riemann zeta of x.");
GMPY_MPFR_UNIOP_EX(Zeta, zeta)
PyDoc_STRVAR(GMPy_doc_context_erf,
"context.erf(x) -> number\n\n"
"Return error function of x.");
PyDoc_STRVAR(GMPy_doc_function_erf,
"erf(x) -> number\n\n"
"Return error function of x.");
GMPY_MPFR_UNIOP_EX(Erf, erf)
PyDoc_STRVAR(GMPy_doc_context_erfc,
"context.erfc(x) -> number\n\n"
"Return complementary error function of x.");
PyDoc_STRVAR(GMPy_doc_function_erfc,
"erfc(x) -> number\n\n"
"Return complementary error function of x.");
GMPY_MPFR_UNIOP_EX(Erfc, erfc)
PyDoc_STRVAR(GMPy_doc_context_j0,
"context.j0(x) -> number\n\n"
"Return first kind Bessel function of order 0 of x.");
PyDoc_STRVAR(GMPy_doc_function_j0,
"j0(x) -> number\n\n"
"Return first kind Bessel function of order 0 of x.");
GMPY_MPFR_UNIOP_EX(J0, j0)
PyDoc_STRVAR(GMPy_doc_context_j1,
"context.j1(x) -> number\n\n"
"Return first kind Bessel function of order 1 of x.");
PyDoc_STRVAR(GMPy_doc_function_j1,
"j1(x) -> number\n\n"
"Return first kind Bessel function of order 1 of x.");
GMPY_MPFR_UNIOP_EX(J1, j1)
PyDoc_STRVAR(GMPy_doc_context_y0,
"context.y0(x) -> number\n\n"
"Return second kind Bessel function of order 0 of x.");
PyDoc_STRVAR(GMPy_doc_function_y0,
"y0(x) -> number\n\n"
"Return second kind Bessel function of order 0 of x.");
GMPY_MPFR_UNIOP_EX(Y0, y0)
PyDoc_STRVAR(GMPy_doc_context_y1,
"context.y1(x) -> number\n\n"
"Return second kind Bessel function of order 1 of x.");
PyDoc_STRVAR(GMPy_doc_function_y1,
"y1(x) -> number\n\n"
"Return second kind Bessel function of order 1 of x.");
GMPY_MPFR_UNIOP_EX(Y1, y1)
PyDoc_STRVAR(GMPy_doc_context_ai,
"context.ai(x) -> number\n\n"
"Return Airy function of x.");
PyDoc_STRVAR(GMPy_doc_function_ai,
"ai(x) -> number\n\n"
"Return Airy function of x.");
GMPY_MPFR_UNIOP_EX(Ai, ai)
/* Section 3:
* The following functions may return an mpc result for certain mpfr arguments.
* Since the expectional values vary between functions, the 'Real' and 'Complex'
* functions do not use macros. However, they do use a macro to create the
* higher-level functions.
*
* GMPY_MPFR_MPC_UNIOP_TEMPLATE(NAME, FUNC) creates the following functions:
* GMPy_Number_NAME(x, context)
* - assumes GMPy_Real_NAME & GMPy_Complex_NAME exist
* GMPy_Context_NAME(self, other)
* - called with METH_O
*/
PyDoc_STRVAR(GMPy_doc_context_acos,
"context.acos(x) -> number\n\n"
"Return inverse cosine of x; result in radians.");
PyDoc_STRVAR(GMPy_doc_function_acos,
"acos(x) -> number\n\n"
"Return inverse cosine of x; result in radians.");
static PyObject *
_GMPy_MPFR_Acos(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
if (!mpfr_nan_p(MPFR(x)) &&
(mpfr_cmp_si(MPFR(x), 1) > 0 || mpfr_cmp_si(MPFR(x), -1) < 0) &&
context->ctx.allow_complex
) {
return GMPy_Complex_Acos(x, context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_acos(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Acos(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Acos(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPC_Acos(PyObject *x, CTXT_Object *context)
{
MPC_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_acos(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Acos(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Acos(tempx, context);
Py_DECREF(tempx);
return result;
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EX(Acos, acos)
PyDoc_STRVAR(GMPy_doc_context_asin,
"context.asin(x) -> number\n\n"
"Return inverse sine of x; result in radians.");
PyDoc_STRVAR(GMPy_doc_function_asin,
"asin(x) -> number\n\n"
"Return inverse sine of x; result in radians.");
static PyObject *
_GMPy_MPFR_Asin(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!mpfr_nan_p(MPFR(x)) &&
(mpfr_cmp_si(MPFR(x), 1) > 0 || mpfr_cmp_si(MPFR(x), -1) < 0) &&
context->ctx.allow_complex
) {
return GMPy_Complex_Asin(x, context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_asin(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Asin(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Asin(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPC_Asin(PyObject *x, CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_asin(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Asin(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Asin(tempx, context);
Py_DECREF(tempx);
return result;
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EX(Asin, asin)
PyDoc_STRVAR(GMPy_doc_context_atanh,
"context.atanh(x) -> number\n\n"
"Return inverse hyperbolic tanget of x.");
PyDoc_STRVAR(GMPy_doc_function_atanh,
"atanh(x) -> number\n\n"
"Return inverse hyperbolic tangent of x.");
static PyObject *
_GMPy_MPFR_Atanh(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!mpfr_nan_p(MPFR(x)) &&
(mpfr_cmp_si(MPFR(x), 1) > 0 || mpfr_cmp_si(MPFR(x), -1) < 0) &&
context->ctx.allow_complex
) {
return GMPy_Complex_Atanh(x, context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_atanh(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Atanh(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Atanh(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPC_Atanh(PyObject *x, CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_atanh(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Atanh(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Atanh(tempx, context);
Py_DECREF(tempx);
return result;
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EX(Atanh, atanh)
PyDoc_STRVAR(GMPy_doc_function_atan2,
"atan2(y, x) -> number\n\n"
"Return arc-tangent of (y/x); result in radians.");
PyDoc_STRVAR(GMPy_doc_context_atan2,
"context.atan2(y, x) -> number\n\n"
"Return arc-tangent of (y/x); result in radians.");
GMPY_MPFR_BINOP_EX(Atan2, atan2)
PyDoc_STRVAR(GMPy_doc_function_hypot,
"hypot(x, y) -> number\n\n"
"Return square root of (x**2 + y**2).");
PyDoc_STRVAR(GMPy_doc_context_hypot,
"context.hypot(x, y) -> number\n\n"
"Return square root of (x**2 + y**2).");
GMPY_MPFR_BINOP_EX(Hypot, hypot)
static PyObject *
_GMPy_MPFR_Sin_Cos(PyObject *x, CTXT_Object *context)
{
MPFR_Object *s, *c;
PyObject *result;
int code;
CHECK_CONTEXT(context);
s = GMPy_MPFR_New(0, context);
c = GMPy_MPFR_New(0, context);
result = PyTuple_New(2);
if (!s || !c || !result) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
code = mpfr_sin_cos(s->f, c->f, MPFR(x), GET_MPFR_ROUND(context));
s->rc = code & 0x03;
c->rc = code >> 2;
if (s->rc == 2) s->rc = -1;
if (c->rc == 2) c->rc = -1;
_GMPy_MPFR_Cleanup(&s, context);
_GMPy_MPFR_Cleanup(&c, context);
if (!s || !c) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)s);
PyTuple_SET_ITEM(result, 1, (PyObject*)c);
return result;
}
static PyObject *
GMPy_Real_Sin_Cos(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Sin_Cos(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPC_Sin_Cos(PyObject *x, CTXT_Object *context)
{
MPC_Object *s, *c;
PyObject *result;
int code;
CHECK_CONTEXT(context);
s = GMPy_MPC_New(0, 0, context);
c = GMPy_MPC_New(0, 0, context);
result = PyTuple_New(2);
if (!s || !c || !result) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
code = mpc_sin_cos(s->c, c->c, MPC(x), GET_MPC_ROUND(context), GET_MPC_ROUND(context));
s->rc = MPC_INEX1(code);
c->rc = MPC_INEX2(code);
_GMPy_MPC_Cleanup(&s, context);
_GMPy_MPC_Cleanup(&c, context);
if (!s || !c) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)s);
PyTuple_SET_ITEM(result, 1, (PyObject*)c);
return result;
}
static PyObject *
GMPy_Complex_Sin_Cos(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Sin_Cos(tempx, context);
Py_DECREF(tempx);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_sin_cos,
"context.sin_cos(x) -> (number, number)\n\n"
"Return a tuple containing the sine and cosine of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_sin_cos,
"sin_cos(x) -> (number, number)\n\n"
"Return a tuple containing the sine and cosine of x; x in radians.");
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EX(Sin_Cos, sin_cos)
static PyObject *
_GMPy_MPFR_Sinh_Cosh(PyObject *x, CTXT_Object *context)
{
MPFR_Object *s, *c;
PyObject *result;
int code;
CHECK_CONTEXT(context);
s = GMPy_MPFR_New(0, context);
c = GMPy_MPFR_New(0, context);
result = PyTuple_New(2);
if (!s || !c || !result) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
code = mpfr_sinh_cosh(s->f, c->f, MPFR(x), GET_MPFR_ROUND(context));
s->rc = code & 0x03;
c->rc = code >> 2;
if (s->rc == 2) s->rc = -1;
if (c->rc == 2) c->rc = -1;
_GMPy_MPFR_Cleanup(&s, context);
_GMPy_MPFR_Cleanup(&c, context);
if (!s || !c) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)s);
PyTuple_SET_ITEM(result, 1, (PyObject*)c);
return result;
}
static PyObject *
GMPy_Real_Sinh_Cosh(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Sinh_Cosh(tempx, context);
Py_DECREF(tempx);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_sinh_cosh,
"context.sinh_cosh(x) -> (number, number)\n\n"
"Return a tuple containing the hyperbolic sine and cosine of x.");
PyDoc_STRVAR(GMPy_doc_function_sinh_cosh,
"sinh_cosh(x) -> (number, number)\n\n"
"Return a tuple containing the hyperbolic sine and cosine of x.");
GMPY_MPFR_UNIOP_TEMPLATE_EX(Sinh_Cosh, sinh_cosh)
PyDoc_STRVAR(GMPy_doc_function_degrees,
"degrees(x) -> mpfr\n\n"
"Convert angle x from radians to degrees.\n"
"Note: In rare cases the result may not be correctly rounded.");
PyDoc_STRVAR(GMPy_doc_context_degrees,
"context.degrees(x) -> mpfr\n\n"
"Convert angle x from radians to degrees.\n"
"Note: In rare cases the result may not be correctly rounded.");
static PyObject *
GMPy_Context_Degrees(PyObject *self, PyObject *other)
{
MPFR_Object *result, *tempx, *temp;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
result = GMPy_MPFR_New(0, context);
temp = GMPy_MPFR_New(context->ctx.mpfr_prec + 100, context);
tempx = GMPy_MPFR_From_Real(other, 1, context);
if (!result || !temp || !tempx) {
Py_XDECREF((PyObject*)temp);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_const_pi(temp->f, MPFR_RNDN);
mpfr_ui_div(temp->f, 180, temp->f, MPFR_RNDN);
mpfr_clear_flags();
mpfr_mul(result->f, temp->f, tempx->f, MPFR_RNDN);
Py_DECREF((PyObject*)temp);
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_radians,
"radians(x) -> mpfr\n\n"
"Convert angle x from degrees to radians.\n"
"Note: In rare cases the result may not be correctly rounded.");
PyDoc_STRVAR(GMPy_doc_context_radians,
"context.radians(x) -> mpfr\n\n"
"Convert angle x from degrees to radians.\n"
"Note: In rare cases the result may not be correctly rounded.");
static PyObject *
GMPy_Context_Radians(PyObject *self, PyObject *other)
{
MPFR_Object *result, *tempx, *temp;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
result = GMPy_MPFR_New(0, context);
temp = GMPy_MPFR_New(context->ctx.mpfr_prec + 100, context);
tempx = GMPy_MPFR_From_Real(other, 1, context);
if (!result || !temp || !tempx) {
Py_XDECREF((PyObject*)temp);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_const_pi(temp->f, MPFR_RNDN);
mpfr_div_ui(temp->f, temp->f, 180, MPFR_RNDN);
mpfr_clear_flags();
mpfr_mul(result->f, tempx->f, temp->f, MPFR_RNDN);
Py_DECREF((PyObject*)temp);
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_log10,
"context.log10(x) -> number\n\n"
"Return the base-10 logarithm of x.");
PyDoc_STRVAR(GMPy_doc_function_log10,
"log10(x) -> number\n\n"
"Return the base-10 logarithm of x.");
GMPY_MPFR_MPC_UNIOP_EX(Log10, log10)
PyDoc_STRVAR(GMPy_doc_context_log,
"context.log(x) -> number\n\n"
"Return the natural logarithm of x.");
PyDoc_STRVAR(GMPy_doc_function_log,
"log(x) -> number\n\n"
"Return the natural logarithm of x.");
GMPY_MPFR_MPC_UNIOP_EX(Log, log)
PyDoc_STRVAR(GMPy_doc_context_exp,
"context.exp(x) -> number\n\n"
"Return the exponential of x.");
PyDoc_STRVAR(GMPy_doc_function_exp,
"exp(x) -> number\n\n"
"Return the exponential of x.");
GMPY_MPFR_MPC_UNIOP_EX(Exp, exp)
PyDoc_STRVAR(GMPy_doc_context_sqrt,
"context.sqrt(x) -> number\n\n"
"Return the square root of x.");
PyDoc_STRVAR(GMPy_doc_function_sqrt,
"sqrt(x) -> number\n\n"
"Return the square root of x.");
static PyObject *
_GMPy_MPFR_Sqrt(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (mpfr_sgn(MPFR(x)) < 0 && context->ctx.allow_complex) {
return GMPy_Complex_Sqrt(x, context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_sqrt(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Sqrt(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Sqrt(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPC_Sqrt(PyObject *x, CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_sqrt(result->c, MPC(x), GET_MPFR_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Sqrt(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Sqrt(tempx, context);
Py_DECREF(tempx);
return result;
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EX(Sqrt, sqrt)
PyDoc_STRVAR(GMPy_doc_function_root,
"root(x, n) -> mpfr\n\n"
"Return n-th root of x. The result always an 'mpfr'.\n"
"Note: not IEEE 754-2008 compliant; result differs when\n"
"x = -0 and n is even. See rootn().");
PyDoc_STRVAR(GMPy_doc_context_root,
"context.root(x, n) -> mpfr\n\n"
"Return n-th root of x. The result always an 'mpfr'.\n"
"Note: not IEEE 754-2008 compliant; result differs when\n"
"x = -0 and n is even. See rootn().");
PyDoc_STRVAR(GMPy_doc_function_rootn,
"rootn(x, n) -> mpfr\n\n"
"Return n-th root of x. The result always an 'mpfr'.\n"
"Note: this is IEEE 754-2008 compliant version of root().");
PyDoc_STRVAR(GMPy_doc_context_rootn,
"context.rootn(x, n) -> mpfr\n\n"
"Return n-th root of x. The result always an 'mpfr'.\n"
"Note: this is IEEE 754-2008 compliant version of root().");
#if MPFR_VERSION_MAJOR > 3
/* Since mpfr_root is deprecated in MPFR 4, we use mpfr_rootn_ui to
* mimic the behavior of mpfr_root. And the converse will be true when
* using MPFR 3.
*/
static PyObject *
GMPy_Real_Rootn(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = c_ulong_From_Integer(y);
if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_rootn_ui(result->f, tempx->f, n, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Root(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = c_ulong_From_Integer(y);
if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
/* Mimic the non-compliant IEEE 752-2008 behavior. */
if (mpfr_zero_p(tempx->f)) {
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
}
else {
result->rc = mpfr_rootn_ui(result->f, tempx->f, n, GET_MPFR_ROUND(context));
}
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
#else
static PyObject *
GMPy_Real_Rootn(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = c_ulong_From_Integer(y);
if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
/* Mimic the compliant IEEE 752-2008 behavior. */
if (mpfr_zero_p(tempx->f) && mpfr_signbit(tempx->f)) {
if ((n & 1)) {
/* Odd, so result is -0. */
mpfr_set_zero(result->f, -1);
}
else {
/* Even, so result is 0. */
mpfr_set_zero(result->f, 1);
}
}
else {
result->rc = mpfr_root(result->f, tempx->f, n, GET_MPFR_ROUND(context));
}
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Root(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = c_ulong_From_Integer(y);
if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_root(result->f, tempx->f, n, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
#endif
static PyObject *
GMPy_Number_Rootn(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && PyIntOrLong_Check(y))
return GMPy_Real_Rootn(x, y, context);
TYPE_ERROR("rootn() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Rootn(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("rootn() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Rootn(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}
static PyObject *
GMPy_Number_Root(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && PyIntOrLong_Check(y))
return GMPy_Real_Root(x, y, context);
TYPE_ERROR("root() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Root(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("root() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Root(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}
PyDoc_STRVAR(GMPy_doc_function_jn,
"jn(x,n) -> mpfr\n\n"
"Return the first kind Bessel function of order n of x.");
PyDoc_STRVAR(GMPy_doc_context_jn,
"context.jn(x,n) -> mpfr\n\n"
"Return the first kind Bessel function of order n of x.");
GMPY_MPFR_BINOP_REAL_LONG(Jn, jn)
PyDoc_STRVAR(GMPy_doc_function_yn,
"yn(x,n) -> mpfr\n\n"
"Return the second kind Bessel function of order n of x.");
PyDoc_STRVAR(GMPy_doc_context_yn,
"context.yn(x,n) -> mpfr\n\n"
"Return the second kind Bessel function of order n of x.");
GMPY_MPFR_BINOP_REAL_LONG(Yn, yn)
PyDoc_STRVAR(GMPy_doc_function_agm,
"agm(x, y) -> mpfr\n\n"
"Return arithmetic-geometric mean of x and y.");
PyDoc_STRVAR(GMPy_doc_context_agm,
"context.agm(x, y) -> mpfr\n\n"
"Return arithmetic-geometric mean of x and y.");
GMPY_MPFR_BINOP(AGM, agm)
PyDoc_STRVAR(GMPy_doc_function_maxnum,
"maxnum(x, y) -> mpfr\n\n"
"Return the maximum number of x and y. If x and y are not 'mpfr', they are\n"
"converted to 'mpfr'. The result is rounded to match the current context.\n"
"If only one of x or y is a number, then that number is returned.");
PyDoc_STRVAR(GMPy_doc_context_maxnum,
"context.maxnum(x, y) -> mpfr\n\n"
"Return the maximum number of x and y. If x and y are not 'mpfr', they are\n"
"converted to 'mpfr'. The result is rounded to match the specified context.\n"
"If only one of x or y is a number, then that number is returned.");
GMPY_MPFR_BINOP(Maxnum, max)
PyDoc_STRVAR(GMPy_doc_function_minnum,
"minnum(x, y) -> mpfr\n\n"
"Return the minimum number of x and y. If x and y are not 'mpfr', they are\n"
"converted to 'mpfr'. The result is rounded to match the current context.\n"
"If only one of x or y is a number, then that number is returned.");
PyDoc_STRVAR(GMPy_doc_context_minnum,
"context.minnum(x, y) -> mpfr\n\n"
"Return the minimum number of x and y. If x and y are not 'mpfr', they are\n"
"converted to 'mpfr'. The result is rounded to match the specified context.\n"
"If only one of x or y is a number, then that number is returned.");
GMPY_MPFR_BINOP(Minnum, min)
PyDoc_STRVAR(GMPy_doc_function_remainder,
"remainder(x, y) -> mpfr\n\n"
"Return x - n*y where n is the integer quotient of x/y, rounded to\n"
"the nearest integer and ties rounded to even.");
PyDoc_STRVAR(GMPy_doc_context_remainder,
"context.remainder(x, y) -> mpfr\n\n"
"Return x - n*y where n is the integer quotient of x/y, rounded to\n"
"the nearest integer and ties rounded to even.");
GMPY_MPFR_BINOP(Remainder, remainder)
PyDoc_STRVAR(GMPy_doc_function_fmod,
"fmod(x, y) -> mpfr\n\n"
"Return x - n*y where n is the integer quotient of x/y, rounded to 0.");
PyDoc_STRVAR(GMPy_doc_context_fmod,
"context.fmod(x, y) -> mpfr\n\n"
"Return x - n*y where n is the integer quotient of x/y, rounded to 0.");
GMPY_MPFR_BINOP(Fmod, fmod)
PyDoc_STRVAR(GMPy_doc_function_round2,
"round2(x[, n]) -> mpfr\n\n"
"Return x rounded to n bits. Uses default precision if n is not\n"
"specified. See round_away() to access the mpfr_round() function.");
PyDoc_STRVAR(GMPy_doc_context_round2,
"context.round2(x[, n]) -> mpfr\n\n"
"Return x rounded to n bits. Uses default precision if n is not\n"
"specified. See round_away() to access the mpfr_round() function.");
static PyObject *
GMPy_Real_Round2(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result, *tempx;
long n;
CHECK_CONTEXT(context);
n = GET_MPFR_PREC(context);
if (y) {
n = PyIntOrLong_AsLong(y);
if ( (n == -1 && PyErr_Occurred()) || n < MPFR_PREC_MIN || n > MPFR_PREC_MAX) {
VALUE_ERROR("invalid precision");
return NULL;
}
}
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(tempx->f), context))) {
Py_DECREF((PyObject*)tempx);
return NULL;
}
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
mpfr_clear_flags();
result->rc = mpfr_prec_round(result->f, n, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Number_Round2(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && (!y || PyIntOrLong_Check(y)))
return GMPy_Real_Round2(x, y, context);
TYPE_ERROR("round2() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Round2(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) < 1 || PyTuple_GET_SIZE(args) > 2) {
TYPE_ERROR("round2() requires 1 or 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (PyTuple_GET_SIZE(args) == 1) {
return GMPy_Number_Round2(PyTuple_GET_ITEM(args, 0), NULL, context);
}
else {
return GMPy_Number_Round2(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}
}
PyDoc_STRVAR(GMPy_doc_function_reldiff,
"reldiff(x, y) -> mpfr\n\n"
"Return the relative difference between x and y. Result is equal to\n"
"abs(x-y)/x.");
PyDoc_STRVAR(GMPy_doc_context_reldiff,
"context.reldiff(x, y) -> mpfr\n\n"
"Return the relative difference between x and y. Result is equal to\n"
"abs(x-y)/x.");
static PyObject *
GMPy_Real_RelDiff(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *tempx, *tempy, *result;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
tempy = GMPy_MPFR_From_Real(y, 1, context);
if (!result || !tempx || !tempy) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
mpfr_clear_flags();
mpfr_reldiff(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context));
result->rc = 0;
_GMPy_MPFR_Cleanup(&result, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
GMPY_MPFR_BINOP_TEMPLATE(RelDiff, reldiff)
PyDoc_STRVAR(GMPy_doc_mpfr_ceil_method,
"x.__ceil__() -> mpfr\n\n"
"Return an 'mpfr' that is the smallest integer >= x.");
PyDoc_STRVAR(GMPy_doc_function_ceil,
"ceil(x) ->mpfr\n\n"
"Return an 'mpfr' that is the smallest integer >= x.");
PyDoc_STRVAR(GMPy_doc_context_ceil,
"context.ceil(x) ->mpfr\n\n"
"Return an 'mpfr' that is the smallest integer >= x.");
GMPY_MPFR_UNIOP_NOROUND(Ceil, ceil)
PyDoc_STRVAR(GMPy_doc_mpfr_floor_method,
"x.__floor__() -> mpfr\n\n"
"Return an 'mpfr' that is the smallest integer <= x.");
PyDoc_STRVAR(GMPy_doc_function_floor,
"floor(x) -> mpfr\n\n"
"Return an 'mpfr' that is the smallest integer <= x.");
PyDoc_STRVAR(GMPy_doc_context_floor,
"context.floor(x) -> mpfr\n\n"
"Return an 'mpfr' that is the smallest integer <= x.");
GMPY_MPFR_UNIOP_NOROUND(Floor, floor);
PyDoc_STRVAR(GMPy_doc_mpfr_trunc_method,
"x.__trunc__() -> mpfr\n\n"
"Return an 'mpfr' that is truncated towards 0. Same as\n"
"x.floor() if x>=0 or x.ceil() if x<0.");
PyDoc_STRVAR(GMPy_doc_function_trunc,
"trunc(x) -> mpfr\n\n"
"Return an 'mpfr' that is x truncated towards 0. Same as\n"
"x.floor() if x>=0 or x.ceil() if x<0.");
PyDoc_STRVAR(GMPy_doc_context_trunc,
"context.trunc(x) -> mpfr\n\n"
"Return an 'mpfr' that is x truncated towards 0. Same as\n"
"x.floor() if x>=0 or x.ceil() if x<0.");
GMPY_MPFR_UNIOP_NOROUND(Trunc, trunc)
PyDoc_STRVAR(GMPy_doc_function_round_away,
"round_away(x) -> mpfr\n\n"
"Return an 'mpfr' that is x rounded to the nearest integer,\n"
"with ties rounded away from 0.");
PyDoc_STRVAR(GMPy_doc_context_round_away,
"context.round_away(x) -> mpfr\n\n"
"Return an 'mpfr' that is x rounded to the nearest integer,\n"
"with ties rounded away from 0.");
GMPY_MPFR_UNIOP_NOROUND_NOMETHOD(RoundAway, round)
PyDoc_STRVAR(GMPy_doc_function_modf,
"modf(x) -> (mpfr, mpfr)\n\n"
"Return a tuple containing the integer and fractional portions\n"
"of x.");
PyDoc_STRVAR(GMPy_doc_context_modf,
"context.modf(x) -> (mpfr, mpfr)\n\n"
"Return a tuple containing the integer and fractional portions\n"
"of x.");
static PyObject *
GMPy_Real_Modf(PyObject *x, CTXT_Object *context)
{
MPFR_Object *s, *c, *tempx;
PyObject *result;
int code;
CHECK_CONTEXT(context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
s = GMPy_MPFR_New(0, context);
c = GMPy_MPFR_New(0, context);
result = PyTuple_New(2);
if (! tempx || !s || !c || !result) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
code = mpfr_modf(s->f, c->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
s->rc = code & 0x03;
c->rc = code >> 2;
if (s->rc == 2) s->rc = -1;
if (c->rc == 2) c->rc = -1;
_GMPy_MPFR_Cleanup(&s, context);
_GMPy_MPFR_Cleanup(&c, context);
if (!s || !c) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)s);
PyTuple_SET_ITEM(result, 1, (PyObject*)c);
return result;
}
GMPY_MPFR_UNIOP_TEMPLATE(Modf, modf)
PyDoc_STRVAR(GMPy_doc_function_lgamma,
"lgamma(x) -> (mpfr, int)\n\n"
"Return a tuple containing the logarithm of the absolute value of\n"
"gamma(x) and the sign of gamma(x)");
PyDoc_STRVAR(GMPy_doc_context_lgamma,
"context.lgamma(x) -> (mpfr, int)\n\n"
"Return a tuple containing the logarithm of the absolute value of\n"
"gamma(x) and the sign of gamma(x)");
static PyObject *
GMPy_Real_Lgamma(PyObject *x, CTXT_Object *context)
{
PyObject *result;
MPFR_Object *value, *tempx;
int signp = 0;
CHECK_CONTEXT(context)
tempx = GMPy_MPFR_From_Real(x, 1, context);
value = GMPy_MPFR_New(0, context);
result = PyTuple_New(2);
if (!tempx || !value || !result) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)value);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
value->rc = mpfr_lgamma(value->f, &signp, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&value, context);
if (!value) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)value);
PyTuple_SET_ITEM(result, 1, PyIntOrLong_FromLong((long)signp));
return result;
}
GMPY_MPFR_UNIOP_TEMPLATE(Lgamma, lgamma)
PyDoc_STRVAR(GMPy_doc_function_remquo,
"remquo(x, y) -> (mpfr, int)\n\n"
"Return a tuple containing the remainder(x,y) and the low bits of the\n"
"quotient.");
PyDoc_STRVAR(GMPy_doc_context_remquo,
"context.remquo(x, y) -> (mpfr, int)\n\n"
"Return a tuple containing the remainder(x,y) and the low bits of the\n"
"quotient.");
static PyObject *
GMPy_Real_RemQuo(PyObject *x, PyObject *y, CTXT_Object *context)
{
PyObject *result;
MPFR_Object *value, *tempx, *tempy;
long quobits = 0;
CHECK_CONTEXT(context);
value = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
tempy = GMPy_MPFR_From_Real(y, 1, context);
result = PyTuple_New(2);
if (!value || !tempx || !tempx || !result) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)value);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
value->rc = mpfr_remquo(value->f, &quobits, tempx->f, tempy->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPFR_Cleanup(&value, context);
PyTuple_SET_ITEM(result, 0, (PyObject*)value);
PyTuple_SET_ITEM(result, 1, PyIntOrLong_FromLong(quobits));
return result;
}
GMPY_MPFR_BINOP_TEMPLATE(RemQuo, remquo);
PyDoc_STRVAR(GMPy_doc_function_frexp,
"frexp(x) -> (int, mpfr)\n\n"
"Return a tuple containing the exponent and mantissa of x.");
PyDoc_STRVAR(GMPy_doc_context_frexp,
"context.frexp(x) -> (int, mpfr)\n\n"
"Return a tuple containing the exponent and mantissa of x.");
static PyObject *
GMPy_Real_Frexp(PyObject *x, CTXT_Object *context)
{
PyObject *result;
MPFR_Object *value, *tempx;
mpfr_exp_t exp = 0;
CHECK_CONTEXT(context);
value = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
result = PyTuple_New(2);
if (!value || !result || !tempx) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)value);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
value->rc = mpfr_frexp(&exp, value->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&value, context);
PyTuple_SET_ITEM(result, 0, PyIntOrLong_FromSsize_t((Py_ssize_t)exp));
PyTuple_SET_ITEM(result, 1, (PyObject*)value);
return result;
}
GMPY_MPFR_UNIOP_TEMPLATE(Frexp, frexp)
PyDoc_STRVAR(GMPy_doc_function_next_toward,
"next_toward(x, y) -> mpfr\n\n"
"Return the next 'mpfr' from x in the direction of y. The result has\n"
"the same precision as x.");
PyDoc_STRVAR(GMPy_doc_context_next_toward,
"context.next_toward(x, y) -> mpfr\n\n"
"Return the next 'mpfr' from x in the direction of y. The result has\n"
"the same precision as x.");
static PyObject *
GMPy_Context_NextToward(PyObject *self, PyObject *args)
{
MPFR_Object *result, *tempx, *tempy;
CTXT_Object *context = NULL;
int direction;
mpfr_rnd_t temp_round;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("next_toward() requires 2 arguments");
return NULL;
}
tempx = GMPy_MPFR_From_Real(PyTuple_GET_ITEM(args, 0), 1, context);
tempy = GMPy_MPFR_From_Real(PyTuple_GET_ITEM(args, 1), 1, context);
if (!tempx || !tempy) {
TYPE_ERROR("next_toward() argument type not supported");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(tempx->f), context))) {
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return NULL;
}
mpfr_clear_flags();
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
mpfr_nexttoward(result->f, tempy->f);
result->rc = 0;
direction = mpfr_signbit(tempy->f);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
temp_round = GET_MPFR_ROUND(context);
if (direction)
context->ctx.mpfr_round = MPFR_RNDD;
else
context->ctx.mpfr_round = MPFR_RNDU;
_GMPy_MPFR_Cleanup(&result, context);
context->ctx.mpfr_round = temp_round;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_next_above,
"next_above(x) -> mpfr\n\n"
"Return the next 'mpfr' from x toward +Infinity.");
PyDoc_STRVAR(GMPy_doc_context_next_above,
"context.next_above(x) -> mpfr\n\n"
"Return the next 'mpfr' from x toward +Infinity.");
static PyObject *
GMPy_Context_NextAbove(PyObject *self, PyObject *other)
{
MPFR_Object *result, *tempx;
CTXT_Object *context = NULL;
mpfr_rnd_t temp_round;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (!(tempx = GMPy_MPFR_From_Real(other, 1, context))) {
TYPE_ERROR("next_above() argument type not supported");
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(tempx->f), context))) {
Py_DECREF((PyObject*)tempx);
return NULL;
}
mpfr_clear_flags();
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
mpfr_nextabove(result->f);
result->rc = 0;
temp_round = GET_MPFR_ROUND(context);
context->ctx.mpfr_round = MPFR_RNDU;
_GMPy_MPFR_Cleanup(&result, context);
context->ctx.mpfr_round = temp_round;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_next_below,
"next_below(x) -> mpfr\n\n"
"Return the next 'mpfr' from x toward -Infinity.");
PyDoc_STRVAR(GMPy_doc_context_next_below,
"context.next_below(x) -> mpfr\n\n"
"Return the next 'mpfr' from x toward -Infinity.");
static PyObject *
GMPy_Context_NextBelow(PyObject *self, PyObject *other)
{
MPFR_Object *result, *tempx;
CTXT_Object *context = NULL;
mpfr_rnd_t temp_round;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (!(tempx = GMPy_MPFR_From_Real(other, 1, context))) {
TYPE_ERROR("next_below() argument type not supported");
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(tempx->f), context))) {
Py_DECREF((PyObject*)tempx);
return NULL;
}
mpfr_clear_flags();
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
mpfr_nextbelow(result->f);
result->rc = 0;
temp_round = GET_MPFR_ROUND(context);
context->ctx.mpfr_round = MPFR_RNDD;
_GMPy_MPFR_Cleanup(&result, context);
context->ctx.mpfr_round = temp_round;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_factorial,
"factorial(n) -> mpfr\n\n"
"Return the floating-point approximation to the factorial of n.\n\n"
"See fac(n) to get the exact integer result.");
PyDoc_STRVAR(GMPy_doc_context_factorial,
"context.factorial(n) -> mpfr\n\n"
"Return the floating-point approximation to the factorial of n.\n\n"
"See fac(n) to get the exact integer result.");
static PyObject *
GMPy_Context_Factorial(PyObject *self, PyObject *other)
{
MPFR_Object *result;
long n;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
n = PyLong_AsLong(other);
if ((n == -1) && PyErr_Occurred()) {
TYPE_ERROR("factorial() requires 'int' argument");
return NULL;
}
if (n < 0) {
VALUE_ERROR("factorial() of negative number");
return NULL;
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
mpfr_fac_ui(result->f, n, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_fsum,
"fsum(iterable) -> mpfr\n\n"
"Return an accurate sum of the values in the iterable.");
PyDoc_STRVAR(GMPy_doc_context_fsum,
"fsum(iterable) -> mpfr\n\n"
"Return an accurate sum of the values in the iterable.");
static PyObject *
GMPy_Context_Fsum(PyObject *self, PyObject *other)
{
MPFR_Object *temp, *result;
mpfr_ptr *tab;
int errcode;
Py_ssize_t i, seq_length = 0;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
if (!(other = PySequence_List(other))) {
Py_DECREF((PyObject*)result);
TYPE_ERROR("argument must be an iterable");
return NULL;
}
/* other contains a new list containing all the values from the
* iterable. Now make sure each item in the list is an mpfr.
*/
seq_length = PyList_GET_SIZE(other);
if (seq_length > LONG_MAX) {
OVERFLOW_ERROR("temporary array is too large");
Py_DECREF(other);
Py_DECREF((PyObject*)result);
return NULL;
}
for (i=0; i < seq_length; i++) {
if (!(temp = GMPy_MPFR_From_Real(PyList_GET_ITEM(other, i), 1, context))) {
Py_DECREF(other);
Py_DECREF((PyObject*)result);
TYPE_ERROR("all items in iterable must be real numbers");
return NULL;
}
errcode = PyList_SetItem(other, i,(PyObject*)temp);
if (errcode < 0) {
Py_DECREF(other);
Py_DECREF((PyObject*)result);
TYPE_ERROR("all items in iterable must be real numbers");
return NULL;
}
}
/* create an array of pointers to the mpfr_t field of a Pympfr object */
if (!(tab = (mpfr_ptr *)malloc((sizeof(mpfr_srcptr) * seq_length)))) {
Py_DECREF(other);
Py_DECREF((PyObject*)result);
return PyErr_NoMemory();
}
for (i=0; i < seq_length; i++) {
temp = (MPFR_Object*)PyList_GET_ITEM(other, i);
tab[i] = temp->f;
}
mpfr_clear_flags();
/* The cast is safe since we have compared seq_length to LONG_MAX. */
result->rc = mpfr_sum(result->f, tab, (unsigned long)seq_length, GET_MPFR_ROUND(context));
Py_DECREF(other);
free(tab);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
gmpy2-2.1.0b3/src/gmpy2_math.h 0000664 0001750 0001750 00000046370 13425752437 015704 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_math.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MATH_H
#define GMPY_MATH_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Real_Sin(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Sin(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Sin(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sin(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Cos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Cos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Cos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Cos(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Tan(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Tan(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Tan(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Tan(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Atan(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Atan(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Atan(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Atan(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Sinh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Sinh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Sinh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sinh(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Cosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Cosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Cosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Cosh(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Tanh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Tanh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Tanh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Tanh(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Asinh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Asinh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Asinh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Asinh(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Acosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Acosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Acosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Acosh(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Sec(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Sec(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sec(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Csc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Csc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Csc(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Cot(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Cot(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Cot(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Sech(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Sech(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sech(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Csch(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Csch(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Csch(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Coth(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Coth(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Coth(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Acos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Acos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Acos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Acos(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Asin(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Asin(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Asin(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Asin(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Atanh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Atanh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Atanh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Atanh(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Sin_Cos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Sin_Cos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Sin_Cos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sin_Cos(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Sinh_Cosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Sinh_Cosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sinh_Cosh(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Atan2(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Atan2(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Atan2(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Hypot(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Hypot(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Hypot(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Degrees(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_Radians(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Log(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Log(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Log(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Log(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Log10(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Log10(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Log10(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Log10(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Exp(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Exp(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Exp(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Exp(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Sqrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Sqrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Sqrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sqrt(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_RecSqrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_RecSqrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RecSqrt(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Rint(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Rint(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Rint(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_RintCeil(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_RintCeil(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RintCeil(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_RintFloor(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_RintFloor(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RintFloor(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_RintRound(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_RintRound(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RintRound(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_RintTrunc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_RintTrunc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RintTrunc(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Frac(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Frac(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Frac(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Cbrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Cbrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Cbrt(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Log2(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Log2(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Log2(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Exp2(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Exp2(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Exp2(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Exp10(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Exp10(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Exp10(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Log1p(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Log1p(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Log1p(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Expm1(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Expm1(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Expm1(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Eint(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Eint(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Eint(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Li2(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Li2(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Li2(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Lngamma(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Lngamma(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Lngamma(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Digamma(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Digamma(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Digamma(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Zeta(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Zeta(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Zeta(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Erf(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Erf(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Erf(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Erfc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Erfc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Erfc(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_J0(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_J0(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_J0(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_J1(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_J1(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_J1(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Y0(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Y0(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Y0(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Y1(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Y1(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Y1(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Ai(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Ai(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Ai(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Number_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Context_FMA(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Number_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Context_FMS(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Root(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Root(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Root(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Jn(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Jn(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Jn(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Yn(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Yn(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Yn(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_AGM(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_AGM(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_AGM(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Maxnum(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Maxnum(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Maxnum(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Minnum(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Minnum(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Minnum(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Remainder(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Remainder(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Remainder(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Fmod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Fmod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Fmod(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_RelDiff(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_RelDiff(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_RelDiff(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Ceil(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Ceil(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Method_Ceil(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Ceil(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Floor(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Floor(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Method_Floor(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Floor(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Trunc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Trunc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Method_Trunc(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Trunc(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Round2(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Round2(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Round2(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_RoundAway(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_RoundAway(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RoundAway(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Modf(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Modf(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Modf(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Lgamma(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Lgamma(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Lgamma(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_RemQuo(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_RemQuo(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_RemQuo(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Frexp(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Frexp(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Frexp(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_NextToward(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_NextAbove(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_NextBelow(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_Factorial(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_Fsum(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_minus.c 0000664 0001750 0001750 00000015363 13425752452 016074 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_minus.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __neg__ and context.minus().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. If the value
* of context is NULL, then the function should use the currently active
* context.
*
* GMPy_Number_Minus(Number, context)
*
* Private API
* ===========
* GMPy_MPZ_Minus_Slot
* GMPy_MPQ_Minus_Slot
* GMPy_MPFR_Minus_Slot
* GMPy_MPC_Minus_Slot
*
* GMPy_Integer_Minus(Integer, context|NULL)
* GMPy_Rational_Minus(Rational, context|NULL)
* GMPy_Real_Minus(Real, context|NULL)
* GMPy_Complex_Minus(Complex, context|NULL)
*
* GMPy_Context_Minus(context, args)
*/
static PyObject *
_GMPy_MPZ_Minus(PyObject *x, CTXT_Object *context)
{
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_neg(result->z, MPZ(x));
return (PyObject*)result;
}
static PyObject *
GMPy_Integer_Minus(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
if (!(tempx = (PyObject*)GMPy_MPZ_From_Integer(x, context))) {
return NULL;
}
result = _GMPy_MPZ_Minus(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
GMPy_MPZ_Minus_Slot(MPZ_Object *x)
{
return _GMPy_MPZ_Minus((PyObject*)x, NULL);
}
static PyObject *
_GMPy_MPQ_Minus(PyObject *x, CTXT_Object *context)
{
MPQ_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPQ_New(context))) {
return NULL;
}
mpq_neg(result->q, MPQ(x));
return (PyObject*)result;
}
static PyObject *
GMPy_Rational_Minus(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPQ_From_Rational(x, context))) {
return NULL;
}
result = _GMPy_MPQ_Minus(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
GMPy_MPQ_Minus_Slot(MPQ_Object *x)
{
return _GMPy_MPQ_Minus((PyObject*)x, NULL);
}
static PyObject *
_GMPy_MPFR_Minus(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_neg(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Minus(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Minus(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
GMPy_MPFR_Minus_Slot(MPFR_Object *x)
{
return _GMPy_MPFR_Minus((PyObject*)x, NULL);
}
static PyObject *
_GMPy_MPC_Minus(PyObject *x, CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_neg(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Minus(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Minus(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
GMPy_MPC_Minus_Slot(MPC_Object *x)
{
return _GMPy_MPC_Minus((PyObject*)x, NULL);
}
static PyObject *
GMPy_Number_Minus(PyObject *x, CTXT_Object *context)
{
if (MPZ_Check(x))
return _GMPy_MPZ_Minus(x, context);
if (MPQ_Check(x))
return _GMPy_MPQ_Minus(x, context);
if (MPFR_Check(x))
return _GMPy_MPFR_Minus(x, context);
if (MPC_Check(x))
return _GMPy_MPC_Minus(x, context);
if (IS_INTEGER(x))
return GMPy_Integer_Minus(x, context);
if (IS_RATIONAL_ONLY(x))
return GMPy_Rational_Minus(x, context);
if (IS_REAL_ONLY(x))
return GMPy_Real_Minus(x, context);
if (IS_COMPLEX_ONLY(x))
return GMPy_Complex_Minus(x, context);
TYPE_ERROR("minus() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_minus,
"context.minus(x) -> number\n\n"
"Return -x. The context is applied to the result.");
static PyObject *
GMPy_Context_Minus(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("minus() requires 1 argument.");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Minus(PyTuple_GET_ITEM(args, 0), context);
}
gmpy2-2.1.0b3/src/gmpy2_minus.h 0000664 0001750 0001750 00000005514 13425752464 016101 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_minus.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_MINUS_H
#define GMPY2_MINUS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Minus(PyObject *x, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_Minus(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Rational_Minus(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Real_Minus(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Minus(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPZ_Minus_Slot(MPZ_Object *x);
static PyObject * GMPy_MPQ_Minus_Slot(MPQ_Object *x);
static PyObject * GMPy_MPFR_Minus_Slot(MPFR_Object *x);
static PyObject * GMPy_MPC_Minus_Slot(MPC_Object *x);
static PyObject * GMPy_Context_Minus(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_misc.c 0000664 0001750 0001750 00000015027 13425752502 015665 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Miscellaneous module-level functions and helper functions. */
PyDoc_STRVAR(GMPy_doc_license,
"license() -> string\n\n"
"Return string giving license information.");
static PyObject *
GMPy_get_license(PyObject *self, PyObject *args)
{
return Py_BuildValue("s", gmpy_license);
}
PyDoc_STRVAR(GMPy_doc_version,
"version() -> string\n\n"
"Return string giving current GMPY2 version.");
static PyObject *
GMPy_get_version(PyObject *self, PyObject *args)
{
return Py_BuildValue("s", gmpy_version);
}
PyDoc_STRVAR(GMPy_doc_mp_version,
"mp_version() -> string\n\n"
"Return string giving the name and version of the multiple precision\n"
"library used.");
static PyObject *
GMPy_get_mp_version(PyObject *self, PyObject *args)
{
#ifndef __MPIR_VERSION
return Py2or3String_FromFormat("%s %s", "GMP", gmp_version);
#else
return Py2or3String_FromFormat("%s %s", "MPIR", mpir_version);
#endif
}
PyDoc_STRVAR(GMPy_doc_mpfr_version,
"mpfr_version() -> string\n\n"
"Return string giving current MPFR version.");
static PyObject *
GMPy_get_mpfr_version(PyObject *self, PyObject *args)
{
return Py2or3String_FromFormat("%s %s", "MPFR", MPFR_VERSION_STRING);
}
PyDoc_STRVAR(GMPy_doc_mpc_version,
"mpc_version() -> string\n\n"
"Return string giving current MPC version.");
static PyObject *
GMPy_get_mpc_version(PyObject *self, PyObject *args)
{
return Py2or3String_FromFormat("%s %s", "MPC", MPC_VERSION_STRING);
}
PyDoc_STRVAR(GMPy_doc_mp_limbsize,
"mp_limbsize() -> integer\n\n\
Return the number of bits per limb.");
static PyObject *
GMPy_get_mp_limbsize(PyObject *self, PyObject *args)
{
return Py_BuildValue("i", mp_bits_per_limb);
}
/*
* access cache options
*/
PyDoc_STRVAR(GMPy_doc_get_cache,
"get_cache() -> (cache_size, object_size)\n\n\
Return the current cache size (number of objects) and maximum size\n\
per object (number of limbs) for all GMPY2 objects.");
static PyObject *
GMPy_get_cache(PyObject *self, PyObject *args)
{
return Py_BuildValue("(ii)", global.cache_size, global.cache_obsize);
}
PyDoc_STRVAR(GMPy_doc_set_cache,
"set_cache(cache_size, object_size)\n\n\
Set the current cache size (number of objects) and the maximum size\n\
per object (number of limbs). Raises ValueError if cache size exceeds\n\
1000 or object size exceeds 16384.");
static PyObject *
GMPy_set_cache(PyObject *self, PyObject *args)
{
int newcache = -1, newsize = -1;
if (!PyArg_ParseTuple(args, "ii", &newcache, &newsize))
return NULL;
if (newcache<0 || newcache>MAX_CACHE) {
VALUE_ERROR("cache size must between 0 and 1000");
return NULL;
}
if (newsize<0 || newsize>MAX_CACHE_LIMBS) {
VALUE_ERROR("object size must between 0 and 16384");
return NULL;
}
global.cache_size = newcache;
global.cache_obsize = newsize;
set_gmpympzcache();
set_gmpympqcache();
set_gmpyxmpzcache();
set_gmpympfrcache();
set_gmpympccache();
Py_RETURN_NONE;
}
PyDoc_STRVAR(GMPy_doc_function_printf,
"_printf(fmt, x) -> string\n\n"
"Return a Python string by formatting 'x' using the format string\n"
"'fmt'.\n\n"
"WARNING: Invalid format strings will cause a crash. Please see the\n"
" GMP and MPFR manuals for details on the format code. 'mpc'\n"
" objects are not supported.");
static PyObject *
GMPy_printf(PyObject *self, PyObject *args)
{
PyObject *result = NULL, *x = NULL;
char *buffer = NULL, *fmtcode = NULL;
void *generic;
int buflen;
if (!PyArg_ParseTuple(args, "sO", &fmtcode, &x))
return NULL;
if (CHECK_MPZANY(x) || MPQ_Check(x)) {
if (CHECK_MPZANY(x))
generic = MPZ(x);
else
generic = MPQ(x);
buflen = mpfr_asprintf(&buffer, fmtcode, generic);
if (buflen < 0) {
VALUE_ERROR("_printf() could not format the 'mpz' or 'mpq' object");
}
else {
result = Py_BuildValue("s", buffer);
mpfr_free_str(buffer);
}
return result;
}
else if(MPFR_Check(x)) {
generic = MPFR(x);
buflen = mpfr_asprintf(&buffer, fmtcode, generic);
if (buflen < 0) {
VALUE_ERROR("_printf() could not format the 'mpfr' object");
}
else {
result = Py_BuildValue("s", buffer);
mpfr_free_str(buffer);
}
return result;
}
else if(MPC_Check(x)) {
TYPE_ERROR("_printf() does not support 'mpc'");
return NULL;
}
else {
TYPE_ERROR("_printf() argument type not supported");
return NULL;
}
}
gmpy2-2.1.0b3/src/gmpy2_misc.h 0000664 0001750 0001750 00000005401 13425752543 015672 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MISC_H
#define GMPY_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_get_license(PyObject *self, PyObject *args);
static PyObject * GMPy_get_version(PyObject *self, PyObject *args);
static PyObject * GMPy_get_mp_version(PyObject *self, PyObject *args);
static PyObject * GMPy_get_mpfr_version(PyObject *self, PyObject *args);
static PyObject * GMPy_get_mpc_version(PyObject *self, PyObject *args);
static PyObject * GMPy_get_mp_limbsize(PyObject *self, PyObject *args);
static PyObject * GMPy_get_cache(PyObject *self, PyObject *args);
static PyObject * GMPy_set_cache(PyObject *self, PyObject *args);
static PyObject * GMPy_printf(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mod.c 0000664 0001750 0001750 00000027646 13452562272 015526 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mod.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __mod__, gmpy2.mod(), and context.mod().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*
* GMPy_Number_Mod(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_MPZ_Mod_Slot
* GMPy_MPQ_Mod_Slot
* GMPy_MPFR_Mod_Slot
* GMPy_MPC_Mod_Slot
*
* GMPy_Integer_Mod(Integer, Integer, context|NULL)
* GMPy_Rational_Mod(Rational, Rational, context|NULL)
* GMPy_Real_Mod(Real, Real, context|NULL)
* GMPy_Complex_Mod(Complex, Complex, context|NULL)
*
* GMPy_Context_Mod(context, args)
*
*/
static PyObject *
GMPy_Integer_Mod(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPZ_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPZ_New(context)))
return NULL;
if (CHECK_MPZANY(x)) {
if (PyIntOrLong_Check(y)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(y, &error);
if (!error) {
if (temp > 0) {
mpz_fdiv_r_ui(result->z, MPZ(x), temp);
}
else if (temp == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
else {
mpz_cdiv_r_ui(result->z, MPZ(x), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpz_fdiv_r(result->z, MPZ(x), global.tempz);
}
return (PyObject*)result;
}
if (CHECK_MPZANY(y)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_fdiv_r(result->z, MPZ(x), MPZ(y));
return (PyObject*)result;
}
}
if (CHECK_MPZANY(y)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
if (PyIntOrLong_Check(x)) {
mpz_set_PyIntOrLong(global.tempz, x);
mpz_fdiv_r(result->z, global.tempz, MPZ(y));
return (PyObject*)result;
}
}
if (IS_INTEGER(x) && IS_INTEGER(y)) {
MPZ_Object *tempx, *tempy;
tempx = GMPy_MPZ_From_Integer(x, context);
tempy = GMPy_MPZ_From_Integer(y, context);
if (!tempx || !tempy) {
SYSTEM_ERROR("could not convert Integer to mpz");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_fdiv_r(result->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_MPZ_Mod_Slot(PyObject *x, PyObject *y)
{
if (MPZ_Check(x) && MPZ_Check(y)) {
MPZ_Object *result = NULL;
if ((result = GMPy_MPZ_New(NULL))) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_fdiv_r(result->z, MPZ(x), MPZ(y));
}
return (PyObject*)result;
}
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_Mod(x, y, NULL);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Mod(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Mod(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Mod(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Rational_Mod(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPQ_Object *tempx, *tempy, *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPQ_New(context)))
return NULL;
if (IS_RATIONAL(x) && IS_RATIONAL(y)) {
tempx = GMPy_MPQ_From_Number(x, context);
tempy = GMPy_MPQ_From_Number(y, context);
if (!tempx || !tempy) {
SYSTEM_ERROR("could not convert Rational to mpq");
goto error;
}
if (mpq_sgn(tempy->q) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
mpq_div(result->q, tempx->q, tempy->q);
mpz_fdiv_q(global.tempz, mpq_numref(result->q), mpq_denref(result->q));
/* Need to calculate x - tempz * y. */
mpq_set_z(result->q, global.tempz);
mpq_mul(result->q, result->q, tempy->q);
mpq_sub(result->q, tempx->q, result->q);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
static PyObject *
GMPy_MPQ_Mod_Slot(PyObject *x, PyObject *y)
{
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Mod(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Mod(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Mod(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Real_Mod(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *tempx = NULL, *tempy = NULL, *result;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
if (!result) {
Py_XDECREF((PyObject*)result);
return NULL;
}
if (IS_REAL(x) && IS_REAL(y)) {
tempx = GMPy_MPFR_From_Real(x, 1, context);
tempy = GMPy_MPFR_From_Real(y, 1, context);
if (!tempx || !tempy) {
SYSTEM_ERROR("could not convert Real to mpfr");
goto error;
}
if (mpfr_zero_p(tempy->f)) {
context->ctx.divzero = 1;
if (context->ctx.traps & TRAP_DIVZERO) {
GMPY_DIVZERO("mod() modulo by zero");
goto error;
}
}
mpfr_clear_flags();
if (mpfr_nan_p(tempx->f) || mpfr_nan_p(tempy->f) || mpfr_inf_p(tempx->f)) {
context->ctx.invalid = 1;
if (context->ctx.traps & TRAP_INVALID) {
GMPY_INVALID("mod() invalid operation");
goto error;
}
mpfr_set_nan(result->f);
}
else if (mpfr_inf_p(tempy->f)) {
context->ctx.invalid = 1;
if (context->ctx.traps & TRAP_INVALID) {
GMPY_INVALID("mod() invalid operation");
goto error;
}
if (mpfr_signbit(tempy->f)) {
mpfr_set_inf(result->f, -1);
}
else {
result->rc = mpfr_set(result->f, tempx->f,
GET_MPFR_ROUND(context));
}
}
else {
mpfr_fmod(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context));
if (!mpfr_zero_p(result->f)) {
if ((mpfr_sgn(tempy->f) < 0) != (mpfr_sgn(result->f) < 0)) {
mpfr_add(result->f, result->f, tempy->f, GET_MPFR_ROUND(context));
}
}
else {
mpfr_copysign(result->f, result->f, tempy->f, GET_MPFR_ROUND(context));
}
}
_GMPy_MPFR_Cleanup(&result, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
static PyObject *
GMPy_MPFR_Mod_Slot(PyObject *x, PyObject *y)
{
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Mod(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Mod(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Complex_Mod(PyObject *x, PyObject *y, CTXT_Object *context)
{
TYPE_ERROR("can't take mod of complex number");
return NULL;
}
static PyObject *
GMPy_MPC_Mod_Slot(PyObject *x, PyObject *y)
{
return GMPy_Complex_Mod(x, y, NULL);
}
PyDoc_STRVAR(GMPy_doc_mod,
"mod(x, y) -> number\n\n"
"Return mod(x, y).\n"
"Note: overflow, underflow, and inexact exceptions are not supported for\n"
"mpfr arguments to mod().");
static PyObject *
GMPy_Number_Mod(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_Mod(x, y, context);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Mod(x, y, context);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Mod(x, y, context);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Mod(x, y, context);
TYPE_ERROR("mod() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_mod,
"context.mod(x, y) -> number\n\n"
"Return mod(x, y).\n"
"Note: overflow, underflow, and inexact exceptions are not supported for\n"
"mpfr arguments to context.mod().");
static PyObject *
GMPy_Context_Mod(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mod() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Mod(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}
gmpy2-2.1.0b3/src/gmpy2_mod.h 0000664 0001750 0001750 00000005640 13425752600 015515 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mod.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_MOD_H
#define GMPY2_MOD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Mod(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_Mod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Rational_Mod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Real_Mod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_Mod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_MPZ_Mod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPQ_Mod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPFR_Mod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPC_Mod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_Mod(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpc.c 0000664 0001750 0001750 00000041711 13444070732 015507 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void
_GMPy_MPC_Cleanup(MPC_Object **v, CTXT_Object *ctext)
{
/* GMPY_MPC_CHECK_RANGE(V, CTX) */
{
int rcr, rci;
rcr = MPC_INEX_RE((*v)->rc);
rci = MPC_INEX_IM((*v)->rc);
if (mpfr_regular_p(mpc_realref((*v)->c)) &&
(!((mpc_realref((*v)->c)->_mpfr_exp >= ctext->ctx.emin) &&
(mpc_realref((*v)->c)->_mpfr_exp <= ctext->ctx.emax)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
rcr = mpfr_check_range(mpc_realref((*v)->c), rcr, GET_REAL_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
if (mpfr_regular_p(mpc_imagref((*v)->c)) &&
(!((mpc_imagref((*v)->c)->_mpfr_exp >= ctext->ctx.emin) &&
(mpc_imagref((*v)->c)->_mpfr_exp <= ctext->ctx.emax)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
rci = mpfr_check_range(mpc_imagref((*v)->c), rci, GET_IMAG_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
(*v)->rc = MPC_INEX(rcr, rci);
}
/* GMPY_MPC_SUBNORMALIZE(V, CTX) */
{
int rcr, rci;
rcr = MPC_INEX_RE((*v)->rc);
rci = MPC_INEX_IM((*v)->rc);
if (ctext->ctx.subnormalize &&
(!((mpc_realref((*v)->c)->_mpfr_exp >= ctext->ctx.emin) &&
(mpc_realref((*v)->c)->_mpfr_exp <= ctext->ctx.emin + mpfr_get_prec(mpc_realref((*v)->c)) - 2)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
rcr = mpfr_subnormalize(mpc_realref((*v)->c), rcr, GET_REAL_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
if (ctext->ctx.subnormalize &&
(!((mpc_imagref((*v)->c)->_mpfr_exp >= ctext->ctx.emin) &&
(mpc_imagref((*v)->c)->_mpfr_exp <= ctext->ctx.emin + mpfr_get_prec(mpc_imagref((*v)->c)) - 2)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
rci = mpfr_check_range(mpc_imagref((*v)->c), rci, GET_IMAG_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
(*v)->rc = MPC_INEX(rcr, rci);
}
/* GMPY_MPC_EXCEPTIONS(V, CTX) */
{
int _invalid = 0, _underflow = 0, _overflow = 0, _inexact = 0;
int rcr, rci;
rcr = MPC_INEX_RE((*v)->rc);
rci = MPC_INEX_IM((*v)->rc);
if (MPC_IS_NAN_P(*v)) {
ctext->ctx.invalid = 1;
_invalid = 1;
}
if ((*v)->rc) {
ctext->ctx.inexact = 1;
_inexact = 1;
}
if ((rcr && mpfr_zero_p(mpc_realref((*v)->c))) || (rci && mpfr_zero_p(mpc_imagref((*v)->c)))) {
ctext->ctx.underflow = 1;
_underflow = 1;
}
if ((rcr && mpfr_inf_p(mpc_realref((*v)->c))) || (rci && mpfr_inf_p(mpc_imagref((*v)->c)))) {
ctext->ctx.overflow = 1;
_overflow = 1;
}
if (ctext->ctx.traps) {
if ((ctext->ctx.traps & TRAP_UNDERFLOW) && _underflow) { \
GMPY_UNDERFLOW("underflow");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_OVERFLOW) && _overflow) {
GMPY_OVERFLOW("overflow");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_INEXACT) && _inexact) {
GMPY_INEXACT("inexact result");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_INVALID) && _invalid) {
GMPY_INVALID("invalid operation");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
}
}
}
PyDoc_STRVAR(GMPy_doc_mpc,
"mpc() -> mpc(0.0+0.0j)\n\n"
" If no argument is given, return mpc(0.0+0.0j).\n\n"
"mpc(c [, precision=0]) -> mpc\n\n"
" Return a new 'mpc' object from an existing complex number (either\n"
" a Python complex object or another 'mpc' object).\n\n"
"mpc(real [,imag=0 [, precision=0]]) -> mpc\n\n"
" Return a new 'mpc' object by converting two non-complex numbers\n"
" into the real and imaginary components of an 'mpc' object.\n\n"
"mpc(s [, precision=0 [, base=10]]) -> mpc\n\n"
" Return a new 'mpc' object by converting a string s into a complex\n"
" number. If base is omitted, then a base-10 representation is\n"
" assumed otherwise the base must be in the interval [2,36].\n\n"
"Note: The precision can be specified either a single number that\n"
" is used for both the real and imaginary components, or as a\n"
" tuple that can specify different precisions for the real\n"
" and imaginary components.\n\n"
" If a precision greater than or equal to 2 is specified, then it\n"
" is used.\n\n"
" A precision of 0 (the default) implies the precision of the\n"
" current context is used.\n\n"
" A precision of 1 minimizes the loss of precision by following\n"
" these rules:\n"
" 1) If n is a radix-2 floating point number, then the full\n"
" precision of n is retained.\n"
" 2) If n is an integer, then the precision is the bit length\n"
" of the integer.\n" );
static PyMethodDef Pympc_methods[] =
{
{ "__complex__", GMPy_PyComplex_From_MPC, METH_NOARGS, GMPy_doc_mpc_complex },
{ "__format__", GMPy_MPC_Format, METH_VARARGS, GMPy_doc_mpc_format },
{ "__sizeof__", GMPy_MPC_SizeOf_Method, METH_NOARGS, GMPy_doc_mpc_sizeof_method },
{ "conjugate", GMPy_MPC_Conjugate_Method, METH_NOARGS, GMPy_doc_mpc_conjugate_method },
{ "digits", GMPy_MPC_Digits_Method, METH_VARARGS, GMPy_doc_mpc_digits_method },
{ "is_finite", GMPy_MPC_Is_Finite_Method, METH_NOARGS, GMPy_doc_method_is_finite },
{ "is_infinite", GMPy_MPC_Is_Infinite_Method, METH_NOARGS, GMPy_doc_method_is_infinite },
{ "is_nan", GMPy_MPC_Is_NAN_Method, METH_NOARGS, GMPy_doc_method_is_nan },
{ "is_zero", GMPy_MPC_Is_Zero_Method, METH_NOARGS, GMPy_doc_method_is_zero },
{ NULL, NULL, 1 }
};
#ifdef PY3
static PyNumberMethods mpc_number_methods =
{
(binaryfunc) GMPy_MPC_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPC_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPC_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPC_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPC_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPANY_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_MPC_Minus_Slot, /* nb_negative */
(unaryfunc) GMPy_MPC_Plus_Slot, /* nb_positive */
(unaryfunc) GMPy_MPC_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_MPC_NonZero_Slot, /* nb_bool */
0, /* nb_invert */
0, /* nb_lshift */
0, /* nb_rshift */
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
(unaryfunc) GMPy_MPC_Int_Slot, /* nb_int */
0, /* nb_reserved */
(unaryfunc) GMPy_MPC_Float_Slot, /* nb_float */
0, /* nb_inplace_add */
0, /* nb_inplace_subtract */
0, /* nb_inplace_multiply */
0, /* nb_inplace_remainder */
0, /* nb_inplace_power */
0, /* nb_inplace_lshift */
0, /* nb_inplace_rshift */
0, /* nb_inplace_and */
0, /* nb_inplace_xor */
0, /* nb_inplace_or */
(binaryfunc) GMPy_MPC_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPC_TrueDiv_Slot, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
0, /* nb_index */
};
#else
static PyNumberMethods mpc_number_methods =
{
(binaryfunc) GMPy_MPC_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPC_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPC_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPC_TrueDiv_Slot, /* nb_divide */
(binaryfunc) GMPy_MPC_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPC_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPANY_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_MPC_Minus_Slot, /* nb_negative */
(unaryfunc) GMPy_MPC_Plus_Slot, /* nb_positive */
(unaryfunc) GMPy_MPC_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_MPC_NonZero_Slot, /* nb_bool */
0, /* nb_invert */
0, /* nb_lshift */
0, /* nb_rshift */
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
0, /* nb_coerce */
(unaryfunc) GMPy_MPC_Int_Slot, /* nb_int */
(unaryfunc) GMPy_MPC_Long_Slot, /* nb_long */
(unaryfunc) GMPy_MPC_Float_Slot, /* nb_float */
0, /* nb_oct */
0, /* nb_hex */
0, /* nb_inplace_add */
0, /* nb_inplace_subtract */
0, /* nb_inplace_multiply */
0, /* nb_inplace_divide */
0, /* nb_inplace_remainder */
0, /* nb_inplace_power */
0, /* nb_inplace_lshift */
0, /* nb_inplace_rshift */
0, /* nb_inplace_and */
0, /* nb_inplace_xor */
0, /* nb_inplace_or */
(binaryfunc) GMPy_MPC_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPC_TrueDiv_Slot, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
};
#endif
static PyGetSetDef Pympc_getseters[] =
{
{"precision", (getter)GMPy_MPC_GetPrec_Attrib, NULL, "precision in bits", NULL},
{"rc", (getter)GMPy_MPC_GetRc_Attrib, NULL, "return code", NULL},
{"imag", (getter)GMPy_MPC_GetImag_Attrib, NULL, "imaginary component", NULL},
{"real", (getter)GMPy_MPC_GetReal_Attrib, NULL, "real component", NULL},
{NULL}
};
static PyTypeObject MPC_Type =
{
/* PyObject_HEAD_INIT(&PyType_Type) */
#ifdef PY3
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyObject_HEAD_INIT(0)
0, /* ob_size */
#endif
"mpc", /* tp_name */
sizeof(MPC_Object), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor) GMPy_MPC_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_MPC_Repr_Slot, /* tp_repr */
&mpc_number_methods, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc) GMPy_MPC_Hash_Slot, /* tp_hash */
0, /* tp_call */
(reprfunc) GMPy_MPC_Str_Slot, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
#ifdef PY3
Py_TPFLAGS_DEFAULT, /* tp_flags */
#else
Py_TPFLAGS_HAVE_RICHCOMPARE|Py_TPFLAGS_CHECKTYPES, /* tp_flags */
#endif
GMPy_doc_mpc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)&GMPy_RichCompare_Slot, /* tp_richcompare */
0, /* tp_weaklistoffset*/
0, /* tp_iter */
0, /* tp_iternext */
Pympc_methods, /* tp_methods */
0, /* tp_members */
Pympc_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
GMPy_MPC_NewInit, /* tp_new */
0, /* tp_free */
};
gmpy2-2.1.0b3/src/gmpy2_mpc.h 0000664 0001750 0001750 00000017474 13425752625 015534 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPC_H
#define GMPY_MPC_H
#ifdef __cplusplus
extern "C" {
#endif
/* gmpy_mpc C API extension header file.
*
* Provide interface to the MPC (Multiple Precision Complex) library.
*
* Version 2.00, April 2011 (created) casevh
*
* This file is expected to be included from gmpy.h
*/
#if defined(MS_WIN32) && defined(_MSC_VER)
# pragma comment(lib,"mpc.lib")
#endif
static PyTypeObject MPC_Type;
#define MPC_Check(v) (((PyObject*)v)->ob_type == &MPC_Type)
/*
* Define macros for comparing with zero, checking if either component is
* 'nan' or 'inf', etc. Based on the macros found in mpc-impl.h.
*/
#define MPC_IS_ZERO_P(x) \
(mpfr_zero_p(mpc_realref(MPC(x))) && \
mpfr_zero_p(mpc_imagref(MPC(x))))
#define MPC_IS_NAN_P(x) \
((mpfr_nan_p(mpc_realref(MPC(x))) && !mpfr_inf_p(mpc_imagref(MPC(x)))) || \
(mpfr_nan_p(mpc_imagref(MPC(x))) && !mpfr_inf_p(mpc_realref(MPC(x)))))
#define MPC_IS_INF_P(x) \
(mpfr_inf_p(mpc_realref(MPC(x))) || \
mpfr_inf_p(mpc_imagref(MPC(x))))
#define MPC_IS_FINITE_P(x) \
(mpfr_number_p(mpc_realref(MPC(x))) && \
mpfr_number_p(mpc_imagref(MPC(x))))
/* V is the value that is expected to be returned.
* CTX is the context.
* NAME is prepended to the error message.
*/
#define GMPY_MPC_CHECK_RANGE(V, CTX) \
{ \
int rcr, rci; \
rcr = MPC_INEX_RE(V->rc); \
rci = MPC_INEX_IM(V->rc); \
if (mpfr_regular_p(mpc_realref(V->c)) && \
(!((mpc_realref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \
(mpc_realref(V->c)->_mpfr_exp <= CTX->ctx.emax)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
rcr = mpfr_check_range(mpc_realref(V->c), rcr, GET_REAL_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
} \
if (mpfr_regular_p(mpc_imagref(V->c)) && \
(!((mpc_imagref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \
(mpc_imagref(V->c)->_mpfr_exp <= CTX->ctx.emax)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
rci = mpfr_check_range(mpc_imagref(V->c), rci, GET_IMAG_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
} \
V->rc = MPC_INEX(rcr, rci); \
}
#define GMPY_MPC_SUBNORMALIZE(V, CTX) \
{ \
int rcr, rci; \
rcr = MPC_INEX_RE(V->rc); \
rci = MPC_INEX_IM(V->rc); \
if (CTX->ctx.subnormalize && \
(!((mpc_realref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \
(mpc_realref(V->c)->_mpfr_exp <= CTX->ctx.emin + mpfr_get_prec(mpc_realref(V->c)) - 2)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
rcr = mpfr_subnormalize(mpc_realref(V->c), rcr, GET_REAL_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
} \
if (CTX->ctx.subnormalize && \
(!((mpc_imagref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \
(mpc_imagref(V->c)->_mpfr_exp <= CTX->ctx.emin + mpfr_get_prec(mpc_imagref(V->c)) - 2)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
rci = mpfr_check_range(mpc_imagref(V->c), rci, GET_IMAG_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
} \
V->rc = MPC_INEX(rcr, rci); \
}
#define GMPY_MPC_EXCEPTIONS(V, CTX) \
do { \
int _invalid = 0, _underflow = 0, _overflow = 0, _inexact = 0; \
int rcr, rci; \
rcr = MPC_INEX_RE(V->rc); \
rci = MPC_INEX_IM(V->rc); \
if (MPC_IS_NAN_P(V)) { \
CTX->ctx.invalid = 1; \
_invalid = 1; \
} \
if (V->rc) { \
CTX->ctx.inexact = 1; \
_inexact = 1; \
} \
if ((rcr && mpfr_zero_p(mpc_realref(V->c))) || (rci && mpfr_zero_p(mpc_imagref(V->c)))) { \
CTX->ctx.underflow = 1; \
_underflow = 1; \
} \
if ((rcr && mpfr_inf_p(mpc_realref(V->c))) || (rci && mpfr_inf_p(mpc_imagref(V->c)))) { \
CTX->ctx.overflow = 1; \
_overflow = 1; \
} \
if (CTX->ctx.traps) { \
if ((CTX->ctx.traps & TRAP_UNDERFLOW) && _underflow) { \
GMPY_UNDERFLOW("underflow"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_OVERFLOW) && _overflow) { \
GMPY_OVERFLOW("overflow"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_INEXACT) && _inexact) { \
GMPY_INEXACT("inexact result"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_INVALID) && _invalid) { \
GMPY_INVALID("invalid operation"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
} \
} while(0); \
#define GMPY_MPC_CLEANUP(V, CTX) \
GMPY_MPC_CHECK_RANGE(V, CTX); \
GMPY_MPC_SUBNORMALIZE(V, CTX); \
GMPY_MPC_EXCEPTIONS(V, CTX); \
static void _GMPy_MPC_Cleanup(MPC_Object **v, CTXT_Object *ctext);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpc_misc.c 0000664 0001750 0001750 00000032523 13444615157 016531 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpc_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_context_phase,
"context.phase(x) -> mpfr\n\n"
"Return the phase angle, also known as argument, of a complex x.");
PyDoc_STRVAR(GMPy_doc_function_phase,
"phase(x) -> mpfr\n\n"
"Return the phase angle, also known as argument, of a complex x.");
static PyObject *
GMPy_Complex_Phase(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPC_Object *tempx = NULL;
CHECK_CONTEXT(context)
if (!(IS_COMPLEX_ONLY(x))) {
TYPE_ERROR("phase() argument type not supported");
return NULL;
}
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
Py_XDECREF(result);
Py_XDECREF(tempx);
return NULL;
}
mpfr_clear_flags();
result->rc = mpc_arg(result->f, tempx->c, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Phase(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Complex_Phase(other, context);
}
#ifdef MPC_110
PyDoc_STRVAR(GMPy_doc_context_root_of_unity,
"context.root_of_unity(n, k) -> mpc\n\n"
"Return the n-th root of mpc(1) raised to the k-th power..");
PyDoc_STRVAR(GMPy_doc_function_root_of_unity,
"root_of_unity(n, k) -> mpc\n\n"
"Return the n-th root of mpc(1) raised to the k-th power..");
static PyObject *
GMPy_Complex_Root_Of_Unity(PyObject *n, PyObject *k, CTXT_Object *context)
{
MPC_Object *result;
unsigned long n_val, k_val;
CHECK_CONTEXT(context)
result = GMPy_MPC_New(0, 0, context);
if (!result) {
return NULL;
}
n_val = c_ulong_From_Integer(n);
k_val = c_ulong_From_Integer(k);
if ((n_val == (unsigned long)(-1) && PyErr_Occurred()) ||
(k_val == (unsigned long)(-1) && PyErr_Occurred())) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("root_of_unity() requires positive integer arguments.");
return NULL;
}
result->rc = mpc_rootofunity(result->c, n_val, k_val, GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Root_Of_Unity(PyObject *self, PyObject *args)
{
PyObject *n, *k;
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("root_of_unity() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
n = PyTuple_GET_ITEM(args, 0);
k = PyTuple_GET_ITEM(args, 1);
if (IS_INTEGER(n) && IS_INTEGER(k)) {
return GMPy_Complex_Root_Of_Unity(n, k, context);
}
else {
TYPE_ERROR("root_of_unity() requires integer arguments");
return NULL;
}
}
#endif
PyDoc_STRVAR(GMPy_doc_context_norm,
"context.norm(x) -> mpfr\n\n"
"Return the norm of a complex x. The norm(x) is defined as\n"
"x.real**2 + x.imag**2. abs(x) is the square root of norm(x).\n");
PyDoc_STRVAR(GMPy_doc_function_norm,
"norm(x) -> mpfr\n\n"
"Return the norm of a complex x. The norm(x) is defined as\n"
"x.real**2 + x.imag**2. abs(x) is the square root of norm(x).\n");
static PyObject *
GMPy_Complex_Norm(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPC_Object *tempx = NULL;
CHECK_CONTEXT(context);
if (!(IS_COMPLEX_ONLY(x))) {
TYPE_ERROR("norm() argument type not supported");
return NULL;
}
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
Py_XDECREF(result);
Py_XDECREF(tempx);
return NULL;
}
mpfr_clear_flags();
result->rc = mpc_norm(result->f, tempx->c, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Norm(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Complex_Norm(other, context);
}
PyDoc_STRVAR(GMPy_doc_context_polar,
"context.polar(x) -> (abs(x), phase(x))\n\n"
"Return the polar coordinate form of a complex x that is in\n"
"rectangular form.");
PyDoc_STRVAR(GMPy_doc_function_polar,
"polar(x) -> (abs(x), phase(x))\n\n"
"Return the polar coordinate form of a complex x that is in\n"
"rectangular form.");
static PyObject *
GMPy_Complex_Polar(PyObject *x, CTXT_Object *context)
{
PyObject *tempx, *abs, *phase, *result;
CHECK_CONTEXT(context);
if (!(IS_COMPLEX_ONLY(x))) {
TYPE_ERROR("polar() argument type not supported");
return NULL;
}
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
abs = GMPy_Complex_Abs(tempx, context);
phase = GMPy_Complex_Phase(tempx, context);
Py_DECREF(tempx);
result = PyTuple_New(2);
if (!abs || !phase || !result) {
Py_XDECREF(abs);
Py_XDECREF(phase);
Py_XDECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, abs);
PyTuple_SET_ITEM(result, 1, phase);
return result;
}
static PyObject *
GMPy_Context_Polar(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Complex_Polar(other, context);
}
PyDoc_STRVAR(GMPy_doc_context_rect,
"context.rect(r, phi) -> mpc\n\n"
"Return the rectangular coordinate form of a complex number that is\n"
"given in polar form.");
PyDoc_STRVAR(GMPy_doc_function_rect,
"rect(r, phi) -> mpc\n\n"
"Return the rectangular coordinate form of a complex number that is\n"
"given in polar form.");
static PyObject *
GMPy_Complex_Rect(PyObject *r, PyObject *phi, CTXT_Object *context)
{
MPFR_Object *tempx, *tempy;
MPC_Object *result;
CHECK_CONTEXT(context);
tempx = GMPy_MPFR_From_Real(r, 1, context);
tempy = GMPy_MPFR_From_Real(phi, 1, context);
result = GMPy_MPC_New(0, 0, context);
if (!tempx || !tempy || !result) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_cos(mpc_realref(result->c), tempy->f, GET_REAL_ROUND(context));
mpfr_mul(mpc_realref(result->c), mpc_realref(result->c), tempx->f, GET_REAL_ROUND(context));
mpfr_sin(mpc_imagref(result->c), tempy->f, GET_IMAG_ROUND(context));
mpfr_mul(mpc_imagref(result->c), mpc_imagref(result->c), tempx->f, GET_IMAG_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Rect(PyObject *self, PyObject *args)
{
PyObject *r, *phi;
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("rect() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
r = PyTuple_GET_ITEM(args, 0);
phi = PyTuple_GET_ITEM(args, 1);
if (IS_REAL(r) && IS_REAL(phi)) {
return GMPy_Complex_Rect(r, phi, context);
}
else {
TYPE_ERROR("rect() argument type not supported");
return NULL;
}
}
PyDoc_STRVAR(GMPy_doc_context_proj,
"context.proj(x) -> mpc\n\n"
"Returns the projection of a complex x on to the Riemann sphere.");
PyDoc_STRVAR(GMPy_doc_function_proj,
"proj(x) -> mpc\n\n"
"Returns the projection of a complex x on to the Riemann sphere.");
static PyObject *
GMPy_Complex_Proj(PyObject *x, CTXT_Object *context)
{
MPC_Object *result = NULL, *tempx = NULL;
CHECK_CONTEXT(context);
if (!(IS_COMPLEX_ONLY(x))) {
TYPE_ERROR("proj() argument type not supported");
return NULL;
}
result = GMPy_MPC_New(0, 0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
Py_XDECREF(result);
Py_XDECREF(tempx);
return NULL;
}
mpfr_clear_flags();
result->rc = mpc_proj(result->c, tempx->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Proj(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Complex_Proj(other, context);
}
/* Implement the conjugate() method. */
PyDoc_STRVAR(GMPy_doc_mpc_conjugate_method,
"x.conjugate() -> mpc\n\n"
"Returns the conjugate of x.");
static PyObject *
GMPy_MPC_Conjugate_Method(PyObject *self, PyObject *args)
{
MPC_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_conj(result->c, MPC(self), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
/* Implement the .precision attribute of an mpc. */
static PyObject *
GMPy_MPC_GetPrec_Attrib(MPC_Object *self, void *closure)
{
mpfr_prec_t rprec = 0, iprec = 0;
mpc_get_prec2(&rprec, &iprec, self->c);
return Py_BuildValue("(nn)", rprec, iprec);
}
/* Implement the .rc attribute of an mpc. */
static PyObject *
GMPy_MPC_GetRc_Attrib(MPC_Object *self, void *closure)
{
return Py_BuildValue("(ii)", MPC_INEX_RE(self->rc), MPC_INEX_IM(self->rc));
}
/* Implement the .imag attribute of an mpc. */
static PyObject *
GMPy_MPC_GetImag_Attrib(MPC_Object *self, void *closure)
{
MPFR_Object *result = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
mpfr_prec_t rprec = 0, iprec = 0;
mpc_get_prec2(&rprec, &iprec, self->c);
if ((result = GMPy_MPFR_New(iprec, context))) {
result->rc = mpc_imag(result->f, self->c, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
/* Implement the .real attribute of an mpc. */
static PyObject *
GMPy_MPC_GetReal_Attrib(MPC_Object *self, void *closure)
{
MPFR_Object *result = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
mpfr_prec_t rprec = 0, iprec = 0;
mpc_get_prec2(&rprec, &iprec, self->c);
if ((result = GMPy_MPFR_New(rprec, context))) {
result->rc = mpc_real(result->f, self->c, context->ctx.mpfr_round);
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
/* Implement the nb_bool slot. */
static int
GMPy_MPC_NonZero_Slot(MPC_Object *self)
{
return !MPC_IS_ZERO_P(self->c);
}
PyDoc_STRVAR(GMPy_doc_mpc_sizeof_method,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x.");
static PyObject *
GMPy_MPC_SizeOf_Method(PyObject *self, PyObject *other)
{
return PyIntOrLong_FromSize_t(sizeof(MPC_Object) + \
(((mpc_realref(MPC(self))->_mpfr_prec + mp_bits_per_limb - 1) / \
mp_bits_per_limb) * sizeof(mp_limb_t)) + \
(((mpc_imagref(MPC(self))->_mpfr_prec + mp_bits_per_limb - 1) / \
mp_bits_per_limb) * sizeof(mp_limb_t)));
}
gmpy2-2.1.0b3/src/gmpy2_mpc_misc.h 0000664 0001750 0001750 00000007766 13446330331 016537 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpc_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPC_MISC_H
#define GMPY_MPC_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Complex_Phase(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Phase(PyObject *self, PyObject *other);
#ifdef MPC_110
static PyObject * GMPy_Complex_Root_Of_Unity(PyObject *n, PyObject *k, CTXT_Object *context);
static PyObject * GMPy_Context_Root_Of_Unity(PyObject *self, PyObject *args);
#endif
static PyObject * GMPy_Complex_Norm(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Norm(PyObject *self, PyObject *other);
static PyObject * GMPy_Complex_Polar(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Polar(PyObject *self, PyObject *other);
static PyObject * GMPy_Complex_Rect(PyObject *r, PyObject *phi, CTXT_Object *context);
static PyObject * GMPy_Context_Rect(PyObject *self, PyObject *args);
static PyObject * GMPy_Complex_Proj(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Proj(PyObject *self, PyObject *other);
static PyObject * GMPy_MPC_Conjugate_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_GetPrec_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetRc_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetImag_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetReal_Attrib(MPC_Object *self, void *closure);
static int GMPy_MPC_NonZero_Slot(MPC_Object *self);
static PyObject * GMPy_MPC_SizeOf_Method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPC_Conjugate_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_GetPrec_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetRc_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetImag_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetReal_Attrib(MPC_Object *self, void *closure);
static int GMPy_MPC_NonZero_Slot(MPC_Object *self);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpfr.c 0000664 0001750 0001750 00000040364 13525427233 015701 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpfr.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* General purpose functions are defined here. They are used as an alternative
* to code bloat via macro overuse.
*/
static void
_GMPy_MPFR_Cleanup(MPFR_Object **v, CTXT_Object *ctext)
{
/* GMPY_MPFR_CHECK_RANGE(V, CTX) */
if (mpfr_regular_p((*v)->f) &&
(!(((*v)->f->_mpfr_exp >= ctext->ctx.emin) &&
((*v)->f->_mpfr_exp <= ctext->ctx.emax)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax); \
(*v)->rc = mpfr_check_range((*v)->f, (*v)->rc, GET_MPFR_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
/* GMPY_MPFR_SUBNORMALIZE(V, CTX) */
if (ctext->ctx.subnormalize &&
(*v)->f->_mpfr_exp >= ctext->ctx.emin &&
(*v)->f->_mpfr_exp <= ctext->ctx.emin + mpfr_get_prec((*v)->f) - 2) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
(*v)->rc = mpfr_subnormalize((*v)->f, (*v)->rc, GET_MPFR_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
/* GMPY_MPFR_EXCEPTIONS(V, CTX) */
ctext->ctx.underflow |= mpfr_underflow_p();
ctext->ctx.overflow |= mpfr_overflow_p();
ctext->ctx.invalid |= mpfr_nanflag_p();
ctext->ctx.inexact |= mpfr_inexflag_p();
ctext->ctx.divzero |= mpfr_divby0_p();
if (ctext->ctx.traps) {
if ((ctext->ctx.traps & TRAP_UNDERFLOW) && mpfr_underflow_p()) {
PyErr_SetString(GMPyExc_Underflow, "underflow");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_OVERFLOW) && mpfr_overflow_p()) {
PyErr_SetString(GMPyExc_Overflow, "overflow");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_INEXACT) && mpfr_inexflag_p()) {
PyErr_SetString(GMPyExc_Inexact, "inexact result");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_INVALID) && mpfr_nanflag_p()) {
PyErr_SetString(GMPyExc_Invalid, "invalid operation");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_DIVZERO) && mpfr_divby0_p()) {
PyErr_SetString(GMPyExc_DivZero, "division by zero");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
}
}
PyDoc_STRVAR(GMPy_doc_mpfr,
"mpfr() -> mpfr(0.0)\n\n"
" If no argument is given, return mpfr(0.0).\n\n"
"mpfr(n [, precision=0 [, context]]) -> mpfr\n\n"
" Return an 'mpfr' object after converting a numeric value. See\n"
" below for the interpretation of precision.\n\n"
"mpfr(s [, precision=0 [, base=0 [, context]]]) -> mpfr\n\n"
" Return a new 'mpfr' object by converting a string s made of\n"
" digits in the given base, possibly with fraction-part (with a\n"
" period as a separator) and/or exponent-part (with an exponent\n"
" marker 'e' for base<=10, else '@'). The base of the string\n"
" representation must be 0 or in the interval [2,62]. If the base\n"
" is 0, the leading digits of the string are used to identify the\n"
" base: 0b implies base=2, 0x implies base=16, otherwise base=10\n"
" is assumed.\n\n"
"Note: If a precision greater than or equal to 2 is specified, then it\n"
" is used.\n\n"
" A precision of 0 (the default) implies the precision of either\n"
" the specified context or the current context is used.\n\n"
" A precision of 1 minimizes the loss of precision by following\n"
" these rules:\n"
" 1) If n is a radix-2 floating point number, then the full\n"
" precision of n is retained.\n"
" 2) If n is an integer, then the precision is the bit length\n"
" of the integer.\n" );
#ifdef PY3
static PyNumberMethods mpfr_number_methods =
{
(binaryfunc) GMPy_MPFR_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPFR_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPFR_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPFR_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPFR_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPFR_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_MPFR_Minus_Slot, /* nb_negative */
(unaryfunc) GMPy_MPFR_Plus_Slot, /* nb_positive */
(unaryfunc) GMPy_MPFR_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_MPFR_NonZero_Slot, /* nb_bool */
0, /* nb_invert */
0, /* nb_lshift */
0, /* nb_rshift */
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
(unaryfunc) GMPy_MPFR_Int_Slot, /* nb_int */
0, /* nb_reserved */
(unaryfunc) GMPy_MPFR_Float_Slot, /* nb_float */
0, /* nb_inplace_add */
0, /* nb_inplace_subtract */
0, /* nb_inplace_multiply */
0, /* nb_inplace_remainder */
0, /* nb_inplace_power */
0, /* nb_inplace_lshift */
0, /* nb_inplace_rshift */
0, /* nb_inplace_and */
0, /* nb_inplace_xor */
0, /* nb_inplace_or */
(binaryfunc) GMPy_MPFR_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPFR_TrueDiv_Slot, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
0, /* nb_index */
};
#else
static PyNumberMethods mpfr_number_methods =
{
(binaryfunc) GMPy_MPFR_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPFR_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPFR_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPFR_TrueDiv_Slot, /* nb_divide */
(binaryfunc) GMPy_MPFR_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPFR_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPFR_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_MPFR_Minus_Slot, /* nb_negative */
(unaryfunc) GMPy_MPFR_Plus_Slot, /* nb_positive */
(unaryfunc) GMPy_MPFR_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_MPFR_NonZero_Slot, /* nb_bool */
0, /* nb_invert */
0, /* nb_lshift */
0, /* nb_rshift */
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
0, /* nb_coerce */
(unaryfunc) GMPy_MPFR_Int_Slot, /* nb_int */
(unaryfunc) GMPy_MPFR_Long_Slot, /* nb_long */
(unaryfunc) GMPy_MPFR_Float_Slot, /* nb_float */
0, /* nb_oct */
0, /* nb_hex */
0, /* nb_inplace_add */
0, /* nb_inplace_subtract */
0, /* nb_inplace_multiply */
0, /* nb_inplace_divide */
0, /* nb_inplace_remainder */
0, /* nb_inplace_power */
0, /* nb_inplace_lshift */
0, /* nb_inplace_rshift */
0, /* nb_inplace_and */
0, /* nb_inplace_xor */
0, /* nb_inplace_or */
(binaryfunc) GMPy_MPFR_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPFR_TrueDiv_Slot, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
};
#endif
static PyGetSetDef Pympfr_getseters[] =
{
{"precision", (getter)GMPy_MPFR_GetPrec_Attrib, NULL, "precision in bits", NULL},
{"rc", (getter)GMPy_MPFR_GetRc_Attrib, NULL, "return code", NULL},
{"imag", (getter)GMPy_MPFR_GetImag_Attrib, NULL, "imaginary component", NULL},
{"real", (getter)GMPy_MPFR_GetReal_Attrib, NULL, "real component", NULL},
{NULL}
};
static PyMethodDef Pympfr_methods [] =
{
{ "__ceil__", GMPy_MPFR_Method_Ceil, METH_NOARGS, GMPy_doc_mpfr_ceil_method },
{ "__floor__", GMPy_MPFR_Method_Floor, METH_NOARGS, GMPy_doc_mpfr_floor_method },
{ "__format__", GMPy_MPFR_Format, METH_VARARGS, GMPy_doc_mpfr_format },
{ "__round__", GMPy_MPFR_Method_Round10, METH_VARARGS, GMPy_doc_method_round10 },
{ "__sizeof__", GMPy_MPFR_SizeOf_Method, METH_NOARGS, GMPy_doc_mpfr_sizeof_method },
{ "__trunc__", GMPy_MPFR_Method_Trunc, METH_NOARGS, GMPy_doc_mpfr_trunc_method },
{ "as_integer_ratio", GMPy_MPFR_Integer_Ratio_Method, METH_NOARGS, GMPy_doc_method_integer_ratio },
{ "as_mantissa_exp", GMPy_MPFR_Mantissa_Exp_Method, METH_NOARGS, GMPy_doc_method_mantissa_exp },
{ "as_simple_fraction", (PyCFunction)GMPy_MPFR_Simple_Fraction_Method, METH_VARARGS | METH_KEYWORDS, GMPy_doc_method_simple_fraction },
{ "conjugate", GMPy_MP_Method_Conjugate, METH_NOARGS, GMPy_doc_mp_method_conjugate },
{ "digits", GMPy_MPFR_Digits_Method, METH_VARARGS, GMPy_doc_mpfr_digits_method },
{ "is_finite", GMPy_MPFR_Is_Finite_Method, METH_NOARGS, GMPy_doc_method_is_finite },
{ "is_infinite", GMPy_MPFR_Is_Infinite_Method, METH_NOARGS, GMPy_doc_method_is_infinite },
{ "is_integer", GMPy_MPFR_Is_Integer_Method, METH_NOARGS, GMPy_doc_method_is_integer },
{ "is_nan", GMPy_MPFR_Is_NAN_Method, METH_NOARGS, GMPy_doc_method_is_nan },
{ "is_signed", GMPy_MPFR_Is_Regular_Method, METH_NOARGS, GMPy_doc_method_is_regular },
{ "is_signed", GMPy_MPFR_Is_Signed_Method, METH_NOARGS, GMPy_doc_method_is_signed },
{ "is_zero", GMPy_MPFR_Is_Zero_Method, METH_NOARGS, GMPy_doc_method_is_zero },
{ NULL, NULL, 1 }
};
static PyTypeObject MPFR_Type =
{
/* PyObject_HEAD_INIT(&PyType_Type) */
#ifdef PY3
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyObject_HEAD_INIT(0)
0, /* ob_size */
#endif
"mpfr", /* tp_name */
sizeof(MPFR_Object), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor) GMPy_MPFR_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_MPFR_Repr_Slot, /* tp_repr */
&mpfr_number_methods, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc) GMPy_MPFR_Hash_Slot, /* tp_hash */
0, /* tp_call */
(reprfunc) GMPy_MPFR_Str_Slot, /* tp_str */
(getattrofunc) 0, /* tp_getattro */
(setattrofunc) 0, /* tp_setattro */
0, /* tp_as_buffer */
#ifdef PY3
Py_TPFLAGS_DEFAULT, /* tp_flags */
#else
Py_TPFLAGS_HAVE_RICHCOMPARE|Py_TPFLAGS_CHECKTYPES, /* tp_flags */
#endif
GMPy_doc_mpfr, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)&GMPy_RichCompare_Slot, /* tp_richcompare */
0, /* tp_weaklistoffset*/
0, /* tp_iter */
0, /* tp_iternext */
Pympfr_methods, /* tp_methods */
0, /* tp_members */
Pympfr_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
GMPy_MPFR_NewInit, /* tp_new */
0, /* tp_free */
};
gmpy2-2.1.0b3/src/gmpy2_mpfr.h 0000664 0001750 0001750 00000017750 13425752720 015712 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpfr.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* gmpy_mpfr C API extension header file.
*
* Provide interface to the MPFR (Multiple Precision Floating-point with
* Rounding) library.
*
* Version 2.00, April 2011 (created) casevh
*/
#ifndef GMPY_MPFR_H
#define GMPY_MPFR_H
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(FLT_RADIX) || (FLT_RADIX!=2)
# error "FLT_RADIX undefined or != 2, GMPY2 is confused. :("
#endif
#if defined(MS_WIN32) && defined(_MSC_VER)
# pragma comment(lib,"mpfr.lib")
#endif
#ifdef FAST
/* Very bad code ahead. I've copied portions of mpfr-impl.h and
* hacked them so they work. This code will only be enabled if you
* specify the --fast option.
*/
#define MPFR_THREAD_ATTR __thread
__MPFR_DECLSPEC extern MPFR_THREAD_ATTR unsigned int __gmpfr_flags;
__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emin;
__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emax;
/* Flags of __gmpfr_flags */
#define MPFR_FLAGS_UNDERFLOW 1
#define MPFR_FLAGS_OVERFLOW 2
#define MPFR_FLAGS_NAN 4
#define MPFR_FLAGS_INEXACT 8
#define MPFR_FLAGS_ERANGE 16
#define MPFR_FLAGS_DIVBY0 32
#define MPFR_FLAGS_ALL 63
/* Replace some common functions for direct access to the global vars */
#define mpfr_get_emin() (__gmpfr_emin + 0)
#define mpfr_get_emax() (__gmpfr_emax + 0)
#define mpfr_clear_flags() ((void) (__gmpfr_flags = 0))
#define mpfr_clear_underflow() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_UNDERFLOW))
#define mpfr_clear_overflow() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_OVERFLOW))
#define mpfr_clear_nanflag() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_NAN))
#define mpfr_clear_inexflag() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_INEXACT))
#define mpfr_clear_erangeflag() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE))
#define mpfr_clear_divby0() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_DIVBY0))
#define mpfr_underflow_p() ((int) (__gmpfr_flags & MPFR_FLAGS_UNDERFLOW))
#define mpfr_overflow_p() ((int) (__gmpfr_flags & MPFR_FLAGS_OVERFLOW))
#define mpfr_nanflag_p() ((int) (__gmpfr_flags & MPFR_FLAGS_NAN))
#define mpfr_inexflag_p() ((int) (__gmpfr_flags & MPFR_FLAGS_INEXACT))
#define mpfr_erangeflag_p() ((int) (__gmpfr_flags & MPFR_FLAGS_ERANGE))
#define mpfr_divby0_p() ((int) (__gmpfr_flags & MPFR_FLAGS_DIVBY0))
#define mpfr_check_range(x,t,r) \
((((x)->_mpfr_exp) >= __gmpfr_emin && ((x)->_mpfr_exp) <= __gmpfr_emax) \
? ((t) ? (__gmpfr_flags |= MPFR_FLAGS_INEXACT, (t)) : 0) \
: mpfr_check_range(x,t,r))
/* End of the really bad code. Hopefully.
*/
#endif
static PyTypeObject MPFR_Type;
#define MPFR_Check(v) (((PyObject*)v)->ob_type == &MPFR_Type)
#define GMPY_DIVZERO(msg) PyErr_SetString(GMPyExc_DivZero, msg)
#define GMPY_INEXACT(msg) PyErr_SetString(GMPyExc_Inexact, msg)
#define GMPY_INVALID(msg) PyErr_SetString(GMPyExc_Invalid, msg)
#define GMPY_OVERFLOW(msg) PyErr_SetString(GMPyExc_Overflow, msg)
#define GMPY_UNDERFLOW(msg) PyErr_SetString(GMPyExc_Underflow, msg)
#define GMPY_ERANGE(msg) PyErr_SetString(GMPyExc_Erange, msg)
#define GMPY_MPFR_CHECK_RANGE(V, CTX) \
if (mpfr_regular_p(V->f) && \
(!((V->f->_mpfr_exp >= CTX->ctx.emin) && \
(V->f->_mpfr_exp <= CTX->ctx.emax)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
V->rc = mpfr_check_range(V->f, V->rc, GET_MPFR_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
}
#define GMPY_MPFR_SUBNORMALIZE(V, CTX) \
if (CTX->ctx.subnormalize && \
V->f->_mpfr_exp >= CTX->ctx.emin && \
V->f->_mpfr_exp <= CTX->ctx.emin + mpfr_get_prec(V->f) - 2) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
V->rc = mpfr_subnormalize(V->f, V->rc, GET_MPFR_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
}
/* Exceptions should be checked in order of least important to most important.
*/
#define GMPY_MPFR_EXCEPTIONS(V, CTX) \
CTX->ctx.underflow |= mpfr_underflow_p(); \
CTX->ctx.overflow |= mpfr_overflow_p(); \
CTX->ctx.invalid |= mpfr_nanflag_p(); \
CTX->ctx.inexact |= mpfr_inexflag_p(); \
CTX->ctx.divzero |= mpfr_divby0_p(); \
if (CTX->ctx.traps) { \
if ((CTX->ctx.traps & TRAP_UNDERFLOW) && mpfr_underflow_p()) { \
GMPY_UNDERFLOW("underflow"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_OVERFLOW) && mpfr_overflow_p()) { \
GMPY_OVERFLOW("overflow"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_INEXACT) && mpfr_inexflag_p()) { \
GMPY_INEXACT("inexact result"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_INVALID) && mpfr_nanflag_p()) { \
GMPY_INVALID("invalid operation"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_DIVZERO) && mpfr_divby0_p()) { \
GMPY_DIVZERO("division by zero"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
}
#define GMPY_MPFR_CLEANUP(V, CTX) \
GMPY_MPFR_CHECK_RANGE(V, CTX); \
GMPY_MPFR_SUBNORMALIZE(V, CTX); \
GMPY_MPFR_EXCEPTIONS(V, CTX);
#define GMPY_CHECK_ERANGE(V, CTX, MSG) \
CTX->ctx.erange |= mpfr_erangeflag_p(); \
if (CTX->ctx.traps) { \
if ((CTX->ctx.traps & TRAP_ERANGE) && mpfr_erangeflag_p()) { \
GMPY_ERANGE(MSG); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
} \
static void _GMPy_MPFR_Cleanup(MPFR_Object **v, CTXT_Object *ctext);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpfr_misc.c 0000664 0001750 0001750 00000052162 13444071152 016706 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpfr_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_function_f2q,
"f2q(x,[err]) -> mpq\n\n"
"Return the 'best' mpq approximating x to within relative error 'err'.\n"
"Default is the precision of x. Uses Stern-Brocot tree to find the\n"
"'best' approximation. An 'mpz' is returned if the the denominator\n"
"is 1. If 'err'<0, relative error is 2.0 ** err.");
static PyObject *
GMPy_Real_F2Q(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *tempx, *tempy = NULL;
PyObject *result;
CHECK_CONTEXT(context);
if (y) {
if (!(tempy = GMPy_MPFR_From_Real(y, 1, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
}
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
/* See gmpy2_convert_mpfr for stern_brocot(). */
result = stern_brocot(tempx, tempy, 0, 1, context);
Py_DECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return result;
}
static PyObject *
GMPy_Number_F2Q(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && (!y || IS_REAL(y)))
return GMPy_Real_F2Q(x, y, context);
TYPE_ERROR("f2q() argument types not supported");
return NULL;
}
static PyObject *
GMPy_Context_F2Q(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) < 1 || PyTuple_GET_SIZE(args) > 2) {
TYPE_ERROR("f2q() requires 1 or 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
/* LCOV_EXCL_START */
context = (CTXT_Object*)self;
/* LCOV_EXCL_STOP */
}
else {
CHECK_CONTEXT(context);
}
if (PyTuple_GET_SIZE(args) == 1) {
return GMPy_Number_F2Q(PyTuple_GET_ITEM(args, 0), NULL, context);
}
else {
return GMPy_Number_F2Q(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}
}
PyDoc_STRVAR(GMPy_doc_mpfr_free_cache,
"free_cache()\n\n"
"Free the internal cache of constants maintained by MPFR.");
static PyObject *
GMPy_MPFR_Free_Cache(PyObject *self, PyObject *args)
{
mpfr_free_cache();
Py_RETURN_NONE;
}
PyDoc_STRVAR(GMPy_doc_mpfr_can_round,
"can_round(b, err, rnd1, rnd2, prec)\n\n"
"Let b be an approximation to an unknown number x that is rounded\n"
"according to rnd1. Assume the b has an error at most two to the power\n"
"of E(b)-err where E(b) is the exponent of b. Then return true if x\n"
"can be rounded correctly to prec bits with rounding mode rnd2.");
static PyObject *
GMPy_MPFR_Can_Round(PyObject *self, PyObject *args)
{
int rnd1, rnd2;
long err, prec;
PyObject *b;
if (!PyArg_ParseTuple(args, "O!liil", &MPFR_Type, &b, &err, &rnd1, &rnd2, &prec)) {
return NULL;
}
if (!(rnd1 == MPFR_RNDN || rnd1 == MPFR_RNDZ ||
rnd1 == MPFR_RNDU || rnd1 == MPFR_RNDD ||
rnd1 == MPFR_RNDA)) {
VALUE_ERROR("invalid value for rounding mode");
return NULL;
}
if (!(rnd2 == MPFR_RNDN || rnd2 == MPFR_RNDZ ||
rnd2 == MPFR_RNDU || rnd2 == MPFR_RNDD ||
rnd2 == MPFR_RNDA)) {
VALUE_ERROR("invalid value for rounding mode");
return NULL;
}
if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return NULL;
}
if (mpfr_can_round(MPFR(b), err, rnd1, rnd2, prec))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpfr_get_emin_min,
"get_emin_min() -> integer\n\n"
"Return the minimum possible exponent that can be set for 'mpfr'.");
static PyObject *
GMPy_MPFR_get_emin_min(PyObject *self, PyObject *args)
{
return PyIntOrLong_FromSsize_t((Py_ssize_t)mpfr_get_emin_min());
}
PyDoc_STRVAR(GMPy_doc_mpfr_get_emax_max,
"get_emax_max() -> integer\n\n"
"Return the maximum possible exponent that can be set for 'mpfr'.");
static PyObject *
GMPy_MPFR_get_emax_max(PyObject *self, PyObject *args)
{
return PyIntOrLong_FromSsize_t((Py_ssize_t)mpfr_get_emax_max());
}
PyDoc_STRVAR(GMPy_doc_mpfr_get_max_precision,
"get_max_precision() -> integer\n\n"
"Return the maximum bits of precision that can be used for calculations.\n"
"Note: to allow extra precision for intermediate calculations, avoid\n"
"setting precision close the maximum precision.");
static PyObject *
GMPy_MPFR_get_max_precision(PyObject *self, PyObject *args)
{
return PyIntOrLong_FromSsize_t((Py_ssize_t)MPFR_PREC_MAX);
}
PyDoc_STRVAR(GMPy_doc_mpfr_get_exp,
"get_exp(mpfr) -> integer\n\n"
"Return the exponent of an mpfr. Returns 0 for NaN or Infinity and\n"
"sets the erange flag and will raise an exception if trap_erange\n"
"is set.");
static PyObject *
GMPy_MPFR_get_exp(PyObject *self, PyObject *other)
{
PyObject *result = NULL;
Py_ssize_t exp;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(MPFR_Check(other))) {
TYPE_ERROR("get_exp() requires 'mpfr' argument");
return NULL;
}
if (mpfr_regular_p(MPFR(other))) {
exp = (Py_ssize_t)mpfr_get_exp(MPFR(other));
result = PyIntOrLong_FromSsize_t(exp);
}
else if (mpfr_zero_p(MPFR(other))) {
result = PyIntOrLong_FromSsize_t(0);
}
else {
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("Can not get exponent from NaN or Infinity.");
}
else {
result = PyIntOrLong_FromSsize_t(0);
}
}
return result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_exp,
"set_exp(mpfr, n) -> mpfr\n\n"
"Set the exponent of an mpfr to n. If n is outside the range of\n"
"valid exponents, set_exp() will set the erange flag and either\n"
"return the original value or raise an exception if trap_erange\n"
"is set.");
static PyObject *
GMPy_MPFR_set_exp(PyObject *self, PyObject *args)
{
MPFR_Object *result;
PyObject *temp;
mpfr_exp_t _oldemin, _oldemax, exp;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2 ||
!MPFR_Check(PyTuple_GET_ITEM(args, 0)) ||
!PyIntOrLong_Check(PyTuple_GET_ITEM(args, 1))) {
TYPE_ERROR("set_exp() requires 'mpfr', 'integer' arguments");
return NULL;
}
temp = PyTuple_GET_ITEM(args, 0);
exp = (mpfr_exp_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(args, 1));
if (exp == -1 && PyErr_Occurred()) {
VALUE_ERROR("exponent too large");
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(MPFR(temp)), context))) {
return NULL;
}
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(context->ctx.emin);
mpfr_set_emax(context->ctx.emax);
mpfr_set(MPFR(result), MPFR(temp), GET_MPFR_ROUND(context));
result->rc = mpfr_set_exp(MPFR(result), exp);
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
if (result->rc) {
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("new exponent is out-of-bounds");
Py_DECREF((PyObject*)result);
return NULL;
}
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_sign,
"set_sign(mpfr, bool) -> mpfr\n\n"
"If 'bool' is True, then return an 'mpfr' with the sign bit set.");
static PyObject *
GMPy_MPFR_set_sign(PyObject *self, PyObject *args)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2 ||
!MPFR_Check(PyTuple_GET_ITEM(args, 0)) ||
!PyIntOrLong_Check(PyTuple_GET_ITEM(args, 1))) {
TYPE_ERROR("set_sign() requires 'mpfr', 'boolean' arguments");
return NULL;
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
result->rc = mpfr_setsign(MPFR(result), MPFR(PyTuple_GET_ITEM(args, 0)),
PyObject_IsTrue(PyTuple_GET_ITEM(args, 1)),
GET_MPFR_ROUND(context));
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_copy_sign,
"copy_sign(mpfr, mpfr) -> mpfr\n\n"
"Return an 'mpfr' composed of the first argument with the sign of the\n"
"second argument.");
static PyObject *
GMPy_MPFR_copy_sign(PyObject *self, PyObject *args)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2 ||
!MPFR_Check(PyTuple_GET_ITEM(args, 0)) ||
!MPFR_Check(PyTuple_GET_ITEM(args, 1))) {
TYPE_ERROR("copy_sign() requires 'mpfr', 'mpfr' arguments");
return NULL;
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
result->rc = mpfr_copysign(MPFR(result), MPFR(PyTuple_GET_ITEM(args, 0)),
MPFR(PyTuple_GET_ITEM(args, 1)),
GET_MPFR_ROUND(context));
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_nan,
"nan() -> mpfr\n\n"
"Return an 'mpfr' initialized to NaN (Not-A-Number).");
static PyObject *
GMPy_MPFR_set_nan(PyObject *self, PyObject *other)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_set_nan(result->f);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_inf,
"inf(n) -> mpfr\n\n"
"Return an 'mpfr' initialized to Infinity with the same sign as n.\n"
"If n is not given, +Infinity is returned.");
static PyObject *
GMPy_MPFR_set_inf(PyObject *self, PyObject *args)
{
MPFR_Object *result;
long s = 1;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_Size(args) == 1) {
s = c_long_From_Integer(PyTuple_GET_ITEM(args, 0));
if (s == -1 && PyErr_Occurred()) {
return NULL;
}
}
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_set_inf(result->f, s < 0 ? -1 : 1);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_zero,
"zero(n) -> mpfr\n\n"
"Return an 'mpfr' inialized to 0.0 with the same sign as n.\n"
"If n is not given, +0.0 is returned.");
static PyObject *
GMPy_MPFR_set_zero(PyObject *self, PyObject *args)
{
MPFR_Object *result;
long s = 1;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_Size(args) == 1) {
s = c_long_From_Integer(PyTuple_GET_ITEM(args, 0));
if (s == -1 && PyErr_Occurred()) {
return NULL;
}
}
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_set_zero(result->f, s < 0 ? -1 : 1);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_method_integer_ratio,
"x.as_integer_ratio() -> (num, den)\n\n"
"Return the exact rational equivalent of an mpfr. Value is a tuple\n"
"for compatibility with Python's float.as_integer_ratio().");
/* Note: almost identical code exists in gmpy2_convert_mpfr.c as the
* function GMPy_MPQ_From_MPFR. They should be refactored.
*/
static PyObject *
GMPy_MPFR_Integer_Ratio_Method(PyObject *self, PyObject *args)
{
MPZ_Object *num, *den;
mpfr_exp_t temp, twocount;
PyObject *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (mpfr_nan_p(MPFR(self))) {
VALUE_ERROR("Cannot pass NaN to mpfr.as_integer_ratio.");
return NULL;
}
if (mpfr_inf_p(MPFR(self))) {
OVERFLOW_ERROR("Cannot pass Infinity to mpfr.as_integer_ratio.");
return NULL;
}
num = GMPy_MPZ_New(context);
den = GMPy_MPZ_New(context);
if (!num || !den) {
Py_XDECREF((PyObject*)num);
Py_XDECREF((PyObject*)den);
return NULL;
}
if (mpfr_zero_p(MPFR(self))) {
mpz_set_ui(num->z, 0);
mpz_set_ui(den->z, 1);
}
else {
temp = mpfr_get_z_2exp(num->z, MPFR(self));
twocount = (mpfr_exp_t)mpz_scan1(num->z, 0);
if (twocount) {
temp += twocount;
mpz_div_2exp(num->z, num->z, twocount);
}
mpz_set_ui(den->z, 1);
if (temp > 0)
mpz_mul_2exp(num->z, num->z, temp);
else if (temp < 0)
mpz_mul_2exp(den->z, den->z, -temp);
}
result = Py_BuildValue("(NN)", (PyObject*)num, (PyObject*)den);
if (!result) {
Py_DECREF((PyObject*)num);
Py_DECREF((PyObject*)den);
}
return result;
}
PyDoc_STRVAR(GMPy_doc_method_mantissa_exp,
"x.as_mantissa_exp() -> (mantissa,exponent)\n\n"
"Return the mantissa and exponent of an mpfr.");
static PyObject *
GMPy_MPFR_Mantissa_Exp_Method(PyObject *self, PyObject *args)
{
MPZ_Object *mantissa , *exponent;
mpfr_exp_t temp;
PyObject *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (mpfr_nan_p(MPFR(self))) {
VALUE_ERROR("Cannot pass NaN to mpfr.as_mantissa_exp.");
return NULL;
}
if (mpfr_inf_p(MPFR(self))) {
OVERFLOW_ERROR("Cannot pass Infinity to mpfr.as_mantissa_exp.");
return NULL;
}
mantissa = GMPy_MPZ_New(context);
exponent = GMPy_MPZ_New(context);
if (!mantissa || !exponent) {
Py_XDECREF((PyObject*)mantissa);
Py_XDECREF((PyObject*)exponent);
return NULL;
}
if (mpfr_zero_p(MPFR(self))) {
mpz_set_ui(mantissa->z, 0);
mpz_set_ui(exponent->z, 1);
}
else {
temp = mpfr_get_z_2exp(mantissa->z, MPFR(self));
mpz_set_si(exponent->z, temp);
}
result = Py_BuildValue("(NN)", (PyObject*)mantissa, (PyObject*)exponent);
if (!result) {
Py_DECREF((PyObject*)mantissa);
Py_DECREF((PyObject*)exponent);
}
return result;
}
PyDoc_STRVAR(GMPy_doc_method_simple_fraction,
"x.as_simple_fraction([precision=0]) -> mpq\n\n"
"Return a simple rational approximation to x. The result will be\n"
"accurate to 'precision' bits. If 'precision' is 0, the precision\n"
"of 'x' will be used.");
static PyObject *
GMPy_MPFR_Simple_Fraction_Method(PyObject *self, PyObject *args, PyObject *keywds)
{
mpfr_prec_t prec = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &prec)) {
return NULL;
}
return (PyObject*)stern_brocot((MPFR_Object*)self, 0, prec, 0, context);
}
/* Implement the .precision attribute of an mpfr. */
static PyObject *
GMPy_MPFR_GetPrec_Attrib(MPFR_Object *self, void *closure)
{
return PyIntOrLong_FromSsize_t((Py_ssize_t)mpfr_get_prec(self->f));
}
/* Implement the .rc attribute of an mpfr. */
static PyObject *
GMPy_MPFR_GetRc_Attrib(MPFR_Object *self, void *closure)
{
return PyIntOrLong_FromLong((long)self->rc);
}
/* Implement the .imag attribute of an mpfr. */
static PyObject *
GMPy_MPFR_GetImag_Attrib(MPFR_Object *self, void *closure)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(0, context)))
mpfr_set_zero(result->f, 1);
return (PyObject*)result;
}
/* Implement the .real attribute of an mpfr. */
static PyObject *
GMPy_MPFR_GetReal_Attrib(MPFR_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
/* Implement the nb_bool slot. */
static int
GMPy_MPFR_NonZero_Slot(MPFR_Object *self)
{
return !mpfr_zero_p(self->f);
}
PyDoc_STRVAR(GMPy_doc_function_check_range,
"check_range(x) -> mpfr\n\n"
"Return a new 'mpfr' with exponent that lies within the current range\n"
"of emin and emax.");
PyDoc_STRVAR(GMPy_doc_context_check_range,
"context.check_range(x) -> mpfr\n\n"
"Return a new 'mpfr' with exponent that lies within the range of emin\n"
"and emax specified by context.");
static PyObject *
GMPy_MPFR_CheckRange(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(mpfr_get_prec(MPFR(x)), context))) {
mpfr_set(result->f, MPFR(x), GET_MPFR_ROUND(context));
mpfr_clear_flags();
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
static PyObject *
GMPy_Number_CheckRange(PyObject *x, CTXT_Object *context)
{
if (MPFR_Check(x))
return GMPy_MPFR_CheckRange(x, context);
TYPE_ERROR("check_range() argument types not supported");
return NULL;
}
static PyObject *
GMPy_Context_CheckRange(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_CheckRange(other, context);
}
PyDoc_STRVAR(GMPy_doc_mpfr_sizeof_method,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x.");
static PyObject *
GMPy_MPFR_SizeOf_Method(PyObject *self, PyObject *other)
{
return PyIntOrLong_FromSize_t(sizeof(MPFR_Object) + \
(((MPFR(self))->_mpfr_prec + mp_bits_per_limb - 1) / \
mp_bits_per_limb) * sizeof(mp_limb_t));
}
PyDoc_STRVAR(GMPy_doc_method_round10,
"__round__(x[, n = 0]) -> mpfr\n\n"
"Return x rounded to n decimal digits before (n < 0) or after (n > 0)\n"
"the decimal point. Rounds to an integer if n is not specified.");
static PyObject *
GMPy_MPFR_Method_Round10(PyObject *self, PyObject *args)
{
long digits = 0;
mpz_t temp;
MPFR_Object *resultf = 0;
MPZ_Object *resultz;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
/* If the size of args is 0, we just return an mpz. */
if (PyTuple_GET_SIZE(args) == 0) {
if ((resultz = GMPy_MPZ_New(context))) {
if (mpfr_nan_p(MPFR(self))) {
Py_DECREF((PyObject*)resultz);
VALUE_ERROR("'mpz' does not support NaN");
return NULL;
}
if (mpfr_inf_p(MPFR(self))) {
Py_DECREF((PyObject*)resultz);
OVERFLOW_ERROR("'mpz' does not support Infinity");
return NULL;
}
/* return code is ignored */
mpfr_get_z(resultz->z, MPFR(self), MPFR_RNDN);
}
return (PyObject*)resultz;
}
/* Now we need to return an mpfr, so handle the simple cases. */
if (!mpfr_regular_p(MPFR(self))) {
Py_INCREF(self);
return self;
}
if (PyTuple_GET_SIZE(args) > 1) {
TYPE_ERROR("__round__() requires 0 or 1 argument");
return NULL;
}
if (PyTuple_GET_SIZE(args) == 1) {
digits = PyIntOrLong_AsLong(PyTuple_GET_ITEM(args, 0));
if (digits == -1 && PyErr_Occurred()) {
TYPE_ERROR("__round__() requires 'int' argument");
return NULL;
}
}
/* TODO: better error analysis, or else convert the mpfr to an exact
* fraction, round the fraction, and then convert back to an mpfr.
*/
if (!(resultf = GMPy_MPFR_New(mpfr_get_prec(MPFR(self))+100, context))) {
return NULL;
}
mpz_init(temp);
mpz_ui_pow_ui(temp, 10, digits > 0 ? digits : -digits);
if (digits >= 0) {
mpfr_mul_z(resultf->f, MPFR(self), temp, MPFR_RNDN);
}
else {
mpfr_div_z(resultf->f, MPFR(self), temp, MPFR_RNDN);
}
mpfr_rint(resultf->f, resultf->f, MPFR_RNDN);
if (digits >= 0) {
mpfr_div_z(resultf->f, resultf->f, temp, MPFR_RNDN);
}
else {
mpfr_mul_z(resultf->f, resultf->f, temp, MPFR_RNDN);
}
mpfr_prec_round(resultf->f, mpfr_get_prec(MPFR(self)), MPFR_RNDN);
mpz_clear(temp);
return((PyObject*)resultf);
}
gmpy2-2.1.0b3/src/gmpy2_mpfr_misc.h 0000664 0001750 0001750 00000007776 13444071152 016726 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpfr_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPFR_MISC_H
#define GMPY_MPFR_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Real_F2Q(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_MPFR_Free_Cache(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Can_Round(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_get_emax_max(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_get_max_precision(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_get_exp(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_set_exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_set_sign(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_copy_sign(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Integer_Ratio_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Mantissa_Exp_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Simple_Fraction_Method(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_MPFR_set_nan(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_set_inf(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_set_zero(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_GetPrec_Attrib(MPFR_Object *self, void *closure);
static PyObject * GMPy_MPFR_GetRc_Attrib(MPFR_Object *self, void *closure);
static PyObject * GMPy_MPFR_GetImag_Attrib(MPFR_Object *self, void *closure);
static PyObject * GMPy_MPFR_GetReal_Attrib(MPFR_Object *self, void *closure);
static int GMPy_MPFR_NonZero_Slot(MPFR_Object *self);
static PyObject * GMPy_MPFR_SizeOf_Method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_CheckRange(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_CheckRange(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_CheckRange(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_Method_Round10(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpmath.c 0000664 0001750 0001750 00000031144 13425752764 016230 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpmath.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Internal helper function for mpmath. */
static PyObject *
mpmath_build_mpf(long sign, MPZ_Object *man, PyObject *exp, mp_bitcnt_t bc)
{
PyObject *tup, *tsign, *tbc;
if (!(tup = PyTuple_New(4))) {
Py_DECREF((PyObject*)man);
Py_DECREF(exp);
return NULL;
}
if (!(tsign = PyIntOrLong_FromLong(sign))) {
Py_DECREF((PyObject*)man);
Py_DECREF(exp);
Py_DECREF(tup);
return NULL;
}
if (!(tbc = PyIntOrLong_FromMpBitCnt(bc))) {
Py_DECREF((PyObject*)man);
Py_DECREF(exp);
Py_DECREF(tup);
Py_DECREF(tsign);
return NULL;
}
PyTuple_SET_ITEM(tup, 0, tsign);
PyTuple_SET_ITEM(tup, 1, (PyObject*)man);
PyTuple_SET_ITEM(tup, 2, (exp)?exp:PyIntOrLong_FromLong(0));
PyTuple_SET_ITEM(tup, 3, tbc);
return tup;
}
PyDoc_STRVAR(doc_mpmath_normalizeg,
"_mpmath_normalize(...): helper function for mpmath.");
static PyObject *
Pympz_mpmath_normalize(PyObject *self, PyObject *args)
{
long sign = 0;
mp_bitcnt_t zbits, bc = 0, prec = 0, shift;
long carry = 0;
PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0, *rndstr = 0;
MPZ_Object *man = 0, *upper = 0, *lower = 0;
char rnd = 0;
int err1, err2, err3;
if (PyTuple_GET_SIZE(args) == 6) {
/* Need better error-checking here. Under Python 3.0, overflow into
C-long is possible. */
sign = GMPy_Integer_AsLongAndError(PyTuple_GET_ITEM(args, 0), &err1);
man = (MPZ_Object*)PyTuple_GET_ITEM(args, 1);
exp = PyTuple_GET_ITEM(args, 2);
bc = GMPy_Integer_AsMpBitCntAndError(PyTuple_GET_ITEM(args, 3), &err2);
prec = GMPy_Integer_AsMpBitCntAndError(PyTuple_GET_ITEM(args, 4), &err3);
rndstr = PyTuple_GET_ITEM(args, 5);
if (err1 || err2 || err3) {
TYPE_ERROR("arguments long, MPZ_Object*, PyObject*, long, long, char needed");
return NULL;
}
}
else {
TYPE_ERROR("6 arguments required");
return NULL;
}
if (!MPZ_Check(man)) {
/* Try to convert to an mpz... */
if (!(man = GMPy_MPZ_From_Integer((PyObject*)man, NULL))) {
TYPE_ERROR("argument is not an mpz");
return NULL;
}
}
/* If rndstr really is a string, extract the first character. */
if (Py2or3String_Check(rndstr)) {
rnd = Py2or3String_AsString(rndstr)[0];
}
else {
VALUE_ERROR("invalid rounding mode specified");
return NULL;
}
/* If the mantissa is 0, return the normalized representation. */
if (!mpz_sgn(man->z)) {
Py_INCREF((PyObject*)man);
return mpmath_build_mpf(0, man, 0, 0);
}
/* if bc <= prec and the number is odd return it */
if ((bc <= prec) && mpz_odd_p(man->z)) {
Py_INCREF((PyObject*)man);
Py_INCREF((PyObject*)exp);
return mpmath_build_mpf(sign, man, exp, bc);
}
if (!(upper = GMPy_MPZ_New(NULL)) || !(lower = GMPy_MPZ_New(NULL))) {
Py_XDECREF((PyObject*)upper);
Py_XDECREF((PyObject*)lower);
}
if (bc > prec) {
shift = bc - prec;
switch (rnd) {
case 'f':
if(sign) {
mpz_cdiv_q_2exp(upper->z, man->z, shift);
}
else {
mpz_fdiv_q_2exp(upper->z, man->z, shift);
}
break;
case 'c':
if(sign) {
mpz_fdiv_q_2exp(upper->z, man->z, shift);
}
else {
mpz_cdiv_q_2exp(upper->z, man->z, shift);
}
break;
case 'd':
mpz_fdiv_q_2exp(upper->z, man->z, shift);
break;
case 'u':
mpz_cdiv_q_2exp(upper->z, man->z, shift);
break;
case 'n':
default:
mpz_tdiv_r_2exp(lower->z, man->z, shift);
mpz_tdiv_q_2exp(upper->z, man->z, shift);
if (mpz_sgn(lower->z)) {
/* lower is not 0 so it must have at least 1 bit set */
if (mpz_sizeinbase(lower->z, 2) == shift) {
/* lower is >= 1/2 */
if (mpz_scan1(lower->z, 0) == shift-1) {
/* lower is exactly 1/2 */
if (mpz_odd_p(upper->z))
carry = 1;
}
else {
carry = 1;
}
}
}
if (carry)
mpz_add_ui(upper->z, upper->z, 1);
}
if (!(tmp = PyIntOrLong_FromMpBitCnt(shift))) {
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
return NULL;
}
if (!(newexp = PyNumber_Add(exp, tmp))) {
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
return NULL;
}
Py_DECREF(tmp);
bc = prec;
}
else {
mpz_set(upper->z, man->z);
newexp = exp;
Py_INCREF(newexp);
}
/* Strip trailing 0 bits. */
if ((zbits = mpz_scan1(upper->z, 0)))
mpz_tdiv_q_2exp(upper->z, upper->z, zbits);
if (!(tmp = PyIntOrLong_FromMpBitCnt(zbits))) {
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(newexp);
return NULL;
}
if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
Py_DECREF(newexp);
return NULL;
}
Py_DECREF(newexp);
Py_DECREF(tmp);
bc -= zbits;
/* Check if one less than a power of 2 was rounded up. */
if (!mpz_cmp_ui(upper->z, 1))
bc = 1;
Py_DECREF((PyObject*)lower);
return mpmath_build_mpf(sign, upper, newexp2, bc);
}
PyDoc_STRVAR(doc_mpmath_createg,
"_mpmath_create(...): helper function for mpmath.");
static PyObject *
Pympz_mpmath_create(PyObject *self, PyObject *args)
{
long sign;
mp_bitcnt_t zbits, bc = 0, prec = 0, shift;
long carry = 0;
PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0;
MPZ_Object *man = 0, *upper = 0, *lower = 0;
int error;
const char *rnd = "f";
if (PyTuple_GET_SIZE(args) < 2) {
TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments");
return NULL;
}
switch (PyTuple_GET_SIZE(args)) {
case 4:
rnd = Py2or3String_AsString(PyTuple_GET_ITEM(args, 3));
case 3:
prec = GMPy_Integer_AsMpBitCntAndError(PyTuple_GET_ITEM(args, 2), &error);
if (error)
return NULL;
case 2:
exp = PyTuple_GET_ITEM(args, 1);
case 1:
man = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
if (!man) {
TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments");
return NULL;
}
}
/* If the mantissa is 0, return the normalized representation. */
if (!mpz_sgn(man->z)) {
return mpmath_build_mpf(0, man, 0, 0);
}
upper = GMPy_MPZ_New(NULL);
lower = GMPy_MPZ_New(NULL);
if (!upper || !lower) {
Py_DECREF((PyObject*)man);
Py_XDECREF((PyObject*)upper);
Py_XDECREF((PyObject*)lower);
return NULL;
}
/* Extract sign, make man positive, and set bit count */
sign = (mpz_sgn(man->z) == -1);
mpz_abs(upper->z, man->z);
bc = mpz_sizeinbase(upper->z, 2);
if (!prec) {
prec = bc;
}
if (bc > prec) {
shift = bc - prec;
switch (rnd[0]) {
case 'f':
if (sign) {
mpz_cdiv_q_2exp(upper->z, upper->z, shift);
}
else {
mpz_fdiv_q_2exp(upper->z, upper->z, shift);
}
break;
case 'c':
if (sign) {
mpz_fdiv_q_2exp(upper->z, upper->z, shift);
}
else {
mpz_cdiv_q_2exp(upper->z, upper->z, shift);
}
break;
case 'd':
mpz_fdiv_q_2exp(upper->z, upper->z, shift);
break;
case 'u':
mpz_cdiv_q_2exp(upper->z, upper->z, shift);
break;
case 'n':
default:
mpz_tdiv_r_2exp(lower->z, upper->z, shift);
mpz_tdiv_q_2exp(upper->z, upper->z, shift);
if (mpz_sgn(lower->z)) {
/* lower is not 0 so it must have at least 1 bit set */
if (mpz_sizeinbase(lower->z, 2)==shift) {
/* lower is >= 1/2 */
if (mpz_scan1(lower->z, 0)==shift-1) {
/* lower is exactly 1/2 */
if (mpz_odd_p(upper->z))
carry = 1;
}
else {
carry = 1;
}
}
}
if (carry) {
mpz_add_ui(upper->z, upper->z, 1);
}
}
if (!(tmp = PyIntOrLong_FromMpBitCnt(shift))) {
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
return NULL;
}
if (!(newexp = PyNumber_Add(exp, tmp))) {
Py_DECREF((PyObject*)man);
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
return NULL;
}
Py_DECREF(tmp);
bc = prec;
}
else {
newexp = exp;
Py_INCREF(newexp);
}
/* Strip trailing 0 bits. */
if ((zbits = mpz_scan1(upper->z, 0)))
mpz_tdiv_q_2exp(upper->z, upper->z, zbits);
if (!(tmp = PyIntOrLong_FromMpBitCnt(zbits))) {
Py_DECREF((PyObject*)man);
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(newexp);
return NULL;
}
if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
Py_DECREF((PyObject*)man);
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
Py_DECREF(newexp);
return NULL;
}
Py_DECREF(newexp);
Py_DECREF(tmp);
bc -= zbits;
/* Check if one less than a power of 2 was rounded up. */
if (!mpz_cmp_ui(upper->z, 1))
bc = 1;
Py_DECREF((PyObject*)lower);
Py_DECREF((PyObject*)man);
return mpmath_build_mpf(sign, upper, newexp2, bc);
}
gmpy2-2.1.0b3/src/gmpy2_mpq.c 0000664 0001750 0001750 00000030040 13444071152 015513 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpq.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_mpq,
"mpq() -> mpq(0,1)\n\n"
" If no argument is given, return mpq(0,1).\n\n"
"mpq(n) -> mpq\n\n"
" Return an 'mpq' object with a numeric value n. Fraction values\n"
" are converted exactly.\n\n"
"mpq(n,m) -> mpq\n\n"
" Return an 'mpq' object with a numeric value n/m.\n\n"
"mpq(s[, base=10]) -> mpq\n\n"
" Return an 'mpq' object from a string s made up of digits in\n"
" the given base. s may be made up of two numbers in the same\n"
" base separated by a '/' character.\n");
/* Since `gmpy2.mpq` is now a type and no longer a factory function, see
* gmpy2_cache.c/GMPy_MPQ_NewInit for details on creation.
*/
#ifdef PY3
static PyNumberMethods mpq_number_methods =
{
(binaryfunc) GMPy_MPQ_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPQ_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPQ_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPQ_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPQ_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPANY_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_MPQ_Minus_Slot, /* nb_negative */
(unaryfunc) GMPy_MPQ_Plus_Slot, /* nb_positive */
(unaryfunc) GMPy_MPQ_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_MPQ_NonZero_Slot, /* nb_bool */
0, /* nb_invert */
0, /* nb_lshift */
0, /* nb_rshift */
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
(unaryfunc) GMPy_MPQ_Int_Slot, /* nb_int */
0, /* nb_reserved */
(unaryfunc) GMPy_MPQ_Float_Slot, /* nb_float */
0, /* nb_inplace_add */
0, /* nb_inplace_subtract */
0, /* nb_inplace_multiply */
0, /* nb_inplace_remainder */
0, /* nb_inplace_power */
0, /* nb_inplace_lshift */
0, /* nb_inplace_rshift */
0, /* nb_inplace_and */
0, /* nb_inplace_xor */
0, /* nb_inplace_or */
(binaryfunc) GMPy_MPQ_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPQ_TrueDiv_Slot, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
0, /* nb_index */
};
#else
static PyNumberMethods mpq_number_methods =
{
(binaryfunc) GMPy_MPQ_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPQ_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPQ_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPQ_TrueDiv_Slot, /* nb_divide */
(binaryfunc) GMPy_MPQ_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPQ_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPANY_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_MPQ_Minus_Slot, /* nb_negative */
(unaryfunc) GMPy_MPQ_Plus_Slot, /* nb_positive */
(unaryfunc) GMPy_MPQ_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_MPQ_NonZero_Slot, /* nb_bool */
0, /* nb_invert */
0, /* nb_lshift */
0, /* nb_rshift */
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
0, /* nb_coerce */
(unaryfunc) GMPy_MPQ_Int_Slot, /* nb_int */
(unaryfunc) GMPy_MPQ_Long_Slot, /* nb_long */
(unaryfunc) GMPy_MPQ_Float_Slot, /* nb_float */
0, /* nb_oct */
0, /* nb_hex */
0, /* nb_inplace_add; */
0, /* nb_inplace_subtract */
0, /* nb_inplace_multiply */
0, /* nb_inplace_divide */
0, /* nb_inplace_remainder */
0, /* nb_inplace_power */
0, /* nb_inplace_lshift */
0, /* nb_inplace_rshift */
0, /* nb_inplace_and */
0, /* nb_inplace_xor */
0, /* nb_inplace_or */
(binaryfunc) GMPy_MPQ_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPQ_TrueDiv_Slot, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
};
#endif
static PyGetSetDef GMPy_MPQ_getseters[] =
{
{ "numerator", (getter)GMPy_MPQ_Attrib_GetNumer, NULL,
"the numerator of a rational number in lowest terms", NULL },
{ "denominator", (getter)GMPy_MPQ_Attrib_GetDenom, NULL,
"the denominator of a rational number in lowest terms", NULL },
{ "real", (getter)GMPy_MPQ_Attrib_GetReal, NULL,
"the real part of a complex number", NULL },
{ "imag", (getter)GMPy_MPQ_Attrib_GetImag, NULL,
"the imaginary part of a complex number", NULL },
{NULL}
};
static PyMethodDef GMPy_MPQ_methods [] =
{
{ "__ceil__", GMPy_MPQ_Method_Ceil, METH_NOARGS, GMPy_doc_mpq_method_ceil },
{ "__floor__", GMPy_MPQ_Method_Floor, METH_NOARGS, GMPy_doc_mpq_method_floor },
{ "__round__", GMPy_MPQ_Method_Round, METH_VARARGS, GMPy_doc_mpq_method_round },
{ "__sizeof__", GMPy_MPQ_Method_Sizeof, METH_NOARGS, GMPy_doc_mpq_method_sizeof },
{ "__trunc__", GMPy_MPQ_Method_Trunc, METH_NOARGS, GMPy_doc_mpq_method_trunc },
{ "conjugate", GMPy_MP_Method_Conjugate, METH_NOARGS, GMPy_doc_mp_method_conjugate },
{ "digits", GMPy_MPQ_Digits_Method, METH_VARARGS, GMPy_doc_mpq_digits_method },
{ NULL, NULL, 1 }
};
static PyTypeObject MPQ_Type =
{
/* PyObject_HEAD_INIT(&PyType_Type) */
#ifdef PY3
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyObject_HEAD_INIT(0)
0, /* ob_size */
#endif
"mpq", /* tp_name */
sizeof(MPQ_Object), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor) GMPy_MPQ_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_MPQ_Repr_Slot, /* tp_repr */
&mpq_number_methods, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc) GMPy_MPQ_Hash_Slot, /* tp_hash */
0, /* tp_call */
(reprfunc) GMPy_MPQ_Str_Slot, /* tp_str */
(getattrofunc) 0, /* tp_getattro */
(setattrofunc) 0, /* tp_setattro */
0, /* tp_as_buffer */
#ifdef PY3
Py_TPFLAGS_DEFAULT, /* tp_flags */
#else
Py_TPFLAGS_HAVE_RICHCOMPARE |
Py_TPFLAGS_CHECKTYPES, /* tp_flags */
#endif
GMPy_doc_mpq, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)&GMPy_RichCompare_Slot, /* tp_richcompare */
0, /* tp_weaklistoffset*/
0, /* tp_iter */
0, /* tp_iternext */
GMPy_MPQ_methods, /* tp_methods */
0, /* tp_members */
GMPy_MPQ_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
GMPy_MPQ_NewInit, /* tp_new */
0, /* tp_free */
};
gmpy2-2.1.0b3/src/gmpy2_mpq.h 0000664 0001750 0001750 00000004356 13425753021 015534 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpq.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPQ_H
#define GMPY_MPQ_H
#ifdef __cplusplus
extern "C" {
#endif
static PyTypeObject MPQ_Type;
#define MPQ_Check(v) (((PyObject*)v)->ob_type == &MPQ_Type)
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpq_misc.c 0000664 0001750 0001750 00000026432 13473131605 016542 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpq_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *
GMPy_MPQ_Attrib_GetNumer(MPQ_Object *self, void *closure)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
if ((result = GMPy_MPZ_New(context)))
mpz_set(result->z, mpq_numref(self->q));
return (PyObject*)result;
}
static PyObject *
GMPy_MPQ_Attrib_GetReal(MPQ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_MPQ_Attrib_GetDenom(MPQ_Object *self, void *closure)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
if ((result = GMPy_MPZ_New(context)))
mpz_set(result->z, mpq_denref(self->q));
return (PyObject*)result;
}
static PyObject *
GMPy_MPQ_Attrib_GetImag(MPQ_Object *self, void *closure)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
if ((result = GMPy_MPZ_New(context)))
mpz_set_ui(result->z, 0);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_function_numer,
"numer(x) -> mpz\n\n"
"Return the numerator of x.");
static PyObject *
GMPy_MPQ_Function_Numer(PyObject *self, PyObject *other)
{
MPZ_Object *result;
MPQ_Object *tempq;
CTXT_Object *context = NULL;
if (!(result = (MPZ_Object*)GMPy_MPZ_New(context)))
return NULL;
if (!(tempq = GMPy_MPQ_From_Rational(other, context))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_set(result->z, mpq_numref(tempq->q));
Py_DECREF((PyObject*)tempq);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_function_denom,
"denom(x) -> mpz\n\n"
"Return the denominator of x.");
static PyObject *
GMPy_MPQ_Function_Denom(PyObject *self, PyObject *other)
{
MPZ_Object *result;
MPQ_Object *tempq;
CTXT_Object *context = NULL;
if (!(result = (MPZ_Object*)GMPy_MPZ_New(context)))
return NULL;
if (!(tempq = GMPy_MPQ_From_Rational(other, context))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_set(result->z, mpq_denref(tempq->q));
Py_DECREF((PyObject*)tempq);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_qdiv,
"qdiv(x[, y=1]) -> number\n\n"
"Return x/y as 'mpz' if possible, or as 'mpq' if x is not exactly\n"
"divisible by y.");
static PyObject *
GMPy_MPQ_Function_Qdiv(PyObject *self, PyObject *args)
{
Py_ssize_t argc;
PyObject *result = NULL, *x, *y;
MPQ_Object *tempx = NULL, *tempy = NULL, *tempr = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
/* Validate the argument(s). */
/* If there is only one argument, it should be either an integer or
* rational type. If it is an integer, then immediately return an mpz().
* If it is a rational type, convert it to an mpq and check the denominator.
*/
argc = PyTuple_GET_SIZE(args);
if (argc == 1) {
x = PyTuple_GET_ITEM(args, 0);
if (!IS_RATIONAL(x)) {
goto arg_error;
}
if (IS_INTEGER(x)) {
return (PyObject*)GMPy_MPZ_From_Integer(x, context);
}
if (!(tempx = GMPy_MPQ_From_Rational(x, context))) {
return NULL;
}
if (mpz_cmp_ui(mpq_denref(tempx->q), 1) == 0) {
if ((result = (PyObject*)GMPy_MPZ_New(context))) {
mpz_set(MPZ(result), mpq_numref(tempx->q));
}
Py_DECREF((PyObject*)tempx);
return result;
}
else {
return (PyObject*)tempx;
}
}
/* If there are two rational arguments, just convert them both to mpq,
* divide, and then check the denominator.
*/
if (argc == 2) {
x = PyTuple_GET_ITEM(args, 0);
y = PyTuple_GET_ITEM(args, 1);
if (!IS_RATIONAL(x) || !IS_RATIONAL(y)) {
goto arg_error;
}
if (!(tempx = GMPy_MPQ_From_Rational(x, context)) ||
!(tempy = GMPy_MPQ_From_Rational(y, context))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
if (mpq_sgn(tempy->q) == 0) {
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
ZERO_ERROR("qdiv() division by zero");
return NULL;
}
/* tempr contains the result of the division. */
if (!(tempr = GMPy_MPQ_New(context))) {
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return NULL;
}
mpq_div(tempr->q, tempx->q, tempy->q);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
if (mpz_cmp_ui(mpq_denref(tempr->q), 1) == 0) {
if ((result = (PyObject*)GMPy_MPZ_New(context))) {
mpz_set(MPZ(result), mpq_numref(tempr->q));
}
Py_DECREF((PyObject*)tempr);
return result;
}
else {
return (PyObject*)tempr;
};
}
arg_error:
TYPE_ERROR("qdiv() requires 1 or 2 integer or rational arguments");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_floor,
"Return greatest integer less than or equal to an mpq.");
static PyObject *
GMPy_MPQ_Method_Floor(PyObject *self, PyObject *other)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPZ_New(context))) {
mpz_fdiv_q(result->z, mpq_numref(MPQ(self)), mpq_denref(MPQ(self)));
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_ceil,
"Return least integer greater than or equal to an mpq.");
static PyObject *
GMPy_MPQ_Method_Ceil(PyObject *self, PyObject *other)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPZ_New(context))) {
mpz_cdiv_q(result->z, mpq_numref(MPQ(self)), mpq_denref(MPQ(self)));
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_trunc,
"Return integer portion of an mpq.");
static PyObject *
GMPy_MPQ_Method_Trunc(PyObject *self, PyObject *other)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPZ_New(context))) {
mpz_tdiv_q(result->z, mpq_numref(MPQ(self)), mpq_denref(MPQ(self)));
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_round, "Round an mpq to power of 10.");
static PyObject *
GMPy_MPQ_Method_Round(PyObject *self, PyObject *args)
{
Py_ssize_t round_digits = 0;
MPQ_Object *resultq;
MPZ_Object *resultz;
mpz_t temp, rem;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
/* If args is NULL or the size of args is 0, we just return an mpz. */
if (!args || PyTuple_GET_SIZE(args) == 0) {
if (!(resultz = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_init(rem);
mpz_fdiv_qr(resultz->z, rem, mpq_numref(MPQ(self)), mpq_denref(MPQ(self)));
mpz_mul_2exp(rem, rem, 1);
if (mpz_cmp(rem, mpq_denref(MPQ(self))) > 0) {
mpz_add_ui(resultz->z, resultz->z, 1);
}
else if (mpz_cmp(rem, mpq_denref(MPQ(self))) == 0) {
if (mpz_odd_p(resultz->z)) {
mpz_add_ui(resultz->z, resultz->z, 1);
}
}
mpz_clear(rem);
return (PyObject*)resultz;
}
if (PyTuple_GET_SIZE(args) > 1) {
TYPE_ERROR("Too many arguments for __round__()");
return NULL;
}
if (PyTuple_GET_SIZE(args) == 1) {
round_digits = PyIntOrLong_AsSsize_t(PyTuple_GET_ITEM(args, 0));
if (round_digits == -1 && PyErr_Occurred()) {
TYPE_ERROR("__round__() requires 'int' argument");
return NULL;
}
}
if (!(resultq = GMPy_MPQ_New(context))) {
return NULL;
}
mpz_init(temp);
mpz_ui_pow_ui(temp, 10, round_digits > 0 ? round_digits : -round_digits);
mpq_set(resultq->q, MPQ(self));
if (round_digits > 0) {
mpz_mul(mpq_numref(resultq->q), mpq_numref(resultq->q), temp);
mpq_canonicalize(resultq->q);
if (!(resultz = (MPZ_Object*)GMPy_MPQ_Method_Round((PyObject*)resultq, NULL))) {
mpz_clear(temp);
return NULL;
}
mpz_set(mpq_numref(resultq->q), resultz->z);
Py_DECREF((PyObject*)resultz);
mpz_set(mpq_denref(resultq->q), temp);
mpz_clear(temp);
mpq_canonicalize(resultq->q);
}
else {
mpz_mul(mpq_denref(resultq->q), mpq_denref(resultq->q), temp);
mpq_canonicalize(resultq->q);
if (!(resultz = (MPZ_Object*)GMPy_MPQ_Method_Round((PyObject*)resultq, NULL))) {
mpz_clear(temp);
return NULL;
}
mpq_set_ui(resultq->q, 0, 1);
mpz_mul(mpq_numref(resultq->q), resultz->z, temp);
Py_DECREF((PyObject*)resultz);
mpz_clear(temp);
mpq_canonicalize(resultq->q);
}
return (PyObject*)resultq;
}
static int
GMPy_MPQ_NonZero_Slot(MPQ_Object *self)
{
return mpq_sgn(self->q) != 0;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_sizeof,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x. Note: deleted mpq objects\n"
"are reused and may or may not be resized when a new value is assigned.");
static PyObject *
GMPy_MPQ_Method_Sizeof(PyObject *self, PyObject *other)
{
return PyIntOrLong_FromSize_t(sizeof(MPQ_Object) + \
(mpq_numref(MPQ(self))->_mp_alloc * sizeof(mp_limb_t)) + \
(mpq_denref(MPQ(self))->_mp_alloc * sizeof(mp_limb_t)));
}
gmpy2-2.1.0b3/src/gmpy2_mpq_misc.h 0000664 0001750 0001750 00000006022 13444071152 016536 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpq_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPQ_MISC_H
#define GMPY_MPQ_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPQ_Attrib_GetNumer(MPQ_Object *self, void *closure);
static PyObject * GMPy_MPQ_Attrib_GetDenom(MPQ_Object *self, void *closure);
static PyObject * GMPy_MPQ_Attrib_GetReal(MPQ_Object *self, void *closure);
static PyObject * GMPy_MPQ_Attrib_GetImag(MPQ_Object *self, void *closure);
static PyObject * GMPy_MPQ_Function_Numer(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Function_Denom(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Function_Qdiv(PyObject *self, PyObject *args);
static PyObject * GMPy_MPQ_Method_Ceil(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Method_Floor(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Method_Trunc(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Method_Round(PyObject *self, PyObject *other);
static int GMPy_MPQ_NonZero_Slot(MPQ_Object *x);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpz.c 0000664 0001750 0001750 00000033173 13444071152 015536 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_mpz,
"mpz() -> mpz(0)\n\n"
" If no argument is given, return mpz(0).\n\n"
"mpz(n) -> mpz\n\n"
" Return an 'mpz' object with a numeric value 'n' (truncating n\n"
" to its integer part if it's a Fraction, 'mpq', float or 'mpfr').\n\n"
"mpz(s[, base=0]):\n\n"
" Return an 'mpz' object from a string 's' made of digits in the\n"
" given base. If base=0, binary, octal, or hex Python strings\n"
" are recognized by leading 0b, 0o, or 0x characters, otherwise\n"
" the string is assumed to be decimal. Values for base can range\n"
" between 2 and 62.");
/* Since `gmpy2.mpz` is now a type and no longer a factory function, see
* gmpy2_cache.c/GMPy_MPZ_NewInit for details on creation.
*/
#ifdef PY3
static PyNumberMethods GMPy_MPZ_number_methods =
{
(binaryfunc) GMPy_MPZ_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPZ_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPZ_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPZ_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPZ_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPANY_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_MPZ_Minus_Slot, /* nb_negative */
(unaryfunc) GMPy_MPZ_Plus_Slot, /* nb_positive */
(unaryfunc) GMPy_MPZ_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_MPZ_NonZero_Slot, /* nb_bool */
(unaryfunc) GMPy_MPZ_Invert_Slot, /* nb_invert */
(binaryfunc) GMPy_MPZ_Lshift_Slot, /* nb_lshift */
(binaryfunc) GMPy_MPZ_Rshift_Slot, /* nb_rshift */
(binaryfunc) GMPy_MPZ_And_Slot, /* nb_and */
(binaryfunc) GMPy_MPZ_Xor_Slot, /* nb_xor */
(binaryfunc) GMPy_MPZ_Ior_Slot, /* nb_or */
(unaryfunc) GMPy_MPZ_Int_Slot, /* nb_int */
0, /* nb_reserved */
(unaryfunc) GMPy_MPZ_Float_Slot, /* nb_float */
(binaryfunc) GMPy_MPZ_IAdd_Slot, /* nb_inplace_add */
(binaryfunc) GMPy_MPZ_ISub_Slot, /* nb_inplace_subtract */
(binaryfunc) GMPy_MPZ_IMul_Slot, /* nb_inplace_multiply */
(binaryfunc) GMPy_MPZ_IRem_Slot, /* nb_inplace_remainder */
(ternaryfunc) GMPy_MPZ_IPow_Slot, /* nb_inplace_power */
(binaryfunc) GMPy_MPZ_ILshift_Slot, /* nb_inplace_lshift */
(binaryfunc) GMPy_MPZ_IRshift_Slot, /* nb_inplace_rshift */
0, /* nb_inplace_and */
0, /* nb_inplace_xor */
0, /* nb_inplace_or */
(binaryfunc) GMPy_MPZ_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPZ_TrueDiv_Slot, /* nb_true_divide */
(binaryfunc) GMPy_MPZ_IFloorDiv_Slot, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
(unaryfunc) GMPy_MPZ_Int_Slot, /* nb_index */
};
#else
static PyNumberMethods GMPy_MPZ_number_methods =
{
(binaryfunc) GMPy_MPZ_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPZ_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPZ_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPZ_Div2_Slot, /* nb_divide */
(binaryfunc) GMPy_MPZ_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPZ_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPANY_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_MPZ_Minus_Slot, /* nb_negative */
(unaryfunc) GMPy_MPZ_Plus_Slot, /* nb_positive */
(unaryfunc) GMPy_MPZ_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_MPZ_NonZero_Slot, /* nb_bool */
(unaryfunc) GMPy_MPZ_Invert_Slot, /* nb_invert */
(binaryfunc) GMPy_MPZ_Lshift_Slot, /* nb_lshift */
(binaryfunc) GMPy_MPZ_Rshift_Slot, /* nb_rshift */
(binaryfunc) GMPy_MPZ_And_Slot, /* nb_and */
(binaryfunc) GMPy_MPZ_Xor_Slot, /* nb_xor */
(binaryfunc) GMPy_MPZ_Ior_Slot, /* nb_or */
0, /* nb_coerce */
(unaryfunc) GMPy_MPZ_Int_Slot, /* nb_int */
(unaryfunc) GMPy_MPZ_Long_Slot, /* nb_long */
(unaryfunc) GMPy_MPZ_Float_Slot, /* nb_float */
(unaryfunc) GMPy_MPZ_Oct_Slot, /* nb_oct */
(unaryfunc) GMPy_MPZ_Hex_Slot, /* nb_hex */
(binaryfunc) GMPy_MPZ_IAdd_Slot, /* nb_inplace_add */
(binaryfunc) GMPy_MPZ_ISub_Slot, /* nb_inplace_subtract */
(binaryfunc) GMPy_MPZ_IMul_Slot, /* nb_inplace_multiply */
0, /* nb_inplace_divide */
(binaryfunc) GMPy_MPZ_IRem_Slot, /* nb_inplace_remainder */
(ternaryfunc) GMPy_MPZ_IPow_Slot, /* nb_inplace_power */
(binaryfunc) GMPy_MPZ_ILshift_Slot, /* nb_inplace_lshift */
(binaryfunc) GMPy_MPZ_IRshift_Slot, /* nb_inplace_rshift */
0, /* nb_inplace_and */
0, /* nb_inplace_xor */
0, /* nb_inplace_or */
(binaryfunc) GMPy_MPZ_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPZ_TrueDiv_Slot, /* nb_true_divide */
(binaryfunc) GMPy_MPZ_IFloorDiv_Slot, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
(unaryfunc) GMPy_MPZ_Int_Slot, /* nb_index */
};
#endif
static PyMappingMethods GMPy_MPZ_mapping_methods = {
(lenfunc)GMPy_MPZ_Method_Length,
(binaryfunc)GMPy_MPZ_Method_SubScript,
NULL
};
static PyGetSetDef GMPy_MPZ_getseters[] =
{
{ "numerator", (getter)GMPy_MPZ_Attrib_GetNumer, NULL,
"the numerator of a rational number in lowest terms", NULL },
{ "denominator", (getter)GMPy_MPZ_Attrib_GetDenom, NULL,
"the denominator of a rational number in lowest terms", NULL },
{ "real", (getter)GMPy_MPZ_Attrib_GetReal, NULL,
"the real part of a complex number", NULL },
{ "imag", (getter)GMPy_MPZ_Attrib_GetImag, NULL,
"the imaginary part of a complex number", NULL },
{NULL}
};
static PyMethodDef GMPy_MPZ_methods [] =
{
{ "__format__", GMPy_MPZ_Format, METH_VARARGS, GMPy_doc_mpz_format },
{ "__ceil__", GMPy_MPZ_Method_Ceil, METH_NOARGS, GMPy_doc_mpz_method_ceil },
{ "__floor__", GMPy_MPZ_Method_Floor, METH_NOARGS, GMPy_doc_mpz_method_floor },
{ "__round__", GMPy_MPZ_Method_Round, METH_VARARGS, GMPy_doc_mpz_method_round },
{ "__sizeof__", GMPy_MPZ_Method_SizeOf, METH_NOARGS, GMPy_doc_mpz_method_sizeof },
{ "__trunc__", GMPy_MPZ_Method_Trunc, METH_NOARGS, GMPy_doc_mpz_method_trunc },
{ "bit_clear", GMPy_MPZ_bit_clear_method, METH_O, doc_bit_clear_method },
{ "bit_flip", GMPy_MPZ_bit_flip_method, METH_O, doc_bit_flip_method },
{ "bit_length", GMPy_MPZ_bit_length_method, METH_NOARGS, doc_bit_length_method },
{ "bit_scan0", GMPy_MPZ_bit_scan0_method, METH_VARARGS, doc_bit_scan0_method },
{ "bit_scan1", GMPy_MPZ_bit_scan1_method, METH_VARARGS, doc_bit_scan1_method },
{ "bit_set", GMPy_MPZ_bit_set_method, METH_O, doc_bit_set_method },
{ "bit_test", GMPy_MPZ_bit_test_method, METH_O, doc_bit_test_method },
{ "conjugate", GMPy_MP_Method_Conjugate, METH_NOARGS, GMPy_doc_mp_method_conjugate },
{ "digits", GMPy_MPZ_Digits_Method, METH_VARARGS, GMPy_doc_mpz_digits_method },
{ "is_congruent", GMPy_MPZ_Method_IsCongruent, METH_VARARGS, GMPy_doc_mpz_method_is_congruent },
{ "is_divisible", GMPy_MPZ_Method_IsDivisible, METH_O, GMPy_doc_mpz_method_is_divisible },
{ "is_even", GMPy_MPZ_Method_IsEven, METH_NOARGS, GMPy_doc_mpz_method_is_even },
{ "is_odd", GMPy_MPZ_Method_IsOdd, METH_NOARGS, GMPy_doc_mpz_method_is_odd },
{ "is_power", GMPy_MPZ_Method_IsPower, METH_NOARGS, GMPy_doc_mpz_method_is_power },
{ "is_prime", GMPy_MPZ_Method_IsPrime, METH_VARARGS, GMPy_doc_mpz_method_is_prime },
{ "is_square", GMPy_MPZ_Method_IsSquare, METH_NOARGS, GMPy_doc_mpz_method_is_square },
{ "num_digits", GMPy_MPZ_Method_NumDigits, METH_VARARGS, GMPy_doc_mpz_method_num_digits },
{ NULL, NULL, 1 }
};
static PyTypeObject MPZ_Type =
{
/* PyObject_HEAD_INIT(&PyType_Type) */
#ifdef PY3
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyObject_HEAD_INIT(0)
0, /* ob_size */
#endif
"mpz", /* tp_name */
sizeof(MPZ_Object), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor) GMPy_MPZ_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_MPZ_Repr_Slot, /* tp_repr */
&GMPy_MPZ_number_methods, /* tp_as_number */
0, /* tp_as_sequence */
&GMPy_MPZ_mapping_methods, /* tp_as_mapping */
(hashfunc) GMPy_MPZ_Hash_Slot, /* tp_hash */
0, /* tp_call */
(reprfunc) GMPy_MPZ_Str_Slot, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
#ifdef PY3
Py_TPFLAGS_DEFAULT, /* tp_flags */
#else
Py_TPFLAGS_HAVE_INDEX|Py_TPFLAGS_HAVE_RICHCOMPARE| \
Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_CLASS| \
Py_TPFLAGS_HAVE_INPLACEOPS,
#endif
GMPy_doc_mpz, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)&GMPy_RichCompare_Slot, /* tp_richcompare */
0, /* tp_weaklistoffset*/
0, /* tp_iter */
0, /* tp_iternext */
GMPy_MPZ_methods, /* tp_methods */
0, /* tp_members */
GMPy_MPZ_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
GMPy_MPZ_NewInit, /* tp_new */
0, /* tp_free */
};
gmpy2-2.1.0b3/src/gmpy2_mpz.h 0000664 0001750 0001750 00000004431 13425753122 015541 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_H
#define GMPY_MPZ_H
#ifdef __cplusplus
extern "C" {
#endif
static PyTypeObject MPZ_Type;
#define MPZ(obj) (((MPZ_Object*)(obj))->z)
#define MPZ_Check(v) (((PyObject*)v)->ob_type == &MPZ_Type)
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpz_bitops.c 0000664 0001750 0001750 00000045461 13452637224 017130 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_bitops.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(doc_bit_length_method,
"x.bit_length() -> int\n\n"
"Return the number of significant bits in the radix-2\n"
"representation of x. Note: mpz(0).bit_length() returns 0.");
static PyObject *
GMPy_MPZ_bit_length_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t n = 0;
if (mpz_size(MPZ(self)))
n = mpz_sizeinbase(MPZ(self), 2);
return PyIntOrLong_FromMpBitCnt(n);
}
PyDoc_STRVAR(doc_bit_length_function,
"bit_length(x) -> int\n\n"
"Return the number of significant bits in the radix-2\n"
"representation of x. Note: bit_length(0) returns 0.");
static PyObject *
GMPy_MPZ_bit_length_function(PyObject *self, PyObject *other)
{
mp_bitcnt_t n = 0;
MPZ_Object* tempx;
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("bit_length() requires 'mpz' argument");
return NULL;
}
if (mpz_size(MPZ(tempx)))
n = mpz_sizeinbase(tempx->z, 2);
Py_DECREF((PyObject*)tempx);
return PyIntOrLong_FromMpBitCnt(n);
}
PyDoc_STRVAR(doc_bit_mask,
"bit_mask(n) -> mpz\n\n"
"Return an 'mpz' exactly n bits in length with all bits set.\n");
static PyObject *
GMPy_MPZ_bit_mask(PyObject *self, PyObject *other)
{
mp_bitcnt_t n = 0;
MPZ_Object* result;
n = mp_bitcnt_t_From_Integer(other);
if (n == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
mpz_set_ui(result->z, 1);
mpz_mul_2exp(result->z, result->z, n);
mpz_sub_ui(result->z, result->z, 1);
return (PyObject*)result;
}
/* return scan0/scan1 for an mpz */
PyDoc_STRVAR(doc_bit_scan0_method,
"x.bit_scan0(n=0) -> int\n\n"
"Return the index of the first 0-bit of x with index >= n. n >= 0.\n"
"If there are no more 0-bits in x at or above index n (which can\n"
"only happen for x<0, assuming an infinitely long 2's complement\n"
"format), then None is returned.");
static PyObject *
GMPy_MPZ_bit_scan0_method(PyObject *self, PyObject *args)
{
mp_bitcnt_t index, starting_bit = 0;
if (PyTuple_GET_SIZE(args) == 1) {
starting_bit = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 0));
if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
}
index = mpz_scan0(MPZ(self), starting_bit);
if (index == (mp_bitcnt_t)(-1)) {
Py_RETURN_NONE;
}
else {
return PyIntOrLong_FromMpBitCnt(index);
}
}
PyDoc_STRVAR(doc_bit_scan0_function,
"bit_scan0(x, n=0) -> int\n\n"
"Return the index of the first 0-bit of x with index >= n. n >= 0.\n"
"If there are no more 0-bits in x at or above index n (which can\n"
"only happen for x<0, assuming an infinitely long 2's complement\n"
"format), then None is returned.");
static PyObject *
GMPy_MPZ_bit_scan0_function(PyObject *self, PyObject *args)
{
mp_bitcnt_t index, starting_bit = 0;
MPZ_Object *tempx = NULL;
if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_SIZE(args) > 2) {
goto err;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
goto err;
}
if (PyTuple_GET_SIZE(args) == 2) {
starting_bit = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
goto err_index;
}
}
index = mpz_scan0(tempx->z, starting_bit);
Py_DECREF((PyObject*)tempx);
if (index == (mp_bitcnt_t)(-1)) {
Py_RETURN_NONE;
}
else {
return PyIntOrLong_FromMpBitCnt(index);
}
err:
TYPE_ERROR("bit_scan0() requires 'mpz',['int'] arguments");
err_index:
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_scan1_method,
"x.bit_scan1(n=0) -> int\n\n"
"Return the index of the first 1-bit of x with index >= n. n >= 0.\n"
"If there are no more 1-bits in x at or above index n (which can\n"
"only happen for x>=0, assuming an infinitely long 2's complement\n"
"format), then None is returned.");
static PyObject *
GMPy_MPZ_bit_scan1_method(PyObject *self, PyObject *args)
{
mp_bitcnt_t index, starting_bit = 0;
if (PyTuple_GET_SIZE(args) == 1) {
starting_bit = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 0));
if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
}
index = mpz_scan1(MPZ(self), starting_bit);
if (index == (mp_bitcnt_t)(-1)) {
Py_RETURN_NONE;
}
else {
return PyIntOrLong_FromMpBitCnt(index);
}
}
PyDoc_STRVAR(doc_bit_scan1_function,
"bit_scan1(x, n=0) -> int\n\n"
"Return the index of the first 1-bit of x with index >= n. n >= 0.\n"
"If there are no more 1-bits in x at or above index n (which can\n"
"only happen for x>=0, assuming an infinitely long 2's complement\n"
"format), then None is returned.");
static PyObject *
GMPy_MPZ_bit_scan1_function(PyObject *self, PyObject *args)
{
mp_bitcnt_t index, starting_bit = 0;
MPZ_Object *tempx = NULL;
if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_SIZE(args) > 2) {
goto err;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
goto err;
}
if (PyTuple_GET_SIZE(args) == 2) {
starting_bit = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
goto err_index;
}
}
index = mpz_scan1(tempx->z, starting_bit);
Py_DECREF((PyObject*)tempx);
if (index == (mp_bitcnt_t)(-1)) {
Py_RETURN_NONE;
}
else {
return PyIntOrLong_FromMpBitCnt(index);
}
err:
TYPE_ERROR("bit_scan1() requires 'mpz',['int'] arguments");
err_index:
Py_XDECREF((PyObject*)tempx);
return NULL;
}
/* get & return one bit from an mpz */
PyDoc_STRVAR(doc_bit_test_function,
"bit_test(x, n) -> bool\n\n"
"Return the value of the n-th bit of x.");
static PyObject *
GMPy_MPZ_bit_test_function(PyObject *self, PyObject *args)
{
mp_bitcnt_t bit_index;
int temp;
MPZ_Object *tempx = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
goto err;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
goto err;
}
bit_index = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
goto err_index;
}
temp = mpz_tstbit(tempx->z, bit_index);
Py_DECREF((PyObject*)tempx);
if (temp)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
err:
TYPE_ERROR("bit_test() requires 'mpz','int' arguments");
err_index:
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_test_method,
"x.bit_test(n) -> bool\n\n"
"Return the value of the n-th bit of x.");
static PyObject *
GMPy_MPZ_bit_test_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t bit_index;
bit_index = mp_bitcnt_t_From_Integer(other);
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (mpz_tstbit(MPZ(self), bit_index))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(doc_bit_clear_function,
"bit_clear(x, n) -> mpz\n\n"
"Return a copy of x with the n-th bit cleared.");
static PyObject *
GMPy_MPZ_bit_clear_function(PyObject *self, PyObject *args)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL, *tempx = NULL;
if (PyTuple_GET_SIZE(args) != 2)
goto err;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)))
goto err;
bit_index = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred())
goto err_index;
mpz_set(result->z, tempx->z);
mpz_clrbit(result->z, bit_index);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
err:
TYPE_ERROR("bit_clear() requires 'mpz','int' arguments");
err_index:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_clear_method,
"x.bit_clear(n) -> mpz\n\n"
"Return a copy of x with the n-th bit cleared.");
static PyObject *
GMPy_MPZ_bit_clear_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
bit_index = mp_bitcnt_t_From_Integer(other);
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
Py_DECREF(result);
return NULL;
}
mpz_set(result->z, MPZ(self));
mpz_clrbit(result->z, bit_index);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_bit_set_function,
"bit_set(x, n) -> mpz\n\n"
"Return a copy of x with the n-th bit set.");
static PyObject *
GMPy_MPZ_bit_set_function(PyObject *self, PyObject *args)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL, *tempx = NULL;
if (PyTuple_GET_SIZE(args) != 2)
goto err;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)))
goto err;
bit_index = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred())
goto err_index;
mpz_set(result->z, tempx->z);
mpz_setbit(result->z, bit_index);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
err:
TYPE_ERROR("bit_set() requires 'mpz','int' arguments");
err_index:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_set_method,
"x.bit_set(n) -> mpz\n\n"
"Return a copy of x with the n-th bit set.");
static PyObject *
GMPy_MPZ_bit_set_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
bit_index = mp_bitcnt_t_From_Integer(other);
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
Py_DECREF(result);
return NULL;
}
mpz_set(result->z, MPZ(self));
mpz_setbit(result->z, bit_index);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_bit_flip_function,
"bit_flip(x, n) -> mpz\n\n"
"Return a copy of x with the n-th bit inverted.");
static PyObject *
GMPy_MPZ_bit_flip_function(PyObject *self, PyObject *args)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL, *tempx = NULL;
if (PyTuple_GET_SIZE(args) != 2)
goto err;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)))
goto err;
bit_index = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred())
goto err_index;
mpz_set(result->z, tempx->z);
mpz_combit(result->z, bit_index);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
err:
TYPE_ERROR("bit_flip() requires 'mpz','int' arguments");
err_index:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_flip_method,
"x.bit_flip(n) -> mpz\n\n"
"Return a copy of x with the n-th bit inverted.");
static PyObject *
GMPy_MPZ_bit_flip_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
bit_index = mp_bitcnt_t_From_Integer(other);
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
Py_DECREF(result);
return NULL;
}
mpz_set(result->z, MPZ(self));
mpz_combit(result->z, bit_index);
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Invert_Slot(MPZ_Object *self)
{
MPZ_Object *result;
if ((result = GMPy_MPZ_New(NULL)))
mpz_com(result->z, MPZ(self));
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_And_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if (CHECK_MPZANY(self)) {
if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
mpz_and(result->z, MPZ(self), MPZ(other));
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL)))
return NULL;
mpz_and(result->z, MPZ(self), result->z);
}
}
else if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_From_Integer(self, NULL)))
return NULL;
mpz_and(result->z, result->z, MPZ(other));
}
else {
Py_RETURN_NOTIMPLEMENTED;
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Ior_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if (CHECK_MPZANY(self)) {
if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
mpz_ior(result->z, MPZ(self), MPZ(other));
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL)))
return NULL;
mpz_ior(result->z, MPZ(self), result->z);
}
}
else if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_From_Integer(self, NULL)))
return NULL;
mpz_ior(result->z, result->z, MPZ(other));
}
else {
Py_RETURN_NOTIMPLEMENTED;
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Xor_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if (CHECK_MPZANY(self)) {
if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
mpz_xor(result->z, MPZ(self), MPZ(other));
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL)))
return NULL;
mpz_xor(result->z, MPZ(self), result->z);
}
}
else if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_From_Integer(self, NULL)))
return NULL;
mpz_xor(result->z, result->z, MPZ(other));
}
else {
Py_RETURN_NOTIMPLEMENTED;
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Rshift_Slot(PyObject *self, PyObject *other)
{
mp_bitcnt_t count;
MPZ_Object *result, *tempx;
count = mp_bitcnt_t_From_Integer(other);
if ((count == (mp_bitcnt_t)(-1)) && PyErr_Occurred())
return NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (CHECK_MPZANY(self)) {
mpz_fdiv_q_2exp(result->z, MPZ(self), count);
return (PyObject*)result;
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(self, NULL))) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_fdiv_q_2exp(result->z, tempx->z, count);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
}
static PyObject *
GMPy_MPZ_Lshift_Slot(PyObject *self, PyObject *other)
{
mp_bitcnt_t count;
MPZ_Object *result, *tempx;
count = mp_bitcnt_t_From_Integer(other);
if ((count == (mp_bitcnt_t)(-1)) && PyErr_Occurred())
return NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (CHECK_MPZANY(self)) {
mpz_mul_2exp(result->z, MPZ(self), count);
return (PyObject*)result;
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(self, NULL))) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_mul_2exp(result->z, tempx->z, count);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
}
PyDoc_STRVAR(doc_popcount,
"popcount(x) -> int\n\n"
"Return the number of 1-bits set in x. If x<0, the number of\n"
"1-bits is infinite so -1 is returned in that case.");
static PyObject *
GMPy_MPZ_popcount(PyObject *self, PyObject *other)
{
mp_bitcnt_t n;
MPZ_Object *tempx;
if ((tempx = GMPy_MPZ_From_Integer(other, NULL))) {
n = mpz_popcount(tempx->z);
Py_DECREF((PyObject*)tempx);
if (n == (mp_bitcnt_t)(-1))
return PyLong_FromLong(-1);
else
return PyIntOrLong_FromMpBitCnt(n);
}
else {
TYPE_ERROR("popcount() requires 'mpz' argument");
return NULL;
}
}
PyDoc_STRVAR(doc_hamdist,
"hamdist(x, y) -> int\n\n"
"Return the Hamming distance (number of bit-positions where the\n"
"bits differ) between integers x and y.");
static PyObject *
GMPy_MPZ_hamdist(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
MPZ_Object *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2)
goto err;
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!tempx || !tempy)
goto err;
result = PyIntOrLong_FromMpBitCnt(mpz_hamdist(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
err:
TYPE_ERROR("hamdist() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
gmpy2-2.1.0b3/src/gmpy2_mpz_bitops.h 0000664 0001750 0001750 00000007527 13425753153 017136 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_bitops.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_BITOPS_H
#define GMPY_MPZ_BITOPS_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_bit_length_function(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_length_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_mask(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_scan0_function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_scan0_method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_scan1_function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_scan1_method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_test_function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_test_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_clear_function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_clear_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_set_function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_set_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_flip_function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_flip_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_popcount(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_hamdist(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Invert_Slot(MPZ_Object *self);
static PyObject * GMPy_MPZ_And_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Ior_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Xor_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Rshift_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Lshift_Slot(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpz_divmod.c 0000664 0001750 0001750 00000031175 13425753171 017107 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_divmod.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains functions related to division and remainder. */
/*
**************************************************************************
* Ceiling division and remainder.
**************************************************************************
*/
PyDoc_STRVAR(doc_c_divmod,
"c_divmod(x, y) -> (quotient, remainder)\n\n"
"Return the quotient and remainder of x divided by y. The quotient\n"
"is rounded towards +Inf (ceiling rounding) and the remainder will\n"
"have the opposite sign of y. x and y must be integers.");
static PyObject *
GMPy_MPZ_c_divmod(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
MPZ_Object *q = NULL, *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_divmod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL)) ||
!(r = GMPy_MPZ_New(NULL)) ||
!(result = PyTuple_New(2))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("c_divmod() division by 0");
goto err;
}
mpz_cdiv_qr(q->z, r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
err:
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
PyDoc_STRVAR(doc_c_div,
"c_div(x, y) -> quotient\n\n"
"Return the quotient of x divided by y. The quotient is rounded\n"
"towards +Inf (ceiling rounding). x and y must be integers.");
static PyObject *
GMPy_MPZ_c_div(PyObject *self, PyObject *args)
{
MPZ_Object *q = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_div() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("c_div() division by 0");
goto err;
}
mpz_cdiv_q(q->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)q;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
return NULL;
}
PyDoc_STRVAR(doc_c_mod,
"c_mod(x, y) -> remainder\n\n"
"Return the remainder of x divided by y. The remainder will have\n"
"the opposite sign of y. x and y must be integers.");
static PyObject *
GMPy_MPZ_c_mod(PyObject *self, PyObject *args)
{
MPZ_Object *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_mod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(r = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("c_mod() division by 0");
goto err;
}
mpz_cdiv_r(r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)r;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)r);
return NULL;
}
/*
**************************************************************************
* Floor division and remainder.
**************************************************************************
*/
PyDoc_STRVAR(doc_f_divmod,
"f_divmod(x, y) -> (quotient, remainder)\n\n"
"Return the quotient and remainder of x divided by y. The quotient\n"
"is rounded towards -Inf (floor rounding) and the remainder will\n"
"have the same sign as y. x and y must be integers.");
static PyObject *
GMPy_MPZ_f_divmod(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
MPZ_Object *q = NULL, *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_divmod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL)) ||
!(r = GMPy_MPZ_New(NULL)) ||
!(result = PyTuple_New(2))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("f_divmod() division by 0");
goto err;
}
mpz_fdiv_qr(q->z, r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
err:
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
PyDoc_STRVAR(doc_f_div,
"f_div(x, y) -> quotient\n\n"
"Return the quotient of x divided by y. The quotient is rounded\n"
"towards -Inf (floor rounding). x and y must be integers.");
static PyObject *
GMPy_MPZ_f_div(PyObject *self, PyObject *args)
{
MPZ_Object *q = NULL, *tempx = NULL, *tempy = NULL;
if(PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_div() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("f_div() division by 0");
goto err;
}
mpz_fdiv_q(q->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)q;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
return NULL;
}
PyDoc_STRVAR(doc_f_mod,
"f_mod(x, y) -> remainder\n\n"
"Return the remainder of x divided by y. The remainder will have\n"
"the same sign as y. x and y must be integers.");
static PyObject *
GMPy_MPZ_f_mod(PyObject *self, PyObject *args)
{
MPZ_Object *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_mod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(r = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("f_mod() division by 0");
goto err;
}
mpz_fdiv_r(r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)r;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)r);
return NULL;
}
/*
**************************************************************************
* Truncating division and remainder.
**************************************************************************
*/
PyDoc_STRVAR(doc_t_divmod,
"t_divmod(x, y) -> (quotient, remainder)\n\n"
"Return the quotient and remainder of x divided by y. The quotient\n"
"is rounded towards zero (truncation) and the remainder will have\n"
"the same sign as x. x and y must be integers.");
static PyObject *
GMPy_MPZ_t_divmod(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
MPZ_Object *q = NULL, *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_divmod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL)) ||
!(r = GMPy_MPZ_New(NULL)) ||
!(result = PyTuple_New(2))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("t_divmod() division by 0");
goto err;
}
mpz_tdiv_qr(q->z, r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
err:
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
PyDoc_STRVAR(doc_t_div,
"t_div(x, y) -> quotient\n\n"
"Return the quotient of x divided by y. The quotient is rounded\n"
"towards 0. x and y must be integers.");
static PyObject *
GMPy_MPZ_t_div(PyObject *self, PyObject *args)
{
MPZ_Object *q = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_div() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("t_div() division by 0");
goto err;
}
mpz_tdiv_q(q->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)q;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
return NULL;
}
PyDoc_STRVAR(doc_t_mod,
"t_mod(x, y) -> remainder\n\n"
"Return the remainder of x divided by y. The remainder will have\n"
"the same sign as x. x and y must be integers.");
static PyObject *
GMPy_MPZ_t_mod(PyObject *self, PyObject *args)
{
MPZ_Object *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_mod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(r = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("t_mod() division by 0");
goto err;
}
mpz_tdiv_r(r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)r;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)r);
return NULL;
}
gmpy2-2.1.0b3/src/gmpy2_mpz_divmod.h 0000664 0001750 0001750 00000005375 13425753202 017112 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_divmod.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_DIVMOD_H
#define GMPY_MPZ_DIVMOD_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_c_divmod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_c_div(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_c_mod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_divmod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_div(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_mod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_divmod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_div(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_mod(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpz_divmod2exp.c 0000664 0001750 0001750 00000030342 13425753215 017700 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_divmod2exp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains functions related to division and remainder by a power
* of two.
*/
/*
**************************************************************************
* Ceiling division and remainder by power of two.
**************************************************************************
*/
PyDoc_STRVAR(doc_c_divmod_2exp,
"c_divmod_2exp(x ,n) -> (quotient, remainder)\n\n"
"Return the quotient and remainder of x divided by 2**n. The quotient\n"
"is rounded towards +Inf (ceiling rounding) and the remainder will\n"
"be negative. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_c_divmod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
PyObject *result = NULL;
MPZ_Object *q = NULL, *r = NULL, *tempx = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_divmod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(q = GMPy_MPZ_New(NULL)) ||
!(r = GMPy_MPZ_New(NULL)) ||
!(result = PyTuple_New(2))) {
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
mpz_cdiv_q_2exp(q->z, tempx->z, nbits);
mpz_cdiv_r_2exp(r->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
}
PyDoc_STRVAR(doc_c_div_2exp,
"c_div_2exp(x, n) -> quotient\n\n"
"Returns the quotient of x divided by 2**n. The quotient is rounded\n"
"towards +Inf (ceiling rounding). x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_c_div_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_div_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_cdiv_q_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_c_mod_2exp,
"c_mod_2exp(x, n) -> remainder\n\n"
"Return the remainder of x divided by 2**n. The remainder will be\n"
"negative. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_c_mod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_mod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_cdiv_r_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
/*
**************************************************************************
* Floor division and remainder by power of two.
**************************************************************************
*/
PyDoc_STRVAR(doc_f_divmod_2exp,
"f_divmod_2exp(x, n) -> (quotient, remainder)\n\n"
"Return quotient and remainder after dividing x by 2**n. The quotient\n"
"is rounded towards -Inf (floor rounding) and the remainder will be\n"
"positive. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_f_divmod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
PyObject *result;
MPZ_Object *q, *r, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_divmod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_New(NULL);
r = GMPy_MPZ_New(NULL);
result = PyTuple_New(2);
if (!tempx || !q || !r || !result) {
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
mpz_fdiv_q_2exp(q->z, tempx->z, nbits);
mpz_fdiv_r_2exp(r->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
}
PyDoc_STRVAR(doc_f_div_2exp,
"f_div_2exp(x, n) -? quotient\n\n"
"Return the quotient of x divided by 2**n. The quotient is rounded\n"
"towards -Inf (floor rounding). x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_f_div_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_div_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_fdiv_q_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_f_mod_2exp,
"f_mod_2exp(x, n) -> remainder\n\n"
"Return remainder of x divided by 2**n. The remainder will be\n"
"positive. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_f_mod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_mod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_fdiv_r_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
/*
**************************************************************************
* Truncating division and remainder by power of two.
**************************************************************************
*/
PyDoc_STRVAR(doc_t_divmod_2exp,
"t_divmod_2exp(x, n) -> (quotient, remaidner)\n\n"
"Return the quotient and remainder of x divided by 2**n. The quotient\n"
"is rounded towards zero (truncation) and the remainder will have the\n"
"same sign as x. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_t_divmod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *q, *r, *tempx;
PyObject *result;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_divmod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_New(NULL);
r = GMPy_MPZ_New(NULL);
result = PyTuple_New(2);
if (!tempx || !q || !r || !result) {
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
mpz_tdiv_q_2exp(q->z, tempx->z, nbits);
mpz_tdiv_r_2exp(r->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
}
PyDoc_STRVAR(doc_t_div_2exp,
"t_div_2exp(x, n) -> quotient\n\n"
"Return the quotient of x divided by 2**n. The quotient is rounded\n"
"towards zero (truncation). n must be >0.");
static PyObject *
GMPy_MPZ_t_div_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_div_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_tdiv_q_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_t_mod_2exp,
"t_mod_2exp(x, n) -> remainder\n\n"
"Return the remainder of x divided by 2**n. The remainder will have\n"
"the same sign as x. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_t_mod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_mod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_tdiv_r_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
gmpy2-2.1.0b3/src/gmpy2_mpz_divmod2exp.h 0000664 0001750 0001750 00000005462 13425753231 017710 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_divmod2exp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_DIVMOD2EXP_H
#define GMPY_MPZ_DIVMOD2EXP_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_c_divmod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_c_div_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_c_mod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_divmod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_div_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_mod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_divmod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_div_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_mod_2exp(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpz_inplace.c 0000664 0001750 0001750 00000021760 13452635451 017237 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_inplace.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Provides inplace operations for mpz. */
#include
static PyObject *
GMPy_MPZ_IAdd_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
if (CHECK_MPZANY(other)) {
if ((result = GMPy_MPZ_New(NULL))) {
mpz_add(result->z, MPZ(self), MPZ(other));
}
return (PyObject*)result;
}
if (PyLong_CheckExact(other)) {
if ((result = GMPy_MPZ_New(NULL))) {
switch (Py_SIZE((PyLongObject*)other)) {
case -1:
mpz_sub_ui(result->z, MPZ(self), ((PyLongObject*)other)->ob_digit[0]);
return (PyObject*)result;
case 0:
mpz_set(result->z, MPZ(self));
return (PyObject*)result;
case 1:
mpz_add_ui(result->z, MPZ(self), ((PyLongObject*)other)->ob_digit[0]);
return (PyObject*)result;
default:
break;
}
}
else {
return NULL;
}
}
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if ((result = GMPy_MPZ_New(NULL))) {
if (!error) {
if (temp >= 0) {
mpz_add_ui(result->z, MPZ(self), temp);
}
else {
mpz_sub_ui(result->z, MPZ(self), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_add(result->z, MPZ(self), global.tempz);
}
}
return (PyObject*)result;
}
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_MPZ_ISub_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *rz;
if (!(rz = GMPy_MPZ_New(NULL))) {
return NULL;
}
if (CHECK_MPZANY(other)) {
mpz_sub(rz->z, MPZ(self), MPZ(other));
return (PyObject*)rz;
}
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if (!error) {
if (temp >= 0) {
mpz_sub_ui(rz->z, MPZ(self), temp);
}
else {
mpz_add_ui(rz->z, MPZ(self), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_sub(rz->z, MPZ(self), global.tempz);
}
return (PyObject*)rz;
}
Py_DECREF(rz);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_MPZ_IMul_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *rz;
if (!(rz = GMPy_MPZ_New(NULL))) {
return NULL;
}
if (CHECK_MPZANY(other)) {
mpz_mul(rz->z, MPZ(self), MPZ(other));
return (PyObject*)rz;
}
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if (!error) {
mpz_mul_si(rz->z, MPZ(self), temp);
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_mul(rz->z, MPZ(self), global.tempz);
}
return (PyObject*)rz;
}
Py_DECREF(rz);
Py_RETURN_NOTIMPLEMENTED;
}
/* Pympany_floordiv follows the // semantics from Python 3.x. The result is
* an mpz when the arguments are mpz or mpq, but the result is an mpf when
* the arguments are mpf.
*/
static PyObject *
GMPy_MPZ_IFloorDiv_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *rz;
if (!(rz = GMPy_MPZ_New(NULL))) {
return NULL;
}
if (CHECK_MPZANY(other)) {
if (mpz_sgn(MPZ(other)) == 0) {
ZERO_ERROR("mpz division by zero");
Py_DECREF(rz);
return NULL;
}
mpz_fdiv_q(rz->z, MPZ(self), MPZ(other));
return (PyObject*)rz;
}
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if (!error) {
if (temp == 0) {
ZERO_ERROR("mpz division by zero");
Py_DECREF(rz);
return NULL;
}
else if(temp > 0) {
mpz_fdiv_q_ui(rz->z, MPZ(self), temp);
}
else {
mpz_cdiv_q_ui(rz->z, MPZ(self), -temp);
mpz_neg(rz->z, rz->z);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_fdiv_q(rz->z, MPZ(self), global.tempz);
}
return (PyObject*)rz;
}
Py_DECREF(rz);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_MPZ_IRem_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *rz;
if (!(rz = GMPy_MPZ_New(NULL))) {
return NULL;
}
if (CHECK_MPZANY(other)) {
if (mpz_sgn(MPZ(other)) == 0) {
ZERO_ERROR("mpz modulo by zero");
Py_DECREF(rz);
return NULL;
}
mpz_fdiv_r(rz->z, MPZ(self), MPZ(other));
return (PyObject*)rz;
}
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if (!error) {
if (temp > 0) {
mpz_fdiv_r_ui(rz->z, MPZ(self), temp);
}
else if (temp == 0) {
Py_DECREF(rz);
ZERO_ERROR("mpz modulo by zero");
return NULL;
}
else {
mpz_cdiv_r_ui(rz->z, MPZ(self), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_fdiv_r(rz->z, MPZ(self), global.tempz);
}
return (PyObject*)rz;
}
Py_DECREF(rz);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_MPZ_IRshift_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *rz;
mp_bitcnt_t shift;
if (IS_INTEGER(other)) {
shift = mp_bitcnt_t_From_Integer(other);
if (shift == (mp_bitcnt_t)(-1) && PyErr_Occurred())
return NULL;
if (!(rz = GMPy_MPZ_New(NULL)))
return NULL;
mpz_fdiv_q_2exp(rz->z, MPZ(self), shift);
return (PyObject *)rz;
}
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_MPZ_ILshift_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *rz;
mp_bitcnt_t shift;
if (IS_INTEGER(other)) {
shift = mp_bitcnt_t_From_Integer(other);
if (shift == (mp_bitcnt_t)(-1) && PyErr_Occurred())
return NULL;
if (!(rz = GMPy_MPZ_New(NULL)))
return NULL;
mpz_mul_2exp(rz->z, MPZ(self), shift);
return (PyObject *)rz;
}
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_MPZ_IPow_Slot(PyObject *self, PyObject *other, PyObject *mod)
{
MPZ_Object *r;
mp_bitcnt_t exp;
exp = mp_bitcnt_t_From_Integer(other);
if (exp == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
PyErr_Clear();
Py_RETURN_NOTIMPLEMENTED;
}
if (!(r = GMPy_MPZ_New(NULL)))
return NULL;
mpz_pow_ui(r->z, MPZ(self), exp);
return (PyObject*)r;
}
gmpy2-2.1.0b3/src/gmpy2_mpz_inplace.h 0000664 0001750 0001750 00000005366 13425753256 017254 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_inplace.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_INPLACE_H
#define GMPY_MPZ_INPLACE_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_IAdd_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_ISub_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_IMul_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_IFloorDiv_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_IRem_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_IRshift_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_ILshift_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_IPow_Slot(PyObject *self, PyObject *other, PyObject *mod);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpz_misc.c 0000664 0001750 0001750 00000136116 13463460564 016564 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* return number-of-digits for an mpz in requested base, default 10 */
PyDoc_STRVAR(GMPy_doc_mpz_method_num_digits,
"x.num_digits([base]) -> int\n\n"
"Return length of string representing the absolute value of x in\n"
"the given base. Values for base can range between 2 and 62. The\n"
"value returned may be 1 too large.");
PyDoc_STRVAR(GMPy_doc_mpz_function_num_digits,
"num_digits(x[, base]) -> int\n\n"
"Return length of string representing the absolute value of x in\n"
"the given base. Values for base can range between 2 and 62. The\n"
"value returned may be 1 too large.");
static PyObject *
GMPy_MPZ_Method_NumDigits(PyObject *self, PyObject *args)
{
long base = 10;
PyObject *result;
if (PyTuple_GET_SIZE(args) == 1) {
base = PyIntOrLong_AsLong(PyTuple_GET_ITEM(args, 0));
if (base == -1 && PyErr_Occurred()) {
return NULL;
}
}
if ((base < 2) || (base > 62)) {
VALUE_ERROR("base must be in the interval [2, 62]");
return NULL;
}
result = PyIntOrLong_FromSize_t(mpz_sizeinbase(MPZ(self), (int)base));
return result;
}
static PyObject *
GMPy_MPZ_Function_NumDigits(PyObject *self, PyObject *args)
{
long base = 10;
Py_ssize_t argc;
MPZ_Object *temp;
PyObject *result;
argc = PyTuple_GET_SIZE(args);
if (argc == 0 || argc > 2) {
TYPE_ERROR("num_digits() requires 'mpz',['int'] arguments");
return NULL;
}
if (argc == 2) {
base = PyIntOrLong_AsLong(PyTuple_GET_ITEM(args, 1));
if (base == -1 && PyErr_Occurred()) {
return NULL;
}
}
if ((base < 2) || (base > 62)) {
VALUE_ERROR("base must be in the interval [2, 62]");
return NULL;
}
if (!(temp = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
return NULL;
}
result = PyIntOrLong_FromSize_t(mpz_sizeinbase(temp->z, (int)base));
Py_DECREF((PyObject*)temp);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_iroot,
"iroot(x,n) -> (number, boolean)\n\n"
"Return the integer n-th root of x and boolean value that is True\n"
"iff the root is exact. x >= 0. n > 0.");
static PyObject *
GMPy_MPZ_Function_Iroot(PyObject *self, PyObject *args)
{
unsigned long n;
int exact;
MPZ_Object *root = NULL, *tempx = NULL;
PyObject *result = NULL;
if ((PyTuple_GET_SIZE(args) != 2) ||
((!IS_INTEGER(PyTuple_GET_ITEM(args, 0))) ||
(!IS_INTEGER(PyTuple_GET_ITEM(args, 1))))) {
TYPE_ERROR("iroot() requires 'int','int' arguments");
return NULL;
}
n = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 1));
if ((n == 0) || ((n == (unsigned long)(-1)) && PyErr_Occurred())) {
VALUE_ERROR("n must be > 0");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempx->z) < 0) {
VALUE_ERROR("iroot() of negative number");
Py_DECREF((PyObject*)tempx);
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(root = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)root);
Py_XDECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
exact = mpz_root(root->z, tempx->z, n);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)root);
PyTuple_SET_ITEM(result, 1, (PyObject*)PyBool_FromLong(exact));
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_iroot_rem,
"iroot_rem(x,n) -> (number, number)\n\n"
"Return a 2-element tuple (y,r), such that y is the integer n-th\n"
"root of x and x=y**n + r. x >= 0. n > 0.");
static PyObject *
GMPy_MPZ_Function_IrootRem(PyObject *self, PyObject *args)
{
unsigned long n;
MPZ_Object *root = NULL, *rem = NULL, *tempx = NULL;
PyObject *result = NULL;
if ((PyTuple_GET_SIZE(args) != 2) ||
((!IS_INTEGER(PyTuple_GET_ITEM(args, 0))) ||
(!IS_INTEGER(PyTuple_GET_ITEM(args, 1))))) {
TYPE_ERROR("iroot_rem() requires 'int','int' arguments");
return NULL;
}
n = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 1));
if ((n == 0) || ((n == (unsigned long)(-1)) && PyErr_Occurred())) {
VALUE_ERROR("n must be > 0");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempx->z) < 0) {
VALUE_ERROR("iroot_rem() of negative number");
Py_DECREF((PyObject*)tempx);
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(root = GMPy_MPZ_New(NULL)) ||
!(rem = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)tempx);
Py_XDECREF(result);
Py_XDECREF((PyObject*)root);
Py_XDECREF((PyObject*)rem);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_rootrem(root->z, rem->z, tempx->z, n);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)root);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_ceil, "Ceiling of an mpz returns itself.");
static PyObject *
GMPy_MPZ_Method_Ceil(PyObject *self, PyObject *other)
{
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_floor, "Floor of an mpz returns itself.");
static PyObject *
GMPy_MPZ_Method_Floor(PyObject *self, PyObject *other)
{
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_trunc, "Truncating an mpz returns itself.");
static PyObject *
GMPy_MPZ_Method_Trunc(PyObject *self, PyObject *other)
{
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_round, "Round an mpz to power of 10.");
static PyObject *
GMPy_MPZ_Method_Round(PyObject *self, PyObject *args)
{
Py_ssize_t round_digits;
MPZ_Object *result;
mpz_t temp, rem;
if (PyTuple_GET_SIZE(args) == 0) {
Py_INCREF(self);
return self;
}
round_digits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 0));
if (round_digits == -1 && PyErr_Occurred()) {
TYPE_ERROR("__round__() requires 'int' argument");
return NULL;
}
if (round_digits >= 0) {
Py_INCREF(self);
return self;
}
/* We can now assume round_digits > 0. */
round_digits = -round_digits;
if ((result = GMPy_MPZ_New(NULL))) {
if ((unsigned)round_digits >= mpz_sizeinbase(MPZ(self), 10)) {
mpz_set_ui(result->z, 0);
}
else {
mpz_init(temp);
mpz_init(rem);
mpz_ui_pow_ui(temp, 10, round_digits);
mpz_fdiv_qr(result->z, rem, MPZ(self), temp);
mpz_mul_2exp(rem, rem, 1);
if (mpz_cmp(rem, temp) > 0) {
mpz_add_ui(result->z, result->z, 1);
}
else if (mpz_cmp(rem, temp) == 0) {
if (mpz_odd_p(result->z)) {
mpz_add_ui(result->z, result->z, 1);
}
}
mpz_mul(result->z, result->z, temp);
mpz_clear(rem);
mpz_clear(temp);
}
}
return (PyObject*)result;
}
static int
GMPy_MPZ_NonZero_Slot(MPZ_Object *self)
{
return mpz_sgn(self->z) != 0;
}
#if PY_MAJOR_VERSION < 3
/* hex/oct formatting (mpz-only) */
static PyObject *
GMPy_MPZ_Oct_Slot(MPZ_Object *self)
{
return GMPy_PyStr_From_MPZ(self, 8, 0, NULL);
}
static PyObject *
GMPy_MPZ_Hex_Slot(MPZ_Object *self)
{
return GMPy_PyStr_From_MPZ(self, 16, 0, NULL);
}
#endif
/* Miscellaneous gmpy functions */
PyDoc_STRVAR(GMPy_doc_mpz_function_gcd,
"gcd(a, b) -> mpz\n\n"
"Return the greatest common divisor of integers a and b.");
static PyObject *
GMPy_MPZ_Function_GCD(PyObject *self, PyObject *args)
{
PyObject *arg0, *arg1;
MPZ_Object *result = NULL, *tempa = NULL, *tempb = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("gcd() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
arg0 = PyTuple_GET_ITEM(args, 0);
arg1 = PyTuple_GET_ITEM(args, 1);
if (MPZ_Check(arg0) && MPZ_Check(arg1)) {
mpz_gcd(result->z, MPZ(arg0), MPZ(arg1));
}
else {
if (!(tempa = GMPy_MPZ_From_Integer(arg0, NULL)) ||
!(tempb = GMPy_MPZ_From_Integer(arg1, NULL))) {
TYPE_ERROR("gcd() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempa);
Py_XDECREF((PyObject*)tempb);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_gcd(result->z, tempa->z, tempb->z);
Py_DECREF((PyObject*)tempa);
Py_DECREF((PyObject*)tempb);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_lcm,
"lcm(a, b) -> mpz\n\n"
"Return the lowest common multiple of integers a and b.");
static PyObject *
GMPy_MPZ_Function_LCM(PyObject *self, PyObject *args)
{
PyObject *arg0, *arg1;
MPZ_Object *result = NULL, *tempa = NULL, *tempb = NULL;
if(PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("lcm() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
arg0 = PyTuple_GET_ITEM(args, 0);
arg1 = PyTuple_GET_ITEM(args, 1);
if (MPZ_Check(arg0) && MPZ_Check(arg1)) {
mpz_lcm(result->z, MPZ(arg0), MPZ(arg1));
}
else {
if (!(tempa = GMPy_MPZ_From_Integer(arg0, NULL)) ||
!(tempb = GMPy_MPZ_From_Integer(arg1, NULL))) {
TYPE_ERROR("lcm() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempa);
Py_XDECREF((PyObject*)tempb);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_lcm(result->z, tempa->z, tempb->z);
Py_DECREF((PyObject*)tempa);
Py_DECREF((PyObject*)tempb);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_gcdext,
"gcdext(a, b) - > tuple\n\n"
"Return a 3-element tuple (g,s,t) such that\n"
" g == gcd(a,b) and g == a*s + b*t");
static PyObject *
GMPy_MPZ_Function_GCDext(PyObject *self, PyObject *args)
{
PyObject *arg0, *arg1, *result = NULL;
MPZ_Object *g = NULL, *s = NULL, *t = NULL, *tempa = NULL, *tempb = NULL;
if(PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("gcdext() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = PyTuple_New(3)) ||
!(g = GMPy_MPZ_New(NULL)) ||
!(s = GMPy_MPZ_New(NULL)) ||
!(t = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)g);
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)t);
Py_XDECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
arg0 = PyTuple_GET_ITEM(args, 0);
arg1 = PyTuple_GET_ITEM(args, 1);
if (MPZ_Check(arg0) && MPZ_Check(arg1)) {
mpz_gcdext(g->z, s->z, t->z, MPZ(arg0), MPZ(arg1));
}
else {
if(!(tempa = GMPy_MPZ_From_Integer(arg0, NULL)) ||
!(tempb = GMPy_MPZ_From_Integer(arg1, NULL))) {
TYPE_ERROR("gcdext() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempa);
Py_XDECREF((PyObject*)tempb);
Py_DECREF((PyObject*)g);
Py_DECREF((PyObject*)s);
Py_DECREF((PyObject*)t);
Py_DECREF(result);
return NULL;
}
mpz_gcdext(g->z, s->z, t->z, tempa->z, tempb->z);
Py_DECREF((PyObject*)tempa);
Py_DECREF((PyObject*)tempb);
}
PyTuple_SET_ITEM(result, 0, (PyObject*)g);
PyTuple_SET_ITEM(result, 1, (PyObject*)s);
PyTuple_SET_ITEM(result, 2, (PyObject*)t);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_divm,
"divm(a, b, m) -> mpz\n\n"
"Return x such that b*x == a mod m. Raises a ZeroDivisionError\n"
"exception if no such value x exists.");
static PyObject *
GMPy_MPZ_Function_Divm(PyObject *self, PyObject *args)
{
MPZ_Object *result = NULL, *num = NULL, *den = NULL, *mod = NULL;
mpz_t numz, denz, modz, gcdz;
int ok = 0;
if (PyTuple_GET_SIZE(args) != 3) {
TYPE_ERROR("divm() requires 'mpz','mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(num = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(den = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(mod = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL))) {
TYPE_ERROR("divm() requires 'mpz','mpz','mpz' arguments");
Py_XDECREF((PyObject*)num);
Py_XDECREF((PyObject*)den);
Py_XDECREF((PyObject*)mod);
Py_DECREF((PyObject*)result);
return NULL;
}
/* Make copies so we don't destroy the input. */
mpz_init(numz);
mpz_init(denz);
mpz_init(modz);
mpz_set(numz, num->z);
mpz_set(denz, den->z);
mpz_set(modz, mod->z);
Py_DECREF((PyObject*)num);
Py_DECREF((PyObject*)den);
Py_DECREF((PyObject*)mod);
if (mpz_invert(result->z, denz, modz)) { /* inverse exists */
ok = 1;
}
else {
/* last-ditch attempt: do num, den AND mod have a gcd>1 ? */
mpz_init(gcdz);
mpz_gcd(gcdz, numz, denz);
mpz_gcd(gcdz, gcdz, modz);
mpz_divexact(numz, numz, gcdz);
mpz_divexact(denz, denz, gcdz);
mpz_divexact(modz, modz, gcdz);
mpz_clear(gcdz);
ok = mpz_invert(result->z, denz, modz);
}
if (ok) {
mpz_mul(result->z, result->z, numz);
mpz_mod(result->z, result->z, modz);
mpz_clear(numz);
mpz_clear(denz);
mpz_clear(modz);
return (PyObject*)result;
}
else {
ZERO_ERROR("not invertible");
mpz_clear(numz);
mpz_clear(denz);
mpz_clear(modz);
Py_DECREF((PyObject*)result);
return NULL;
}
}
PyDoc_STRVAR(GMPy_doc_mpz_function_fac,
"fac(n) -> mpz\n\n"
"Return the exact factorial of n.\n\n"
"See factorial(n) to get the floating-point approximation.");
static PyObject *
GMPy_MPZ_Function_Fac(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = c_ulong_From_Integer(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_fac_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_double_fac,
"double_fac(n) -> mpz\n\n"
"Return the exact double factorial (n!!) of n. The double\n"
"factorial is defined as n*(n-2)*(n-4)...");
static PyObject *
GMPy_MPZ_Function_DoubleFac(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = c_ulong_From_Integer(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_2fac_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_primorial,
"primorial(n) -> mpz\n\n"
"Return the product of all positive prime numbers less than or"
"equal to n.");
static PyObject *
GMPy_MPZ_Function_Primorial(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = c_ulong_From_Integer(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_primorial_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_multi_fac,
"multi_fac(n,m) -> mpz\n\n"
"Return the exact m-multi factorial of n. The m-multi"
"factorial is defined as n*(n-m)*(n-2m)...");
static PyObject *
GMPy_MPZ_Function_MultiFac(PyObject *self, PyObject *args)
{
MPZ_Object *result = NULL;
unsigned long n, m;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("multi_fac() requires 2 integer arguments");
return NULL;
}
n = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 0));
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
m = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 1));
if (m == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_mfac_uiui(result->z, n, m);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_fib,
"fib(n) -> mpz\n\n"
"Return the n-th Fibonacci number.");
static PyObject *
GMPy_MPZ_Function_Fib(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = c_ulong_From_Integer(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_fib_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_fib2,
"fib2(n) -> tuple\n\n"
"Return a 2-tuple with the (n-1)-th and n-th Fibonacci numbers.");
static PyObject *
GMPy_MPZ_Function_Fib2(PyObject *self, PyObject *other)
{
PyObject *result = NULL;
MPZ_Object *fib1 = NULL, *fib2 = NULL;
unsigned long n;
n = c_ulong_From_Integer(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(fib1 = GMPy_MPZ_New(NULL)) ||
!(fib2 = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF((PyObject*)fib1);
Py_XDECREF((PyObject*)fib2);
result = NULL;
/* LCOV_EXCL_STOP */
}
mpz_fib2_ui(fib1->z, fib2->z, n);
PyTuple_SET_ITEM(result, 0, (PyObject*)fib1);
PyTuple_SET_ITEM(result, 1, (PyObject*)fib2);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_lucas,
"lucas(n) -> mpz\n\n"
"Return the n-th Lucas number.");
static PyObject *
GMPy_MPZ_Function_Lucas(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = c_ulong_From_Integer(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_lucnum_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_lucas2,
"lucas2(n) -> tuple\n\n"
"Return a 2-tuple with the (n-1)-th and n-th Lucas numbers.");
static PyObject *
GMPy_MPZ_Function_Lucas2(PyObject *self, PyObject *other)
{
PyObject *result = NULL;
MPZ_Object *luc1 = NULL, *luc2 = NULL;
unsigned long n;
n = c_ulong_From_Integer(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(luc1 = GMPy_MPZ_New(NULL)) ||
!(luc2 = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF((PyObject*)luc1);
Py_XDECREF((PyObject*)luc2);
result = NULL;
/* LCOV_EXCL_STOP */
}
mpz_lucnum2_ui(luc1->z, luc2->z, n);
PyTuple_SET_ITEM(result, 0, (PyObject*)luc1);
PyTuple_SET_ITEM(result, 1, (PyObject*)luc2);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_bincoef,
"bincoef(n, k) -> mpz\n\n"
"Return the binomial coefficient ('n choose k'). k >= 0.");
PyDoc_STRVAR(GMPy_doc_mpz_function_comb,
"comb(n, k) -> mpz\n\n"
"Return the number of combinations of 'n things, taking k at a\n"
"time'. k >= 0. Same as bincoef(n, k)");
static PyObject *
GMPy_MPZ_Function_Bincoef(PyObject *self, PyObject *args)
{
MPZ_Object *result = NULL, *tempx;
unsigned long n, k;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("bincoef() requires two integer arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
k = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 1));
if (k == (unsigned long)(-1) && PyErr_Occurred()) {
Py_DECREF((PyObject*)result);
return NULL;
}
n = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 0));
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
/* Since we plan to skip the else clause and continue,
* we need to clear the error since we aren't acting on it.
*/
PyErr_Clear();
}
else {
/* Use mpz_bin_uiui which should be faster. */
mpz_bin_uiui(result->z, n, k);
return (PyObject*)result;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_bin_ui(result->z, tempx->z, k);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_isqrt,
"isqrt(x) -> mpz\n\n"
"Return the integer square root of an integer x. x >= 0.");
static PyObject *
GMPy_MPZ_Function_Isqrt(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if (CHECK_MPZANY(other)) {
if (mpz_sgn(MPZ(other)) < 0) {
VALUE_ERROR("isqrt() of negative number");
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_sqrt(result->z, MPZ(other));
}
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("isqrt() requires 'mpz' argument");
return NULL;
}
if (mpz_sgn(result->z) < 0) {
VALUE_ERROR("isqrt() of negative number");
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_sqrt(result->z, result->z);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_isqrt_rem,
"isqrt_rem(x) -> tuple\n\n"
"Return a 2-element tuple (s,t) such that s=isqrt(x) and t=x-s*s.\n"
"x >=0.");
static PyObject *
GMPy_MPZ_Function_IsqrtRem(PyObject *self, PyObject *other)
{
MPZ_Object *root = NULL, *rem = NULL, *temp = NULL;
PyObject *result;
if (!(temp = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("isqrt_rem() requires 'mpz' argument");
return NULL;
}
if (mpz_sgn(temp->z) < 0) {
VALUE_ERROR("isqrt_rem() of negative number");
Py_DECREF((PyObject*)temp);
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(root = GMPy_MPZ_New(NULL)) ||
!(rem = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)temp);
Py_XDECREF(result);
Py_XDECREF((PyObject*)root);
Py_XDECREF((PyObject*)rem);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_sqrtrem(root->z, rem->z, temp->z);
Py_DECREF((PyObject*)temp);
PyTuple_SET_ITEM(result, 0, (PyObject*)root);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_remove,
"remove(x, f) -> tuple\n\n"
"Return a 2-element tuple (y,m) such that x=y*(f**m) and f does\n"
"not divide y. Remove the factor f from x as many times as\n"
"possible. m is the multiplicity f in x. f > 1.");
static PyObject *
GMPy_MPZ_Function_Remove(PyObject *self, PyObject *args)
{
MPZ_Object *result = NULL, *tempx = NULL, *tempf = NULL;
PyObject *x, *f;
size_t multiplicity;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("remove() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
x = PyTuple_GET_ITEM(args, 0);
f = PyTuple_GET_ITEM(args, 1);
if (MPZ_Check(x) && MPZ_Check(f)) {
if (mpz_cmp_si(MPZ(f), 2) < 0) {
VALUE_ERROR("factor must be > 1");
Py_DECREF((PyObject*)result);
return NULL;
}
multiplicity = mpz_remove(result->z, MPZ(x), MPZ(f));
return Py_BuildValue("(Nk)", result, multiplicity);
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(x, NULL)) ||
!(tempf = GMPy_MPZ_From_Integer(f, NULL))) {
TYPE_ERROR("remove() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempf);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_cmp_si(MPZ(tempf), 2) < 0) {
VALUE_ERROR("factor must be > 1");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempf);
Py_DECREF((PyObject*)result);
return NULL;
}
multiplicity = mpz_remove(result->z, tempx->z, tempf->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempf);
return Py_BuildValue("(Nk)", result, multiplicity);
}
}
PyDoc_STRVAR(GMPy_doc_mpz_function_invert,
"invert(x, m) -> mpz\n\n"
"Return y such that x*y == 1 modulo m. Raises ZeroDivisionError if no\n"
"inverse exists.");
static PyObject *
GMPy_MPZ_Function_Invert(PyObject *self, PyObject *args)
{
PyObject *x, *y;
MPZ_Object *result = NULL, *tempx = NULL, *tempy = NULL;
int success;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("invert() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
x = PyTuple_GET_ITEM(args, 0);
y = PyTuple_GET_ITEM(args, 1);
if (MPZ_Check(x) && MPZ_Check(y)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("invert() division by 0");
Py_DECREF((PyObject*)result);
return NULL;
}
success = mpz_invert(result->z, MPZ(x), MPZ(y));
if (!success) {
ZERO_ERROR("invert() no inverse exists");
Py_DECREF((PyObject*)result);
return NULL;
}
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(x, NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(y, NULL))) {
TYPE_ERROR("invert() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("invert() division by 0");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF(result);
return NULL;
}
success = mpz_invert(result->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
if (!success) {
ZERO_ERROR("invert() no inverse exists");
Py_DECREF((PyObject*)result);
return NULL;
}
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_divexact,
"divexact(x, y) -> mpz\n\n"
"Return the quotient of x divided by y. Faster than standard\n"
"division but requires the remainder is zero!");
static PyObject *
GMPy_MPZ_Function_Divexact(PyObject *self, PyObject *args)
{
PyObject *x, *y;
MPZ_Object *result, *tempx= NULL, *tempy = NULL;
if(PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("divexact() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
x = PyTuple_GET_ITEM(args, 0);
y = PyTuple_GET_ITEM(args, 1);
if (MPZ_Check(x) && MPZ_Check(y)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("divexact() division by 0");
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_divexact(result->z, MPZ(x), MPZ(y));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(x, NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(y, NULL))) {
TYPE_ERROR("divexact() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_sgn(MPZ(tempy)) == 0) {
ZERO_ERROR("divexact() division by 0");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_divexact(result->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_square,
"is_square(x) -> bool\n\n"
"Returns True if x is a perfect square, else return False.");
static PyObject *
GMPy_MPZ_Function_IsSquare(PyObject *self, PyObject *other)
{
int res;
MPZ_Object *tempx;
if (MPZ_Check(other)) {
res = mpz_perfect_square_p(MPZ(other));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_square() requires 'mpz' argument");
return NULL;
}
else {
res = mpz_perfect_square_p(tempx->z);
Py_DECREF((PyObject*)tempx);
}
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_square,
"x.is_square() -> bool\n\n"
"Returns True if x is a perfect square, else return False.");
static PyObject *
GMPy_MPZ_Method_IsSquare(PyObject *self, PyObject *other)
{
int res;
res = mpz_perfect_square_p(MPZ(self));
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_divisible,
"is_divisible(x, d) -> bool\n\n"
"Returns True if x is divisible by d, else return False.");
static PyObject *
GMPy_MPZ_Function_IsDivisible(PyObject *self, PyObject *args)
{
native_ui temp;
int error, res;
MPZ_Object *tempx, *tempd;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("is_divisible() requires 2 integer arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
return NULL;
}
temp = GMPy_Integer_AsNative_uiAndError(PyTuple_GET_ITEM(args, 1), &error);
if (!error) {
res = mpz_divisible_ui_p(tempx->z, temp);
Py_DECREF((PyObject*)tempx);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
if (!(tempd = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) {
TYPE_ERROR("is_divisible() requires 2 integer arguments");
Py_DECREF((PyObject*)tempx);
return NULL;
}
res = mpz_divisible_p(tempx->z, tempd->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempd);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_divisible,
"x.is_divisible(d) -> bool\n\n"
"Returns True if x is divisible by d, else return False.");
static PyObject *
GMPy_MPZ_Method_IsDivisible(PyObject *self, PyObject *other)
{
native_ui temp;
int error, res;
MPZ_Object *tempd;
temp = GMPy_Integer_AsNative_uiAndError(other, &error);
if (!error) {
res = mpz_divisible_ui_p(MPZ(self), temp);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
if (!(tempd = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_divisible() requires integer argument");
return NULL;
}
res = mpz_divisible_p(MPZ(self), tempd->z);
Py_DECREF((PyObject*)tempd);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_congruent,
"is_congruent(x, y, m) -> bool\n\n"
"Returns True if x is congruent to y modulo m, else return False.");
static PyObject *
GMPy_MPZ_Function_IsCongruent(PyObject *self, PyObject *args)
{
int res;
MPZ_Object *tempx = NULL, *tempy = NULL, *tempm = NULL;
if (PyTuple_GET_SIZE(args) != 3) {
TYPE_ERROR("is_congruent() requires 3 integer arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(tempm = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)tempm);
TYPE_ERROR("is_congruent() requires 3 integer arguments");
return NULL;
}
res = mpz_congruent_p(tempx->z, tempy->z, tempm->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempm);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_congruent,
"x.is_congruent(y, m) -> bool\n\n"
"Returns True if x is congruent to y modulo m, else return False.");
static PyObject *
GMPy_MPZ_Method_IsCongruent(PyObject *self, PyObject *args)
{
int res;
MPZ_Object *tempy = NULL, *tempm = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("is_congruent() requires 2 integer arguments");
return NULL;
}
if (!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempm = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) {
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)tempm);
TYPE_ERROR("is_congruent() requires 2 integer arguments");
return NULL;
}
res = mpz_congruent_p(MPZ(self), tempy->z, tempm->z);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempm);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_power,
"is_power(x) -> bool\n\n"
"Return True if x is a perfect power (there exists a y and an\n"
"n > 1, such that x=y**n), else return False.");
static PyObject *
GMPy_MPZ_Function_IsPower(PyObject *self, PyObject *other)
{
int res;
MPZ_Object* tempx;
if (MPZ_Check(other)) {
res = mpz_perfect_power_p(MPZ(other));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_power() requires 'mpz' argument");
return NULL;
}
else {
res = mpz_perfect_power_p(tempx->z);
Py_DECREF((PyObject*)tempx);
}
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_power,
"x.is_power() -> bool\n\n"
"Return True if x is a perfect power (there exists a y and an\n"
"n > 1, such that x=y**n), else return False.");
static PyObject *
GMPy_MPZ_Method_IsPower(PyObject *self, PyObject *other)
{
int res;
res = mpz_perfect_power_p(MPZ(self));
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_prime,
"is_prime(x[, n=25]) -> bool\n\n"
"Return True if x is _probably_ prime, else False if x is\n"
"definitely composite. x is checked for small divisors and up\n"
"to n Miller-Rabin tests are performed.");
static PyObject *
GMPy_MPZ_Function_IsPrime(PyObject *self, PyObject *args)
{
int i;
unsigned long reps = 25;
MPZ_Object* tempx;
Py_ssize_t argc;
argc = PyTuple_GET_SIZE(args);
if (argc == 0 || argc > 2) {
TYPE_ERROR("is_prime() requires 'mpz'[,'int'] arguments");
return NULL;
}
if (PyTuple_GET_SIZE(args) == 2) {
reps = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 1));
if (reps == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
/* Silently limit n to a reasonable value. */
if (reps > 1000) {
reps = 1000;
}
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
return NULL;
}
i = mpz_probab_prime_p(tempx->z, (int)reps);
Py_DECREF((PyObject*)tempx);
if (i)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_prime,
"x.is_prime([n=25]) -> bool\n\n"
"Return True if x is _probably_ prime, else False if x is\n"
"definitely composite. x is checked for small divisors and up\n"
"to n Miller-Rabin tests are performed.");
static PyObject *
GMPy_MPZ_Method_IsPrime(PyObject *self, PyObject *args)
{
int i;
unsigned long reps = 25;
Py_ssize_t argc;
argc = PyTuple_GET_SIZE(args);
if (argc > 1) {
TYPE_ERROR("is_prime() takes at most 1 argument");
return NULL;
}
if (PyTuple_GET_SIZE(args) == 1) {
reps = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 0));
if (reps == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
/* Silently limit n to a reasonable value. */
if (reps > 1000) {
reps = 1000;
}
}
i = mpz_probab_prime_p(MPZ(self), (int)reps);
if (i)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_next_prime,
"next_prime(x) -> mpz\n\n"
"Return the next _probable_ prime number > x.");
static PyObject *
GMPy_MPZ_Function_NextPrime(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if(MPZ_Check(other)) {
if(!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_nextprime(result->z, MPZ(other));
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("next_prime() requires 'mpz' argument");
return NULL;
}
else {
mpz_nextprime(result->z, result->z);
}
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_jacobi,
"jacobi(x, y) -> mpz\n\n"
"Return the Jacobi symbol (x|y). y must be odd and >0.");
static PyObject *
GMPy_MPZ_Function_Jacobi(PyObject *self, PyObject *args)
{
MPZ_Object *tempx = NULL, *tempy = NULL;
long res;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("jacobi() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
if (mpz_sgn(tempy->z) <= 0 || mpz_even_p(tempy->z)) {
VALUE_ERROR("y must be odd and >0");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return NULL;
}
res = (long)(mpz_jacobi(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return PyIntOrLong_FromLong(res);
}
PyDoc_STRVAR(GMPy_doc_mpz_function_legendre,
"legendre(x, y) -> mpz\n\n"
"Return the Legendre symbol (x|y). y is assumed to be an odd prime.");
static PyObject *
GMPy_MPZ_Function_Legendre(PyObject *self, PyObject *args)
{
MPZ_Object *tempx = NULL, *tempy = NULL;
long res;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("legendre() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
if (mpz_sgn(tempy->z) <= 0 || mpz_even_p(tempy->z)) {
VALUE_ERROR("y must be odd, prime, and >0");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return NULL;
}
res = (long)(mpz_legendre(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return PyIntOrLong_FromLong(res);
}
PyDoc_STRVAR(GMPy_doc_mpz_function_kronecker,
"kronecker(x, y) -> mpz\n\n"
"Return the Kronecker-Jacobi symbol (x|y).");
static PyObject *
GMPy_MPZ_Function_Kronecker(PyObject *self, PyObject *args)
{
MPZ_Object *tempx = NULL, *tempy = NULL;
long res;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("kronecker() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
res = (long)(mpz_kronecker(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return PyIntOrLong_FromLong(res);
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_even,
"is_even(x) -> bool\n\n"
"Return True if x is even, False otherwise.");
static PyObject *
GMPy_MPZ_Function_IsEven(PyObject *self, PyObject *other)
{
int res;
MPZ_Object *tempx;
if (MPZ_Check(other)) {
res = mpz_even_p(MPZ(other));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_even() requires 'mpz' argument");
return NULL;
}
else {
res = mpz_even_p(tempx->z);
Py_DECREF((PyObject*)tempx);
}
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_even,
"x.is_even() -> bool\n\n"
"Return True if x is even, False otherwise.");
static PyObject *
GMPy_MPZ_Method_IsEven(PyObject *self, PyObject *other)
{
int res;
res = mpz_even_p(MPZ(self));
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_odd,
"is_odd(x) -> bool\n\n"
"Return True if x is odd, False otherwise.");
static PyObject *
GMPy_MPZ_Function_IsOdd(PyObject *self, PyObject *other)
{
int res;
MPZ_Object *tempx;
if (CHECK_MPZANY(other)) {
res = mpz_odd_p(MPZ(other));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_odd() requires 'mpz' argument");
return NULL;
}
else {
res = mpz_odd_p(tempx->z);
Py_DECREF((PyObject*)tempx);
}
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_odd,
"x.is_odd() -> bool\n\n"
"Return True if x is odd, False otherwise.");
static PyObject *
GMPy_MPZ_Method_IsOdd(PyObject *self, PyObject *other)
{
int res;
res = mpz_odd_p(MPZ(self));
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
/*
* Add mapping support to mpz objects.
*/
static Py_ssize_t
GMPy_MPZ_Method_Length(MPZ_Object *self)
{
return mpz_sizeinbase(self->z, 2);
}
static PyObject *
GMPy_MPZ_Method_SubScript(MPZ_Object *self, PyObject *item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyIntOrLong_AsSsize_t(item);
if (i == -1 && PyErr_Occurred()) {
INDEX_ERROR("argument too large to convert to an index");
return NULL;
}
if (i < 0) {
i += mpz_sizeinbase(self->z, 2);
}
return PyIntOrLong_FromLong(mpz_tstbit(self->z, i));
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength, cur, i;
MPZ_Object *result;
#if PY_VERSION_HEX > 0x030200A4
if (PySlice_GetIndicesEx(item,
mpz_sizeinbase(self->z, 2),
&start, &stop, &step, &slicelength) < 0) {
return NULL;
}
#else
if (PySlice_GetIndicesEx((PySliceObject*)item,
mpz_sizeinbase(self->z, 2),
&start, &stop, &step, &slicelength) < 0) {
return NULL;
}
#endif
if ((step < 0 && start < stop) || (step > 0 && start > stop)) {
stop = start;
}
if (!(result = GMPy_MPZ_New(NULL))) {
return NULL;
}
mpz_set_ui(result->z, 0);
if (slicelength > 0) {
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
if(mpz_tstbit(self->z, cur)) {
mpz_setbit(result->z, i);
}
}
}
return (PyObject*)result;
}
else {
TYPE_ERROR("bit positions must be integers");
return NULL;
}
}
static PyObject *
GMPy_MPZ_Attrib_GetNumer(MPZ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_MPZ_Attrib_GetReal(MPZ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_MPZ_Attrib_GetDenom(MPZ_Object *self, void *closure)
{
MPZ_Object *result;
if ((result = GMPy_MPZ_New(NULL))) {
mpz_set_ui(result->z, 1);
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Attrib_GetImag(MPZ_Object *self, void *closure)
{
MPZ_Object *result;
if ((result = GMPy_MPZ_New(NULL))) {
mpz_set_ui(result->z, 0);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_sizeof,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x. Note: deleted mpz objects\n"
"are reused and may or may not be resized when a new value is assigned.");
static PyObject *
GMPy_MPZ_Method_SizeOf(PyObject *self, PyObject *other)
{
return PyIntOrLong_FromSize_t(sizeof(MPZ_Object) + \
(MPZ(self)->_mp_alloc * sizeof(mp_limb_t)));
}
/* Note: this particular function is also used for xmpz, mpq, and mpfr. Only
* mpc.conjugate() does more that just return another reference to the original
* object.
*/
PyDoc_STRVAR(GMPy_doc_mp_method_conjugate,
"x.conjugate() -> number\n\n"
"Return the conjugate of x (which is just a new reference to x since x is\n"
"not a complex number).");
static PyObject *
GMPy_MP_Method_Conjugate(PyObject *self, PyObject *args)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
gmpy2-2.1.0b3/src/gmpy2_mpz_misc.h 0000664 0001750 0001750 00000014244 13444071152 016554 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_MISC_H
#define GMPY_MPZ_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static int GMPy_MPZ_NonZero_Slot(MPZ_Object *self);
static PyObject * GMPy_MPZ_Attrib_GetNumer(MPZ_Object *self, void *closure);
static PyObject * GMPy_MPZ_Attrib_GetDenom(MPZ_Object *self, void *closure);
static PyObject * GMPy_MPZ_Attrib_GetReal(MPZ_Object *self, void *closure);
static PyObject * GMPy_MPZ_Attrib_GetImag(MPZ_Object *self, void *closure);
static PyObject * GMPy_MPZ_Method_Ceil(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_Floor(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_Trunc(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_Round(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_NumDigits(PyObject *self, PyObject *args);
static Py_ssize_t GMPy_MPZ_Method_Length(MPZ_Object *self);
static PyObject * GMPy_MPZ_Method_SubScript(MPZ_Object *self, PyObject *item);
static PyObject * GMPy_MPZ_Method_IsSquare(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_IsDivisible(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_IsCongruent(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Method_IsPower(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_IsPrime(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Method_IsEven(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_IsOdd(PyObject *self, PyObject *other);
static PyObject * GMPy_MP_Method_Conjugate(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_NumDigits(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_Iroot(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_IrootRem(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_Bincoef(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_GCD(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_LCM(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_GCDext(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_Divm(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_Fac(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Primorial(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_DoubleFac(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_MultiFac(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_Fib(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Fib2(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Lucas(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Lucas2(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Isqrt(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_IsqrtRem(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Remove(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_Invert(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_Divexact(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_IsSquare(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_IsDivisible(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_IsCongruent(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_IsPower(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_IsPrime(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_NextPrime(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Jacobi(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_Legendre(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_Kronecker(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_IsEven(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_IsOdd(PyObject *self, PyObject *other);
#if PY_MAJOR_VERSION < 3
static PyObject * GMPy_MPZ_Oct_Slot(MPZ_Object *self);
static PyObject * GMPy_MPZ_Hex_Slot(MPZ_Object *self);
#endif
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mpz_pack.c 0000664 0001750 0001750 00000020666 13425753314 016545 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_pack.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
**************************************************************************
* pack and unpack methods
*
* Both pack and unpack use a devious trick when stuffing values into the
* internal structure of an mpz_t. By setting a bit beyond the range of
* interest, we are guaranteed that memory will remain available. When
* the bit is cleared, it also triggers normalization of the value by
* accounting for leading bits that are zero.
**************************************************************************
*/
PyDoc_STRVAR(doc_pack,
"pack(lst, n) -> mpz\n\n"
"Pack a list of integers 'lst' into a single 'mpz' by concatenating\n"
"each integer element of 'lst' after padding to length n bits. Raises\n"
"an error if any integer is negative or greater than n bits in\n"
"length.");
static PyObject *
GMPy_MPZ_pack(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits, total_bits, tempx_bits;
Py_ssize_t index, lst_count, i, temp_bits, limb_count;
PyObject *lst;
mpz_t temp, temp1;
MPZ_Object *result, *tempx = 0;
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("pack() requires 'list','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!PyList_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("pack() requires 'list','int' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(context)))
return NULL;
lst = PyTuple_GET_ITEM(args, 0);
lst_count = PyList_GET_SIZE(lst);
total_bits = nbits * lst_count;
if ((total_bits / lst_count) != nbits) {
VALUE_ERROR("result too large to store in an 'mpz'");
return NULL;
}
mpz_set_ui(result->z, 0);
mpz_setbit(result->z, total_bits + (mp_bits_per_limb * 2));
mpz_init(temp);
mpz_init(temp1);
mpz_set_ui(temp, 0);
limb_count = 0;
tempx_bits = 0;
for (index = 0; index < lst_count; index++) {
if (!(tempx = GMPy_MPZ_From_Integer(PyList_GetItem(lst, index), context))
|| (mpz_sgn(tempx->z) < 0)
|| (mpz_sizeinbase(tempx->z,2) > (size_t)nbits)) {
TYPE_ERROR("pack() requires list elements be positive integers < 2^n bits");
mpz_clear(temp);
Py_XDECREF((PyObject*)tempx);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_mul_2exp(temp1, tempx->z, tempx_bits);
mpz_add(temp, temp, temp1);
tempx_bits += nbits;
i = 0;
temp_bits = mpz_sizeinbase(temp, 2) * mpz_sgn(temp);
while (tempx_bits >= (mp_bitcnt_t)mp_bits_per_limb) {
if (temp_bits > 0) {
result->z->_mp_d[limb_count] = mpz_getlimbn(temp, i);
}
i += 1;
tempx_bits -= mp_bits_per_limb;
limb_count += 1;
temp_bits -= mp_bits_per_limb;
}
if (temp_bits > 0) {
mpz_tdiv_q_2exp(temp, temp, mp_bits_per_limb * i);
}
else {
mpz_set_ui(temp, 0);
}
Py_DECREF((PyObject*)tempx);
}
result->z->_mp_d[limb_count] = mpz_getlimbn(temp, 0);
mpz_clrbit(result->z, total_bits + (mp_bits_per_limb * 2));
mpz_clear(temp);
mpz_clear(temp1);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_unpack,
"unpack(x, n) -> list\n\n"
"Unpack an integer 'x' into a list of n-bit values. Equivalent to\n"
"repeated division by 2**n. Raises error if 'x' is negative.");
static PyObject *
GMPy_MPZ_unpack(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits, total_bits, guard_bit, extra_bits, temp_bits;
Py_ssize_t index = 0, lst_count, i, lst_ptr = 0;
PyObject *result;
mpz_t temp;
mp_limb_t extra = 0;
MPZ_Object *item, *tempx = NULL;
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("unpack() requires 'int','int' arguments");
return NULL;
}
nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), context))) {
TYPE_ERROR("unpack() requires 'int','int' arguments");
return NULL;
}
if (mpz_sgn(tempx->z) < 0) {
VALUE_ERROR("unpack() requires x >= 0");
return NULL;
}
if (mpz_sgn(tempx->z) == 0) {
total_bits = 0;
}
else {
total_bits = mpz_sizeinbase(tempx->z, 2);
}
lst_count = total_bits / nbits;
if ((total_bits % nbits) || !lst_count) {
lst_count += 1;
}
if (!(result = PyList_New(lst_count))) {
Py_DECREF((PyObject*)tempx);
return NULL;
}
if (mpz_sgn(tempx->z) == 0) {
if (!(item = GMPy_MPZ_New(context))) {
Py_DECREF((PyObject*)tempx);
Py_DECREF(result);
return NULL;
}
mpz_set_ui(item->z, 0);
PyList_SET_ITEM(result, 0, (PyObject*)item);
Py_DECREF((PyObject*)tempx);
return result;
}
mpz_init(temp);
guard_bit = nbits + (2 * mp_bits_per_limb);
extra_bits = 0;
index = 0;
while (lst_ptr < lst_count) {
i = 0;
temp_bits = 0;
mpz_set_ui(temp, 0);
mpz_setbit(temp, guard_bit);
while (temp_bits + extra_bits < nbits) {
temp->_mp_d[i++] = mpz_getlimbn(tempx->z, index++);
temp_bits += mp_bits_per_limb;
}
mpz_clrbit(temp, guard_bit);
mpz_mul_2exp(temp, temp, extra_bits);
if (mpz_sgn(temp) == 0 && extra != 0) {
mpz_set_ui(temp, 1);
temp->_mp_d[0] = extra;
}
else {
mpn_add_1(temp->_mp_d, temp->_mp_d, mpz_size(temp), extra);
}
temp_bits += extra_bits;
while ((lst_ptr < lst_count) && (temp_bits >= nbits)) {
if(!(item = GMPy_MPZ_New(context))) {
mpz_clear(temp);
Py_DECREF((PyObject*)tempx);
Py_DECREF(result);
return NULL;
}
mpz_tdiv_r_2exp(item->z, temp, nbits);
PyList_SET_ITEM(result, lst_ptr++, (PyObject*)item);
mpz_tdiv_q_2exp(temp, temp, nbits);
temp_bits -= nbits;
}
extra = mpz_getlimbn(temp, 0);
extra_bits = temp_bits;
}
Py_DECREF((PyObject*)tempx);
mpz_clear(temp);
return result;
}
gmpy2-2.1.0b3/src/gmpy2_mpz_pack.h 0000664 0001750 0001750 00000004435 13425753360 016547 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_pack.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_PACK_H
#define GMPY_MPZ_PACK_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_pack(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_unpack(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_mul.c 0000664 0001750 0001750 00000040626 13425753373 015541 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mul.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the * operator, gmpy2.mul() and context.mul().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*
* GMPy_Number_Mul(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_MPZ_Mul_Slot
* GMPy_MPQ_Mul_Slot
* GMPy_MPFR_Mul_Slot
* GMPy_MPC_Mul_Slot
*
* GMPy_Integer_Mul(Integer, Integer, context|NULL)
* GMPy_Rational_Mul(Rational, Rational, context|NULL)
* GMPy_Real_Mul(Real, Real, context|NULL)
* GMPy_Complex_Mul(Complex, Complex, context|NULL)
*
* GMPy_Context_Mul(context, args)
*
*/
/* Multiply two Integer objects (see gmpy2_convert.c). If an error occurs,
* NULL is returned and an exception is set. If either x or y can't be
* converted into an mpz, Py_NotImplemented is returned. */
static PyObject *
GMPy_Integer_Mul(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPZ_Check(x)) {
if (PyIntOrLong_Check(y)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(y, &error);
if (!error) {
mpz_mul_si(result->z, MPZ(x), temp);
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpz_mul(result->z, MPZ(x), global.tempz);
}
return (PyObject*)result;
}
if (MPZ_Check(y)) {
mpz_mul(result->z, MPZ(x), MPZ(y));
return (PyObject*)result;
}
}
if (MPZ_Check(y)) {
if (PyIntOrLong_Check(x)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(x, &error);
if (!error) {
mpz_mul_si(result->z, MPZ(y), temp);
}
else {
mpz_set_PyIntOrLong(global.tempz, x);
mpz_mul(result->z, MPZ(y), global.tempz);
}
return (PyObject*)result;
}
}
if (IS_INTEGER(x) && IS_INTEGER(y)) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_Integer(x, context)) ||
!(tempy = GMPy_MPZ_From_Integer(y, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_mul(result->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
SYSTEM_ERROR("Internal error in GMPy_Integer_Mul().");
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Implement __mul__ for MPZ_Object. On entry, one of the two arguments must
* be an MPZ_Object. If the other object is an Integer, add and return an
* MPZ_Object. If the other object isn't an MPZ_Object, call the appropriate
* function. If no appropriate function can be found, return NotImplemented. */
static PyObject *
GMPy_MPZ_Mul_Slot(PyObject *x, PyObject *y)
{
if (MPZ_Check(x) && MPZ_Check(y)) {
MPZ_Object *result = NULL;
if ((result = GMPy_MPZ_New(NULL))) {
mpz_mul(result->z, MPZ(x), MPZ(y));
}
return (PyObject*)result;
}
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_Mul(x, y, NULL);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Mul(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Mul(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Mul(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* Multiply two Rational objects (see convert.c/IS_RATIONAL). Returns None and
* raises TypeError if both objects are not valid rationals. GMPy_Rational_Mul
* is intended to be called from GMPy_Number_Mul. */
static PyObject *
GMPy_Rational_Mul(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPQ_Check(x) && MPQ_Check(y)) {
mpq_mul(result->q, MPQ(x), MPQ(y));
return (PyObject*)result;
}
if (IS_RATIONAL(x) && IS_RATIONAL(y)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_Number(x, context)) ||
!(tempy = GMPy_MPQ_From_Number(y, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_mul(result->q, tempx->q, tempy->q);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
SYSTEM_ERROR("Internal error in GMPy_Rational_Mul().");
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Implement __mul__ for Pympq. On entry, one of the two arguments must
* be a Pympq. If the other object is a Rational, add and return a Pympq.
* If the other object isn't a Pympq, call the appropriate function. If
* no appropriate function can be found, return NotImplemented. */
static PyObject *
GMPy_MPQ_Mul_Slot(PyObject *x, PyObject *y)
{
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Mul(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Mul(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Mul(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* Attempt to multiply two numbers and return an mpfr. The code path is
* optimized by checking for mpfr objects first. Returns Py_NotImplemented if
* both objects are not valid reals. */
static PyObject *
GMPy_Real_Mul(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPFR_Check(x) && MPFR_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_mul(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
goto done;
}
if (MPFR_Check(x)) {
if (PyIntOrLong_Check(y)) {
int error;
long temp = GMPy_Integer_AsLongAndError(y, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_mul_si(result->f, MPFR(x), temp, GET_MPFR_ROUND(context));
goto done;
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpfr_clear_flags();
result->rc = mpfr_mul_z(result->f, MPFR(x), global.tempz, GET_MPFR_ROUND(context));
goto done;
}
}
if (CHECK_MPZANY(y)) {
mpfr_clear_flags();
result->rc = mpfr_mul_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context));
goto done;
}
if (IS_RATIONAL(y)) {
MPQ_Object *tempy = NULL;
if (!(tempy = GMPy_MPQ_From_Number(y, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_mul_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempy);
goto done;
}
if (PyFloat_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_mul_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context));
goto done;
}
}
if (MPFR_Check(y)) {
if (PyIntOrLong_Check(x)) {
int error;
long temp = GMPy_Integer_AsLongAndError(x, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_mul_si(result->f, MPFR(y), temp, GET_MPFR_ROUND(context));
goto done;
}
else {
mpz_set_PyIntOrLong(global.tempz, x);
mpfr_clear_flags();
result->rc = mpfr_mul_z(result->f, MPFR(y), global.tempz, GET_MPFR_ROUND(context));
goto done;
}
}
if (CHECK_MPZANY(x)) {
mpfr_clear_flags();
result->rc = mpfr_mul_z(result->f, MPFR(y), MPZ(x), GET_MPFR_ROUND(context));
goto done;
}
if (IS_RATIONAL(x)) {
MPQ_Object *tempx = NULL;
if (!(tempx = GMPy_MPQ_From_Number(x, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_mul_q(result->f, MPFR(y), tempx->q, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
goto done;
}
if (PyFloat_Check(x)) {
mpfr_clear_flags();
result->rc = mpfr_mul_d(result->f, MPFR(y), PyFloat_AS_DOUBLE(x), GET_MPFR_ROUND(context));
goto done;
}
}
if (IS_REAL(x) && IS_REAL(y)) {
MPFR_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context)) ||
!(tempy = GMPy_MPFR_From_Real(y, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_mul(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
goto done;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
SYSTEM_ERROR("Internal error in GMPy_Real_Mul().");
return NULL;
/* LCOV_EXCL_STOP */
done:
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* Implement __mul__ for Pympfr. On entry, one of the two arguments must
* be a Pympfr. If the other object is a Real, add and return a Pympfr.
* If the other object isn't a Pympfr, call the appropriate function. If
* no appropriate function can be found, return NotImplemented. */
static PyObject *
GMPy_MPFR_Mul_Slot(PyObject *x, PyObject *y)
{
if (MPFR_Check(x) && MPFR_Check(y)) {
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_mul(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Mul(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Mul(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* GMPy_Complex_Mul(x, y, context) returns x*y using the provided context. If
* an error occurs, NULL is returned and an exception is set. If either x or
* y can't be converted to an mpc, then Py_NotImplemented is returned. */
static PyObject *
GMPy_Complex_Mul(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPC_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPC_Check(x) && MPC_Check(y)) {
result->rc = mpc_mul(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_COMPLEX(x) && IS_COMPLEX(y)) {
MPC_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context)) ||
!(tempy = GMPy_MPC_From_Complex(y, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpc_mul(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
SYSTEM_ERROR("Internal error in GMPy_Complex_Mul().");
return NULL;
/* LCOV_EXCL_STOP */
}
/* GMPy_MPZ_Mul_Slot() is called by mpc.__mul__. It just gets a borrowed reference
* to the current context and call Pympc_Mul_Complex(). Since mpc is the last
* step of the numeric ladder, the NotImplemented return value from
* Pympc_Add_Complex() is correct and is just passed on. */
static PyObject *
GMPy_MPC_Mul_Slot(PyObject *x, PyObject *y)
{
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Mul(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Number_Mul(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_Mul(x, y, context);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Mul(x, y, context);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Mul(x, y, context);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Mul(x, y, context);
TYPE_ERROR("mul() argument type not supported");
return NULL;
}
/* Implement context.mul() and gmpy2.mul(). */
PyDoc_STRVAR(GMPy_doc_function_mul,
"mul(x, y) -> number\n\n"
"Return x * y.");
PyDoc_STRVAR(GMPy_doc_context_mul,
"context.mul(x, y) -> number\n\n"
"Return x * y.");
static PyObject *
GMPy_Context_Mul(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mul() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Mul(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
gmpy2-2.1.0b3/src/gmpy2_mul.h 0000664 0001750 0001750 00000005640 13425753406 015540 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mul.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_MUL_H
#define GMPY2_MUL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Mul(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_Mul(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Rational_Mul(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Real_Mul(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_Mul(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_MPZ_Mul_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPQ_Mul_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPFR_Mul_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPC_Mul_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_Mul(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_muldiv_2exp.c 0000664 0001750 0001750 00000016072 13425753501 017171 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_muldiv_2exp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *
GMPy_Real_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result, *tempx;
unsigned long exp = 0;
CHECK_CONTEXT(context);
exp = c_ulong_From_Integer(y);
if (exp == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
if (!result || !tempx) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_mul_2ui(result->f, tempx->f, exp, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPC_Object *result, *tempx;
unsigned long exp = 0;
CHECK_CONTEXT(context);
exp = c_ulong_From_Integer(y);
if (exp == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
result = GMPy_MPC_New(0, 0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
result->rc = mpc_mul_2ui(result->c, tempx->c, exp, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_mul_2exp,
"context.mul_2exp(x, n) -> number\n\n"
"Return 'mpfr' or 'mpc' multiplied by 2**n.");
PyDoc_STRVAR(GMPy_doc_function_mul_2exp,
"mul_2exp(x, n) -> number\n\n"
"Return 'mpfr' or 'mpc' multiplied by 2**n.");
static PyObject *
GMPy_Number_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x))
return GMPy_Real_Mul_2exp(x, y, context);
if (IS_COMPLEX(x))
return GMPy_Complex_Mul_2exp(x, y, context);
TYPE_ERROR("mul_2exp() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Mul_2exp(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mul_2exp() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Mul_2exp(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
/* ======================================================================= */
static PyObject *
GMPy_Real_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result, *tempx;
unsigned long exp = 0;
CHECK_CONTEXT(context);
exp = c_ulong_From_Integer(y);
if (exp == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
if (!result || !tempx) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_div_2ui(result->f, tempx->f, exp, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPC_Object *result, *tempx;
unsigned long exp = 0;
CHECK_CONTEXT(context);
exp = c_ulong_From_Integer(y);
if (exp == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
result = GMPy_MPC_New(0, 0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
result->rc = mpc_div_2ui(result->c, tempx->c, exp, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_div_2exp,
"context.div_2exp(x, n) -> number\n\n"
"Return 'mpfr' or 'mpc' divided by 2**n.");
PyDoc_STRVAR(GMPy_doc_function_div_2exp,
"div_2exp(x, n) -> number\n\n"
"Return 'mpfr' or 'mpc' divided by 2**n.");
static PyObject *
GMPy_Number_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x))
return GMPy_Real_Div_2exp(x, y, context);
if (IS_COMPLEX(x))
return GMPy_Complex_Div_2exp(x, y, context);
TYPE_ERROR("div_2exp() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Div_2exp(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("div_2exp() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Div_2exp(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
gmpy2-2.1.0b3/src/gmpy2_muldiv_2exp.h 0000664 0001750 0001750 00000005505 13425753512 017177 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_muldiv_2exp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MULDIV_2EXP_H
#define GMPY_MULDIV_2EXP_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Real_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Mul_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Div_2exp(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_plus.c 0000664 0001750 0001750 00000011267 13425753526 015726 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_plus.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __pos__ and context.plus().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. If the value
* of context is NULL, then the function should use the currently active
* context.
*
* GMPy_Number_Plus(Number, context)
*
* Private API
* ===========
* GMPy_MPZ_Plus_Slot
* GMPy_MPQ_Plus_Slot
* GMPy_MPFR_Plus_Slot
* GMPy_MPC_Plus_Slot
*
* GMPy_Integer_Plus(Integer, context|NULL)
* GMPy_Rational_Plus(Rational, context|NULL)
* GMPy_Real_Plus(Real, context|NULL)
* GMPy_Complex_Plus(Complex, context|NULL)
*
* GMPy_Context_Plus(context, args)
*/
static PyObject *
GMPy_Integer_Plus(PyObject *x, CTXT_Object *context)
{
return (PyObject*)GMPy_MPZ_From_Integer(x, context);
}
static PyObject *
GMPy_MPZ_Plus_Slot(MPZ_Object *x)
{
Py_INCREF((PyObject*)x);
return (PyObject*)x;
}
static PyObject *
GMPy_Rational_Plus(PyObject *x, CTXT_Object *context)
{
return (PyObject*)GMPy_MPQ_From_Rational(x, context);
}
static PyObject *
GMPy_MPQ_Plus_Slot(MPQ_Object *x)
{
Py_INCREF((PyObject*)x);
return (PyObject*)x;
}
static PyObject *
GMPy_Real_Plus(PyObject *x, CTXT_Object *context)
{
return (PyObject*)GMPy_MPFR_From_Real(x, 0, context);
}
static PyObject *
GMPy_MPFR_Plus_Slot(MPFR_Object *x)
{
return (PyObject*)GMPy_MPFR_From_MPFR(x, 0, NULL);
}
static PyObject *
GMPy_Complex_Plus(PyObject *x, CTXT_Object *context)
{
return (PyObject*)GMPy_MPC_From_Complex(x, 0, 0, context);
}
static PyObject *
GMPy_MPC_Plus_Slot(MPC_Object *x)
{
return (PyObject*)GMPy_MPC_From_MPC(x, 0, 0, NULL);
}
static PyObject *
GMPy_Number_Plus(PyObject *x, CTXT_Object *context)
{
if (IS_INTEGER(x))
return GMPy_Integer_Plus(x, context);
if (IS_RATIONAL_ONLY(x))
return GMPy_Rational_Plus(x, context);
if (IS_REAL_ONLY(x))
return GMPy_Real_Plus(x, context);
if (IS_COMPLEX_ONLY(x))
return GMPy_Complex_Plus(x, context);
TYPE_ERROR("plus() argument type not supported");
return NULL;
}
/* Implement context.plus(). The following code assumes it used a as method of
* a context. */
PyDoc_STRVAR(GMPy_doc_context_plus,
"context.plus(x) -> number\n\n"
"Return +x, the context is applied to the result.");
static PyObject *
GMPy_Context_Plus(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("plus() requires 1 argument.");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Plus(PyTuple_GET_ITEM(args, 0), context);
}
gmpy2-2.1.0b3/src/gmpy2_plus.h 0000664 0001750 0001750 00000005501 13425753540 015721 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_plus.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_PLUS_H
#define GMPY2_PLUS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Plus(PyObject *x, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_Plus(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Rational_Plus(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Real_Plus(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Plus(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPZ_Plus_Slot(MPZ_Object *x);
static PyObject * GMPy_MPQ_Plus_Slot(MPQ_Object *x);
static PyObject * GMPy_MPFR_Plus_Slot(MPFR_Object *x);
static PyObject * GMPy_MPC_Plus_Slot(MPC_Object *x);
static PyObject * GMPy_Context_Plus(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_pow.c 0000664 0001750 0001750 00000042035 13425753552 015544 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_pow.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the ** operator, Python's pow() function,
* gmpy2.powmod(), and context.pow().
*
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*
* GMPy_Number_Pow(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_MPANY_Pow_Slot
*
* GMPy_Integer_Pow(Integer, Integer, Integer|Py_None, context|NULL)
* GMPy_Integer_PowMod(Integer, Integer, Integer|Py_None, context|NULL)
* GMPy_Rational_Pow(Rational, Rational, context|NULL)
* GMPy_Real_Pow(Real, Real, context|NULL)
* GMPy_Complex_Pow(Complex, Complex, context|NULL)
*
* GMPy_Context_Pow(context, args)
*/
/* Pympz_Pow_Integer is called by GMPy_Number_Pow() after verifying that the
* first two arguments are integers, but not necessarily mpz. The third
* argument must either be an integer or Py_None. The context argument is not
* currently used but may be used in the future.
*/
/* TODO: refactor to improve performance.
* - dont't convert the exponent to an MPZ if there is no modulus
*/
static PyObject *
GMPy_Integer_Pow(PyObject *b, PyObject *e, PyObject *m, CTXT_Object *context)
{
MPZ_Object *result = NULL, *tempb = NULL, *tempe = NULL, *tempm = NULL;
int has_mod;
/* Try to parse the modulus value first. */
if (m == Py_None) {
has_mod = 0;
}
else {
has_mod = 1;
if (!IS_INTEGER(m)) {
Py_RETURN_NOTIMPLEMENTED;
}
else {
if (!(tempm = GMPy_MPZ_From_Integer(m, context))) {
goto err;
}
}
}
result = GMPy_MPZ_New(context);
tempb = GMPy_MPZ_From_Integer(b, context);
tempe = GMPy_MPZ_From_Integer(e, context);
if (!tempb || !tempe || !result) {
goto err;
}
if (!has_mod) {
/* When no modulo is present, the exponent must fit in unsigned long.
*/
unsigned long el;
if (mpz_sgn(tempe->z) < 0) {
VALUE_ERROR("pow() exponent cannot be negative");
goto err;
}
/* Catch -1, 0, 1 getting raised to large exponents. */
if (mpz_cmp_si(tempb->z, 0) == 0) {
if (mpz_cmp_si(tempe->z, 0) == 0) {
mpz_set_ui(result->z, 1);
}
else {
mpz_set_ui(result->z, 0);
}
goto done;
}
if (mpz_cmp_si(tempb->z, 1) == 0) {
mpz_set_ui(result->z, 1);
goto done;
}
if (mpz_cmp_si(tempb->z, -1) == 0) {
if (mpz_even_p(tempe->z)) {
mpz_set_ui(result->z, 1);
}
else {
mpz_set_si(result->z, -1);
}
goto done;
}
if (!mpz_fits_ulong_p(tempe->z)) {
VALUE_ERROR("pow() outrageous exponent");
goto err;
}
el = (unsigned long) mpz_get_ui(tempe->z);
mpz_pow_ui(result->z, tempb->z, el);
goto done;
}
else {
/* Modulo is present. */
int sign;
mpz_t mm, base, exp;
sign = mpz_sgn(tempm->z);
if (sign == 0) {
VALUE_ERROR("pow() 3rd argument cannot be 0");
goto err;
}
mpz_init(mm);
mpz_abs(mm, tempm->z);
/* A negative exponent is allowed if inverse exists. */
if (mpz_sgn(tempe->z) < 0) {
mpz_init(base);
mpz_init(exp);
if (!mpz_invert(base, tempb->z, mm)) {
VALUE_ERROR("pow() base not invertible");
mpz_clear(base);
mpz_clear(exp);
mpz_clear(mm);
goto err;
}
else {
mpz_abs(exp, tempe->z);
}
mpz_powm(result->z, base, exp, mm);
mpz_clear(base);
mpz_clear(exp);
}
else {
mpz_powm(result->z, tempb->z, tempe->z, mm);
}
mpz_clear(mm);
/* Python uses a rather peculiar convention for negative modulos
* If the modulo is negative, result should be in the interval
* m < r <= 0 .
*/
if ((sign < 0) && (mpz_sgn(MPZ(result)) > 0)) {
mpz_add(result->z, result->z, tempm->z);
}
}
done:
Py_XDECREF((PyObject*)tempb);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempm);
return (PyObject*)result;
err:
Py_XDECREF((PyObject*)tempb);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempm);
Py_DECREF((PyObject*)result);
return NULL;
}
static PyObject *
GMPy_Rational_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context)
{
MPQ_Object *tempbq = NULL, *resultq = NULL;
MPZ_Object *tempez = NULL;
int bsign;
long tempexp;
if (mod != Py_None) {
TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers");
return NULL;
}
/* Only support mpq**int. Everything else gets converted to mpf. */
if (IS_RATIONAL(base) && IS_INTEGER(exp)) {
resultq = GMPy_MPQ_New(context);
tempbq = GMPy_MPQ_From_Rational(base, context);
tempez = GMPy_MPZ_From_Integer(exp, context);
if (!resultq || !tempbq || !tempez) {
Py_XDECREF((PyObject*)resultq);
Py_XDECREF((PyObject*)tempbq);
Py_XDECREF((PyObject*)tempez);
return NULL;
}
if (!mpz_fits_slong_p(tempez->z)) {
VALUE_ERROR("mpq.pow() outrageous exponent");
Py_DECREF((PyObject*)resultq);
Py_DECREF((PyObject*)tempbq);
Py_DECREF((PyObject*)tempez);
return NULL;
}
tempexp = (long) mpz_get_si(tempez->z);
if (tempexp == 0) {
mpq_set_si(resultq->q, 1, 1);
Py_DECREF((PyObject*)tempbq);
Py_DECREF((PyObject*)tempez);
return (PyObject*)resultq;
}
bsign = mpq_sgn(tempbq->q);
if (tempexp < 0) {
if (bsign == 0) {
ZERO_ERROR("pow() 0 base to negative exponent");
Py_DECREF((PyObject*)resultq);
Py_DECREF((PyObject*)tempbq);
Py_DECREF((PyObject*)tempez);
return NULL;
}
if (bsign < 0) {
mpz_neg(mpq_numref(resultq->q), mpq_denref(tempbq->q));
}
else {
mpz_set(mpq_numref(resultq->q), mpq_denref(tempbq->q));
}
mpz_abs(mpq_denref(resultq->q), mpq_numref(tempbq->q));
tempexp = -tempexp;
}
else {
mpq_set(resultq->q, tempbq->q);
}
if (tempexp > 1) {
mpz_pow_ui(mpq_numref(resultq->q), mpq_numref(resultq->q), tempexp);
mpz_pow_ui(mpq_denref(resultq->q), mpq_denref(resultq->q), tempexp);
}
Py_DECREF((PyObject*)tempbq);
Py_DECREF((PyObject*)tempez);
return (PyObject*)resultq;
}
else {
return GMPy_Real_Pow(base, exp, Py_None, context);
}
}
static PyObject *
GMPy_Real_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context)
{
MPFR_Object *tempb = NULL, *tempe = NULL, *result = NULL;
MPZ_Object *tempz = NULL;
MPC_Object *mpc_result = NULL;
if (mod != Py_None) {
TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers");
return NULL;
}
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempb = GMPy_MPFR_From_Real(base, 1, context);
if (!result || !tempb) {
goto err;
}
mpfr_clear_flags();
if (PyIntOrLong_Check(exp)) {
int error;
long temp_exp = GMPy_Integer_AsLongAndError(exp, &error);
if (!error) {
result->rc = mpfr_pow_si(result->f, tempb->f, temp_exp, GET_MPFR_ROUND(context));
}
else {
mpz_t tempzz;
mpz_init(tempzz);
mpz_set_PyIntOrLong(tempzz, exp);
result->rc = mpfr_pow_z(result->f, tempb->f, tempzz, GET_MPFR_ROUND(context));
mpz_clear(tempzz);
}
}
else if (IS_INTEGER(exp)) {
if (!(tempz = GMPy_MPZ_From_Integer(exp, context))) {
goto err;
}
result->rc = mpfr_pow_z(result->f, tempb->f, tempz->z, GET_MPFR_ROUND(context));
}
else {
if (!(tempe = GMPy_MPFR_From_Real(exp, 1, context))) {
goto err;
}
result->rc = mpfr_pow(result->f, tempb->f, tempe->f, GET_MPFR_ROUND(context));
}
/* If the result is NaN, check if a complex result works. */
if (mpfr_nanflag_p() && context->ctx.allow_complex) {
mpc_result = (MPC_Object*)GMPy_Complex_Pow(base, exp, Py_None, context);
if (!mpc_result || MPC_IS_NAN_P(mpc_result)) {
Py_XDECREF((PyObject*)mpc_result);
context->ctx.invalid = 1;
GMPY_INVALID("pow() invalid operation");
goto err;
}
/* return a valid complex result */
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempb);
Py_XDECREF((PyObject*)result);
return (PyObject*)mpc_result;
}
_GMPy_MPFR_Cleanup(&result, context);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempb);
return (PyObject*)result;
err:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempb);
return NULL;
}
static PyObject *
GMPy_Complex_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context)
{
MPC_Object *tempb = NULL, *tempe = NULL, *result= NULL;
MPFR_Object *tempf = NULL;
MPZ_Object *tempz = NULL;
if (mod != Py_None) {
TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers");
return NULL;
}
CHECK_CONTEXT(context);
result = GMPy_MPC_New(0, 0, context);
tempb = GMPy_MPC_From_Complex(base, 1, 1, context);
if (!result || !tempb) {
goto err;
}
mpfr_clear_flags();
if (PyIntOrLong_Check(exp)) {
int error;
long temp_exp = GMPy_Integer_AsLongAndError(exp, &error);
if (!error) {
result->rc = mpc_pow_si(result->c, tempb->c, temp_exp, GET_MPC_ROUND(context));
}
else {
mpz_t tempzz;
mpz_init(tempzz);
mpz_set_PyIntOrLong(tempzz, exp);
result->rc = mpc_pow_z(result->c, tempb->c, tempzz, GET_MPC_ROUND(context));
mpz_clear(tempzz);
}
}
else if (IS_INTEGER(exp)) {
if (!(tempz = GMPy_MPZ_From_Integer(exp, context))) {
goto err;
}
result->rc = mpc_pow_z(result->c, tempb->c, tempz->z, GET_MPC_ROUND(context));
}
else if (IS_REAL(exp)) {
if (!(tempf = GMPy_MPFR_From_Real(exp, 1, context))) {
goto err;
}
result->rc = mpc_pow_fr(result->c, tempb->c, tempf->f, GET_MPC_ROUND(context));
}
else {
if (!(tempe = GMPy_MPC_From_Complex(exp, 1, 1, context))) {
goto err;
}
result->rc = mpc_pow(result->c, tempb->c, tempe->c, GET_MPC_ROUND(context));
}
_GMPy_MPC_Cleanup(&result, context);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempf);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempb);
return (PyObject*)result;
err:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempf);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempb);
return NULL;
}
PyDoc_STRVAR(GMPy_doc_integer_powmod,
"powmod(x, y, m) -> mpz\n\n"
"Return (x**y) mod m. Same as the three argument version of Python's\n"
"built-in pow(), but converts all three arguments to mpz.");
static PyObject *
GMPy_Integer_PowMod(PyObject *self, PyObject *args)
{
PyObject *x, *y, *m;
if (PyTuple_GET_SIZE(args) != 3) {
TYPE_ERROR("powmod() requires 3 arguments.");
return NULL;
}
x = PyTuple_GET_ITEM(args, 0);
y = PyTuple_GET_ITEM(args, 1);
m = PyTuple_GET_ITEM(args, 2);
if (IS_INTEGER(x) && IS_INTEGER(y) && IS_INTEGER(m))
return GMPy_Integer_Pow(x, y, m, NULL);
TYPE_ERROR("powmod() argument types not supported");
return NULL;
}
static PyObject *
GMPy_Number_Pow(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_Pow(x, y, z, context);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Pow(x, y, z, context);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Pow(x, y, z, context);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Pow(x, y, z, context);
TYPE_ERROR("pow() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_pow,
"context.pow(x, y) -> number\n\n"
"Return x ** y.");
static PyObject *
GMPy_Context_Pow(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("pow() requires 2 arguments.");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Pow(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1),
Py_None, context);
}
static PyObject *
GMPy_MPANY_Pow_Slot(PyObject *base, PyObject *exp, PyObject *mod)
{
if (IS_INTEGER(base) && IS_INTEGER(exp))
return GMPy_Integer_Pow(base, exp, mod, NULL);
if (IS_RATIONAL(base) && IS_RATIONAL(exp))
return GMPy_Rational_Pow(base, exp, mod, NULL);
if (IS_REAL(base) && IS_REAL(exp))
return GMPy_Real_Pow(base, exp, mod, NULL);
if (IS_COMPLEX(base) && IS_COMPLEX(exp))
return GMPy_Complex_Pow(base, exp, mod, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_MPFR_Pow_Slot(PyObject *base, PyObject *exp, PyObject *mod)
{
if (MPFR_Check(base) && (PyIntOrLong_Check(exp)) && (mod == Py_None)) {
MPFR_Object *result = NULL;
int error = 0;
long temp_exp;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
temp_exp = GMPy_Integer_AsLongAndError(exp, &error);
if (!error) {
result->rc = mpfr_pow_si(result->f, MPFR(base), temp_exp, GET_MPFR_ROUND(context));
}
else {
mpz_t tempzz;
mpz_init(tempzz);
mpz_set_PyIntOrLong(tempzz, exp);
result->rc = mpfr_pow_z(result->f, MPFR(base), tempzz, GET_MPFR_ROUND(context));
mpz_clear(tempzz);
}
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
if (IS_REAL(base) && IS_REAL(exp))
return GMPy_Real_Pow(base, exp, mod, NULL);
if (IS_COMPLEX(base) && IS_COMPLEX(exp))
return GMPy_Complex_Pow(base, exp, mod, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
gmpy2-2.1.0b3/src/gmpy2_pow.h 0000664 0001750 0001750 00000005735 13425753563 015561 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_pow.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_POW_H
#define GMPY2_POW_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private API */
static PyObject * GMPy_MPANY_Pow_Slot(PyObject *base, PyObject *exp, PyObject *mod);
static PyObject * GMPy_MPFR_Pow_Slot(PyObject *base, PyObject *exp, PyObject *mod);
static PyObject * GMPy_Integer_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context);
static PyObject * GMPy_Rational_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context);
static PyObject * GMPy_Real_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context);
static PyObject * GMPy_Complex_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context);
static PyObject * GMPy_Integer_PowMod(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Pow(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Pow(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_predicate.c 0000664 0001750 0001750 00000034213 13425753604 016674 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_predicate.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* To work with the MPC_IS_ macros, NAN, INF, FINITE, and ZERO are
* all upper-case.
*/
PyDoc_STRVAR(GMPy_doc_function_is_nan,
"is_nan(x) -> boolean\n\n"
"Return True if x is NaN (Not-A-Number).");
PyDoc_STRVAR(GMPy_doc_context_is_nan,
"context.is_nan(x) -> boolean\n\n"
"Return True if x is NaN (Not-A-Number).");
PyDoc_STRVAR(GMPy_doc_method_is_nan,
"x.is_nan() -> boolean\n\n"
"Return True if x is NaN (Not-A-Number).");
static PyObject *
GMPy_Real_Is_NAN(PyObject *x, CTXT_Object *context)
{
MPFR_Object *tempx;
int res;
if (MPFR_Check(x)) {
res = mpfr_nan_p(MPFR(x));
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
res = mpfr_nan_p(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_NAN_Method(PyObject *self, PyObject *args)
{
return GMPy_Real_Is_NAN(self, NULL);
}
static PyObject *
GMPy_Complex_Is_NAN(PyObject *x, CTXT_Object *context)
{
MPC_Object *tempx;
int res;
if (MPC_Check(x)) {
res = MPC_IS_NAN_P(x);
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
res = MPC_IS_NAN_P(tempx);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPC_Is_NAN_Method(PyObject *self, PyObject *args)
{
return GMPy_Complex_Is_NAN(self, NULL);
}
/* This creates the following functions:
* GMPy_Number_Is_NAN(x, context)
* GMPy_Context_Is_NAN(self, other)
*
* They assume the following functions have been defined above:
* GMPy_Real_Is_NAN(x, context)
* GMPy_Complex_Is_NAN(x, context)
*
* In addition, the following function should also be defined:
* GMPy_Real_Is_NAN_Method(self, noargs)
* GMPy_Complex_Is_NAN_Method(self, noargs)
*/
GMPY_MPFR_MPC_UNIOP_TEMPLATE(Is_NAN, is_nan);
PyDoc_STRVAR(GMPy_doc_function_is_infinite,
"is_infinite(x) -> boolean\n\n"
"Return True if x is +Infinity or -Infinity. If x is an mpc, return True\n"
"if either x.real or x.imag is infinite. ");
PyDoc_STRVAR(GMPy_doc_context_is_infinite,
"context.is_infinite(x) -> boolean\n\n"
"Return True if x is +Infinity or -Infinity. If x is an mpc, return True\n"
"if either x.real or x.imag is infinite.");
PyDoc_STRVAR(GMPy_doc_method_is_infinite,
"x.is_infinite() -> boolean\n\n"
"Return True if x is +Infinity or -Infinity. If x is an mpc, return True\n"
"if either x.real or x.imag is infinite.");
static PyObject *
GMPy_Real_Is_Infinite(PyObject *x, CTXT_Object *context)
{
MPFR_Object *tempx;
int res;
if (MPFR_Check(x)) {
res = mpfr_inf_p(MPFR(x));
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
res = mpfr_inf_p(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_Infinite_Method(PyObject *self, PyObject *args)
{
return GMPy_Real_Is_Infinite(self, NULL);
}
static PyObject *
GMPy_Complex_Is_Infinite(PyObject *x, CTXT_Object *context)
{
MPC_Object *tempx;
int res;
if (MPC_Check(x)) {
res = MPC_IS_INF_P(x);
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
res = MPC_IS_INF_P(tempx);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPC_Is_Infinite_Method(PyObject *self, PyObject *args)
{
return GMPy_Complex_Is_Infinite(self, NULL);
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE(Is_Infinite, is_infinite);
PyDoc_STRVAR(GMPy_doc_function_is_finite,
"is_finite(x) -> boolean\n\n"
"Return True if x is an actual number (i.e. non NaN or Infinity). If x is\n"
"an mpc, return True if both x.real and x.imag are finite.");
PyDoc_STRVAR(GMPy_doc_context_is_finite,
"context.is_finite(x) -> boolean\n\n"
"Return True if x is an actual number (i.e. non NaN or Infinity). If x is\n"
"an mpc, return True if both x.real and x.imag are finite.");
PyDoc_STRVAR(GMPy_doc_method_is_finite,
"x.is_finite() -> boolean\n\n"
"Return True if x is an actual number (i.e. non NaN or Infinity). If x is\n"
"an mpc, return True if both x.real and x.imag are finite.");
static PyObject *
GMPy_Real_Is_Finite(PyObject *x, CTXT_Object *context)
{
MPFR_Object *tempx;
int res;
if (MPFR_Check(x)) {
res = mpfr_number_p(MPFR(x));
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
res = mpfr_number_p(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_Finite_Method(PyObject *self, PyObject *args)
{
return GMPy_Real_Is_Finite(self, NULL);
}
static PyObject *
GMPy_Complex_Is_Finite(PyObject *x, CTXT_Object *context)
{
MPC_Object *tempx;
int res;
if (MPC_Check(x)) {
res = MPC_IS_FINITE_P(x);
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
res = MPC_IS_FINITE_P(tempx);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPC_Is_Finite_Method(PyObject *self, PyObject *args)
{
return GMPy_Complex_Is_Finite(self, NULL);
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE(Is_Finite, is_finite);
PyDoc_STRVAR(GMPy_doc_function_is_zero,
"is_zero(x) -> boolean\n\n"
"Return True if x is equal to 0. If x is an mpc, return True if both x.real\n"
"and x.imag are equal to 0.");
PyDoc_STRVAR(GMPy_doc_context_is_zero,
"context.is_zero(x) -> boolean\n\n"
"Return True if x is equal to 0. If x is an mpc, return True if both x.real\n"
"and x.imag are equal to 0.");
PyDoc_STRVAR(GMPy_doc_method_is_zero,
"x.is_zero() -> boolean\n\n"
"Return True if x is equal to 0. If x is an mpc, return True if both x.real\n"
"and x.imag are equal to 0.");
static PyObject *
GMPy_Real_Is_Zero(PyObject *x, CTXT_Object *context)
{
MPFR_Object *tempx;
int res;
if (MPFR_Check(x)) {
res = mpfr_zero_p(MPFR(x));
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
res = mpfr_zero_p(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_Zero_Method(PyObject *self, PyObject *args)
{
return GMPy_Real_Is_Zero(self, NULL);
}
static PyObject *
GMPy_Complex_Is_Zero(PyObject *x, CTXT_Object *context)
{
MPC_Object *tempx;
int res;
if (MPC_Check(x)) {
res = MPC_IS_ZERO_P(x);
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
res = MPC_IS_ZERO_P(tempx);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPC_Is_Zero_Method(PyObject *self, PyObject *args)
{
return GMPy_Complex_Is_Zero(self, NULL);
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE(Is_Zero, is_zero);
PyDoc_STRVAR(GMPy_doc_function_is_signed,
"is_signed(x) -> boolean\n\n"
"Return True if the sign bit of x is set.");
PyDoc_STRVAR(GMPy_doc_context_is_signed,
"context.is_signed(x) -> boolean\n\n"
"Return True if the sign bit of x is set.");
PyDoc_STRVAR(GMPy_doc_method_is_signed,
"x.is_signed() -> boolean\n\n"
"Return True if the sign bit of x is set.");
static PyObject *
GMPy_Real_Is_Signed(PyObject *x, CTXT_Object *context)
{
MPFR_Object *tempx;
int res;
if (MPFR_Check(x)) {
res = mpfr_signbit(MPFR(x));
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
res = mpfr_signbit(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_Signed_Method(PyObject *self, PyObject *args)
{
return GMPy_Real_Is_Signed(self, NULL);
}
GMPY_MPFR_UNIOP_TEMPLATE(Is_Signed, is_signed);
PyDoc_STRVAR(GMPy_doc_function_is_regular,
"is_regular(x) -> boolean\n\n"
"Return True if x is not zero, NaN, or Infinity; False otherwise.");
PyDoc_STRVAR(GMPy_doc_context_is_regular,
"context.is_regular(x) -> boolean\n\n"
"Return True if x is not zero, NaN, or Infinity; False otherwise.");
PyDoc_STRVAR(GMPy_doc_method_is_regular,
"x.is_regular() -> boolean\n\n"
"Return True if x is not zero, NaN, or Infinity; False otherwise.");
static PyObject *
GMPy_Real_Is_Regular(PyObject *x, CTXT_Object *context)
{
MPFR_Object *tempx;
int res;
if (MPFR_Check(x)) {
res = mpfr_regular_p(MPFR(x));
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
res = mpfr_regular_p(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_Regular_Method(PyObject *self, PyObject *args)
{
return GMPy_Real_Is_Regular(self, NULL);
}
GMPY_MPFR_UNIOP_TEMPLATE(Is_Regular, is_regular);
PyDoc_STRVAR(GMPy_doc_function_is_integer,
"is_integer(x) -> boolean\n\n"
"Return True if x is an integer; False otherwise.");
PyDoc_STRVAR(GMPy_doc_context_is_integer,
"context.is_integer(x) -> boolean\n\n"
"Return True if x is an integer; False otherwise.");
PyDoc_STRVAR(GMPy_doc_method_is_integer,
"x.is_integer() -> boolean\n\n"
"Return True if x is an integer; False otherwise.");
static PyObject *
GMPy_Real_Is_Integer(PyObject *x, CTXT_Object *context)
{
MPFR_Object *tempx;
int res;
if (MPFR_Check(x)) {
res = mpfr_integer_p(MPFR(x));
}
else {
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
res = mpfr_integer_p(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_Integer_Method(PyObject *self, PyObject *args)
{
return GMPy_Real_Is_Integer(self, NULL);
}
GMPY_MPFR_UNIOP_TEMPLATE(Is_Integer, is_integer);
PyDoc_STRVAR(GMPy_doc_function_is_lessgreater,
"is_lessgreater(x,y) -> boolean\n\n"
"Return True if x > y or x < y. Return False if x == y or either x\n"
"and/or y is NaN.");
static PyObject *
GMPy_Real_Is_LessGreater(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *tempx, *tempy;
int res;
CHECK_CONTEXT(context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
tempy = GMPy_MPFR_From_Real(y, 1, context);
if (!tempx || !tempy) {
return NULL;
}
res = mpfr_lessgreater_p(tempx->f, tempy->f);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
GMPY_MPFR_BINOP_TEMPLATE(Is_LessGreater, is_lessgreater)
PyDoc_STRVAR(GMPy_doc_function_is_unordered,
"is_unordered(x,y) -> boolean\n\n"
"Return True if either x and/or y is NaN.");
static PyObject *
GMPy_Real_Is_Unordered(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *tempx, *tempy;
int res;
CHECK_CONTEXT(context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
tempy = GMPy_MPFR_From_Real(y, 1, context);
if (!tempx || !tempy) {
return NULL;
}
res = mpfr_unordered_p(tempx->f, tempy->f);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
GMPY_MPFR_BINOP_TEMPLATE(Is_Unordered, is_unordered)
gmpy2-2.1.0b3/src/gmpy2_predicate.h 0000664 0001750 0001750 00000012532 13425753615 016703 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_predicate.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_PREDICATE_H
#define GMPY_PREDICATE_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Real_Is_NAN(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_NAN_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Complex_Is_NAN(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPC_Is_NAN_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_NAN(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_NAN(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Is_Infinite(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_Infinite_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Complex_Is_Infinite(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPC_Is_Infinite_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Infinite(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Infinite(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Is_Finite(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_Finite_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Complex_Is_Finite(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPC_Is_Finite_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Finite(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Finite(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Is_Zero(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_Zero_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Complex_Is_Zero(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPC_Is_Zero_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Zero(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Zero(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Is_Signed(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_Signed_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Signed(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Signed(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Is_Regular(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_Regular_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Regular(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Regular(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Is_Integer(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_Integer_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Integer(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Integer(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Is_LessGreater(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Is_LessGreater(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Is_LessGreater(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Is_Unordered(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Is_Unordered(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Unordered(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_random.c 0000664 0001750 0001750 00000032475 13425753630 016223 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_random.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static RandomState_Object *
GMPy_RandomState_New(void)
{
RandomState_Object *result;
if ((result = PyObject_New(RandomState_Object, &RandomState_Type))) {
gmp_randinit_default(result->state);
}
return result;
};
static void
GMPy_RandomState_Dealloc(RandomState_Object *self)
{
gmp_randclear(self->state);
PyObject_Del(self);
};
static PyObject *
GMPy_RandomState_Repr(RandomState_Object *self)
{
return Py_BuildValue("s", "");
};
PyDoc_STRVAR(GMPy_doc_random_state_factory,
"random_state([seed]) -> object\n\n"
"Return new object containing state information for the random number\n"
"generator. An optional integer can be specified as the seed value.");
static PyObject *
GMPy_RandomState_Factory(PyObject *self, PyObject *args)
{
RandomState_Object *result;
MPZ_Object *temp;
if (!(result = GMPy_RandomState_New())) {
return NULL;
}
if (PyTuple_GET_SIZE(args) == 0) {
gmp_randseed_ui(result->state, 0);
}
else if (PyTuple_GET_SIZE(args) == 1) {
if (!(temp = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args,0), NULL))) {
Py_DECREF((PyObject*)result);
TYPE_ERROR("seed must be an integer");
return NULL;
}
gmp_randseed(result->state, temp->z);
Py_DECREF((PyObject*)temp);
}
else {
Py_DECREF((PyObject*)result);
TYPE_ERROR("random_state() requires 0 or 1 integer arguments");
return NULL;
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_urandomb_function,
"mpz_urandomb(random_state, bit_count) -> mpz\n\n"
"Return uniformly distributed random integer between 0 and\n"
"2**bit_count-1.");
static PyObject *
GMPy_MPZ_urandomb_Function(PyObject *self, PyObject *args)
{
MPZ_Object *result;
mp_bitcnt_t len;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mpz_urandomb() requires 2 arguments");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpz_urandomb() requires 'random_state' and 'bit_count' arguments");
return NULL;
}
len = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (len == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
TYPE_ERROR("mpz_urandomb() requires 'random_state' and 'bit_count' arguments");
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_urandomb(result->z, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), len);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_rrandomb_function,
"mpz_rrandomb(random_state, bit_count) -> mpz\n\n"
"Return a random integer between 0 and 2**bit_count-1 with long\n"
"sequences of zeros and one in its binary representation.");
static PyObject *
GMPy_MPZ_rrandomb_Function(PyObject *self, PyObject *args)
{
MPZ_Object *result;
mp_bitcnt_t len;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mpz_rrandomb() requires 2 arguments");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpz_rrandomb() requires 'random_state' and 'bit_count' arguments");
return NULL;
}
len = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
if (len == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
TYPE_ERROR("mpz_rrandomb() requires 'random_state' and 'bit_count' arguments");
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_rrandomb(result->z, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), len);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_random_function,
"mpz_random(random_state, int) -> mpz\n\n"
"Return uniformly distributed random integer between 0 and n-1.");
static PyObject *
GMPy_MPZ_random_Function(PyObject *self, PyObject *args)
{
MPZ_Object *result, *temp;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mpz_random() requires 2 arguments");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpz_random() requires 'random_state' and 'int' arguments");
return NULL;
}
if (!(temp = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) {
TYPE_ERROR("mpz_random() requires 'random_state' and 'int' arguments");
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_urandomm(result->z, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), temp->z);
}
Py_DECREF((PyObject*)temp);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_random_function,
"mpfr_random(random_state) -> mpfr\n\n"
"Return uniformly distributed number between [0,1].");
static PyObject *
GMPy_MPFR_random_Function(PyObject *self, PyObject *args)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfr_random() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpfr_random() requires 'random_state' argument");
return NULL;
}
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_urandom(result->f, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), GET_MPFR_ROUND(context));
}
return (PyObject*)result;
}
#if MPFR_VERSION_MAJOR > 3
PyDoc_STRVAR(GMPy_doc_mpfr_nrandom_function,
"mpfr_nrandom(random_state) -> (mpfr)\n\n"
"Return a random number with gaussian distribution.");
static PyObject *
GMPy_MPFR_nrandom_Function(PyObject *self, PyObject *args)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfr_nrandom() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpfr_nrandom() requires 'random_state' argument");
return NULL;
}
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_nrandom(result->f,
RANDOM_STATE(PyTuple_GET_ITEM(args, 0)),
GET_MPFR_ROUND(context));
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_grandom_function,
"mpfr_grandom(random_state) -> (mpfr, mpfr)\n\n"
"Return two random numbers with gaussian distribution.");
static PyObject *
GMPy_MPFR_grandom_Function(PyObject *self, PyObject *args)
{
MPFR_Object *result1, *result2;
PyObject *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfr_grandom() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpfr_grandom() requires 'random_state' argument");
return NULL;
}
result1 = GMPy_MPFR_New(0, context);
result2 = GMPy_MPFR_New(0, context);
if (!result1 || !result2) {
Py_XDECREF((PyObject*)result1);
Py_XDECREF((PyObject*)result2);
return NULL;
}
mpfr_nrandom(result1->f,
RANDOM_STATE(PyTuple_GET_ITEM(args, 0)),
GET_MPFR_ROUND(context));
mpfr_nrandom(result2->f,
RANDOM_STATE(PyTuple_GET_ITEM(args, 0)),
GET_MPFR_ROUND(context));
result = Py_BuildValue("(NN)", (PyObject*)result1, (PyObject*)result2);
if (!result) {
Py_DECREF((PyObject*)result1);
Py_DECREF((PyObject*)result2);
}
return result;
}
#else
PyDoc_STRVAR(GMPy_doc_mpfr_grandom_function,
"mpfr_grandom(random_state) -> (mpfr, mpfr)\n\n"
"Return two random numbers with gaussian distribution.");
static PyObject *
GMPy_MPFR_grandom_Function(PyObject *self, PyObject *args)
{
MPFR_Object *result1, *result2;
PyObject *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfr_grandom() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpfr_grandom() requires 'random_state' argument");
return NULL;
}
result1 = GMPy_MPFR_New(0, context);
result2 = GMPy_MPFR_New(0, context);
if (!result1 || !result2) {
Py_XDECREF((PyObject*)result1);
Py_XDECREF((PyObject*)result2);
return NULL;
}
mpfr_grandom(result1->f, result2->f,
RANDOM_STATE(PyTuple_GET_ITEM(args, 0)),
GET_MPFR_ROUND(context));
result = Py_BuildValue("(NN)", (PyObject*)result1, (PyObject*)result2);
if (!result) {
Py_DECREF((PyObject*)result1);
Py_DECREF((PyObject*)result2);
}
return result;
}
#endif
PyDoc_STRVAR(GMPy_doc_mpc_random_function,
"mpc_random(random_state) -> mpc\n\n"
"Return uniformly distributed number in the unit square [0,1]x[0,1].");
static PyObject *
GMPy_MPC_random_Function(PyObject *self, PyObject *args)
{
MPC_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfc_random() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpc_random() requires 'random_state' argument");
return NULL;
}
if ((result = GMPy_MPC_New(0, 0, context))) {
mpc_urandom(result->c, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)));
}
return (PyObject*)result;
}
static PyTypeObject RandomState_Type =
{
#ifdef PY3
PyVarObject_HEAD_INIT(0, 0)
#else
PyObject_HEAD_INIT(0)
0, /* ob_size */
#endif
"gmpy2 random state", /* tp_name */
sizeof(RandomState_Object), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) GMPy_RandomState_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_RandomState_Repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"GMPY2 Random number generator state", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset*/
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
};
gmpy2-2.1.0b3/src/gmpy2_random.h 0000664 0001750 0001750 00000006553 13425753642 016231 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_random.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_RANDOM_H
#define GMPY_RANDOM_H
#ifdef __cplusplus
extern "C" {
#endif
/* gmpy_random C API extension header file.
*
* Provide support random number state.
*
* Version 2.00, December 2011 (created) casevh
*
* This file is expected to be included from gmpy.h
*/
static PyTypeObject RandomState_Type;
#define RANDOM_STATE(obj) (((RandomState_Object *)(obj))->state)
#define RandomState_Check(v) (((PyObject*)v)->ob_type == &RandomState_Type)
static RandomState_Object * GMPy_RandomState_New(void);
static void GMPy_RandomState_Dealloc(RandomState_Object *self);
static PyObject * GMPy_RandomState_Repr(RandomState_Object *self);
static PyObject * GMPy_RandomState_Factory(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_urandomb_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_rrandomb_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_random_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_random_Function(PyObject *self, PyObject *args);
#if MPFR_VERSION_MAJOR > 3
static PyObject * GMPy_MPFR_nrandom_Function(PyObject *self, PyObject *args);
#endif
static PyObject * GMPy_MPFR_grandom_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_random_Function(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_richcompare.c 0000664 0001750 0001750 00000027613 13425753657 017246 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_richcompare.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *_cmp_to_object(int c, int op)
{
PyObject *result;
switch (op) {
case Py_LT: c = c < 0; break;
case Py_LE: c = c <= 0; break;
case Py_EQ: c = c == 0; break;
case Py_NE: c = c != 0; break;
case Py_GT: c = c > 0; break;
case Py_GE: c = c >= 0; break;
}
result = c ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
static PyObject *
GMPy_RichCompare_Slot(PyObject *a, PyObject *b, int op)
{
int c;
PyObject *tempa = NULL, *tempb = NULL, *result = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (CHECK_MPZANY(a)) {
if (PyIntOrLong_Check(b)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(b, &error);
if (!error) {
c = mpz_cmp_si(MPZ(a), temp);
}
else {
mpz_set_PyIntOrLong(global.tempz, b);
c = mpz_cmp(MPZ(a), global.tempz);
}
return _cmp_to_object(c, op);
}
if (CHECK_MPZANY(b)) {
return _cmp_to_object(mpz_cmp(MPZ(a), MPZ(b)), op);
}
if (IS_INTEGER(b)) {
if (!(tempb = (PyObject*)GMPy_MPZ_From_Integer(b, context))) {
return NULL;
}
c = mpz_cmp(MPZ(a), MPZ(tempb));
Py_DECREF(tempb);
return _cmp_to_object(c, op);
}
if (IS_RATIONAL(b)) {
tempa = (PyObject*)GMPy_MPQ_From_Rational(a, context);
tempb = (PyObject*)GMPy_MPQ_From_Rational(b, context);
if (!tempa || !tempb) {
Py_XDECREF(a);
Py_XDECREF(b);
return NULL;
}
c = mpq_cmp(MPQ(tempa), MPQ(tempb));
Py_DECREF(tempa);
Py_DECREF(tempb);
return _cmp_to_object(c, op);
}
if (PyFloat_Check(b)) {
double d = PyFloat_AS_DOUBLE(b);
if (Py_IS_NAN(d)) {
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else if (Py_IS_INFINITY(d)) {
if (d < 0.0)
return _cmp_to_object(1, op);
else
return _cmp_to_object(-1, op);
}
else {
return _cmp_to_object(mpz_cmp_d(MPZ(a), d), op);
}
}
}
if (MPQ_Check(a)) {
if (MPQ_Check(b)) {
return _cmp_to_object(mpq_cmp(MPQ(a), MPQ(b)), op);
}
if (IS_RATIONAL(b)) {
if (!(tempb = (PyObject*)GMPy_MPQ_From_Rational(b, context))) {
return NULL;
}
c = mpq_cmp(MPQ(a), MPQ(tempb));
Py_DECREF(tempb);
return _cmp_to_object(c, op);
}
if (PyFloat_Check(b)) {
double d = PyFloat_AS_DOUBLE(b);
if (Py_IS_NAN(d)) {
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else if (Py_IS_INFINITY(d)) {
if (d < 0.0)
return _cmp_to_object(1, op);
else
return _cmp_to_object(-1, op);
}
else {
if (!(tempb = (PyObject*)GMPy_MPQ_New(context))) {
return NULL;
}
mpq_set_d(MPQ(tempb), d);
c = mpq_cmp(MPQ(a), MPQ(tempb));
Py_DECREF(tempb);
return _cmp_to_object(c, op);
}
}
}
if (MPFR_Check(a)) {
if (MPFR_Check(b)) {
mpfr_clear_flags();
c = mpfr_cmp(MPFR(a), MPFR(b));
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (PyFloat_Check(b)) {
double d = PyFloat_AS_DOUBLE(b);
mpfr_clear_flags();
c = mpfr_cmp_d(MPFR(a), d);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (IS_INTEGER(b)) {
if (!(tempb = (PyObject*)GMPy_MPZ_From_Integer(b, context))) {
return NULL;
}
mpfr_clear_flags();
c = mpfr_cmp_z(MPFR(a), MPZ(tempb));
Py_DECREF(tempb);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (IS_RATIONAL(b)) {
if (!(tempb = (PyObject*)GMPy_MPQ_From_Rational(b, context))) {
return NULL;
}
mpfr_clear_flags();
c = mpfr_cmp_q(MPFR(a), MPQ(tempb));
Py_DECREF(tempb);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (IS_REAL(b)) {
if (!(tempb = (PyObject*)GMPy_MPFR_From_Real(b, 1, context))) {
return NULL;
}
mpfr_clear_flags();
c = mpfr_cmp(MPFR(a), MPFR(tempb));
Py_DECREF(tempb);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
}
if (MPC_Check(a)) {
if (!(op == Py_EQ || op == Py_NE)) {
TYPE_ERROR("no ordering relation is defined for complex numbers");
return NULL;
}
if (MPC_Check(b)) {
mpfr_clear_flags();
c = mpc_cmp(MPC(a), MPC(b));
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (PyComplex_Check(b)) {
if (!(tempb = (PyObject*)GMPy_MPC_From_PyComplex(b, 1, 1, context))) {
return NULL;
}
mpfr_clear_flags();
c = mpc_cmp(MPC(a), MPC(tempb));
Py_DECREF(tempb);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
/* a.imag must be 0 or else all further comparisons will be NE */
if (!mpfr_zero_p(mpc_imagref(MPC(a)))) {
/* if a.real is NaN, possibly raise exception */
if (mpfr_nan_p(mpc_realref(MPC(a)))) {
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
if (!(tempb = (PyObject*)GMPy_MPFR_New(mpfr_get_prec(mpc_realref(MPC(a))), context))) {
return NULL;
}
mpc_real(MPFR(tempb), MPC(a), GET_MPFR_ROUND(context));
result = GMPy_RichCompare_Slot(tempb, b, op);
Py_DECREF(tempb);
return result;
}
}
Py_RETURN_NOTIMPLEMENTED;
}
gmpy2-2.1.0b3/src/gmpy2_richcompare.h 0000664 0001750 0001750 00000004427 13425753673 017247 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_richcompare.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_RICHCOMPARE_H
#define GMPY_RICHCOMPARE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declarations begin here. */
static PyObject * GMPy_RichCompare_Slot(PyObject *a, PyObject *b, int op);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_sign.c 0000664 0001750 0001750 00000007653 13425753710 015702 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_sign.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *
GMPy_Integer_Sign(PyObject *x, CTXT_Object *context)
{
long res;
MPZ_Object *tempx;
if (!(tempx = GMPy_MPZ_From_Integer(x, context))) {
return NULL;
}
else {
res = mpz_sgn(tempx->z);
Py_DECREF((PyObject*)tempx);
return PyIntOrLong_FromLong(res);
}
}
static PyObject *
GMPy_Rational_Sign(PyObject *x, CTXT_Object *context)
{
long res;
MPQ_Object *tempx;
if (!(tempx = GMPy_MPQ_From_Rational(x, context))) {
return NULL;
}
else {
res = mpq_sgn(tempx->q);
Py_DECREF((PyObject*)tempx);
return PyIntOrLong_FromLong(res);
}
}
static PyObject *
GMPy_Real_Sign(PyObject *x, CTXT_Object *context)
{
long sign;
MPFR_Object *tempx;
PyObject *result;
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
else {
mpfr_clear_flags();
sign = mpfr_sgn(tempx->f);
Py_DECREF((PyObject*)tempx);
result = PyIntOrLong_FromLong(sign);
GMPY_CHECK_ERANGE(result, context, "sign() of invalid value (NaN)");
return result;
}
}
static PyObject *
GMPy_Number_Sign(PyObject *x, CTXT_Object *context)
{
if (IS_INTEGER(x))
return GMPy_Integer_Sign(x, context);
else if (IS_RATIONAL_ONLY(x))
return GMPy_Rational_Sign(x, context);
else if (IS_REAL_ONLY(x))
return GMPy_Real_Sign(x, context);
TYPE_ERROR("sign() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_function_sign,
"sign(x) -> number\n\n"
"Return -1 if x < 0, 0 if x == 0, or +1 if x >0.");
static PyObject *
GMPy_Context_Sign(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Sign(other, context);
}
gmpy2-2.1.0b3/src/gmpy2_sign.h 0000664 0001750 0001750 00000004771 13425753724 015712 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpany.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_SIGN_H
#define GMPY_SIGN_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Integer_Sign(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Rational_Sign(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Real_Sign(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Sign(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sign(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_square.c 0000664 0001750 0001750 00000014770 13425753736 016250 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_square.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*
* GMPy_Number_Square(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_Integer_Square(Integer, Integer, context|NULL)
* GMPy_Rational_Square(Rational, Rational, context|NULL)
* GMPy_Real_Square(Real, Real, context|NULL)
* GMPy_Complex_Square(Complex, Complex, context|NULL)
*
* GMPy_Context_Square(context, args)
*
*/
static PyObject *
_GMPy_MPZ_Square(PyObject *x, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_mul(result->z, MPZ(x), MPZ(x));
return (PyObject*)result;
}
static PyObject *
GMPy_Integer_Square(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
if (!(tempx = (PyObject*)GMPy_MPZ_From_Integer(x, context))) {
return NULL;
}
result = _GMPy_MPZ_Square(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPQ_Square(PyObject *x, CTXT_Object *context)
{
MPQ_Object *result;
if (!(result = GMPy_MPQ_New(context))) {
return NULL;
}
mpq_mul(result->q, MPQ(x), MPQ(x));
return (PyObject*)result;
}
static PyObject *
GMPy_Rational_Square(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
if (!(tempx = (PyObject*)GMPy_MPQ_From_Rational(x, context))) {
return NULL;
}
result = _GMPy_MPQ_Square(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPFR_Square(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
mpfr_sqr(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Square(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Square(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPC_Square(PyObject *x, CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
mpc_sqr(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Square(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Square(tempx, context);
Py_DECREF(tempx);
return result;
}
PyDoc_STRVAR(GMPy_doc_function_square,
"square(x) -> number\n\n"
"Return x * x. If x is an integer, then the result is an 'mpz'.\n"
"If x is a rational, then the result is an 'mpq'. If x is a float,\n"
"then the result is an 'mpfr'. If x is a complex number, then the\n"
"result is an 'mpc'.");
PyDoc_STRVAR(GMPy_doc_context_square,
"context.square(x) -> number\n\n"
"Return x * x. If x is an integer, then the result is an 'mpz'.\n"
"If x is a rational, then the result is an 'mpq'. If x is a float,\n"
"then the result is an 'mpfr'. If x is a complex number, then the\n"
"result is an 'mpc'.");
static PyObject *
GMPy_Number_Square(PyObject *x, CTXT_Object *context)
{
if (MPZ_Check(x))
return _GMPy_MPZ_Square(x, context);
if (MPQ_Check(x))
return _GMPy_MPQ_Square(x, context);
if (MPFR_Check(x))
return _GMPy_MPFR_Square(x, context);
if (MPC_Check(x))
return _GMPy_MPC_Square(x, context);
if (IS_INTEGER(x))
return GMPy_Integer_Square(x, context);
if (IS_RATIONAL(x))
return GMPy_Rational_Square(x, context);
if (IS_REAL(x))
return GMPy_Real_Square(x, context);
if (IS_COMPLEX(x))
return GMPy_Complex_Square(x, context);
TYPE_ERROR("square() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Square(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Square(other, context);
}
gmpy2-2.1.0b3/src/gmpy2_square.h 0000664 0001750 0001750 00000005123 13425753750 016241 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_square.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_SQUARE_H
#define GMPY2_SQUARE_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Integer_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Rational_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Real_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Square(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_sub.c 0000664 0001750 0001750 00000042672 13425753766 015546 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_sub.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the - operator, gmpy2.add(), and context.sub().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*
* GMPy_Number_Sub(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_MPZ_Sub_Slot
* GMPy_MPQ_Sub_Slot
* GMPy_MPFR_Sub_Slot
* GMPy_MPC_Sub_Slot
*
* GMPy_Integer_Sub(Integer, Integer, context|NULL)
* GMPy_Rational_Sub(Rational, Rational, context|NULL)
* GMPy_Real_Sub(Real, Real, context|NULL)
* GMPy_Complex_Sub(Complex, Complex, context|NULL)
*
* GMPy_Context_Sub(context, args)
*
*/
/* Subtract two Integer objects (see gmpy2_convert.c). If an error occurs,
* NULL is returned and an exception is set. If either x or y can't be
* converted into an mpz, Py_NotImplemented is returned. */
static PyObject *
GMPy_Integer_Sub(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPZ_Check(x)) {
if (PyIntOrLong_Check(y)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(y, &error);
if (!error) {
if (temp >= 0) {
mpz_sub_ui(result->z, MPZ(x), temp);
}
else {
mpz_add_ui(result->z, MPZ(x), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpz_sub(result->z, MPZ(x), global.tempz);
}
return (PyObject*)result;
}
if (MPZ_Check(y)) {
mpz_sub(result->z, MPZ(x), MPZ(y));
return (PyObject*)result;
}
}
if (MPZ_Check(y)) {
if (PyIntOrLong_Check(x)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(x, &error);
if (!error) {
if (temp >= 0) {
mpz_ui_sub(result->z, temp, MPZ(y));
}
else {
mpz_add_ui(result->z, MPZ(y), -temp);
mpz_neg(result->z, result->z);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, x);
mpz_sub(result->z, global.tempz, MPZ(y));
}
return (PyObject*)result;
}
}
if (IS_INTEGER(x) && IS_INTEGER(y)) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_Integer(x, context)) ||
!(tempy = GMPy_MPZ_From_Integer(y, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_sub(result->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
SYSTEM_ERROR("Internal error in GMPy_Integer_Sub().");
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Implement __sub__ for MPZ_Object. On entry, one of the two arguments must
* be an MPZ_Object. If the other object is an Integer, add and return an
* MPZ_Object. If the other object isn't an MPZ_Object, call the appropriate
* function. If no appropriate function can be found, return NotImplemented.
*/
static PyObject *
GMPy_MPZ_Sub_Slot(PyObject *x, PyObject *y)
{
if (MPZ_Check(x) && MPZ_Check(y)) {
MPZ_Object *result = NULL;
if ((result = GMPy_MPZ_New(NULL))) {
mpz_sub(result->z, MPZ(x), MPZ(y));
}
return (PyObject*)result;
}
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_Sub(x, y, NULL);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Sub(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Sub(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Sub(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* Subtract two Rational objects (see gmpy2_convert.h). Returns None and
* raises TypeError if both objects are not valid rationals. Pympq_Sub_Rational
* is intended to be called from GMPy_Number_Sub(). */
static PyObject *
GMPy_Rational_Sub(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPQ_Check(x) && MPQ_Check(y)) {
mpq_sub(result->q, MPQ(x), MPQ(y));
return (PyObject*)result;
}
if (IS_RATIONAL(x) && IS_RATIONAL(y)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_Number(x, context)) ||
!(tempy = GMPy_MPQ_From_Number(y, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_sub(result->q, tempx->q, tempy->q);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
SYSTEM_ERROR("Internal error in GMPy_Rational_Sub().");
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Implement __sub__ for MPQ_Object. On entry, one of the two arguments must
* be an MPQ_Object. If the other object is a Rational, subtrace and return
* an MPQ_Object. If the other object isn't an MPQ_Object, call the
* appropriate function. If no appropriate function can be found, return
* NotImplemented.
*/
static PyObject *
GMPy_MPQ_Sub_Slot(PyObject *x, PyObject *y)
{
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Sub(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Sub(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Sub(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* GMPy_Real_Sub(x, y, context) returns x-y using the provided context. If
* provided context is NULL, then the current context is used. If an error
* occurs, NULL is returned and an exception is set. If either x or y can't
* be converted to an mpfr, then Py_NotImplemented is returned.
* GMPy_Real_Sub() will not try to promote the result to a different type
* (i.e. mpc).
*
* GMPy_mpfr_sub_fast(x, y) is the entry point for mpfr.__sub__.
*/
static PyObject *
GMPy_Real_Sub(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPFR_Check(x) && MPFR_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_sub(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
goto done;
}
if (MPFR_Check(x)) {
if (PyIntOrLong_Check(y)) {
int error;
long temp = GMPy_Integer_AsLongAndError(y, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_sub_si(result->f, MPFR(x), temp, GET_MPFR_ROUND(context));
goto done;
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpfr_clear_flags();
result->rc = mpfr_sub_z(result->f, MPFR(x), global.tempz, GET_MPFR_ROUND(context));
goto done;
}
}
if (CHECK_MPZANY(y)) {
mpfr_clear_flags();
result->rc = mpfr_sub_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context));
goto done;
}
if (IS_RATIONAL(y)) {
MPQ_Object *tempy = NULL;
if (!(tempy = GMPy_MPQ_From_Number(y, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_sub_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempy);
goto done;
}
if (PyFloat_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_sub_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context));
goto done;
}
}
if (MPFR_Check(y)) {
if (PyIntOrLong_Check(x)) {
int error;
long temp = GMPy_Integer_AsLongAndError(x, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_sub_si(result->f, MPFR(y), temp, GET_MPFR_ROUND(context));
mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context));
goto done;
}
else {
mpz_set_PyIntOrLong(global.tempz, x);
mpfr_clear_flags();
result->rc = mpfr_sub_z(result->f, MPFR(y), global.tempz, GET_MPFR_ROUND(context));
mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context));
goto done;
}
}
if (CHECK_MPZANY(x)) {
mpfr_clear_flags();
result->rc = mpfr_sub_z(result->f, MPFR(y), MPZ(x), GET_MPFR_ROUND(context));
mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context));
goto done;
}
if (IS_RATIONAL(x)) {
MPQ_Object *tempx = NULL;
if (!(tempx = GMPy_MPQ_From_Number(x, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_sub_q(result->f, MPFR(y), tempx->q, GET_MPFR_ROUND(context));
mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
goto done;
}
if (PyFloat_Check(x)) {
mpfr_clear_flags();
result->rc = mpfr_sub_d(result->f, MPFR(y), PyFloat_AS_DOUBLE(x), GET_MPFR_ROUND(context));
mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context));
goto done;
}
}
if (IS_REAL(x) && IS_REAL(y)) {
MPFR_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context)) ||
!(tempy = GMPy_MPFR_From_Real(y, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_sub(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
goto done;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
SYSTEM_ERROR("Internal error in GMPy_Real_Sub().");
return NULL;
/* LCOV_EXCL_STOP */
done:
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* Implement __sub__ for Pympfr. On entry, one of the two arguments must
* be a Pympfr. If the other object is a Real, add and return a Pympfr.
* If the other object isn't a Pympfr, call the appropriate function. If
* no appropriate function can be found, return NotImplemented. */
static PyObject *
GMPy_MPFR_Sub_Slot(PyObject *x, PyObject *y)
{
if (MPFR_Check(x) && MPFR_Check(y)) {
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_sub(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Sub(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Sub(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* GMPy_Complex_Sub(x, y, context) returns x-y using the provided context. If
* context is NULL, then the current context is used. If an error occurs, NULL
* is returned and an exception is set. If either x or y can't be converted to
* an mpc, then Py_NotImplemented is returned. */
static PyObject *
GMPy_Complex_Sub(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPC_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPC_Check(x) && MPC_Check(y)) {
result->rc = mpc_sub(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_COMPLEX(x) && IS_COMPLEX(y)) {
MPC_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context)) ||
!(tempy = GMPy_MPC_From_Complex(y, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpc_sub(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
SYSTEM_ERROR("Internal error in GMPy_Complex_Sub().");
return NULL;
/* LCOV_EXCL_STOP */
}
/* Pympc_sub_fast() is called by mpc.__sub__. It just gets a borrowed reference
* to the current context and call Pympc_Add_Complex(). Since mpc is the last
* step of the numeric ladder, the NotImplemented return value from
* Pympc_Sub_Complex() is correct and is just passed on. */
static PyObject *
GMPy_MPC_Sub_Slot(PyObject *x, PyObject *y)
{
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Sub(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Number_Sub(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_Sub(x, y, context);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_Sub(x, y, context);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_Sub(x, y, context);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_Sub(x, y, context);
TYPE_ERROR("sub() argument type not supported");
return NULL;
}
/* Implement context.sub() and gmpy2.sub(). */
PyDoc_STRVAR(GMPy_doc_sub,
"sub(x, y) -> number\n\n"
"Return x - y.");
PyDoc_STRVAR(GMPy_doc_context_sub,
"context.sub(x, y) -> number\n\n"
"Return x - y.");
static PyObject *
GMPy_Context_Sub(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("sub() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Sub(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
gmpy2-2.1.0b3/src/gmpy2_sub.h 0000664 0001750 0001750 00000005640 13425753776 015546 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_sub.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_SUB_H
#define GMPY2_SUB_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Sub(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_Sub(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Rational_Sub(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Real_Sub(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_Sub(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_MPZ_Sub_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPQ_Sub_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPFR_Sub_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPC_Sub_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_Sub(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_truediv.c 0000664 0001750 0001750 00000034251 13425754010 016410 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_truediv.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the / operator, gmpy2.div() and context.div().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*
* GMPy_Number_TrueDiv(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_MPZ_TrueDiv_Slot
* GMPy_MPQ_TrueDiv_Slot
* GMPy_MPFR_TrueDiv_Slot
* GMPy_MPC_TrueDiv_Slot
*
* GMPy_Integer_TrueDiv(Integer, Integer, context|NULL)
* GMPy_Rational_TrueDiv(Rational, Rational, context|NULL)
* GMPy_Real_TrueDiv(Real, Real, context|NULL)
* GMPy_Complex_TrueDiv(Complex, Complex, context|NULL)
*
* GMPy_Context_TrueDiv(context, args)
*
*/
/* Multiply two Integer objects (see gmpy2_convert.c). If an error occurs,
* NULL is returned and an exception is set. If either x or y can't be
* converted into an mpz, Py_NotImplemented is returned. */
/* Divide two Integer objects (see convert.c/isInteger) using true division.
* If an error occurs, NULL is returned and an exception is set. If either x
* or y can't be converted into an mpz, Py_NotImplemented is returned. */
static PyObject *
GMPy_Integer_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPZ_Object *tempx, *tempy;
mpq_t tempq;
MPFR_Object *result;
CHECK_CONTEXT(context);
if (GET_DIV_MODE(context))
return GMPy_Rational_TrueDiv(x, y, context);
if (!(result = GMPy_MPFR_New(0, context)))
return NULL;
if (IS_INTEGER(x) && IS_INTEGER(y)) {
tempx = GMPy_MPZ_From_Integer(x, context);
tempy = GMPy_MPZ_From_Integer(y, context);
if (!tempx || !tempy) {
SYSTEM_ERROR("could not convert Integer to mpz");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
mpq_init(tempq);
mpq_set_num(tempq, tempx->z);
mpq_set_den(tempq, tempy->z);
mpq_canonicalize(tempq);
mpfr_clear_flags();
result->rc = mpfr_set_q(result->f, tempq, GET_MPFR_ROUND(context));
mpq_clear(tempq);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
}
/* Implement true division for MPZ_Object. On entry, one of the two arguments
* must be an MPZ_Object. If the other object is an Integer, return an
* MPZ_Object. If the other object isn't an MPZ_Object, call the appropriate
* function. If no appropriate function can be found, return NotImplemented.
*/
static PyObject *
GMPy_MPZ_TrueDiv_Slot(PyObject *x, PyObject *y)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_TrueDiv(x, y, NULL);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_TrueDiv(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_TrueDiv(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_TrueDiv(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
#ifdef PY2
static PyObject *
GMPy_MPZ_Div2_Slot(PyObject *x, PyObject *y)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_FloorDiv(x, y, NULL);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_TrueDiv(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_TrueDiv(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_TrueDiv(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
#endif
static PyObject *
GMPy_Rational_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPQ_Object *result, *tempx = NULL, *tempy = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPQ_New(context)))
return NULL;
if (MPQ_Check(x) && MPQ_Check(y)) {
if (mpq_sgn(MPQ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
mpq_div(result->q, MPQ(x), MPQ(y));
return (PyObject*)result;
}
if (IS_RATIONAL(x) && IS_RATIONAL(y)) {
tempx = GMPy_MPQ_From_Number(x, context);
tempy = GMPy_MPQ_From_Number(y, context);
if (!tempx || !tempy) {
SYSTEM_ERROR("could not convert Rational to mpq");
goto error;
}
if (mpq_sgn(tempy->q) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
mpq_div(result->q, tempx->q, tempy->q);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
static PyObject *
GMPy_MPQ_TrueDiv_Slot(PyObject *x, PyObject *y)
{
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_TrueDiv(x, y, NULL);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_TrueDiv(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_TrueDiv(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
/* Attempt true division of two numbers and return an mpfr. The code path is
* optimized by checking for mpfr objects first. Returns Py_NotImplemented if
* both objects are not valid reals. */
static PyObject *
GMPy_Real_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (MPFR_Check(x) && MPFR_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_div(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
goto done;
}
if (MPFR_Check(x)) {
if (PyIntOrLong_Check(y)) {
int error;
long temp = GMPy_Integer_AsLongAndError(y, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_div_si(result->f, MPFR(x), temp, GET_MPFR_ROUND(context));
goto done;
}
else {
mpz_set_PyIntOrLong(global.tempz, y);
mpfr_clear_flags();
result->rc = mpfr_div_z(result->f, MPFR(x), global.tempz, GET_MPFR_ROUND(context));
goto done;
}
}
if (CHECK_MPZANY(y)) {
mpfr_clear_flags();
result->rc = mpfr_div_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context));
goto done;
}
if (IS_RATIONAL(y)) {
MPQ_Object *tempy;
if (!(tempy = GMPy_MPQ_From_Number(y, context))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_div_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempy);
goto done;
}
if (PyFloat_Check(y)) {
mpfr_clear_flags();
result->rc = mpfr_div_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context));
goto done;
}
}
if (MPFR_Check(y)) {
if (PyIntOrLong_Check(x)) {
int error;
long temp = GMPy_Integer_AsLongAndError(x, &error);
if (!error) {
mpfr_clear_flags();
result->rc = mpfr_si_div(result->f, temp, MPFR(y), GET_MPFR_ROUND(context));
goto done;
}
}
/* Since mpfr_z_div does not exist, this combination is handled at the
* end by converting x to an mpfr. Ditto for rational.*/
if (PyFloat_Check(x)) {
mpfr_clear_flags();
result->rc = mpfr_d_div(result->f, PyFloat_AS_DOUBLE(x), MPFR(y), GET_MPFR_ROUND(context));
goto done;
}
}
if (IS_REAL(x) && IS_REAL(y)) {
MPFR_Object *tempx, *tempy;
tempx = GMPy_MPFR_From_Real(x, 1, context);
tempy = GMPy_MPFR_From_Real(y, 1, context);
if (!tempx || !tempy) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_div(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
goto done;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
done:
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_MPFR_TrueDiv_Slot(PyObject *x, PyObject *y)
{
if (MPFR_Check(x) && MPFR_Check(y)) {
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_div(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_TrueDiv(x, y, NULL);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_TrueDiv(x, y, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Complex_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPC_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context)))
return NULL;
if (MPC_Check(x) && MPC_Check(y)) {
if (MPC_IS_ZERO_P(y)) {
context->ctx.divzero = 1;
if (context->ctx.traps & TRAP_DIVZERO) {
GMPY_DIVZERO("'mpc' division by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
}
result->rc = mpc_div(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context));
goto done;
}
if (IS_COMPLEX(x) && IS_COMPLEX(y)) {
MPC_Object *tempx, *tempy;
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
tempy = GMPy_MPC_From_Complex(y, 1, 1, context);
if (!tempx || !tempy) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
result->rc = mpc_div(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
goto done;
}
Py_DECREF((PyObject*)result);
Py_RETURN_NOTIMPLEMENTED;
done:
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_MPC_TrueDiv_Slot(PyObject *x, PyObject *y)
{
return GMPy_Complex_TrueDiv(x, y, NULL);
}
PyDoc_STRVAR(GMPy_doc_truediv,
"div(x, y) -> number\n\n"
"Return x / y; uses true division.");
static PyObject *
GMPy_Number_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_INTEGER(x) && IS_INTEGER(y))
return GMPy_Integer_TrueDiv(x, y, context);
if (IS_RATIONAL(x) && IS_RATIONAL(y))
return GMPy_Rational_TrueDiv(x, y, context);
if (IS_REAL(x) && IS_REAL(y))
return GMPy_Real_TrueDiv(x, y, context);
if (IS_COMPLEX(x) && IS_COMPLEX(y))
return GMPy_Complex_TrueDiv(x, y, context);
TYPE_ERROR("div() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_truediv,
"context.div(x, y) -> number\n\n"
"Return x / y; uses true division.");
static PyObject *
GMPy_Context_TrueDiv(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("div() requires 2 arguments.");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_TrueDiv(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1),
context);
}
gmpy2-2.1.0b3/src/gmpy2_truediv.h 0000664 0001750 0001750 00000005720 13425754023 016420 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_truediv.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_TRUEDIV_H
#define GMPY2_TRUEDIV_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Rational_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Real_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_MPZ_TrueDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPQ_TrueDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPFR_TrueDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_MPC_TrueDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_TrueDiv(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_types.h 0000664 0001750 0001750 00000010552 13525427233 016102 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_types.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_TYPES_H
#define GMPY_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
PyObject_HEAD
mpz_t z;
Py_hash_t hash_cache;
} MPZ_Object;
typedef struct {
PyObject_HEAD
mpz_t z;
} XMPZ_Object;
typedef struct {
PyObject_HEAD
mpq_t q;
Py_hash_t hash_cache;
} MPQ_Object;
typedef struct {
PyObject_HEAD
mpfr_t f;
Py_hash_t hash_cache;
int rc;
} MPFR_Object;
typedef struct {
PyObject_HEAD
mpc_t c;
Py_hash_t hash_cache;
int rc;
} MPC_Object;
typedef struct {
PyObject_HEAD
gmp_randstate_t state;
} RandomState_Object;
typedef struct {
mpfr_prec_t mpfr_prec; /* current precision in bits, for MPFR */
mpfr_rnd_t mpfr_round; /* current rounding mode for float (MPFR) */
mpfr_exp_t emax; /* maximum exponent */
mpfr_exp_t emin; /* minimum exponent */
int subnormalize; /* if 1, subnormalization is performed */
int underflow; /* did an underflow occur? */
int overflow; /* did an overflow occur? */
int inexact; /* was the result inexact? */
int invalid; /* invalid operation (i.e. NaN)? */
int erange; /* did a range error occur? */
int divzero; /* divided by zero? */
int traps; /* if 0, do not trap any exceptions */
/* if not 0, then raise traps per bits above */
mpfr_prec_t real_prec; /* current precision in bits, for Re(MPC) */
mpfr_prec_t imag_prec; /* current precision in bits, for Im(MPC) */
mpfr_rnd_t real_round; /* current rounding mode for Re(MPC) */
mpfr_rnd_t imag_round; /* current rounding mode for Im(MPC) */
int allow_complex; /* if 1, allow mpfr functions to return an mpc */
int rational_division; /* if 1, mpz/mpz returns an mpq result */
} gmpy_context;
typedef struct {
PyObject_HEAD
gmpy_context ctx;
#ifndef WITHOUT_THREADS
PyThreadState *tstate;
#endif
} CTXT_Object;
typedef struct {
PyObject_HEAD
CTXT_Object *new_context; /* Context that will be returned when
* __enter__ is called. */
CTXT_Object *old_context; /* Context that will restored when
* __exit__ is called. */
} CTXT_Manager_Object;
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_vector.c 0000664 0001750 0001750 00000014370 13425754064 016241 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_vector.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* The following code was a test case for creating a gmpy2 function that would
* apply an MPFR function to all the elements of a list. It was slightly faster
* than map(gmpy2.list, <>) but not enough to justify the effort. The
* code is left for possible future use.
*/
PyDoc_STRVAR(GMPy_doc_function_vector,
"vector(iterable) -> list\n\n"
"Template for applying a function to an iterable.");
PyDoc_STRVAR(GMPy_doc_context_vector,
"vector(iterable) -> list\n\n"
"Template for applying a function to an iterable.");
static PyObject *
GMPy_Context_Vector(PyObject *self, PyObject *other)
{
PyObject *result, *tempres;
Py_ssize_t i, seq_length;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (!(other = PySequence_List(other))) {
TYPE_ERROR("argument must be an iterable");
return NULL;
}
/* other contains a new list containing all the values from the
* iterable. Create a list to store the results.
*/
seq_length = PyList_GET_SIZE(other);
if (!(result = PyList_New(seq_length))) {
Py_DECREF(other);
return NULL;
}
/* Iterate through the list. */
for (i=0; i < seq_length; i++) {
if (!(tempres = GMPy_Number_Sin(PyList_GET_ITEM(other, i), context))) {
Py_DECREF(other);
Py_DECREF(result);
TYPE_ERROR("all items in iterable must be numbers");
return NULL;
}
if (PyList_SetItem(result, i, tempres) < 0) {
Py_DECREF(other);
Py_DECREF(result);
return NULL;
}
}
Py_DECREF(other);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_vector2,
"vector2(iterable, iterable) -> list\n\n"
"Template for applying a function to a pair of iterables.");
PyDoc_STRVAR(GMPy_doc_context_vector2,
"vector2(iterable) -> list\n\n"
"Template for applying a function to a pair of iterables.");
static PyObject *
GMPy_Context_Vector2(PyObject *self, PyObject *args)
{
PyObject *arg1, *arg2, *result;
MPFR_Object *tempres;
Py_ssize_t i, seq_length;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("vector2() requires 2 arguments");
return NULL;
}
if (!(arg1 = PySequence_List(PyTuple_GET_ITEM(args, 0)))) {
TYPE_ERROR("argument must be an iterable");
return NULL;
}
if (!(arg2 = PySequence_List(PyTuple_GET_ITEM(args, 1)))) {
Py_DECREF(arg1);
TYPE_ERROR("argument must be an iterable");
return NULL;
}
/* other contains a new list containing all the values from the
* iterable. Create a list to store the results.
*/
if (PyList_GET_SIZE(arg1) != PyList_GET_SIZE(arg2)) {
Py_DECREF(arg1);
Py_DECREF(arg2);
TYPE_ERROR("arguments must be the same length");
return NULL;
}
seq_length = PyList_GET_SIZE(arg1);
if (!(result = PyList_New(seq_length))) {
Py_DECREF(arg1);
Py_DECREF(arg2);
return NULL;
}
/* Iterate through the list. */
for (i=0; i < seq_length; i++) {
//~ if (!(tempres = GMPy_Number_Mul(PyList_GET_ITEM(arg1, i),
//~ PyList_GET_ITEM(arg2, i),
//~ context))) {
//~ Py_DECREF(arg1);
//~ Py_DECREF(arg2);
//~ Py_DECREF(result);
//~ TYPE_ERROR("all items in iterable must be numbers");
//~ return NULL;
//~ }
tempres = GMPy_MPFR_New(0, context);
tempres->rc = mpfr_mul(tempres->f,
MPFR(PyList_GET_ITEM(arg1, i)),
MPFR(PyList_GET_ITEM(arg2, i)),
GET_MPFR_ROUND(context));
if (PyList_SetItem(result, i, (PyObject*)tempres) < 0) {
Py_DECREF(arg1);
Py_DECREF(arg2);
Py_DECREF(result);
return NULL;
}
}
Py_DECREF(arg1);
Py_DECREF(arg2);
return (PyObject*)result;
}
gmpy2-2.1.0b3/src/gmpy2_vector.h 0000664 0001750 0001750 00000004452 13425754077 016252 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_vector.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_VECTOR_H
#define GMPY_VECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Context_Vector(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_Vector2(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_xmpz.c 0000664 0001750 0001750 00000032613 13444071152 015724 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_xmpz,
"xmpz() -> xmpz(0)\n\n"
" If no argument is given, return xmpz(0).\n\n"
"xmpz(n) -> xmpz\n\n"
" Return an 'xmpz' object with a numeric value 'n' (truncating n\n"
" to its integer part if it's a Fraction, 'mpq', float or 'mpfr').\n\n"
"xmpz(s[, base=0]):\n\n"
" Return an 'xmpz' object from a string 's' made of digits in the\n"
" given base. If base=0, binary, octal, or hex Python strings\n"
" are recognized by leading 0b, 0o, or 0x characters, otherwise\n"
" the string is assumed to be decimal. Values for base can range\n"
" between 2 and 62.\n\n"
" Note: 'xmpz' is a mutable integer. It can be faster when used\n"
" for augmented assignment (+=, *=, etc.). 'xmpz' objects cannot\n"
" be used as dictionary keys. The use of 'mpz' objects is recommended\n"
" in most cases.");
#ifdef PY3
static PyNumberMethods GMPy_XMPZ_number_methods =
{
(binaryfunc) GMPy_MPZ_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPZ_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPZ_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPZ_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPZ_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPANY_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_XMPZ_Neg_Slot, /* nb_negative */
(unaryfunc) GMPy_XMPZ_Pos_Slot, /* nb_positive */
(unaryfunc) GMPy_XMPZ_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_XMPZ_NonZero_Slot, /* nb_bool */
(unaryfunc) GMPy_XMPZ_Com_Slot, /* nb_invert */
(binaryfunc) GMPy_MPZ_Lshift_Slot, /* nb_lshift */
(binaryfunc) GMPy_MPZ_Rshift_Slot, /* nb_rshift */
(binaryfunc) GMPy_MPZ_And_Slot, /* nb_and */
(binaryfunc) GMPy_MPZ_Xor_Slot, /* nb_xor */
(binaryfunc) GMPy_MPZ_Ior_Slot, /* nb_or */
(unaryfunc) GMPy_MPZ_Int_Slot, /* nb_int */
0, /* nb_reserved */
(unaryfunc) GMPy_MPZ_Float_Slot, /* nb_float */
(binaryfunc) GMPy_XMPZ_IAdd_Slot, /* nb_inplace_add */
(binaryfunc) GMPy_XMPZ_ISub_Slot, /* nb_inplace_subtract */
(binaryfunc) GMPy_XMPZ_IMul_Slot, /* nb_inplace_multiply */
(binaryfunc) GMPy_XMPZ_IRem_Slot, /* nb_inplace_remainder */
(ternaryfunc) GMPy_XMPZ_IPow_Slot, /* nb_inplace_power */
(binaryfunc) GMPy_XMPZ_ILshift_Slot, /* nb_inplace_lshift */
(binaryfunc) GMPy_XMPZ_IRshift_Slot, /* nb_inplace_rshift */
(binaryfunc) GMPy_XMPZ_IAnd_Slot, /* nb_inplace_and */
(binaryfunc) GMPy_XMPZ_IXor_Slot, /* nb_inplace_xor */
(binaryfunc) GMPy_XMPZ_IIor_Slot, /* nb_inplace_or */
(binaryfunc) GMPy_MPZ_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPZ_TrueDiv_Slot, /* nb_true_divide */
(binaryfunc) GMPy_XMPZ_IFloorDiv_Slot, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
(unaryfunc) GMPy_MPZ_Int_Slot, /* nb_index */
};
#else
static PyNumberMethods GMPy_XMPZ_number_methods =
{
(binaryfunc) GMPy_MPZ_Add_Slot, /* nb_add */
(binaryfunc) GMPy_MPZ_Sub_Slot, /* nb_subtract */
(binaryfunc) GMPy_MPZ_Mul_Slot, /* nb_multiply */
(binaryfunc) GMPy_MPZ_Div2_Slot, /* nb_divide */
(binaryfunc) GMPy_MPZ_Mod_Slot, /* nb_remainder */
(binaryfunc) GMPy_MPZ_DivMod_Slot, /* nb_divmod */
(ternaryfunc) GMPy_MPANY_Pow_Slot, /* nb_power */
(unaryfunc) GMPy_XMPZ_Neg_Slot, /* nb_negative */
(unaryfunc) GMPy_XMPZ_Pos_Slot, /* nb_positive */
(unaryfunc) GMPy_XMPZ_Abs_Slot, /* nb_absolute */
(inquiry) GMPy_XMPZ_NonZero_Slot, /* nb_bool */
(unaryfunc) GMPy_XMPZ_Com_Slot, /* nb_invert */
(binaryfunc) GMPy_MPZ_Lshift_Slot, /* nb_lshift */
(binaryfunc) GMPy_MPZ_Rshift_Slot, /* nb_rshift */
(binaryfunc) GMPy_MPZ_And_Slot, /* nb_and */
(binaryfunc) GMPy_MPZ_Xor_Slot, /* nb_xor */
(binaryfunc) GMPy_MPZ_Ior_Slot, /* nb_or */
0, /* nb_coerce */
(unaryfunc) GMPy_MPZ_Int_Slot, /* nb_int */
(unaryfunc) GMPy_MPZ_Long_Slot, /* nb_long */
(unaryfunc) GMPy_MPZ_Float_Slot, /* nb_float */
(unaryfunc) GMPy_XMPZ_Oct_Slot, /* nb_oct */
(unaryfunc) GMPy_XMPZ_Hex_Slot, /* nb_hex */
(binaryfunc) GMPy_XMPZ_IAdd_Slot, /* nb_inplace_add */
(binaryfunc) GMPy_XMPZ_ISub_Slot, /* nb_inplace_subtract */
(binaryfunc) GMPy_XMPZ_IMul_Slot, /* nb_inplace_multiply */
0, /* nb_inplace_divide */
(binaryfunc) GMPy_XMPZ_IRem_Slot, /* nb_inplace_remainder */
(ternaryfunc) GMPy_XMPZ_IPow_Slot, /* nb_inplace_power */
(binaryfunc) GMPy_XMPZ_ILshift_Slot, /* nb_inplace_lshift */
(binaryfunc) GMPy_XMPZ_IRshift_Slot, /* nb_inplace_rshift */
(binaryfunc) GMPy_XMPZ_IAnd_Slot, /* nb_inplace_and */
(binaryfunc) GMPy_XMPZ_IXor_Slot, /* nb_inplace_xor */
(binaryfunc) GMPy_XMPZ_IIor_Slot, /* nb_inplace_or */
(binaryfunc) GMPy_MPZ_FloorDiv_Slot, /* nb_floor_divide */
(binaryfunc) GMPy_MPZ_TrueDiv_Slot, /* nb_true_divide */
(binaryfunc) GMPy_XMPZ_IFloorDiv_Slot, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
(unaryfunc) GMPy_MPZ_Int_Slot, /* nb_index */
};
#endif
static PyMappingMethods GMPy_XMPZ_mapping_methods = {
(lenfunc)GMPy_XMPZ_Method_Length,
(binaryfunc)GMPy_XMPZ_Method_SubScript,
(objobjargproc)GMPy_XMPZ_Method_AssignSubScript
};
static PyGetSetDef GMPy_XMPZ_getseters[] =
{
{ "numerator", (getter)GMPy_XMPZ_Attrib_GetNumer, NULL,
"the numerator of a rational number in lowest terms", NULL },
{ "denominator", (getter)GMPy_XMPZ_Attrib_GetDenom, NULL,
"the denominator of a rational number in lowest terms", NULL },
{ "real", (getter)GMPy_XMPZ_Attrib_GetReal, NULL,
"the real part of a complex number", NULL },
{ "denominator", (getter)GMPy_XMPZ_Attrib_GetImag, NULL,
"the imaginary part of a complex number", NULL },
{NULL}
};
static PyMethodDef GMPy_XMPZ_methods [] =
{
{ "__format__", GMPy_MPZ_Format, METH_VARARGS, GMPy_doc_mpz_format },
{ "__sizeof__", GMPy_XMPZ_Method_SizeOf, METH_NOARGS, GMPy_doc_xmpz_method_sizeof },
{ "bit_clear", GMPy_MPZ_bit_clear_method, METH_O, doc_bit_clear_method },
{ "bit_flip", GMPy_MPZ_bit_flip_method, METH_O, doc_bit_flip_method },
{ "bit_length", GMPy_MPZ_bit_length_method, METH_NOARGS, doc_bit_length_method },
{ "bit_scan0", GMPy_MPZ_bit_scan0_method, METH_VARARGS, doc_bit_scan0_method },
{ "bit_scan1", GMPy_MPZ_bit_scan1_method, METH_VARARGS, doc_bit_scan1_method },
{ "bit_set", GMPy_MPZ_bit_set_method, METH_O, doc_bit_set_method },
{ "bit_test", GMPy_MPZ_bit_test_method, METH_O, doc_bit_test_method },
{ "conjugate", GMPy_MP_Method_Conjugate, METH_NOARGS, GMPy_doc_mp_method_conjugate },
{ "copy", GMPy_XMPZ_Method_Copy, METH_NOARGS, GMPy_doc_xmpz_method_copy },
{ "digits", GMPy_XMPZ_Digits_Method, METH_VARARGS, GMPy_doc_mpz_digits_method },
{ "iter_bits", (PyCFunction)GMPy_XMPZ_Method_IterBits, METH_VARARGS | METH_KEYWORDS, GMPy_doc_xmpz_method_iter_bits },
{ "iter_clear", (PyCFunction)GMPy_XMPZ_Method_IterClear, METH_VARARGS | METH_KEYWORDS, GMPy_doc_xmpz_method_iter_clear },
{ "iter_set", (PyCFunction)GMPy_XMPZ_Method_IterSet, METH_VARARGS | METH_KEYWORDS, GMPy_doc_xmpz_method_iter_set },
{ "make_mpz", GMPy_XMPZ_Method_MakeMPZ, METH_NOARGS, GMPy_doc_xmpz_method_make_mpz },
{ "num_digits", GMPy_MPZ_Method_NumDigits, METH_VARARGS, GMPy_doc_mpz_method_num_digits },
{ NULL, NULL, 1 }
};
static PyTypeObject XMPZ_Type =
{
/* PyObject_HEAD_INIT(&PyType_Type) */
#ifdef PY3
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyObject_HEAD_INIT(0)
0, /* ob_size */
#endif
"xmpz", /* tp_name */
sizeof(XMPZ_Object), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor) GMPy_XMPZ_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_XMPZ_Repr_Slot, /* tp_repr */
&GMPy_XMPZ_number_methods, /* tp_as_number */
0, /* tp_as_sequence */
&GMPy_XMPZ_mapping_methods, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
(reprfunc) GMPy_XMPZ_Str_Slot, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
#ifdef PY3
Py_TPFLAGS_DEFAULT, /* tp_flags */
#else
Py_TPFLAGS_HAVE_INDEX|Py_TPFLAGS_HAVE_RICHCOMPARE| \
Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_CLASS| \
Py_TPFLAGS_HAVE_INPLACEOPS,
#endif
GMPy_doc_xmpz, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)&GMPy_RichCompare_Slot, /* tp_richcompare */
0, /* tp_weaklistoffset*/
0, /* tp_iter */
0, /* tp_iternext */
GMPy_XMPZ_methods, /* tp_methods */
0, /* tp_members */
GMPy_XMPZ_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
GMPy_XMPZ_NewInit, /* tp_new */
0, /* tp_free */
};
gmpy2-2.1.0b3/src/gmpy2_xmpz.h 0000664 0001750 0001750 00000005106 13425754140 015732 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_XMPZ_H
#define GMPY_XMPZ_H
#ifdef __cplusplus
extern "C" {
#endif
static PyTypeObject XMPZ_Type;
#define XMPZ(obj) (((XMPZ_Object*)(obj))->z)
#define XMPZ_Check(v) (((PyObject*)v)->ob_type == &XMPZ_Type)
#define CHECK_MPZANY(v) (MPZ_Check(v) || XMPZ_Check(v))
typedef struct {
PyObject_HEAD
XMPZ_Object *bitmap;
mp_bitcnt_t start, stop;
int iter_type;
} GMPy_Iter_Object;
static PyTypeObject GMPy_Iter_Type;
#define GMPy_Iter_Check(v) (((PyObject*)v)->ob_type == &GMPy_Iter_Type)
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_xmpz_inplace.c 0000664 0001750 0001750 00000022432 13425754150 017422 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * *
* gmpy2_xmpz_inplace.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Provides inplace mutating operations for xmpz. */
#include
/* Inplace xmpz addition. */
static PyObject *
GMPy_XMPZ_IAdd_Slot(PyObject *self, PyObject *other)
{
/* Try to make mpz + small_int faster */
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if (!error) {
if (temp >= 0) {
mpz_add_ui(MPZ(self), MPZ(self), temp);
}
else {
mpz_sub_ui(MPZ(self), MPZ(self), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_add(MPZ(self), MPZ(self), global.tempz);
}
Py_INCREF(self);
return self;
}
if (CHECK_MPZANY(other)) {
mpz_add(MPZ(self), MPZ(self), MPZ(other));
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace mpz subtraction.
*/
static PyObject *
GMPy_XMPZ_ISub_Slot(PyObject *self, PyObject *other)
{
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if (!error) {
if (temp >= 0) {
mpz_sub_ui(MPZ(self), MPZ(self), temp);
}
else {
mpz_add_ui(MPZ(self), MPZ(self), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_sub(MPZ(self), MPZ(self), global.tempz);
}
Py_INCREF(self);
return self;
}
if (CHECK_MPZANY(other)) {
mpz_sub(MPZ(self), MPZ(self), MPZ(other));
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz multiplication.
*/
static PyObject *
GMPy_XMPZ_IMul_Slot(PyObject *self, PyObject *other)
{
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if (!error) {
mpz_mul_si(MPZ(self), MPZ(self), temp);
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_mul(MPZ(self), MPZ(self), global.tempz);
}
Py_INCREF(self);
return self;
}
if (CHECK_MPZANY(other)) {
mpz_mul(MPZ(self), MPZ(self), MPZ(other));
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Pympany_floordiv follows the // semantics from Python 3.x. The result is
* an mpz when the arguments are mpz or mpq, but the result is an mpf when
* the arguments are mpf.
*/
static PyObject *
GMPy_XMPZ_IFloorDiv_Slot(PyObject *self, PyObject *other)
{
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if (!error) {
if (temp == 0) {
ZERO_ERROR("xmpz division by zero");
return NULL;
}
else if(temp > 0) {
mpz_fdiv_q_ui(MPZ(self), MPZ(self), temp);
}
else {
mpz_cdiv_q_ui(MPZ(self), MPZ(self), -temp);
mpz_neg(MPZ(self), MPZ(self));
}
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_fdiv_q(MPZ(self), MPZ(self), global.tempz);
}
Py_INCREF(self);
return self;
}
if (CHECK_MPZANY(other)) {
if (mpz_sgn(MPZ(other)) == 0) {
ZERO_ERROR("xmpz division by zero");
return NULL;
}
mpz_fdiv_q(MPZ(self), MPZ(self), MPZ(other));
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz remainder.
*/
static PyObject *
GMPy_XMPZ_IRem_Slot(PyObject *self, PyObject *other)
{
if (PyIntOrLong_Check(other)) {
int error;
native_si temp = GMPy_Integer_AsNative_siAndError(other, &error);
if (!error) {
if (temp > 0) {
mpz_fdiv_r_ui(MPZ(self), MPZ(self), temp);
}
else if (temp == 0) {
ZERO_ERROR("xmpz modulo by zero");
return NULL;
}
else {
mpz_cdiv_r_ui(MPZ(self), MPZ(self), -temp);
}
}
else {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_fdiv_r(MPZ(self), MPZ(self), global.tempz);
}
Py_INCREF(self);
return self;
}
if (CHECK_MPZANY(other)) {
if(mpz_sgn(MPZ(other)) == 0) {
ZERO_ERROR("xmpz modulo by zero");
return NULL;
}
mpz_fdiv_r(MPZ(self), MPZ(self), MPZ(other));
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz rshift.
*/
static PyObject *
GMPy_XMPZ_IRshift_Slot(PyObject *self, PyObject *other)
{
mp_bitcnt_t shift;
if (IS_INTEGER(other)) {
shift = mp_bitcnt_t_From_Integer(other);
if (shift == (mp_bitcnt_t)(-1) && PyErr_Occurred())
return NULL;
mpz_fdiv_q_2exp(MPZ(self), MPZ(self), shift);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz lshift.
*/
static PyObject *
GMPy_XMPZ_ILshift_Slot(PyObject *self, PyObject *other)
{
mp_bitcnt_t shift;
if (IS_INTEGER(other)) {
shift = mp_bitcnt_t_From_Integer(other);
if (shift == (mp_bitcnt_t)(-1) && PyErr_Occurred())
return NULL;
mpz_mul_2exp(MPZ(self), MPZ(self), shift);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz_pow.
*/
static PyObject *
GMPy_XMPZ_IPow_Slot(PyObject *self, PyObject *other, PyObject *mod)
{
mp_bitcnt_t exp;
exp = mp_bitcnt_t_From_Integer(other);
if (exp == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
PyErr_Clear();
Py_RETURN_NOTIMPLEMENTED;
}
mpz_pow_ui(MPZ(self), MPZ(self), exp);
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
/* Inplace xmpz and.
*/
static PyObject *
GMPy_XMPZ_IAnd_Slot(PyObject *self, PyObject *other)
{
if (CHECK_MPZANY(other)) {
mpz_and(MPZ(self), MPZ(self), MPZ(other));
Py_INCREF(self);
return self;
}
if (PyIntOrLong_Check(other)) {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_and(MPZ(self), MPZ(self), global.tempz);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz xor.
*/
static PyObject *
GMPy_XMPZ_IXor_Slot(PyObject *self, PyObject *other)
{
if(CHECK_MPZANY(other)) {
mpz_xor(MPZ(self), MPZ(self), MPZ(other));
Py_INCREF(self);
return self;
}
if(PyIntOrLong_Check(other)) {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_xor(MPZ(self), MPZ(self), global.tempz);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz or.
*/
static PyObject *
GMPy_XMPZ_IIor_Slot(PyObject *self, PyObject *other)
{
if(CHECK_MPZANY(other)) {
mpz_ior(MPZ(self), MPZ(self), MPZ(other));
Py_INCREF(self);
return self;
}
if(PyIntOrLong_Check(other)) {
mpz_set_PyIntOrLong(global.tempz, other);
mpz_ior(MPZ(self), MPZ(self), global.tempz);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
gmpy2-2.1.0b3/src/gmpy2_xmpz_inplace.h 0000664 0001750 0001750 00000005730 13425754162 017434 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz_inplace.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_XMPZ_INPLACE_H
#define GMPY_XMPZ_INPLACE_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_XMPZ_IAdd_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_ISub_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IMul_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IFloorDiv_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IRem_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IRshift_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_ILshift_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IPow_Slot(PyObject *self, PyObject *other, PyObject *mod);
static PyObject * GMPy_XMPZ_IAnd_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IXor_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IIor_Slot(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy2_xmpz_misc.c 0000664 0001750 0001750 00000045742 13444071152 016746 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_xmpz_function_xbit_mask,
"xbit_mask(n) -> xmpz\n\n"
"Return an 'xmpz' exactly n bits in length with all bits set.\n");
static PyObject *
GMPy_XMPZ_Function_XbitMask(PyObject *self, PyObject *other)
{
Py_ssize_t i = 0;
XMPZ_Object* result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
i = ssize_t_From_Integer(other);
if (i == -1 && PyErr_Occurred()) {
TYPE_ERROR("xbit_mask() requires 'int' argument");
return NULL;
}
if (i < 0) {
VALUE_ERROR("mask length must be >= 0");
return NULL;
}
if (!(result = GMPy_XMPZ_New(context))) {
return NULL;
}
mpz_set_ui(result->z, 1);
mpz_mul_2exp(result->z, result->z, i);
mpz_sub_ui(result->z, result->z, 1);
return (PyObject*)result;
}
static PyObject *
GMPy_XMPZ_Abs_Slot(XMPZ_Object *x)
{
mpz_abs(x->z, x->z);
Py_RETURN_NONE;
}
static PyObject *
GMPy_XMPZ_Neg_Slot(XMPZ_Object *x)
{
mpz_neg(x->z, x->z);
Py_RETURN_NONE;
}
static PyObject *
GMPy_XMPZ_Pos_Slot(XMPZ_Object *x)
{
Py_RETURN_NONE;
}
static int
GMPy_XMPZ_NonZero_Slot(XMPZ_Object *x)
{
return mpz_sgn(x->z) != 0;
}
/* BIT OPERATIONS */
static PyObject *
GMPy_XMPZ_Com_Slot(XMPZ_Object *x)
{
mpz_com(x->z, x->z);
Py_RETURN_NONE;
}
#if PY_MAJOR_VERSION < 3
/* hex/oct formatting (mpz-only) */
static PyObject *
GMPy_XMPZ_Oct_Slot(XMPZ_Object *self)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
return GMPy_PyStr_From_XMPZ(self, 8, 0, context);
}
static PyObject *
GMPy_XMPZ_Hex_Slot(XMPZ_Object *self)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
return GMPy_PyStr_From_XMPZ(self, 16, 0, context);
}
#endif
PyDoc_STRVAR(GMPy_doc_xmpz_method_make_mpz,
"xmpz.make_mpz() -> mpz\n\n"
"Return an mpz by converting an 'xmpz' to an 'mpz' as quickly as\n"
"possible.\n\n"
"NOTE: Optimized for speed so the original xmpz is set to 0!");
static PyObject *
GMPy_XMPZ_Method_MakeMPZ(PyObject *self, PyObject *other)
{
MPZ_Object* result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_swap(result->z, MPZ(self));
mpz_set_ui(MPZ(self), 0);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_copy,
"xmpz.copy() -> xmpz\n\n"
"Return a copy of an xmpz.");
static PyObject *
GMPy_XMPZ_Method_Copy(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
return (PyObject*)GMPy_XMPZ_From_XMPZ((XMPZ_Object*)self, context);
}
/*
* Add mapping support to xmpz objects.
*/
static Py_ssize_t
GMPy_XMPZ_Method_Length(XMPZ_Object *obj)
{
return mpz_sizeinbase(obj->z, 2);
}
static PyObject *
GMPy_XMPZ_Method_SubScript(XMPZ_Object* self, PyObject* item)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyIntOrLong_AsSsize_t(item);
if (i == -1 && PyErr_Occurred()) {
INDEX_ERROR("argument too large to be converted to an index");
return NULL;
}
if (i < 0) {
i += mpz_sizeinbase(self->z, 2);
}
return PyIntOrLong_FromLong(mpz_tstbit(self->z, i));
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength, cur, i;
MPZ_Object *result;
#if PY_VERSION_HEX > 0x030200A4
if (PySlice_GetIndicesEx(item,
mpz_sizeinbase(self->z, 2),
&start, &stop, &step, &slicelength) < 0) {
return NULL;
}
#else
if (PySlice_GetIndicesEx((PySliceObject*)item,
mpz_sizeinbase(self->z, 2),
&start, &stop, &step, &slicelength) < 0) {
return NULL;
}
#endif
if ((step < 0 && start < stop) || (step > 0 && start > stop)) {
stop = start;
}
if (!(result = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_set_ui(result->z, 0);
if (slicelength > 0) {
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
if (mpz_tstbit(self->z, cur)) {
mpz_setbit(result->z, i);
}
}
}
return (PyObject*)result;
}
else {
TYPE_ERROR("bit positions must be integers");
return NULL;
}
}
static int
GMPy_XMPZ_Method_AssignSubScript(XMPZ_Object* self, PyObject* item, PyObject* value)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyIndex_Check(item)) {
Py_ssize_t bit_value, i;
i = PyIntOrLong_AsSsize_t(item);
if (i == -1 && PyErr_Occurred()) {
INDEX_ERROR("argument too large to be converted to an index");
return -1;
}
if (i < 0) {
i += mpz_sizeinbase(self->z, 2);
}
bit_value = PyIntOrLong_AsSsize_t(value);
if (bit_value == -1 && PyErr_Occurred()) {
VALUE_ERROR("bit value must be 0 or 1");
return -1;
}
if (bit_value == 1) {
mpz_setbit(self->z, i);
return 0;
}
else if (bit_value == 0) {
mpz_clrbit(self->z, i);
return 0;
}
else {
VALUE_ERROR("bit value must be 0 or 1");
return -1;
}
}
else if (PySlice_Check(item)) {
Py_ssize_t cur, i, seq_len, start, stop, step, slicelength, temp;
seq_len = mpz_sizeinbase(self->z, 2);
if (((PySliceObject*)item)->stop != Py_None) {
/* If a fixed endpoint is specified, and the endpoint is greater
* than the length of the xmpz object, allow the underlying xmpz
* object to be made larger.
*/
temp = PyIntOrLong_AsSsize_t(((PySliceObject*)item)->stop);
if (temp == -1 && PyErr_Occurred()) {
return 0;
}
if (temp > seq_len) {
seq_len = temp;
}
}
#if PY_VERSION_HEX > 0x030200A4
if (PySlice_GetIndicesEx(item,
seq_len,
&start, &stop, &step, &slicelength) < 0) {
return -1;
}
#else
if (PySlice_GetIndicesEx((PySliceObject*)item,
seq_len,
&start, &stop, &step, &slicelength) < 0) {
return -1;
}
#endif
if ((step < 0 && start < stop) || (step > 0 && start > stop)) {
stop = start;
}
if (value == NULL) {
TYPE_ERROR("deleting bits not supported");
return -1;
}
else {
int bit;
MPZ_Object *tempx;
if (!(tempx = GMPy_MPZ_From_Integer(value, context))) {
VALUE_ERROR("must specify bit sequence as an integer");
return -1;
}
if (mpz_sgn(tempx->z) == 0) {
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
mpz_clrbit(self->z, cur);
}
}
else if (!(mpz_cmp_si(tempx->z, -1))) {
for (cur = start + (slicelength-1) * step, i = 0;
i < slicelength;
cur -= step, i++) {
mpz_setbit(self->z, cur);
}
}
else {
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
bit = mpz_tstbit(tempx->z, i);
if (bit)
mpz_setbit(self->z, cur);
else
mpz_clrbit(self->z, cur);
}
}
Py_DECREF((PyObject*)tempx);
}
return 0;
}
else {
TYPE_ERROR("bit positions must be integers");
return -1;
}
return -1;
}
/* Implement a multi-purpose iterator object that iterates over the bits in
* an xmpz. Three different iterators can be created:
* 1) xmpz.iter_bits(start=0, stop=-1) will return True/False for each bit
* position in the xmpz, beginning with bit 'start'. If stop is specified,
* the xmpz will be padded with 0-bits (False) until stop is reached.
* 2) xmpz.iter_set(start=0, stop=-1, scale=1, offset=0) will return
* (scale*bit_position + offset) when bit_position is set, beginning at
* 'start', ending at 'stop'.
* 3) xmpz.iter_clear(start=0, stop=-1, scale=1, offset=0) will return
* (scale*bit_position + offset) when bit_position is clear, beginning at
* 'start', ending at 'stop'.
*
*/
static GMPy_Iter_Object *
GMPy_Iter_New(void)
{
GMPy_Iter_Object *result;
if ((result = PyObject_New(GMPy_Iter_Object,
&GMPy_Iter_Type))) {
result->bitmap = NULL;
result->start = 0;
result->stop = (mp_bitcnt_t)-1;
result->iter_type = 1;
}
return result;
};
static void
GMPy_Iter_Dealloc(GMPy_Iter_Object *self)
{
Py_XDECREF((PyObject*)self->bitmap);
PyObject_Del(self);
};
static PyObject *
GMPy_Iter_Next(GMPy_Iter_Object *self) {
PyObject *result = 0;
mp_bitcnt_t temp, current_stop;
if (self->stop == (mp_bitcnt_t)(-1))
current_stop = mpz_sizeinbase(self->bitmap->z, 2);
else
current_stop = self->stop;
switch (self->iter_type) {
case 1:
if (self->start >= current_stop)
PyErr_SetNone(PyExc_StopIteration);
else {
temp = mpz_tstbit(self->bitmap->z, self->start);
self->start += 1;
result = temp ? Py_True : Py_False;
Py_INCREF(result);
}
break;
case 2:
if (self->start >= current_stop)
PyErr_SetNone(PyExc_StopIteration);
else {
temp = mpz_scan1(self->bitmap->z, self->start);
if (temp == (mp_bitcnt_t)(-1))
PyErr_SetNone(PyExc_StopIteration);
else {
self->start = temp + 1;
result = PyIntOrLong_FromSsize_t(temp);
}
}
break;
case 3:
if (self->start >= current_stop)
PyErr_SetNone(PyExc_StopIteration);
else {
temp = mpz_scan0(self->bitmap->z, self->start);
if (temp >= current_stop)
PyErr_SetNone(PyExc_StopIteration);
else {
self->start = temp + 1;
result = PyIntOrLong_FromSsize_t(temp);
}
}
break;
default:
SYSTEM_ERROR("Illegal iter_type in gmpy2.Iterator.");
}
return result;
}
static PyObject *
GMPy_Iter_Repr(GMPy_Iter_Object *self)
{
return Py_BuildValue("s", "");
};
PyDoc_STRVAR(GMPy_doc_xmpz_method_iter_bits,
"xmpz.iter_bits(start=0, stop=-1) -> iterator\n\n"
"Return True or False for each bit position in 'xmpz' beginning at\n"
"'start'. If a positive value is specified for 'stop', iteration is\n"
"continued until 'stop' is reached. If a negative value is specified,\n"
"iteration is continued until the last 1-bit. Note: the value of the\n"
"underlying xmpz object can change during iteration.");
static PyObject *
GMPy_XMPZ_Method_IterBits(PyObject *self, PyObject *args, PyObject *kwargs)
{
GMPy_Iter_Object *result;
Py_ssize_t start = 0, stop = -1;
static char *kwlist[] = {"start", "stop", NULL };
if (!(result = GMPy_Iter_New())) {
return NULL;
}
if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|nn", kwlist, &start, &stop))) {
Py_XDECREF((PyObject*)result);
return NULL;
}
result->iter_type = 1;
result->bitmap = (XMPZ_Object*)self;
Py_INCREF(self);
result->start = start;
result->stop = stop;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_iter_set,
"xmpz.iter_set(start=0, stop=-1) -> iterator\n\n"
"Return an iterator yielding the bit position for every bit that\n"
"is set in 'xmpz', beginning at 'start'. If a positive value is\n"
"specified for 'stop', iteration is continued until 'stop' is\n"
"reached. To match the behavior of slicing, 'stop' is not included.\n"
"If a negative value is specified, iteration is continued until\n"
"the last 1-bit. Note: the value of the underlying xmpz object can\n"
"change during iteration.");
static PyObject *
GMPy_XMPZ_Method_IterSet(PyObject *self, PyObject *args, PyObject *kwargs)
{
GMPy_Iter_Object *result;
Py_ssize_t start = 0, stop = -1;
static char *kwlist[] = {"start", "stop", NULL };
if (!(result = GMPy_Iter_New())) {
return NULL;
}
if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|nn", kwlist, &start, &stop))) {
Py_XDECREF((PyObject*)result);
return NULL;
}
result->iter_type = 2;
result->bitmap = (XMPZ_Object*)self;
Py_INCREF(self);
result->start = start;
result->stop = stop;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_iter_clear,
"xmpz.iter_clear(start=0, stop=-1) -> iterator\n\n"
"Return every bit position that is clear in 'xmpz', beginning at\n"
"'start'. If a positive value is specified for 'stop', iteration\n"
"is continued until 'stop' is reached. If a negative value is specified,\n"
"iteration is continued until the last 1-bit. Note: the value of the\n"
"underlying xmpz object can change during iteration.");
static PyObject *
GMPy_XMPZ_Method_IterClear(PyObject *self, PyObject *args, PyObject *kwargs)
{
GMPy_Iter_Object *result;
Py_ssize_t start = 0, stop = -1;
static char *kwlist[] = {"start", "stop", NULL };
if (!(result = GMPy_Iter_New())) {
return NULL;
}
if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|nn", kwlist, &start, &stop))) {
Py_XDECREF((PyObject*)result);
return NULL;
}
result->iter_type = 3;
result->bitmap = (XMPZ_Object*)self;
Py_INCREF(self);
result->start = start;
result->stop = stop;
return (PyObject*)result;
}
static PyObject *
GMPy_XMPZ_Attrib_GetNumer(XMPZ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_XMPZ_Attrib_GetReal(XMPZ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_XMPZ_Attrib_GetDenom(XMPZ_Object *self, void *closure)
{
XMPZ_Object *result;
if ((result = GMPy_XMPZ_New(NULL))) {
mpz_set_ui(result->z, 1);
}
return (PyObject*)result;
}
static PyObject *
GMPy_XMPZ_Attrib_GetImag(XMPZ_Object *self, void *closure)
{
XMPZ_Object *result;
if ((result = GMPy_XMPZ_New(NULL))) {
mpz_set_ui(result->z, 0);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_sizeof,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x. Note: deleted xmpz objects\n"
"are reused and may or may not be resized when a new value is assigned.");
static PyObject *
GMPy_XMPZ_Method_SizeOf(PyObject *self, PyObject *other)
{
return PyIntOrLong_FromSize_t(sizeof(XMPZ_Object) + \
(MPZ(self)->_mp_alloc * sizeof(mp_limb_t)));
}
static PyTypeObject GMPy_Iter_Type =
{
#ifdef PY3
PyVarObject_HEAD_INIT(0, 0)
#else
PyObject_HEAD_INIT(0)
0, /* ob_size */
#endif
"gmpy2 iterator", /* tp_name */
sizeof(GMPy_Iter_Object), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) GMPy_Iter_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_Iter_Repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"GMPY2 Iterator Object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset*/
PyObject_SelfIter, /* tp_iter */
(iternextfunc)GMPy_Iter_Next, /* tp_iternext */
};
gmpy2-2.1.0b3/src/gmpy2_xmpz_misc.h 0000664 0001750 0001750 00000010004 13444071152 016732 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009 Alex Martelli *
* *
* Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, *
* 2015, 2016, 2017, 2018, 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_XMPZ_MISC_H
#define GMPY_XMPZ_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static int GMPy_XMPZ_NonZero_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Function_XbitMask(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_Abs_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Neg_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Pos_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Com_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Method_MakeMPZ(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_Method_Copy(PyObject *self, PyObject *other);
static Py_ssize_t GMPy_XMPZ_Method_Length(XMPZ_Object *obj);
static PyObject * GMPy_XMPZ_Method_SubScript(XMPZ_Object* self, PyObject* item);
static int GMPy_XMPZ_Method_AssignSubScript(XMPZ_Object* self, PyObject* item, PyObject* value);
static PyObject * GMPy_XMPZ_Attrib_GetNumer(XMPZ_Object *self, void *closure);
static PyObject * GMPy_XMPZ_Attrib_GetDenom(XMPZ_Object *self, void *closure);
static PyObject * GMPy_XMPZ_Attrib_GetReal(XMPZ_Object *self, void *closure);
static PyObject * GMPy_XMPZ_Attrib_GetImag(XMPZ_Object *self, void *closure);
static GMPy_Iter_Object * GMPy_Iter_New(void);
static void GMPy_Iter_Dealloc(GMPy_Iter_Object *self);
static PyObject * GMPy_Iter_Next(GMPy_Iter_Object *self);
static PyObject * GMPy_Iter_Repr(GMPy_Iter_Object *self);
static PyObject * GMPy_XMPZ_Method_IterBits(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_XMPZ_Method_IterSet(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_XMPZ_Method_IterClear(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_XMPZ_Method_SizeOf(PyObject *self, PyObject *other);
#if PY_MAJOR_VERSION < 3
/* hex/oct formatting (mpz-only) */
static PyObject * GMPy_XMPZ_Oct_Slot(XMPZ_Object *self);
static PyObject * GMPy_XMPZ_Hex_Slot(XMPZ_Object *self);
#endif
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy_mpz_lucas.c 0000664 0001750 0001750 00000044103 13425754250 016644 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpz_lucas.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2011 David Cleaver *
* *
* Copyright 2012, 2013, 2014, 2015, 2016, 2017, 2018, *
* 2019 Case Van Horsen *
* *
* The original file is available at: *
* *
* *
* Modified by Case Van Horsen for inclusion into GMPY2. *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(doc_mpz_lucasu,
"lucasu(p,q,k) -> mpz\n\n"
"Return the k-th element of the Lucas U sequence defined by p,q.\n"
"p*p - 4*q must not equal 0; k must be greater than or equal to 0.");
static PyObject *
GMPY_mpz_lucasu(PyObject *self, PyObject *args)
{
/* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
* calculate u[k] of Lucas U sequence for p,q.
* Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
*/
MPZ_Object *result = NULL, *p = NULL, *q = NULL, *k = NULL;
size_t s = 0, j = 0;
mpz_t uh, vl, vh, ql, qh, tmp;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("lucasu() requires 3 integer arguments");
return NULL;
}
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!p || !q || !k) {
TYPE_ERROR("lucasu() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in lucasu()");
goto cleanup;
}
/* Check if k < 0. */
if (mpz_sgn(k->z) < 0) {
VALUE_ERROR("invalid value for k in lucasu()");
goto cleanup;
}
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp, 0);
s = mpz_scan1(k->z, 0);
for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
if (mpz_tstbit(k->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vh */
mpz_mul(uh, uh, vh);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* vh = vh*vh - 2*qh */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vh = vh*vl - p*ql */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
/* vl = vl*vl - 2*ql */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* uh = uh*vl */
mpz_mul(uh, uh, vl);
/* vl = vl*vl - 2*ql */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
/* ql = ql*ql */
mpz_mul(ql, ql, ql);
}
if (!(result = GMPy_MPZ_New(NULL)))
goto cleanup;
/* uh contains our return value */
mpz_set(result->z, uh);
cleanup:
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)k);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpz_lucasu_mod,
"lucasu_mod(p,q,k,n) -> mpz\n\n"
"Return the k-th element of the Lucas U sequence defined by p,q (mod n).\n"
"p*p - 4*q must not equal 0; k must be greater than or equal to 0;\n"
"n must be greater than 0.");
static PyObject *
GMPY_mpz_lucasu_mod(PyObject *self, PyObject *args)
{
/* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
* calculate u[k] (modulo n) of Lucas U sequence for p,q.
* Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
*/
MPZ_Object *result = NULL, *p = NULL, *q = NULL, *k = NULL, *n = NULL;
size_t s = 0, j = 0;
mpz_t uh, vl, vh, ql, qh, tmp;
if (PyTuple_Size(args) != 4) {
TYPE_ERROR("lucasu_mod() requires 4 integer arguments");
return NULL;
}
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 3), NULL);
if (!p || !q || !k || !n) {
TYPE_ERROR("lucasu_mod() requires 4 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in lucasu_mod()");
goto cleanup;
}
/* Check if k < 0. */
if (mpz_sgn(k->z) < 0) {
VALUE_ERROR("invalid value for k in lucasu_mod()");
goto cleanup;
}
/* Check if n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("invalid value for n in lucasu_mod()");
goto cleanup;
}
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp, 0);
s = mpz_scan1(k->z, 0);
for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(k->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vh (mod n) */
mpz_mul(uh, uh, vh);
mpz_mod(uh, uh, n->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql (mod n) */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
mpz_mod(uh, uh, n->z);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* uh = uh*vl (mod n) */
mpz_mul(uh, uh, vl);
mpz_mod(uh, uh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
}
if (!(result = GMPy_MPZ_New(NULL)))
goto cleanup;
/* uh contains our return value */
mpz_mod(result->z, uh, n->z);
cleanup:
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)k);
Py_XDECREF((PyObject*)n);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpz_lucasv,
"lucasv(p,q,k) -> mpz\n\n"
"Return the k-th element of the Lucas V sequence defined by p,q.\n"
"p*p - 4*q must not equal 0; k must be greater than or equal to 0.");
static PyObject *
GMPY_mpz_lucasv(PyObject *self, PyObject *args)
{
/* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
* calculate v[k] of Lucas V sequence for p,q.
* Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
*/
MPZ_Object *result = NULL, *p = NULL, *q = NULL, *k = NULL;
size_t s = 0, j = 0;
mpz_t vl, vh, ql, qh, tmp;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("lucasv() requires 3 integer arguments");
return NULL;
}
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!p || !q || !k) {
TYPE_ERROR("lucasv() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in lucasv()");
goto cleanup;
}
/* Check if k < 0. */
if (mpz_sgn(k->z) < 0) {
VALUE_ERROR("invalid value for k in lucasv()");
goto cleanup;
}
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
s = mpz_scan1(k->z, 0);
for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
if (mpz_tstbit(k->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* vh = vh*vh - 2*qh */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* vh = vh*vl - p*ql */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
/* vl = vl*vl - 2*ql */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* vl = vl*vl - 2*ql */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
/* ql = ql*ql */
mpz_mul(ql, ql, ql);
}
if (!(result = GMPy_MPZ_New(NULL)))
goto cleanup;
/* vl contains our return value */
mpz_set(result->z, vl);
cleanup:
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)k);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpz_lucasv_mod,
"lucasv_mod(p,q,k,n) -> mpz\n\n"
"Return the k-th element of the Lucas V sequence defined by p,q (mod n).\n"
"p*p - 4*q must not equal 0; k must be greater than or equal to 0;\n"
"n must be greater than 0.");
static PyObject *
GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args)
{
/* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
* calculate v[k] (modulo n) of Lucas V sequence for p,q.
* Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
*/
MPZ_Object *result = NULL, *p = NULL, *q = NULL, *k = NULL, *n = NULL;
size_t s = 0, j = 0;
mpz_t vl, vh, ql, qh, tmp;
if (PyTuple_Size(args) != 4) {
TYPE_ERROR("lucasv_mod() requires 4 integer arguments");
return NULL;
}
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 3), NULL);
if (!p || !q || !k || !n) {
TYPE_ERROR("lucasv_mod() requires 4 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in lucasv_mod()");
goto cleanup;
}
/* Check if k < 0. */
if (mpz_sgn(k->z) < 0) {
VALUE_ERROR("invalid value for k in lucasv_mod()");
goto cleanup;
}
/* Check if n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("invalid value for n in lucasv_mod()");
goto cleanup;
}
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
s = mpz_scan1(k->z, 0);
for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(k->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
}
if (!(result = GMPy_MPZ_New(NULL)))
goto cleanup;
/* vl contains our return value */
mpz_mod(result->z, vl, n->z);
cleanup:
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)k);
Py_XDECREF((PyObject*)n);
return (PyObject*)result;
}
gmpy2-2.1.0b3/src/gmpy_mpz_lucas.h 0000664 0001750 0001750 00000004356 13425754313 016657 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpz_lucas.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2012, 2013, 2014, 2015, 2016, 2017, 2018, *
* 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_LUCAS_H
#define GMPY_LUCAS_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPY_mpz_lucasu(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_lucasu_mod(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_lucasv(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/gmpy_mpz_prp.c 0000664 0001750 0001750 00000130025 13425754352 016340 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpz_prp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2011 David Cleaver *
* *
* Copyright 2012, 2013, 2014, 2015, 2016, 2017, 2018, *
* 2019 Case Van Horsen *
* *
* The original file is available at: *
* *
* *
* Modified by Case Van Horsen for inclusion into GMPY2. *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* ******************************************************************
* mpz_prp: (also called a Fermat probable prime)
* A "probable prime" to the base a is a number n such that,
* (a,n)=1 and a^(n-1) = 1 mod n
* ******************************************************************/
PyDoc_STRVAR(doc_mpz_is_fermat_prp,
"is_fermat_prp(n,a) -> boolean\n\n"
"Return True if n is a Fermat probable prime to the base a.\n"
"Assuming:\n"
" gcd(n,a) == 1\n"
"Then a Fermat probable prime requires:\n"
" a**(n-1) == 1 (mod n)");
static PyObject *
GMPY_mpz_is_fermat_prp(PyObject *self, PyObject *args)
{
MPZ_Object *a = NULL, *n = NULL;
PyObject *result = NULL;
mpz_t res, nm1;
if (PyTuple_Size(args) != 2) {
TYPE_ERROR("is_fermat_prp() requires 2 integer arguments");
return NULL;
}
mpz_init(res);
mpz_init(nm1);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!a || !n) {
TYPE_ERROR("is_fermat_prp() requires 2 integer arguments");
goto cleanup;
}
/* Require a >= 2. */
if (mpz_cmp_ui(a->z, 2) < 0) {
VALUE_ERROR("is_fermat_prp() requires 'a' greater than or equal to 2");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_fermat_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
/* Should n even raise an exception? */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check gcd(a,n) */
mpz_gcd(res, n->z, a->z);
if (mpz_cmp_ui(res, 1) > 0) {
VALUE_ERROR("is_fermat_prp() requires gcd(n,a) == 1");
goto cleanup;
}
mpz_set(nm1, n->z);
mpz_sub_ui(nm1, nm1, 1);
mpz_powm(res, a->z, nm1, n->z);
if (mpz_cmp_ui(res, 1) == 0)
result = Py_True;
else
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(res);
mpz_clear(nm1);
Py_XDECREF((PyObject*)a);
Py_XDECREF((PyObject*)n);
return result;
}
/* *************************************************************************
* mpz_euler_prp: (also called a Solovay-Strassen probable prime)
* An "Euler probable prime" to the base a is an odd composite number n with,
* (a,n)=1 such that a^((n-1)/2)=(a/n) mod n [(a/n) is the Jacobi symbol]
* *************************************************************************/
PyDoc_STRVAR(doc_mpz_is_euler_prp,
"is_euler_prp(n,a) -> boolean\n\n"
"Return True if n is an Euler (also known as Solovay-Strassen)\n"
"probable prime to the base a.\n"
"Assuming:\n"
" gcd(n,a) == 1\n"
" n is odd\n"
"Then an Euler probable prime requires:\n"
" a**((n-1)/2) == 1 (mod n)");
static PyObject *
GMPY_mpz_is_euler_prp(PyObject *self, PyObject *args)
{
MPZ_Object *a = NULL, *n = NULL;
PyObject *result = NULL;
mpz_t res, exp;
int ret;
if (PyTuple_Size(args) != 2) {
TYPE_ERROR("is_euler_prp() requires 2 integer arguments");
return NULL;
}
mpz_init(res);
mpz_init(exp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!a || !n) {
TYPE_ERROR("is_euler_prp() requires 2 integer arguments");
goto cleanup;
}
/* Require a >= 2. */
if (mpz_cmp_ui(a->z, 2) < 0) {
VALUE_ERROR("is_euler_prp() requires 'a' greater than or equal to 2");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_euler_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check gcd(a,b) */
mpz_gcd(res, n->z, a->z);
if (mpz_cmp_ui(res, 1) > 0) {
VALUE_ERROR("is_euler_prp() requires gcd(n,a) == 1");
goto cleanup;
}
mpz_set(exp, n->z);
mpz_sub_ui(exp, exp, 1);
mpz_divexact_ui(exp, exp, 2);
mpz_powm(res, a->z, exp, n->z);
/* reuse exp to calculate jacobi(a,n) mod n */
ret = mpz_jacobi(a->z,n->z);
mpz_set(exp, n->z);
if (ret == -1)
mpz_sub_ui(exp, exp, 1);
else if (ret == 1)
mpz_add_ui(exp, exp, 1);
mpz_mod(exp, exp, n->z);
if (mpz_cmp(res, exp) == 0)
result = Py_True;
else
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(res);
mpz_clear(exp);
Py_XDECREF((PyObject*)a);
Py_XDECREF((PyObject*)n);
return result;
}
/* *********************************************************************************************
* mpz_sprp: (also called a Miller-Rabin probable prime)
* A "strong probable prime" to the base a is an odd composite n = (2^r)*s+1 with s odd such that
* either a^s == 1 mod n, or a^((2^t)*s) == -1 mod n, for some integer t, with 0 <= t < r.
* *********************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_strong_prp,
"is_strong_prp(n,a) -> boolean\n\n"
"Return True if n is an strong (also known as Miller-Rabin)\n"
"probable prime to the base a.\n"
"Assuming:\n"
" gcd(n,a) == 1\n"
" n is odd\n"
" n = s*(2**r) + 1, with s odd\n"
"Then a strong probable prime requires one of the following is true:\n"
" a**s == 1 (mod n)\n"
" or\n"
" a**(s*(2**t)) == -1 (mod n) for some t, 0 <= t < r.");
static PyObject *
GMPY_mpz_is_strong_prp(PyObject *self, PyObject *args)
{
MPZ_Object *a = NULL, *n = NULL;
PyObject *result = NULL;
mpz_t s, nm1, mpz_test;
mp_bitcnt_t r = 0;
if (PyTuple_Size(args) != 2) {
TYPE_ERROR("is_strong_prp() requires 2 integer arguments");
return NULL;
}
mpz_init(s);
mpz_init(nm1);
mpz_init(mpz_test);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!a || !n) {
TYPE_ERROR("is_strong_prp() requires 2 integer arguments");
goto cleanup;
}
/* Require a >= 2. */
if (mpz_cmp_ui(a->z, 2) < 0) {
VALUE_ERROR("is_strong_prp() requires 'a' greater than or equal to 2");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_strong_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check gcd(a,b) */
mpz_gcd(s, n->z, a->z);
if (mpz_cmp_ui(s, 1) > 0) {
VALUE_ERROR("is_strong_prp() requires gcd(n,a) == 1");
goto cleanup;
}
mpz_set(nm1, n->z);
mpz_sub_ui(nm1, nm1, 1);
/* Find s and r satisfying: n-1=(2^r)*s, s odd */
r = mpz_scan1(nm1, 0);
mpz_fdiv_q_2exp(s, nm1, r);
/* Check a^((2^t)*s) mod n for 0 <= t < r */
mpz_powm(mpz_test, a->z, s, n->z);
if ((mpz_cmp_ui(mpz_test, 1) == 0) || (mpz_cmp(mpz_test, nm1) == 0)) {
result = Py_True;
goto cleanup;
}
while (--r) {
/* mpz_test = mpz_test^2%n */
mpz_mul(mpz_test, mpz_test, mpz_test);
mpz_mod(mpz_test, mpz_test, n->z);
if (mpz_cmp(mpz_test, nm1) == 0) {
result = Py_True;
goto cleanup;
}
}
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(s);
mpz_clear(nm1);
mpz_clear(mpz_test);
Py_XDECREF((PyObject*)a);
Py_XDECREF((PyObject*)n);
return result;
}
/* *************************************************************************
* mpz_fibonacci_prp:
* A "Fibonacci probable prime" with parameters (P,Q), P > 0, Q=+/-1, is a
* composite n for which V_n == P mod n
* [V is the Lucas V sequence with parameters P,Q]
* *************************************************************************/
PyDoc_STRVAR(doc_mpz_is_fibonacci_prp,
"is_fibonacci_prp(n,p,q) -> boolean\n\n"
"Return True if n is an Fibonacci probable prime with parameters (p,q).\n"
"Assuming:\n"
" n is odd\n"
" p > 0, q = +/-1\n"
" p*p - 4*q != 0\n"
"Then a Fibonacci probable prime requires:\n"
" lucasv(p,q,n) == p (mod n).");
static PyObject *
GMPY_mpz_is_fibonacci_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL, *p = NULL, *q = NULL;
PyObject *result = NULL;
mpz_t pmodn, zP;
/* used for calculating the Lucas V sequence */
mpz_t vl, vh, ql, qh, tmp;
mp_bitcnt_t s = 0, j = 0;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments");
return NULL;
}
mpz_init(pmodn);
mpz_init(zP);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!n || !p || !q) {
TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()");
goto cleanup;
}
/* Verify q = +/-1 */
if ((mpz_cmp_si(q->z, 1) && mpz_cmp_si(q->z, -1)) || (mpz_sgn(p->z) <= 0)) {
VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_fibonacci_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
mpz_set(zP, p->z);
mpz_mod(pmodn, zP, n->z);
/* mpz_lucasvmod(res, p, q, n, n); */
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
s = mpz_scan1(n->z, 0);
for (j = mpz_sizeinbase(n->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(n->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
}
/* vl contains our return value */
mpz_mod(vl, vl, n->z);
if (mpz_cmp(vl, pmodn) == 0)
result = Py_True;
else
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(pmodn);
mpz_clear(zP);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)n);
return result;
}
/* *******************************************************************************
* mpz_lucas_prp:
* A "Lucas probable prime" with parameters (P,Q) is a composite n with D=P^2-4Q,
* (n,2QD)=1 such that U_(n-(D/n)) == 0 mod n [(D/n) is the Jacobi symbol]
* *******************************************************************************/
PyDoc_STRVAR(doc_mpz_is_lucas_prp,
"is_lucas_prp(n,p,q) -> boolean\n\n"
"Return True if n is a Lucas probable prime with parameters (p,q).\n"
"Assuming:\n"
" n is odd\n"
" D = p*p - 4*q, D != 0\n"
" gcd(n, 2*q*D) == 1\n"
"Then a Lucas probable prime requires:\n"
" lucasu(p,q,n - Jacobi(D,n)) == 0 (mod n)");
static PyObject *
GMPY_mpz_is_lucas_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL, *p = NULL, *q = NULL;
PyObject *result = NULL;
mpz_t zD, res, index;
/* used for calculating the Lucas U sequence */
mpz_t uh, vl, vh, ql, qh, tmp;
mp_bitcnt_t s = 0, j = 0;
int ret;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("is_lucas_prp() requires 3 integer arguments");
return NULL;
}
mpz_init(zD);
mpz_init(res);
mpz_init(index);
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!n || !p || !q) {
TYPE_ERROR("is_lucas_prp() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(zD, p->z, p->z);
mpz_mul_ui(tmp, q->z, 4);
mpz_sub(zD, zD, tmp);
if (mpz_sgn(zD) == 0) {
VALUE_ERROR("invalid values for p,q in is_lucas_prp()");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_lucas_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check GCD */
mpz_mul(res, zD, q->z);
mpz_mul_ui(res, res, 2);
mpz_gcd(res, res, n->z);
if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) {
VALUE_ERROR("is_lucas_prp() requires gcd(n,2*q*D) == 1");
goto cleanup;
}
/* index = n-(D/n), where (D/n) is the Jacobi symbol */
mpz_set(index, n->z);
ret = mpz_jacobi(zD, n->z);
if (ret == -1)
mpz_add_ui(index, index, 1);
else if (ret == 1)
mpz_sub_ui(index, index, 1);
/* mpz_lucasumod(res, p, q, index, n); */
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
s = mpz_scan1(index, 0);
for (j = mpz_sizeinbase(index,2)-1; j >= s+1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(index,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vh (mod n) */
mpz_mul(uh, uh, vh);
mpz_mod(uh, uh, n->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql (mod n) */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
mpz_mod(uh, uh, n->z);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* uh = uh*vl (mod n) */
mpz_mul(uh, uh, vl);
mpz_mod(uh, uh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
}
/* uh contains our return value */
mpz_mod(res, uh, n->z);
if (mpz_cmp_ui(res, 0) == 0)
result = Py_True;
else
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(zD);
mpz_clear(res);
mpz_clear(index);
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)n);
return result;
}
/* *********************************************************************************************
* mpz_stronglucas_prp:
* A "strong Lucas probable prime" with parameters (P,Q) is a composite n = (2^r)*s+(D/n), where
* s is odd, D=P^2-4Q, and (n,2QD)=1 such that either U_s == 0 mod n or V_((2^t)*s) == 0 mod n
* for some t, 0 <= t < r. [(D/n) is the Jacobi symbol]
* *********************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_stronglucas_prp,
"is_strong_lucas_prp(n,p,q) -> boolean\n\n"
"Return True if n is a strong Lucas probable prime with parameters (p,q).\n"
"Assuming:\n"
" n is odd\n"
" D = p*p - 4*q, D != 0\n"
" gcd(n, 2*q*D) == 1\n"
" n = s*(2**r) + Jacobi(D,n), s odd\n"
"Then a strong Lucas probable prime requires:\n"
" lucasu(p,q,s) == 0 (mod n)\n"
" or\n"
" lucasv(p,q,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r");
static PyObject *
GMPY_mpz_is_stronglucas_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL, *p= NULL, *q = NULL;
PyObject *result = NULL;
mpz_t zD, s, nmj, res;
/* these are needed for the LucasU and LucasV part of this function */
mpz_t uh, vl, vh, ql, qh, tmp;
mp_bitcnt_t r = 0, j = 0;
int ret = 0;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("is_strong_lucas_prp() requires 3 integer arguments");
return NULL;
}
mpz_init(zD);
mpz_init(s);
mpz_init(nmj);
mpz_init(res);
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!n || !p || !q) {
TYPE_ERROR("is_strong_lucas_prp() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(zD, p->z, p->z);
mpz_mul_ui(tmp, q->z, 4);
mpz_sub(zD, zD, tmp);
if (mpz_sgn(zD) == 0) {
VALUE_ERROR("invalid values for p,q in is_strong_lucas_prp()");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_strong_lucas_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check GCD */
mpz_mul(res, zD, q->z);
mpz_mul_ui(res, res, 2);
mpz_gcd(res, res, n->z);
if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) {
VALUE_ERROR("is_strong_lucas_prp() requires gcd(n,2*q*D) == 1");
goto cleanup;
}
/* nmj = n - (D/n), where (D/n) is the Jacobi symbol */
mpz_set(nmj, n->z);
ret = mpz_jacobi(zD, n->z);
if (ret == -1)
mpz_add_ui(nmj, nmj, 1);
else if (ret == 1)
mpz_sub_ui(nmj, nmj, 1);
r = mpz_scan1(nmj, 0);
mpz_fdiv_q_2exp(s, nmj, r);
/* make sure U_s == 0 mod n or V_((2^t)*s) == 0 mod n, for some t, 0 <= t < r */
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(s,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vh (mod n) */
mpz_mul(uh, uh, vh);
mpz_mod(uh, uh, n->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql (mod n) */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
mpz_mod(uh, uh, n->z);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
mpz_mod(uh, uh, n->z);
mpz_mod(vl, vl, n->z);
/* uh contains LucasU_s and vl contains LucasV_s */
if ((mpz_cmp_ui(uh, 0) == 0) || (mpz_cmp_ui(vl, 0) == 0)) {
result = Py_True;
goto cleanup;
}
for (j = 1; j < r; j++) {
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
if (mpz_cmp_ui(vl, 0) == 0) {
result = Py_True;
goto cleanup;
}
}
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(zD);
mpz_clear(s);
mpz_clear(nmj);
mpz_clear(res);
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)n);
return result;
}
/* *******************************************************************************************
* mpz_extrastronglucas_prp:
* Let U_n = LucasU(p,1), V_n = LucasV(p,1), and D=p^2-4.
* An "extra strong Lucas probable prime" to the base p is a composite n = (2^r)*s+(D/n), where
* s is odd and (n,2D)=1, such that either U_s == 0 mod n or V_s == +/-2 mod n, or
* V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 [(D/n) is the Jacobi symbol]
* *******************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_extrastronglucas_prp,
"is_extra_strong_lucas_prp(n,p) -> boolean\n\n"
"Return True if n is an extra strong Lucas probable prime with parameters\n"
"(p,1). Assuming:\n"
" n is odd\n"
" D = p*p - 4, D != 0\n"
" gcd(n, 2*D) == 1\n"
" n = s*(2**r) + Jacobi(D,n), s odd\n"
"Then an extra strong Lucas probable prime requires:\n"
" lucasu(p,1,s) == 0 (mod n)\n"
" or\n"
" lucasv(p,1,s) == +/-2 (mod n)\n"
" or\n"
" lucasv(p,1,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r");
static PyObject *
GMPY_mpz_is_extrastronglucas_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL, *p = NULL;
PyObject *result = NULL;
mpz_t zD, s, nmj, nm2, res;
/* these are needed for the LucasU and LucasV part of this function */
mpz_t uh, vl, vh, ql, qh, tmp;
mp_bitcnt_t r = 0, j = 0;
int ret = 0;
if (PyTuple_Size(args) != 2) {
TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments");
return NULL;
}
mpz_init(zD);
mpz_init(s);
mpz_init(nmj);
mpz_init(nm2);
mpz_init(res);
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!n || !p) {
TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments");
goto cleanup;
}
/* Check if p*p - 4 == 0. */
mpz_mul(zD, p->z, p->z);
mpz_sub_ui(zD, zD, 4);
if (mpz_sgn(zD) == 0) {
VALUE_ERROR("invalid value for p in is_extra_strong_lucas_prp()");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_extra_strong_lucas_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check GCD */
mpz_mul_ui(res, zD, 2);
mpz_gcd(res, res, n->z);
if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) {
VALUE_ERROR("is_extra_strong_lucas_prp() requires gcd(n,2*D) == 1");
goto cleanup;
}
/* nmj = n - (D/n), where (D/n) is the Jacobi symbol */
mpz_set(nmj, n->z);
ret = mpz_jacobi(zD, n->z);
if (ret == -1)
mpz_add_ui(nmj, nmj, 1);
else if (ret == 1)
mpz_sub_ui(nmj, nmj, 1);
r = mpz_scan1(nmj, 0);
mpz_fdiv_q_2exp(s, nmj, r);
mpz_set(nm2, n->z);
mpz_sub_ui(nm2, nm2, 2);
/* make sure that either U_s == 0 mod n or V_s == +/-2 mod n, or */
/* V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 */
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(s,j) == 1) {
/* qh = ql*q */
mpz_set(qh, ql);
/* uh = uh*vh (mod n) */
mpz_mul(uh, uh, vh);
mpz_mod(uh, uh, n->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql (mod n) */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
mpz_mod(uh, uh, n->z);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_set(qh, ql);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
mpz_mod(uh, uh, n->z);
mpz_mod(vl, vl, n->z);
/* uh contains LucasU_s and vl contains LucasV_s */
if ((mpz_cmp_ui(uh, 0) == 0) || (mpz_cmp_ui(vl, 0) == 0) ||
(mpz_cmp(vl, nm2) == 0) || (mpz_cmp_si(vl, 2) == 0)) {
result = Py_True;
goto cleanup;
}
for (j = 1; j < r-1; j++) {
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
if (mpz_cmp_ui(vl, 0) == 0) {
result = Py_True;
goto cleanup;
}
}
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(zD);
mpz_clear(s);
mpz_clear(nmj);
mpz_clear(nm2);
mpz_clear(res);
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)n);
return result;
}
/* ***********************************************************************************************
* mpz_selfridge_prp:
* A "Lucas-Selfridge probable prime" n is a "Lucas probable prime" using Selfridge parameters of:
* Find the first element D in the sequence {5, -7, 9, -11, 13, ...} such that Jacobi(D,n) = -1
* Then use P=1 and Q=(1-D)/4 in the Lucas probable prime test.
* Make sure n is not a perfect square, otherwise the search for D will only stop when D=n.
* ***********************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_selfridge_prp,
"is_selfridge_prp(n) -> boolean\n\n"
"Return True if n is a Lucas probable prime with Selfidge parameters\n"
"(p,q). The Selfridge parameters are chosen by finding the first\n"
"element D in the sequence {5, -7, 9, -11, 13, ...} such that\n"
"Jacobi(D,n) == -1. Then let p=1 and q = (1-D)/4. Then perform\n"
"a Lucas probable prime test.");
static PyObject *
GMPY_mpz_is_selfridge_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL;
PyObject *result = NULL, *temp = NULL;
long d = 5, p = 1, q = 0, max_d = 1000000;
int jacobi = 0;
mpz_t zD;
if (PyTuple_Size(args) != 1) {
TYPE_ERROR("is_selfridge_prp() requires 1 integer argument");
return NULL;
}
mpz_init(zD);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
if (!n) {
TYPE_ERROR("is_selfridge_prp() requires 1 integer argument");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_selfridge_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
mpz_set_ui(zD, d);
while (1) {
jacobi = mpz_jacobi(zD, n->z);
/* if jacobi == 0, d is a factor of n, therefore n is composite... */
/* if d == n, then either n is either prime or 9... */
if (jacobi == 0) {
if ((mpz_cmpabs(zD, n->z) == 0) && (mpz_cmp_ui(zD, 9) != 0)) {
result = Py_True;
goto cleanup;
}
else {
result = Py_False;
goto cleanup;
}
}
if (jacobi == -1)
break;
/* if we get to the 5th d, make sure we aren't dealing with a square... */
if (d == 13) {
if (mpz_perfect_square_p(n->z)) {
result = Py_False;
goto cleanup;
}
}
if (d < 0) {
d *= -1;
d += 2;
}
else {
d += 2;
d *= -1;
}
/* make sure we don't search forever */
if (d >= max_d) {
VALUE_ERROR("appropriate value for D cannot be found in is_selfridge_prp()");
goto cleanup;
}
mpz_set_si(zD, d);
}
q = (1-d)/4;
/* Since "O" is used, the refcount for n is incremented so deleting
* temp will not delete n.
*/
temp = Py_BuildValue("Oll", n, p, q);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_lucas_prp(NULL, temp);
Py_DECREF(temp);
goto return_result;
cleanup:
Py_XINCREF(result);
return_result:
mpz_clear(zD);
Py_DECREF((PyObject*)n);
return result;
}
/* *********************************************************************************************************
* mpz_strongselfridge_prp:
* A "strong Lucas-Selfridge probable prime" n is a "strong Lucas probable prime" using Selfridge parameters of:
* Find the first element D in the sequence {5, -7, 9, -11, 13, ...} such that Jacobi(D,n) = -1
* Then use P=1 and Q=(1-D)/4 in the strong Lucas probable prime test.
* Make sure n is not a perfect square, otherwise the search for D will only stop when D=n.
* **********************************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_strongselfridge_prp,
"is_strong_selfridge_prp(n) -> boolean\n\n"
"Return True if n is a strong Lucas probable prime with Selfidge\n"
"parameters (p,q). The Selfridge parameters are chosen by finding\n"
"the first element D in the sequence {5, -7, 9, -11, 13, ...} such\n"
"that Jacobi(D,n) == -1. Then let p=1 and q = (1-D)/4. Then perform\n"
"a strong Lucas probable prime test.");
static PyObject *
GMPY_mpz_is_strongselfridge_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL;
PyObject *result = NULL, *temp = NULL;
long d = 5, p = 1, q = 0, max_d = 1000000;
int jacobi = 0;
mpz_t zD;
if (PyTuple_Size(args) != 1) {
TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument");
return NULL;
}
mpz_init(zD);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
if (!n) {
TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_strong_selfridge_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
mpz_set_ui(zD, d);
while (1) {
jacobi = mpz_jacobi(zD, n->z);
/* if jacobi == 0, d is a factor of n, therefore n is composite... */
/* if d == n, then either n is either prime or 9... */
if (jacobi == 0) {
if ((mpz_cmpabs(zD, n->z) == 0) && (mpz_cmp_ui(zD, 9) != 0)) {
result = Py_True;
goto cleanup;
}
else {
result = Py_False;
goto cleanup;
}
}
if (jacobi == -1)
break;
/* if we get to the 5th d, make sure we aren't dealing with a square... */
if (d == 13) {
if (mpz_perfect_square_p(n->z)) {
result = Py_False;
goto cleanup;
}
}
if (d < 0) {
d *= -1;
d += 2;
}
else {
d += 2;
d *= -1;
}
/* make sure we don't search forever */
if (d >= max_d) {
VALUE_ERROR("appropriate value for D cannot be found in is_strong_selfridge_prp()");
goto cleanup;
}
mpz_set_si(zD, d);
}
q = (1-d)/4;
/* Since "O" is used, the refcount for n is incremented so deleting
* temp will not delete n.
*/
temp = Py_BuildValue("Oll", n, p, q);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_stronglucas_prp(NULL, temp);
Py_DECREF(temp);
goto return_result;
cleanup:
Py_XINCREF(result);
return_result:
mpz_clear(zD);
Py_DECREF((PyObject*)n);
return result;
}
/* **********************************************************************************
* mpz_bpsw_prp:
* A "Baillie-Pomerance-Selfridge-Wagstaff probable prime" is a composite n such that
* n is a strong probable prime to the base 2 and
* n is a Lucas probable prime using the Selfridge parameters.
* **********************************************************************************/
PyDoc_STRVAR(doc_mpz_is_bpsw_prp,
"is_bpsw_prp(n) -> boolean\n\n"
"Return True if n is a Baillie-Pomerance-Selfridge-Wagstaff probable \n"
"prime. A BPSW probable prime passes the is_strong_prp() test with base\n"
"2 and the is_selfridge_prp() test.\n");
static PyObject *
GMPY_mpz_is_bpsw_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL;
PyObject *result = NULL, *temp = NULL;
if (PyTuple_Size(args) != 1) {
TYPE_ERROR("is_bpsw_prp() requires 1 integer argument");
return NULL;
}
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
if (!n) {
TYPE_ERROR("is_bpsw_prp() requires 1 integer argument");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_bpsw_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* "O" is used to increment the reference to n so deleting temp won't
* delete n.
*/
temp = Py_BuildValue("Oi", n, 2);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_strong_prp(NULL, temp);
Py_DECREF(temp);
if (result == Py_False)
goto return_result;
/* Remember to ignore the preceding result */
Py_DECREF(result);
temp = Py_BuildValue("(O)", n);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_selfridge_prp(NULL, temp);
Py_DECREF(temp);
goto return_result;
cleanup:
Py_XINCREF(result);
return_result:
Py_DECREF((PyObject*)n);
return result;
}
/* ****************************************************************************************
* mpz_strongbpsw_prp:
* A "strong Baillie-Pomerance-Selfridge-Wagstaff probable prime" is a composite n such that
* n is a strong probable prime to the base 2 and
* n is a strong Lucas probable prime using the Selfridge parameters.
* ****************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_strongbpsw_prp,
"is_strong_bpsw_prp(n) -> boolean\n\n"
"Return True if n is a strong Baillie-Pomerance-Selfridge-Wagstaff\n"
"probable prime. A strong BPSW probable prime passes the is_strong_prp()\n"
"test with base and the is_strong_selfridge_prp() test.\n");
static PyObject *
GMPY_mpz_is_strongbpsw_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL;
PyObject *result = NULL, *temp = NULL;
if (PyTuple_Size(args) != 1) {
TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument");
return NULL;
}
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
if (!n) {
TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_strong_bpsw_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* "O" is used to increment the reference to n so deleting temp won't
* delete n.
*/
temp = Py_BuildValue("Oi", n, 2);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_strong_prp(NULL, temp);
Py_DECREF(temp);
if (result == Py_False)
goto return_result;
/* Remember to ignore the preceding result */
Py_DECREF(result);
temp = Py_BuildValue("(O)", n);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_selfridge_prp(NULL, temp);
Py_DECREF(temp);
goto return_result;
cleanup:
Py_XINCREF(result);
return_result:
Py_DECREF((PyObject*)n);
return result;
}
gmpy2-2.1.0b3/src/gmpy_mpz_prp.h 0000664 0001750 0001750 00000005371 13425754405 016351 0 ustar case case 0000000 0000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpz_prp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2012, 2013, 2014, 2015, 2016, 2017, 2018, *
* 2019 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 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. *
* *
* GMPY2 is distributed in the hope that 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 GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_PRP_H
#define GMPY_PRP_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPY_mpz_is_fermat_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_euler_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_strong_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_fibonacci_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_lucas_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_stronglucas_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_extrastronglucas_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_selfridge_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_strongselfridge_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_bpsw_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_strongbpsw_prp(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
gmpy2-2.1.0b3/src/mpz_pylong.c 0000664 0001750 0001750 00000016472 13170047220 016006 0 ustar case case 0000000 0000000 /* mpz <-> pylong conversion and "pythonhash" for mpz
*
* Originally written for sage (http://sagemath.org) by Gonzalo Tornaria
* . If you improve on these functions, please
* contribute them back to sage by posting to sage-devel@googlegroups.com
* or by sending an email to the original author.
*
* Integration with gmpy2 by Case Van Horsen .
*
* License: LGPL v2 or later
*
*/
/* This file created by merging mpn_pylong and mpz_pylong. Permission
* was granted by the original author to make this code available under
* the LGPLv2+ license.
*/
/* This code assumes that SHIFT < GMP_NUMB_BITS */
#if PyLong_SHIFT >= GMP_NUMB_BITS
#error "Python limb larger than GMP limb !!!"
#endif
#ifndef ABS
#define ABS(a) (((a) < 0) ? -(a) : (a))
#endif
/* Use these "portable" (I hope) sizebits functions.
* We could implement this in terms of count_leading_zeros from GMP,
* but it is not exported!
*/
static const
unsigned char
__sizebits_tab[128] =
{
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
#if GMP_LIMB_BITS > 64
#error "word size > 64 unsupported"
#endif
static inline
size_t
mpn_sizebits(mp_ptr up, size_t un) {
size_t cnt;
mp_limb_t x;
if (un==0)
return 0;
cnt = (un - 1) * GMP_NUMB_BITS;
x = up[un - 1];
#if GMP_LIMB_BITS > 32
if ((x >> 32) != 0) { x >>= 32; cnt += 32; }
#endif
#if GMP_LIMB_BITS > 16
if ((x >> 16) != 0) { x >>= 16; cnt += 16; }
#endif
#if GMP_LIMB_BITS > 8
if ((x >> 8) != 0) { x >>= 8; cnt += 8; }
#endif
return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]);
}
static inline
size_t
pylong_sizebits(digit *digits, size_t size) {
size_t cnt;
digit x;
if (size==0)
return 0;
cnt = (size - 1) * PyLong_SHIFT;
x = digits[size - 1];
#if PyLong_SHIFT > 32
if ((x >> 32) != 0) { x >>= 32; cnt += 32; }
#endif
#if PyLong_SHIFT > 16
if ((x >> 16) != 0) { x >>= 16; cnt += 16; }
#endif
#if PyLong_SHIFT > 8
if ((x >> 8) != 0) { x >>= 8; cnt += 8; }
#endif
return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]);
}
/* mpn -> pylong conversion */
size_t
mpn_pylong_size (mp_ptr up, size_t un)
{
return (mpn_sizebits(up, un) + PyLong_SHIFT - 1) / PyLong_SHIFT;
}
/* this is based from GMP code in mpn/get_str.c */
/* Assume digits points to a chunk of size size
* where size >= mpn_pylong_size(up, un)
*/
void
mpn_get_pylong (digit *digits, size_t size, mp_ptr up, size_t un)
{
mp_limb_t n1, n0;
size_t i;
ssize_t bit_pos;
/* point past the allocated chunk */
digit *s = digits + size;
/* input length 0 is special ! */
if (un == 0) {
while (size) digits[--size] = 0;
return;
}
i = un - 1;
n1 = up[i];
bit_pos = size * PyLong_SHIFT - i * GMP_NUMB_BITS;
for (;;) {
bit_pos -= PyLong_SHIFT;
while (bit_pos >= 0) {
*--s = (n1 >> bit_pos) & PyLong_MASK;
bit_pos -= PyLong_SHIFT;
}
if (i == 0)
break;
n0 = (n1 << -bit_pos) & PyLong_MASK;
n1 = up[--i];
bit_pos += GMP_NUMB_BITS;
*--s = (digit)(n0 | (n1 >> bit_pos));
}
}
/* pylong -> mpn conversion */
size_t
mpn_size_from_pylong (digit *digits, size_t size)
{
return (pylong_sizebits(digits, size) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
}
void
mpn_set_pylong(mp_ptr up, size_t un, digit *digits, size_t size)
{
mp_limb_t n1, d;
size_t i;
ssize_t bit_pos;
/* point past the allocated chunk */
digit * s = digits + size;
/* input length 0 is special ! */
if (size == 0) {
while (un) up[--un] = 0;
return;
}
i = un - 1;
n1 = 0;
bit_pos = size * PyLong_SHIFT - i * GMP_NUMB_BITS;
for (;;) {
bit_pos -= PyLong_SHIFT;
while (bit_pos >= 0) {
d = (mp_limb_t) *--s;
n1 |= (d << bit_pos) & GMP_NUMB_MASK;
bit_pos -= PyLong_SHIFT;
}
if (i == 0)
break;
d = (mp_limb_t) *--s;
/* add some high bits of d; maybe none if bit_pos=-SHIFT */
up[i--] = n1 | (d & PyLong_MASK) >> -bit_pos;
bit_pos += GMP_NUMB_BITS;
n1 = (d << bit_pos) & GMP_NUMB_MASK;
}
up[0] = n1;
}
/************************************************************/
/* Hashing functions */
#define LONG_BIT_SHIFT (8*sizeof(long) - PyLong_SHIFT)
/*
* for an mpz, this number has to be multiplied by the sign
* also remember to catch -1 and map it to -2 !
*/
long
mpn_pythonhash (mp_ptr up, mp_size_t un)
{
mp_limb_t n1, n0;
mp_size_t i;
ssize_t bit_pos;
long x = 0;
/* input length 0 is special ! */
if (un == 0)
return 0;
i = un - 1;
n1 = up[i];
{
size_t bits;
bits = mpn_sizebits(up, un) + PyLong_SHIFT - 1;
bits -= bits % PyLong_SHIFT;
/* position of the MSW in base 2^SHIFT, counted from the MSW in
* the GMP representation (in base 2^GMP_NUMB_BITS)
*/
bit_pos = bits - i * GMP_NUMB_BITS;
}
for (;;) {
while (bit_pos >= 0) {
/* Force a native long #-bits (32 or 64) circular shift */
x = ((x << PyLong_SHIFT) & ~(long)PyLong_MASK) | ((x >> LONG_BIT_SHIFT) & (long)PyLong_MASK);
/* Shifting to the right by more than wordsize bits
* actually shifts by (wordsize % 32) bits -- which is
* *not* the intended behavior here. */
if (bit_pos <= 8*sizeof(mp_limb_t))
x += (n1 >> bit_pos) & (long)PyLong_MASK;
bit_pos -= PyLong_SHIFT;
}
i--;
if (i < 0)
break;
n0 = (n1 << -bit_pos) & (long)PyLong_MASK;
n1 = up[i];
bit_pos += GMP_NUMB_BITS;
/* Force a native long #-bits (32 or 64) circular shift */
x = ((x << PyLong_SHIFT) & ~(long)PyLong_MASK) | ((x >> LONG_BIT_SHIFT) & (long)PyLong_MASK);
x += (long)(n0 | (n1 >> bit_pos));
bit_pos -= PyLong_SHIFT;
}
return x;
}
/* mpz python hash */
long
mpz_pythonhash(mpz_srcptr z)
{
long x = mpn_pythonhash(z->_mp_d, ABS(z->_mp_size));
if (z->_mp_size < 0)
x = -x;
if (x == -1)
x = -2;
return x;
}
/* mpz -> pylong conversion */
PyObject *
mpz_get_PyLong(mpz_srcptr z)
{
size_t size = mpn_pylong_size(z->_mp_d, ABS(z->_mp_size));
PyLongObject *lptr = PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size);
if (lptr != NULL) {
mpn_get_pylong(lptr->ob_digit, size, z->_mp_d, ABS(z->_mp_size));
if (z->_mp_size < 0)
Py_SIZE(lptr) = -(Py_SIZE(lptr));
}
return (PyObject*)lptr;
}
/* pylong -> mpz conversion */
void
mpz_set_PyIntOrLong(mpz_ptr z, PyObject *lsrc)
{
register PyLongObject *lptr = (PyLongObject*)lsrc;
ssize_t size;
#ifdef PY2
if (PyInt_Check(lsrc)) {
mpz_set_si(z, PyInt_AS_LONG(lsrc));
return;
}
#endif
size = (ssize_t)mpn_size_from_pylong(lptr->ob_digit, ABS(Py_SIZE(lptr)));
if (z->_mp_alloc < size)
_mpz_realloc(z, (mp_size_t)size);
mpn_set_pylong(z->_mp_d, size, lptr->ob_digit, ABS(Py_SIZE(lptr)));
z->_mp_size = (int)(Py_SIZE(lptr) < 0 ? -size : size);
return;
}
gmpy2-2.1.0b3/test/ 0000775 0001750 0001750 00000000000 13530663166 013637 5 ustar case case 0000000 0000000 gmpy2-2.1.0b3/test/gmpy_test.py 0000664 0001750 0001750 00000000554 13105222070 016207 0 ustar case case 0000000 0000000 from __future__ import print_function
import sys
print("\nImportant test information!\n")
print("Please use 'test/runtests.py' to run the new test suite.\n")
if sys.version_info[0] == 3:
print("Please use 'test3/gmpy_test.py' to run legacy tests with Python 3.x.\n")
else:
print("Please use 'test2/gmpy_test.py' to run legacy tests with Python 2.x.\n")
gmpy2-2.1.0b3/test/runtests.py 0000664 0001750 0001750 00000013454 13461370120 016073 0 ustar case case 0000000 0000000 from __future__ import print_function, division
import sys
import os
import glob
import doctest
from doctest import DocTestParser, Example, SKIP
import gmpy2
# *****************************************************************************
# Test strategy
# -------------
# Tests are divided into two different categories:
#
# 1) The 'txt' files contain doctest style tests. These tests should cover
# basic functionality for all functions/types.
# 2) The 'py' files contain Python code that perform extensive tests, but
# may not test every function.
#
# If run by a debug build of Python, the test suite can be repeated multiple
# times to search for memory leaks.
#
# NOTE: IF THE LAST TEST IN A BLOCK OF TESTS GENERATES AN EXCEPTION, THE
# REFERENCE COUNTING IN A DEBUG BUILD GETS CONFUSED. ALWAYS ENSURE THAT
# AT LEAST ONE VALID TEST IS PERFORMED AFTER AN EXCEPTION IS RAISED!
#
# *****************************************************************************
# Check if this is a debug build of Python.
try:
sys.gettotalrefcount()
debug = True
except AttributeError:
debug = False
# Change repeat to the number of times to repeat each test. Combined with a
# debug build, this can help identify memory leaks.
if debug:
try:
repeat = abs(int(sys.argv[1]))
except:
repeat = 1
else:
repeat = 1
# If mpc version < 1.1.0 gmpy2.root_of_unity is defined and gmpy2.cmp_abs
# doesn't manage complex parameters.
# We create a doctest flag to skip a doctest when mpc version is < 1.1.0
SKIP_MPC_LESS_THAN_110 = doctest.register_optionflag("SKIP_MPC_LESS_THAN_110")
mpc_version_110 = 'root_of_unity' in dir(gmpy2) # True if mpc version >= 1.1.0
SKIP_IN_DEBUG_MODE = doctest.register_optionflag("SKIP_IN_DEBUG_MODE")
class Gmpy2DocTestParser(DocTestParser):
def parse(self, *args, **kwargs):
examples = DocTestParser.parse(self, *args, **kwargs)
for example in examples:
if not isinstance(example, Example):
continue
if not mpc_version_110 and SKIP_MPC_LESS_THAN_110 in example.options:
example.options[SKIP] = True
if debug and SKIP_IN_DEBUG_MODE in example.options:
example.options[SKIP] = True
return examples
parser = Gmpy2DocTestParser()
print()
print("Unit tests for gmpy2 {0} with Python {1}".format(gmpy2.version(), sys.version.split()[0]))
print(" Mutliple-precision library: {0}".format(gmpy2.mp_version()))
print(" Floating-point library: {0}".format(gmpy2.mpfr_version()))
print(" Complex library: {0}".format(gmpy2.mpc_version()))
print(" Caching Values: (Cache size) {0}".format(gmpy2.get_cache()[0]))
print(" Caching Values: (Size in limbs) {0}".format(gmpy2.get_cache()[1]))
print()
if sys.version.startswith('3.1'):
print("Due to differences in formatting of exceptions and Python 3.x, there")
print("will be test failures for exception handling when the tests are run")
print("with Python 3.1. The doctest module in Python 3.2 and later does not")
print("have this issue.")
print()
input("Press ENTER to continue.. ")
print()
mpz_doctests = ["test_mpz_create.txt", "test_mpz.txt", "test_mpz_io.txt",
"test_mpz_pack_unpack.txt", "test_misc.txt"]
mpq_doctests = ["test_mpq.txt"]
mpfr_doctests = ["test_mpfr_create.txt", "test_mpfr.txt",
"test_mpfr_trig.txt", "test_mpfr_min_max.txt",
"test_context.txt", "test_mpfr_subnormalize.txt"]
# Some tests may differ between MPFR3 and MPFR4.
mpfr_major_version = gmpy2.mpfr_version().split()[1].split('.')[0]
mpfr_version_tests = [os.path.basename(i)
for i in glob.glob(os.path.join(os.path.dirname(__file__),
"test_mpfr" + mpfr_major_version + "*.txt"))]
mpc_doctests = ["test_mpc_create.txt", "test_mpc.txt", "test_mpc_trig.txt"]
gmpy2_tests = [os.path.basename(i)
for i in glob.glob(os.path.join(os.path.dirname(__file__),
"test_gmpy2*.txt"))]
# The following tests will only pass on Python 3.2+.
py32_doctests = ["test_py32_hash.txt"]
failed = 0
attempted = 0
all_doctests = gmpy2_tests + mpz_doctests + mpq_doctests
all_doctests += mpfr_doctests + mpfr_version_tests
all_doctests += mpc_doctests
if sys.version >= "3.2":
all_doctests += py32_doctests
for test in sorted(all_doctests):
if test.endswith("py2.txt") and sys.version >= "3":
continue
if test.endswith("py3.txt") and sys.version < "3":
continue
for r in range(repeat):
result = doctest.testfile(test, globs=globals(),
optionflags=doctest.IGNORE_EXCEPTION_DETAIL |
doctest.NORMALIZE_WHITESPACE |
doctest.REPORT_NDIFF,
parser=parser)
print("Results for: {0:25}".format(test.split(".")[0]), end="")
print(" Attempted: {1:4d} Failed: {0:4d}".format(*result), end="")
if debug:
print(" RefCount: {0:6d}".format(sys.gettotalrefcount()))
else:
print()
failed += result[0]
attempted += result[1]
if repeat > 1:
print()
print()
print(" Summary - Attempted: {0:4d} Failed: {1:4d}".format(attempted, failed))
print()
print("Running external test programs.")
print("Running {0:30} ".format("test_pack.py"), end="")
import test_pack
if test_pack.test():
print("successful")
attempted += 1
else:
print("failed")
failed += 1
print("Running {0:30} ".format("test_mpz_args.py"), end="")
import test_mpz_args
if test_mpz_args.test():
print("successful")
attempted += 1
else:
print("failed")
failed += 1
if failed:
sys.exit(1)
else:
sys.exit(0)
gmpy2-2.1.0b3/test/supportclasses.py 0000664 0001750 0001750 00000001641 13452510275 017300 0 ustar case case 0000000 0000000 import gmpy2
class Z:
def __mpz__(self): return gmpy2.mpz(2)
class Q:
def __mpz__(self): return gmpy2.mpz(1)
def __mpq__(self): return gmpy2.mpq(3,2)
class R:
def __mpfr__(self): return gmpy2.mpfr(1.5)
class Cx:
def __mpfr__(self): return gmpy2.mpfr(1.5)
def __mpc__(self): return gmpy2.mpc(42,67)
z = Z()
q = Q()
r = R()
cx = Cx()
class A:
def __mpz__(self): return gmpy2.mpz(1)
def __mpq__(self): return gmpy2.mpq(3,2)
def __mpfr__(self): return gmpy2.mpfr(1.5)
def __mpc__(self): return gmpy2.mpc(42,67)
class B:
def __mpz__(self): return 'hello'
def __mpq__(self): return 'hello'
def __mpfr__(self): return 'hello'
def __mpc__(self): return 'hello'
class C:
pass
class D:
def __mpz__(self): raise TypeError
def __mpq__(self): raise TypeError
def __mpfr__(self): raise TypeError
def __mpc__(self): raise TypeError
a = A()
b = B()
c = C()
d = D()
gmpy2-2.1.0b3/test/supportclasses.pyc 0000664 0001750 0001750 00000010647 13461371257 017456 0 ustar case case 0000000 0000000 ó
½ª\c @ sð d d l Z d d d „ ƒ YZ d d d „ ƒ YZ d d d „ ƒ YZ d d d „ ƒ YZ e ƒ Z e ƒ Z e ƒ Z e ƒ Z d
d d „ ƒ YZ d d d
„ ƒ YZ
d d d „ ƒ YZ d d d „ ƒ YZ e ƒ Z
e
ƒ Z e ƒ Z e ƒ Z d S( iÿÿÿÿNt Zc B s e Z d „ Z RS( c C s
t j d ƒ S( Ni ( t gmpy2t mpz( t self( ( s- /home/case/github/gmpy/test/supportclasses.pyt __mpz__ t ( t __name__t
__module__R ( ( ( s- /home/case/github/gmpy/test/supportclasses.pyR s t Qc B s e Z d „ Z d „ Z RS( c C s
t j d ƒ S( Ni ( R R ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR R c C s t j d d ƒ S( Ni i ( R t mpq( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyt __mpq__ R ( R R R R
( ( ( s- /home/case/github/gmpy/test/supportclasses.pyR s t Rc B s e Z d „ Z RS( c C s
t j d ƒ S( Ng ø?( R t mpfr( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyt __mpfr__ R ( R R R
( ( ( s- /home/case/github/gmpy/test/supportclasses.pyR s t Cxc B s e Z d „ Z d „ Z RS( c C s
t j d ƒ S( Ng ø?( R R ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR
R c C s t j d d ƒ S( Ni* iC ( R t mpc( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyt __mpc__ R ( R R R
R ( ( ( s- /home/case/github/gmpy/test/supportclasses.pyR
s t Ac B s, e Z d „ Z d „ Z d „ Z d „ Z RS( c C s
t j d ƒ S( Ni ( R R ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR R c C s t j d d ƒ S( Ni i ( R R ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR
R c C s
t j d ƒ S( Ng ø?( R R ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR
R c C s t j d d ƒ S( Ni* iC ( R R ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR R ( R R R R
R
R ( ( ( s- /home/case/github/gmpy/test/supportclasses.pyR s t Bc B s, e Z d „ Z d „ Z d „ Z d „ Z RS( c C s d S( Nt hello( ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR R c C s d S( NR ( ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR
R c C s d S( NR ( ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR
R c C s d S( NR ( ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR R ( R R R R
R
R ( ( ( s- /home/case/github/gmpy/test/supportclasses.pyR s t Cc B s e Z RS( ( R R ( ( ( s- /home/case/github/gmpy/test/supportclasses.pyR s t Dc B s, e Z d „ Z d „ Z d „ Z d „ Z RS( c C s
t ‚ d S( N( t TypeError( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR R c C s
t ‚ d S( N( R ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR
! R c C s
t ‚ d S( N( R ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR
" R c C s
t ‚ d S( N( R ( R ( ( s- /home/case/github/gmpy/test/supportclasses.pyR # R ( R R R R
R
R ( ( ( s- /home/case/github/gmpy/test/supportclasses.pyR s ( ( ( ( ( ( ( ( ( R R R R R t zt qt rt cxR R R R t at bt ct d( ( ( s- /home/case/github/gmpy/test/supportclasses.pyt s gmpy2-2.1.0b3/test/test_abs.txt 0000664 0001750 0001750 00000017147 13170047220 016201 0 ustar case case 0000000 0000000 Absolute value
==============
Test abs() and context.abs().
>>> import gmpy2
>>> from gmpy2 import mpz, xmpz, mpq, mpfr, mpc
>>> a=mpz(123)
>>> b=abs(a)
>>> a is b
True
>>> a=xmpz(123)
>>> b=abs(a)
>>> a is b
False
>>> a=mpz(-123)
>>> b=abs(a)
>>> b
mpz(123)
>>> a is b
False
>>> a
mpz(-123)
>>> a=mpq(12,7)
>>> b=abs(a)
>>> a is b
True
>>> a=mpq(-12,7)
>>> b=abs(a)
>>> b
mpq(12,7)
>>> a
mpq(-12,7)
>>> a=xmpz(-123)
>>> b=abs(a)
>>> b
>>> a
xmpz(123)
>>> b is None
True
>>> b = abs(a)
>>> b is None
True
>>> a=mpfr(1.0)
>>> b=abs(a)
>>> a is b
False
>>> abs(mpfr(1, precision=100))
mpfr('1.0')
>>> ctx = gmpy2.get_context()
>>> ctx.clear_flags()
>>> abs(mpfr('nan'))
mpfr('nan')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=True,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> ctx.clear_flags()
>>> abs(mpfr('inf'))
mpfr('inf')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> ctx.clear_flags()
>>> abs(mpfr('-inf'))
mpfr('inf')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> abs(mpc(-1,0))
mpfr('1.0')
>>> abs(-1+0j)
1.0
>>> abs(mpc(1,1))
mpfr('1.4142135623730951')
>>> ctx=gmpy2.get_context()
>>> ctx.clear_flags()
>>> mpc('nan+0j')
mpc('nan+0.0j')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=True,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> abs(mpc('nan+0j'))
mpfr('nan')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=True,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> ctx.clear_flags()
>>> abs(mpc('nanj'))
mpfr('nan')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=True,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> ctx.clear_flags()
>>> abs(mpc('inf+10j'))
mpfr('inf')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> ctx.clear_flags()
>>> abs(mpc('-infj'))
mpfr('inf')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> a=mpc('nan+infj')
>>> ctx.clear_flags()
>>> abs(a)
mpfr('inf')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> a=mpc('-inf+nanj')
>>> ctx.clear_flags()
>>> abs(a)
mpfr('inf')
>>> ctx
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False,
guard_bits=0,
convert_exact=False,
mpfr_divmod_exact=False)
>>> ctx=gmpy2.context()
>>> ctx.abs(-1)
mpz(1)
>>> ctx.abs(0)
mpz(0)
>>> ctx.abs(1)
mpz(1)
>>> ctx.abs(mpz(8))
mpz(8)
>>> ctx.abs(mpz(-8))
mpz(8)
>>> ctx.abs(-1.0)
mpfr('1.0')
>>> ctx.abs(mpfr(-2))
mpfr('2.0')
>>> ctx.abs(2+3j)
mpfr('3.6055512754639891')
>>> ctx.abs(mpc(2+3j))
mpfr('3.6055512754639891')
gmpy2-2.1.0b3/test/test_context.txt 0000664 0001750 0001750 00000027032 13356026702 017122 0 ustar case case 0000000 0000000 Test context handling
---------------------
>>> import gmpy2
>>> from gmpy2 import mpfr,mpc,get_context,set_context,ieee,context,local_context
Test ieee()
-----------
>>> ieee(32)
context(precision=24, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=128, emin=-148,
subnormalize=True,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> ieee(64)
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1024, emin=-1073,
subnormalize=True,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> ieee(128)
context(precision=113, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=16384, emin=-16493,
subnormalize=True,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> gmpy2.ieee(256)
context(precision=237, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=262144, emin=-262377,
subnormalize=True,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> gmpy2.ieee(-1)
Traceback (most recent call last):
File "", line 1, in
ValueError: bitwidth must be 16, 32, 64, 128; or must be greater than 128 and divisible by 32.
>>> gmpy2.ieee("a")
Traceback (most recent call last):
File "", line 1, in
TypeError: ieee() requires 'int' argument
>>> set_context(ieee(32))
>>> gmpy2.const_pi().digits(2)
('110010010000111111011011', 2, 24)
>>> set_context(ieee(64))
>>> gmpy2.const_pi().digits(2)
('11001001000011111101101010100010001000010110100011000', 2, 53)
>>> set_context(ieee(128))
>>> gmpy2.const_pi().digits(2)
('11001001000011111101101010100010001000010110100011000010001101001100010011000110011000101000101110000000110111000', 2, 113)
Test context()
--------------
>>> context()
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> context(precision=100)
context(precision=100, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> context(real_prec=100)
context(precision=53, real_prec=100, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> context(real_prec=100,imag_prec=200)
context(precision=53, real_prec=100, imag_prec=200,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
Test get_context()
------------------
>>> set_context(context())
>>> get_context()
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> a=get_context()
>>> a.precision=100
>>> a
context(precision=100, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> get_context()
context(precision=100, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> b=a.copy()
>>> b.precision=200
>>> b
context(precision=200, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> a
context(precision=100, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> get_context()
context(precision=100, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
Test local_context()
--------------------
>>> set_context(context())
>>> with local_context() as ctx:
... print(ctx.precision)
... ctx.precision+=20
... print(ctx.precision)
...
53
73
>>> get_context()
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> with local_context(ieee(64)) as ctx:
... print(ctx)
...
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1024, emin=-1073,
subnormalize=True,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> get_context()
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> with get_context() as ctx:
... print(ctx.precision)
... ctx.precision+=100
... print(ctx.precision)
...
53
153
>>> get_context()
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
>>> with local_context(precision=200) as ctx:
... print(ctx.precision)
... ctx.precision+=100
... print(ctx.precision)
...
200
300
>>> get_context()
context(precision=53, real_prec=Default, imag_prec=Default,
round=RoundToNearest, real_round=Default, imag_round=Default,
emax=1073741823, emin=-1073741823,
subnormalize=False,
trap_underflow=False, underflow=False,
trap_overflow=False, overflow=False,
trap_inexact=False, inexact=False,
trap_invalid=False, invalid=False,
trap_erange=False, erange=False,
trap_divzero=False, divzero=False,
allow_complex=False,
rational_division=False)
gmpy2-2.1.0b3/test/test_gmpy2_abs.txt 0000664 0001750 0001750 00000004104 13170047220 017304 0 ustar case case 0000000 0000000 Absolute value
==============
Test abs() and context.abs().
>>> import gmpy2
>>> from gmpy2 import mpz, xmpz, mpq, mpfr, mpc
>>> from fractions import Fraction as F
>>> a=mpz(123)
>>> b=abs(a)
>>> a is b
True
>>> a=xmpz(123)
>>> b=abs(a)
>>> a is b
False
>>> a=mpz(-123)
>>> b=abs(a)
>>> b
mpz(123)
>>> a is b
False
>>> a
mpz(-123)
>>> a=mpq(12,7)
>>> b=abs(a)
>>> a is b
True
>>> a=mpq(-12,7)
>>> b=abs(a)
>>> b
mpq(12,7)
>>> a
mpq(-12,7)
>>> a=xmpz(-123)
>>> b=abs(a)
>>> b
>>> a
xmpz(123)
>>> b is None
True
>>> b = abs(a)
>>> b is None
True
>>> a=mpfr(1.0)
>>> b=abs(a)
>>> a is b
False
>>> abs(mpfr(1, precision=100))
mpfr('1.0')
>>> ctx = gmpy2.get_context()
>>> ctx.clear_flags()
>>> abs(mpfr('nan'))
mpfr('nan')
>>> ctx.invalid
True
>>> ctx.clear_flags()
>>> abs(mpfr('inf'))
mpfr('inf')
>>> ctx.overflow
False
>>> ctx.clear_flags()
>>> abs(mpfr('-inf'))
mpfr('inf')
>>> ctx.overflow
False
>>> abs(mpc(-1,0))
mpfr('1.0')
>>> abs(-1+0j)
1.0
>>> abs(mpc(1,1))
mpfr('1.4142135623730951')
>>> ctx=gmpy2.get_context()
>>> ctx.clear_flags()
>>> mpc('nan+0j')
mpc('nan+0.0j')
>>> ctx.invalid
True
>>> abs(mpc('nan+0j'))
mpfr('nan')
>>> ctx.invalid
True
>>> ctx.clear_flags()
>>> abs(mpc('nanj'))
mpfr('nan')
>>> ctx.invalid
True
>>> ctx.clear_flags()
>>> abs(mpc('inf+10j'))
mpfr('inf')
>>> ctx.overflow
False
>>> ctx.clear_flags()
>>> abs(mpc('-infj'))
mpfr('inf')
>>> ctx.overflow
False
>>> a = mpc('nan+infj')
>>> ctx.clear_flags()
>>> abs(a)
mpfr('inf')
>>> ctx.overflow
False
>>> ctx.invalid
False
>>> a=mpc('-inf+nanj')
>>> ctx.clear_flags()
>>> abs(a)
mpfr('inf')
>>> ctx.overflow
False
>>> ctx.invalid
False
>>> ctx=gmpy2.context()
>>> ctx.abs('a')
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> ctx.abs(-1)
mpz(1)
>>> ctx.abs(0)
mpz(0)
>>> ctx.abs(1)
mpz(1)
>>> ctx.abs(mpz(8))
mpz(8)
>>> ctx.abs(mpz(-8))
mpz(8)
>>> ctx.abs(-1.0)
mpfr('1.0')
>>> ctx.abs(mpfr(-2))
mpfr('2.0')
>>> ctx.abs(2+3j)
mpfr('3.6055512754639891')
>>> ctx.abs(mpc(2+3j))
mpfr('3.6055512754639891')
>>> ctx.abs(F(1,2))
mpq(1,2)
>>> ctx.abs(F(-1,2))
mpq(1,2)
gmpy2-2.1.0b3/test/test_gmpy2_add.txt 0000664 0001750 0001750 00000006751 13452510502 017302 0 ustar case case 0000000 0000000 Test gmpy2 Addition
===================
Test all code in the file gmpy2_add.c.
>>> import gmpy2
>>> from gmpy2 import mpz, xmpz, mpq, mpfr, mpc
>>> from supportclasses import *
>>> from decimal import Decimal as D
>>> from fractions import Fraction as F
>>> a = mpz(123)
>>> b = mpz(456)
>>> c = 12345678901234567890
Test integer operations
-----------------------
>>> a+1
mpz(124)
>>> a+(-1)
mpz(122)
>>> 1+a
mpz(124)
>>> (-1)+a
mpz(122)
>>> print(a+c)
12345678901234568013
>>> print(c+a)
12345678901234568013
>>> print(a+(-c))
-12345678901234567767
>>> print((-c)+a)
-12345678901234567767
>>> a+b
mpz(579)
>>> b+a
mpz(579)
>>> a+(-b)
mpz(-333)
>>> (-b)+a
mpz(-333)
>>> a+z
mpz(125)
>>> ctx=gmpy2.context()
>>> ctx.add(a,b) == a+b
True
>>> ctx.add(c,c) == c+c
True
>>> ctx.add(1, 1)
mpz(2)
>>> ctx.add(mpfr(1), mpfr(1))
mpfr('2.0')
>>> ctx.add(a, 1)
mpz(124)
>>> ctx.add(1, a)
mpz(124)
>>> ctx.add(a, mpq(0))
mpq(123,1)
>>> ctx.add(a, mpfr(0))
mpfr('123.0')
>>> ctx.add(a, mpc(0))
mpc('123.0+0.0j')
>>> ctx.add(1)
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> ctx.add(1,2,3)
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> gmpy2.add(1,1)
mpz(2)
>>> a+'b'
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> 'b'+a
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
Test rational operations
------------------------
>>> mpq(1,2) + F(3,2)
mpq(2,1)
>>> F(1,2) + mpq(3,2)
mpq(2,1)
>>> mpq(1,2) + mpq(3,2)
mpq(2,1)
>>> mpq(1,2) + 0
mpq(1,2)
>>> mpq(1,2) + mpz(1)
mpq(3,2)
>>> mpq(1,2) + (-1)
mpq(-1,2)
>>> 1 + mpq(1,2)
mpq(3,2)
>>> mpz(1) + mpq(1,2)
mpq(3,2)
>>> mpq(1,2) + mpz(1)
mpq(3,2)
>>> mpq(1,1) + mpc(0)
mpc('1.0+0.0j')
>>> mpc(0) + mpq(1,1)
mpc('1.0+0.0j')
>>> mpq(1,2) + z
mpq(5,2)
>>> mpq(1,2) + q
mpq(2,1)
>>> ctx=gmpy2.context()
>>> ctx.add(mpq(1,2), mpq(3,2))
mpq(2,1)
>>> ctx.add(mpq(1,2), F(3,2))
mpq(2,1)
>>> ctx.add(F(1,2), mpq(3,2))
mpq(2,1)
>>> ctx.add(F(1,2), F(3,2))
mpq(2,1)
>>> ctx.add(1,'a')
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> mpq(1,2) + 'a'
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> 'a' + mpq(1,2)
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
Test real operations
--------------------
>>> mpfr(1) + 1
mpfr('2.0')
>>> 1 + mpfr(1)
mpfr('2.0')
>>> mpfr(1) + mpz(1)
mpfr('2.0')
>>> mpz(1) + mpfr(1)
mpfr('2.0')
>>> mpfr(1) + mpfr(1)
mpfr('2.0')
>>> mpfr(1) + mpq(1,1)
mpfr('2.0')
>>> mpq(1,1) + mpfr(1)
mpfr('2.0')
>>> mpfr(1) + F(1,1)
mpfr('2.0')
>>> F(1,1) + mpfr(1)
mpfr('2.0')
>>> mpfr(1) + 1.0
mpfr('2.0')
>>> 1.0 + mpfr(1)
mpfr('2.0')
>>> mpfr(0) + (1 << 100) == mpfr('1p100', base=2)
True
>>> (1 << 100) + mpfr(0) == mpfr('1p100', base=2)
True
>>> mpfr(1) + z
mpfr('3.0')
>>> mpfr(0.5) + q
mpfr('2.0')
>>> mpfr(1.5) + r
mpfr('3.0')
Test complex operations
-----------------------
>>> mpc(1,2) + 'a'
Traceback (most recent call last):
...
TypeError:
>>> mpfr(1) + mpc(1,2)
mpc('2.0+2.0j')
>>> mpc(1,2) + mpfr(1)
mpc('2.0+2.0j')
>>> mpc(1,2) + 1+0j
mpc('2.0+2.0j')
>>> 1+0j + mpc(1,2)
mpc('2.0+2.0j')
>>> mpc(1,2) + cx
mpc('43.0+69.0j')
>>> mpc(1,2) + r
mpc('2.5+2.0j')
>>> mpc(1,2) + q
mpc('2.5+2.0j')
>>> mpc(1,2) + z
mpc('3.0+2.0j')
gmpy2-2.1.0b3/test/test_gmpy2_binary.txt 0000664 0001750 0001750 00000012661 13170047220 020032 0 ustar case case 0000000 0000000 Test gmpy2_binary.c
===================
>>> import gmpy2
>>> from gmpy2 import mpz, xmpz, mpq, mpfr, mpc, to_binary, from_binary
>>> gmpy2.mpz_from_old_binary(b'\x15\xcd[\x07')
mpz(123456789)
>>> gmpy2.mpz_from_old_binary(b'\x15\xcd[\x07\xff')
mpz(-123456789)
>>> gmpy2.mpz_from_old_binary(1)
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> gmpy2.mpq_from_old_binary(b'\x01\x00\x00\x00)\x98')
mpq(41,152)
>>> gmpy2.mpq_from_old_binary(b'\x01\x00\x00\x80)\x98')
mpq(-41,152)
>>> gmpy2.mpq_from_old_binary(1)
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> gmpy2.mpq_from_old_binary(b'aa')
Traceback (most recent call last):
File "", line 1, in
ValueError: ** message detail varies **
>>> gmpy2.mpq_from_old_binary(b'aaaaaaaaa')
Traceback (most recent call last):
File "", line 1, in
ValueError: ** message detail varies **
>>> gmpy2.mpfr_from_old_binary(b'\x085\x00\x00\x00\x02\x00\x00\x0009\xac\xcc\xcc\xcc\xcc\xcc\xd0')
mpfr('12345.674999999999')
>>> gmpy2.mpfr_from_old_binary(b'\t5\x00\x00\x00\x02\x00\x00\x0009\xac\xcc\xcc\xcc\xcc\xcc\xd0')
mpfr('-12345.674999999999')
>>> gmpy2.mpfr_from_old_binary(b'\n5\x00\x00\x00\x06\x00\x00\x00\x01\x14\xb3\x7fKQ\xf7\x0en')
mpfr('1.5e-17')
>>> gmpy2.mpfr_from_old_binary(1)
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> gmpy2.mpfr_from_old_binary(b'aaaaa')
Traceback (most recent call last):
File "", line 1, in
ValueError: ** message detail varies **
>>> gmpy2.mpfr_from_old_binary(b'\x04')
mpfr('0.0')
>>> from_binary(to_binary(xmpz(1)))
xmpz(1)
>>> from_binary(to_binary(xmpz(0)))
xmpz(0)
>>> from_binary(to_binary(xmpz(-1)))
xmpz(-1)
>>> from_binary(to_binary(xmpz(1234567890123456789)))
xmpz(1234567890123456789)
>>> from_binary(1)
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> from_binary(b'a')
Traceback (most recent call last):
File "", line 1, in
ValueError: ** message detail varies **
>>> from_binary(to_binary(mpz(1)))
mpz(1)
>>> from_binary(to_binary(mpz(0)))
mpz(0)
>>> from_binary(to_binary(mpz(-1)))
mpz(-1)
>>> from_binary(to_binary(mpz(1234567890123456789)))
mpz(1234567890123456789)
>>> x=mpq(0,1);x==from_binary(to_binary(x))
True
>>> x=mpq(1,1);x==from_binary(to_binary(x))
True
>>> x=mpq(-1,2);x==from_binary(to_binary(x))
True
>>> x=mpq(123456789123456789,9876);x==from_binary(to_binary(x))
True
>>> x=mpfr("0");x==from_binary(to_binary(x))
True
>>> x=mpfr("1");x==from_binary(to_binary(x))
True
>>> x=mpfr("-1");x==from_binary(to_binary(x))
True
>>> x=mpfr("inf");x==from_binary(to_binary(x))
True
>>> x=mpfr("-inf");x==from_binary(to_binary(x))
True
>>> x=mpfr("nan");gmpy2.is_nan(from_binary(to_binary(x)))
True
>>> x=mpfr(1.345);x==from_binary(to_binary(x))
True
>>> x=mpfr("1.345e1000");x==from_binary(to_binary(x))
True
>>> x=mpfr("-1.345e1000");x==from_binary(to_binary(x))
True
>>> x=mpfr("1.345e-1000");x==from_binary(to_binary(x))
True
>>> x=mpfr("-1.345e-1000");x==from_binary(to_binary(x))
True
>>> x=mpfr("1e1234567890123456789");x=from_binary(to_binary(x))
>>> x.rc
1
>>> x=mpfr("-1e1234567890123456789");x=from_binary(to_binary(x))
>>> x.rc
-1
>>> x=gmpy2.const_pi()
>>> x.rc
-1
>>> y=from_binary(to_binary(x))
>>> x==y
True
>>> y.rc
-1
>>> x=gmpy2.const_pi(precision=104)
>>> x.rc
1
>>> y=from_binary(to_binary(x))
>>> x==y
True
>>> y.rc
1
>>> gmpy2.get_context().precision=20
>>> x=gmpy2.const_pi();x==from_binary(to_binary(x))
True
>>> gmpy2.get_context().precision=100
>>> x=gmpy2.const_pi();x==from_binary(to_binary(x))
True
>>> gmpy2.get_context().precision=200
>>> x=mpfr(gmpy2.const_pi());x==from_binary(to_binary(x))
True
>>> gmpy2.get_context().precision=200
>>> x=gmpy2.const_pi()
>>> gmpy2.get_context().precision=300
>>> x=from_binary(to_binary(x))
>>> x.precision
200
>>> gmpy2.set_context(gmpy2.context())
>>> x=mpc("0+0j");x==from_binary(to_binary(x))
True
>>> x=mpc("1+0j");x==from_binary(to_binary(x))
True
>>> x=mpc("-1+0j");x==from_binary(to_binary(x))
True
>>> x=mpc("0+1j");x==from_binary(to_binary(x))
True
>>> x=mpc("0-1j");x==from_binary(to_binary(x))
True
>>> x=mpc("inf+0j");x==from_binary(to_binary(x))
True
>>> x=mpc("0+infj");x==from_binary(to_binary(x))
True
>>> x=mpc("inf-infj");x==from_binary(to_binary(x))
True
>>> x=mpc("inf+nanj")
>>> y=from_binary(to_binary(x))
>>> x.real==y.real
True
>>> gmpy2.is_nan(y.imag)
True
>>> x=mpc("-inf+0j");x==from_binary(to_binary(x))
True
>>> x=mpc("0-infj");x==from_binary(to_binary(x))
True
>>> x=mpc("-inf-infj");x==from_binary(to_binary(x))
True
>>> x=mpc("-inf+nanj")
>>> y=from_binary(to_binary(x))
>>> x.real==y.real
True
>>> gmpy2.is_nan(y.imag)
True
>>> x=mpc("nan+0j")
>>> y=from_binary(to_binary(x))
>>> x.imag==y.imag
True
>>> gmpy2.is_nan(y.real)
True
>>> x=mpc("0+nanj")
>>> y=from_binary(to_binary(x))
>>> x.real==y.real
True
>>> gmpy2.is_nan(y.imag)
True
>>> x=mpc("nan-infj")
>>> y=from_binary(to_binary(x))
>>> x.imag==y.imag
True
>>> gmpy2.is_nan(y.real)
True
>>> x=mpc("nan+nanj")
>>> y=from_binary(to_binary(x))
>>> gmpy2.is_nan(y.real)
True
>>> gmpy2.is_nan(y.imag)
True
>>> gmpy2.get_context().real_prec=100
>>> gmpy2.get_context().imag_prec=110
>>> from_binary(to_binary(mpc("1.3-4.7j")))
mpc('1.2999999999999999999999999999994-4.7000000000000000000000000000000025j',(100,110))
>>> gmpy2.set_context(gmpy2.context())
gmpy2-2.1.0b3/test/test_gmpy2_cmp.txt 0000664 0001750 0001750 00000004320 13461370120 017317 0 ustar case case 0000000 0000000 gmpy2 cmp and cmp_abs
=====================
>>> import gmpy2
>>> from gmpy2 import mpz, mpq, mpfr, mpc, cmp, cmp_abs, nan, inf, zero
MPZ Test comparisons
--------------------
>>> cmp(0,mpz(0)), cmp(1,mpz(0)), cmp(0,mpz(1)), cmp(-1,mpz(0)), cmp(0,mpz(-1))
(0, 1, -1, -1, 1)
>>> cmp_abs(mpz(0),0), cmp_abs(mpz(1),0), cmp_abs(mpz(0),1), cmp_abs(mpz(-1),0), cmp_abs(mpz(0), -1)
(0, 1, -1, 1, -1)
>>> a=mpz(-10)
>>> cmp_abs(a,0)
1
>>> a
mpz(-10)
>>> cmp_abs(100,a)
1
>>> a
mpz(-10)
MPQ Test comparisons
--------------------
>>> cmp(mpq(1,2), mpq(1,2)), cmp(mpq(-1,2), mpq(1,2)), cmp(mpq(1,2), mpq(-1,2))
(0, -1, 1)
>>> cmp(0, mpq(1,2)), cmp(mpq(1,2), 0)
(-1, 1)
>>> cmp_abs(mpq(1,2), mpq(1,3)), cmp_abs(mpq(-1,2), mpq(1,3)), cmp_abs(mpq(1,2),mpq(-1,3))
(1, 1, 1)
>>> cmp_abs(mpq(1,4), mpq(1,3)), cmp_abs(mpq(-1,4), mpq(1,3)), cmp_abs(mpq(1,4),mpq(-1,3))
(-1, -1, -1)
MPFR Test comparisons
---------------------
>>> cmp(mpfr(0), mpfr(0)), cmp(mpfr(0), mpz(0)), cmp(mpfr(0), mpq(0,1))
(0, 0, 0)
>>> cmp(zero(-1), zero(-1)), cmp(zero(1), zero(-1)), cmp(zero(-1), zero(1))
(0, 0, 0)
>>> cmp(mpfr(1), mpfr(0)), cmp(mpfr(1), mpz(0)), cmp(mpfr(1), mpq(0,1))
(1, 1, 1)
>>> cmp(mpfr(-1), mpfr(0)), cmp(mpfr(-1), mpz(0)), cmp(mpfr(-1), mpq(0,1))
(-1, -1, -1)
>>> cmp(nan(), mpfr(0)), cmp(nan(), mpz(0)), cmp(nan(), mpq(0,1))
(0, 0, 0)
>>> gmpy2.get_context().clear_flags()
>>> cmp(nan(), 1)
0
>>> gmpy2.get_context().erange
True
>>> cmp_abs(mpfr(-1), mpfr(0)), cmp_abs(mpfr(-1), mpz(0)), cmp_abs(mpfr(-1), mpq(0,1))
(1, 1, 1)
>>> cmp_abs(mpfr(0), mpfr(-1)), cmp_abs(mpz(0), mpfr(-1)), cmp_abs(mpq(0,1), mpfr(-1))
(-1, -1, -1)
MPC Test comparisons
--------------------
>>> cmp(mpc(1,2), mpc(3,4))
Traceback (most recent call last):
File "", line 1, in
TypeError: ** message detail varies **
>>> cmp_abs(mpc(1,2), mpc(3,4)) # doctest: +SKIP_MPC_LESS_THAN_110
-1
>>> cmp_abs(mpc(1,2), mpc(1,2)) # doctest: +SKIP_MPC_LESS_THAN_110
0
>>> cmp_abs(mpc(3,4), mpc(1,2)) # doctest: +SKIP_MPC_LESS_THAN_110
1
>>> gmpy2.get_context().clear_flags()
>>> nan()
mpfr('nan')
>>> gmpy2.get_context().erange
False
>>> cmp_abs(mpc(nan(),1), mpc(4.5)) # doctest: +SKIP_MPC_LESS_THAN_110
0
>>> gmpy2.get_context().erange # doctest: +SKIP_MPC_LESS_THAN_110
True
gmpy2-2.1.0b3/test/test_gmpy2_comp.txt 0000664 0001750 0001750 00000010063 13452502047 017504 0 ustar case case 0000000 0000000 gmpy2 numbers comparisons
=========================
>>> import gmpy2 as G
>>> from gmpy2 import mpz, mpq, mpfr, mpc
>>> a = mpz(123)
>>> b = mpz(456)
>>> q = mpq(4, 5)
MPZ Test comparisons
--------------------
>>> c=G.mpz(a)
>>> a
mpz(123)
>>> b
mpz(456)
>>> c is a
True
>>> c==a
True
>>> c>a
False
>>> c>> a>b
False
>>> a>> not G.mpz(0)
True
>>> not a
False
>>> G.mpz(1) == None
False
>>> G.mpz(1) == '1'
False
>>> G.mpz(1) == 'abc'
False
>>> [G.mpz(23), None].count(None)
1
>>> a == q, a != q, a > q, a >= q, a < q, a <= q
(False, True, True, True, False, False)
>>> q = mpq(123, 1)
>>> a == q, a != q, a > q, a >= q, a < q, a <= q
(True, False, False, True, False, True)
Test MPZ comparisons with NaN/Inf
---------------------------------
>>> G.context().trap_divzero == False
True
>>> f = float('inf')
>>> a == f, a != f, a > f, a >= f, a < f, a <= f
(False, True, False, False, True, True)
>>> f == a, f != a, f > a, f >= a, f < a, f <= a
(False, True, True, True, False, False)
>>> f = float('-inf')
>>> a == f, a != f, a > f, a >= f, a < f, a <= f
(False, True, True, True, False, False)
>>> f == a, f != a, f > a, f >= a, f < a, f <= a
(False, True, False, False, True, True)
>>> f = float('nan')
>>> a == f, a != f, a > f, a >= f, a < f, a <= f
(False, True, False, False, False, False)
>>> f == a, f != a, f > a, f >= a, f < a, f <= a
(False, True, False, False, False, False)
>>> r = mpfr('inf')
>>> a == r, a != r, a > r, a >= r, a < r, a <= r
(False, True, False, False, True, True)
>>> r = mpfr('-inf')
>>> a == r, a != r, a > r, a >= r, a < r, a <= r
(False, True, True, True, False, False)
>>> r = mpfr('nan')
>>> a == r, a != r, a > r, a >= r, a < r, a <= r
(False, True, False, False, False, False)
MPQ Tests comparisons
---------------------
>>> q = mpq(4, 5)
>>> q == a, q != a, q > a, q >= a, q < a, q <= a
(False, True, False, False, True, True)
>>> mpq(246,2) != a
False
>>> f = float(0.7)
>>> q == f, q != f, q > f, q >= f, q < f, q <= f
(False, True, True, True, False, False)
>>> f = float('nan')
>>> q == f, q != f, q > f, q >= f, q < f, q <= f
(False, True, False, False, False, False)
>>> f = float('inf')
>>> q == f, q != f, q > f, q >= f, q < f, q <= f
(False, True, False, False, True, True)
>>> f = -f
>>> q == f, q != f, q > f, q >= f, q < f, q <= f
(False, True, True, True, False, False)
Tests MPFR comparisons
----------------------
>>> r = mpfr('inf')
>>> q = mpq('45/7')
>>> f = float(0.7)
>>> r2 = mpfr(454.6)
>>> r == a, r != a, r > a, r >= a, r < a, r <= a
(False, True, True, True, False, False)
>>> r = mpfr('-inf')
>>> r == a, r != a, r > a, r >= a, r < a, r <= a
(False, True, False, False, True, True)
>>> r = mpfr('nan')
>>> r == a, r != a, r > a, r >= a, r < a, r <= a
(False, True, False, False, False, False)
>>> r == q, r != q, r > q, r >= q, r < q, r <= q
(False, True, False, False, False, False)
>>> r == f, r != f, r > f, r >= f, r < f, r <= f
(False, True, False, False, False, False)
>>> r == r2, r != r2, r > r2, r >= r2, r < r2, r <= r2
(False, True, False, False, False, False)
>>> r = mpfr(126.5)
>>> r == a, r != a, r > a, r >= a, r < a, r <= a
(False, True, True, True, False, False)
>>> r == q, r != q, r > q, r >= q, r < q, r <= q
(False, True, True, True, False, False)
>>> f = float(126.5)
>>> r == f, r != f, r > f, r >= f, r < f, r <= f
(True, False, False, True, False, True)
>>> r == r2, r != r2, r > r2, r >= r2, r < r2, r <= r2
(False, True, False, False, True, True)
Tests MPC comparisons
---------------------
>>> c = mpc(4.5,6)
>>> c == a, c != a
(False, True)
>>> c < a
Traceback (most recent call last):
File "", line 1, in
TypeError: no ordering relation is defined for complex numbers
>>> cnan = mpc(mpfr('nan'), 6)
>>> c == cnan, c != cnan
(False, True)
>>> c > cnan
Traceback (most recent call last):
File "", line 1, in
TypeError: no ordering relation is defined for complex numbers
>>> cx = complex(4.5,6)
>>> c == cx, c != cx
(True, False)
>>> c > cx
Traceback (most recent call last):
File "", line 1, in
TypeError: no ordering relation is defined for complex numbers
>>> 1
1
gmpy2-2.1.0b3/test/test_gmpy2_const.txt 0000664 0001750 0001750 00000006507 13170047220 017676 0 ustar case case 0000000 0000000 Constants
=========
>>> import gmpy2
>>> gmpy2.const_pi()
mpfr('3.1415926535897931')
>>> gmpy2.const_pi(100)
mpfr('3.1415926535897932384626433832793',100)
>>> gmpy2.const_pi(100,200)
Traceback (most recent call last):
File "", line 1, in
TypeError: function takes at most 1 argument (2 given)
>>> gmpy2.const_pi(prec=100)
Traceback (most recent call last):
File "", line 1, in
TypeError: 'prec' is an invalid keyword argument for this function
>>> gmpy2.const_pi(precision=100)
mpfr('3.1415926535897932384626433832793',100)
>>> gmpy2.ieee(32).const_pi()
mpfr('3.14159274',24)
>>> gmpy2.ieee(32).const_pi(100)
Traceback (most recent call last):
File "", line 1, in
TypeError: const_pi() takes no arguments (1 given)
>>> gmpy2.ieee(128).const_pi()
mpfr('3.1415926535897932384626433832795028',113)
>>> gmpy2.const_log2()
mpfr('0.69314718055994529')
>>> gmpy2.const_log2(100)
mpfr('0.69314718055994530941723212145798',100)
>>> gmpy2.const_log2(100,200)
Traceback (most recent call last):
File "", line 1, in
TypeError: function takes at most 1 argument (2 given)
>>> gmpy2.const_log2(prec=100)
Traceback (most recent call last):
File "", line 1, in
TypeError: 'prec' is an invalid keyword argument for this function
>>> gmpy2.const_log2(precision=100)
mpfr('0.69314718055994530941723212145798',100)
>>> gmpy2.ieee(32).const_log2()
mpfr('0.693147182',24)
>>> gmpy2.ieee(32).const_log2(100)
Traceback (most recent call last):
File "", line 1, in
TypeError: const_log2() takes no arguments (1 given)
>>> gmpy2.ieee(128).const_log2()
mpfr('0.693147180559945309417232121458176575',113)
>>> gmpy2.const_catalan()
mpfr('0.91596559417721901')
>>> gmpy2.const_catalan(100)
mpfr('0.91596559417721901505460351493252',100)
>>> gmpy2.const_catalan(100,200)
Traceback (most recent call last):
File "", line 1, in
TypeError: function takes at most 1 argument (2 given)
>>> gmpy2.const_catalan(prec=100)
Traceback (most recent call last):
File "", line 1, in
TypeError: 'prec' is an invalid keyword argument for this function
>>> gmpy2.const_catalan(precision=100)
mpfr('0.91596559417721901505460351493252',100)
>>> gmpy2.ieee(32).const_catalan()
mpfr('0.915965617',24)
>>> gmpy2.ieee(32).const_catalan(100)
Traceback (most recent call last):
File "", line 1, in
TypeError: const_catalan() takes no arguments (1 given)
>>> gmpy2.ieee(128).const_catalan()
mpfr('0.915965594177219015054603514932384146',113)
>>> gmpy2.const_euler()
mpfr('0.57721566490153287')
>>> gmpy2.const_euler(100)
mpfr('0.57721566490153286060651209008234',100)
>>> gmpy2.const_euler(100,200)
Traceback (most recent call last):
File "", line 1, in
TypeError: function takes at most 1 argument (2 given)
>>> gmpy2.const_euler(prec=100)
Traceback (most recent call last):
File "", line 1, in
TypeError: 'prec' is an invalid keyword argument for this function
>>> gmpy2.const_euler(precision=100)
mpfr('0.57721566490153286060651209008234',100)
>>> gmpy2.ieee(32).const_euler()
mpfr('0.577215672',24)
>>> gmpy2.ieee(32).const_euler(100)
Traceback (most recent call last):
File "", line 1, in
TypeError: const_euler() takes no arguments (1 given)
>>> gmpy2.ieee(128).const_euler()
mpfr('0.577215664901532860606512090082402471',113)
gmpy2-2.1.0b3/test/test_gmpy2_constructors.txt 0000664 0001750 0001750 00000003541 13461370120 021314 0 ustar case case 0000000 0000000 Test constructors via special methods
=====================================
>>> from gmpy2 import mpz, mpq, mpfr, mpc
>>> from supportclasses import *
Test mpz conversion
-------------------
>>> x = mpz(a)
>>> isinstance(x, mpz)
True
>>> x == 1
True
>>> mpz(b)
Traceback (most recent call last):
...
TypeError: object of type 'str' can not be interpreted as mpz
>>> mpz(c)
Traceback (most recent call last):
...
TypeError: mpz() requires numeric or string argument
>>> 1
1
Test mpq conversion
-------------------
>>> x = mpq(a)
>>> isinstance(x, mpq)
True
>>> 2*x == 3
True
>>> mpq(z, z)
mpq(1,1)
>>> class Three:
... def __mpz__(self): return mpz(3)
...
>>> mpq(z, Three())
mpq(2,3)
>>> mpq(b)
Traceback (most recent call last):
...
TypeError: object of type 'str' can not be interpreted as mpq
>>> mpq(c)
Traceback (most recent call last):
...
TypeError: mpq() requires numeric or string argument
>>> 1
1
Test mpfr conversion
--------------------
>>> x = mpfr(a)
>>> isinstance(x, mpfr)
True
>>> x == 1.5
True
>>> mpfr(b)
Traceback (most recent call last):
...
TypeError: object of type 'str' can not be interpreted as mpc
>>> mpfr(c)
Traceback (most recent call last):
...
TypeError: mpfr() requires numeric or string argument
>>> 1
1
Test mpc conversion
--------------------
>>> x = mpc(a)
>>> isinstance(x, mpc)
True
>>> x == 42+67j
True
>>> mpc(b)
Traceback (most recent call last):
...
TypeError: object of type 'str' can not be interpreted as mpc
>>> mpc(c)
Traceback (most recent call last):
...
TypeError: mpc() requires numeric or string argument
>>> 1
1
Test special methods raising errors
--------------------
>>> mpz(d)
Traceback (most recent call last):
...
TypeError
>>> mpq(d)
Traceback (most recent call last):
...
TypeError
>>> mpfr(d)
Traceback (most recent call last):
...
TypeError
>>> mpc(d)
Traceback (most recent call last):
...
TypeError
>>> 1
1
gmpy2-2.1.0b3/test/test_gmpy2_convert.txt 0000664 0001750 0001750 00000006532 13444070732 020236 0 ustar case case 0000000 0000000 Test conversion code to/from GMP
================================
>>> import gmpy2
>>> from gmpy2 import mpz, mpq, mpfr, mpc, xmpz
>>> from fractions import Fraction
Test conversion to/from MPZ
---------------------------
>>> float(mpz(1))
1.0
>>> float(mpz(99**199))
Traceback (most recent call last):
File "", line 1, in
OverflowError: ** message detail varies **
>>> mpz(gmpy2.xmpz(1))
mpz(1)
Test conversion to/from XMPZ
----------------------------
>>> xmpz('5')
xmpz(5)
>>> xmpz('5')
xmpz(5)
>>> xmpz('not')
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid digits
>>> xmpz(-3.5)
xmpz(-3)
>>> xmpz(float('inf'))
Traceback (most recent call last):
File "", line 1, in
OverflowError: 'xmpz' does not support Infinity
>>> xmpz(mpz(100))
xmpz(100)
>>> xmpz(xmpz(100))
xmpz(100)
>>> xmpz(mpq(30,2))
xmpz(15)
>>> str(xmpz(100))
'100'
Test conversion to/from MPQ
---------------------------
>>> mpq(u'2/3')
mpq(2,3)
>>> mpq(b'2/3')
mpq(2,3)
>>> mpq('2,3')
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid digits
>>> mpq('2/a')
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid digits
>>> mpq('2.3')
mpq(23,10)
>>> mpq('2.3/10')
Traceback (most recent call last):
File "", line 1, in
ValueError: illegal string: both . and / found
>>> mpq(4.5)
mpq(9,2)
>>> mpq(float('inf'))
Traceback (most recent call last):
File "", line 1, in
OverflowError: 'mpq' does not support Infinity
>>> mpq(xmpz(15))
mpq(15,1)
>>> mpq(mpfr(4.5))
mpq(9,2)
>>> mpq(dict())
Traceback (most recent call last):
File "", line 1, in
TypeError: mpq() requires numeric or string argument
>>> float(mpq(1,2))
0.5
>>> int(mpq(15,2))
7
Test conversion to/from MPFR
----------------------------
>>> mpz(mpfr('inf'))
Traceback (most recent call last):
File "", line 1, in
OverflowError: 'mpz' does not support Infinity
>>> mpz(mpfr(5.51))
mpz(6)
>>> xmpz(mpfr('inf'))
Traceback (most recent call last):
File "", line 1, in
OverflowError: 'xmpz' does not support Infinity
>>> xmpz(mpfr(5.51))
xmpz(6)
>>> mpq(mpfr('inf'))
Traceback (most recent call last):
File "", line 1, in
OverflowError: can not convert Infinity to MPQ
>>> mpq(mpfr(4.5))
mpq(9,2)
>>> mpq(mpfr(0))
mpq(0,1)
>>> int(mpfr(5.3))
5
>>> float(mpfr(5.3))
5.3
>>> str(float('5.656'))
'5.656'
Test conversion to/from MPC
---------------------------
>>> mpc(mpfr(5.6), precision=(0,0))
mpc('5.5999999999999996+0.0j')
>>> mpc(Fraction(4,5))
mpc('0.80000000000000004+0.0j')
>>> mpc(b'5+6j')
mpc('5.0+6.0j')
>>> mpc(u'5+6j')
mpc('5.0+6.0j')
>>> mpc(u'\xc3')
Traceback (most recent call last):
File "", line 1, in
ValueError: string contains non-ASCII characters
>>> mpc('notanumber')
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid string in mpc()
>>> mpc(u'\0')
Traceback (most recent call last):
File "", line 1, in
ValueError: string without NULL characters expected
>>> mpc('(5+6j)')
mpc('5.0+6.0j')
>>> mpc(' 5+6j ')
mpc('5.0+6.0j')
>>> mpc('5+6ji')
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid string in mpc()
>>> str(mpc(5,6))
'5.0+6.0j'
>>> mpc(4,5).__complex__()
(4+5j)
gmpy2-2.1.0b3/test/test_gmpy2_divmod.txt 0000664 0001750 0001750 00000004707 13244654531 020045 0 ustar case case 0000000 0000000 Test divmod
============
>>> import gmpy2
>>> from gmpy2 import mpz, xmpz, mpq, mpfr, mpc
>>> from decimal import Decimal as D
>>> from fractions import Fraction as F
>>> a = mpz(123)
>>> b = mpz(456)
>>> c = 12345678901234567890
Test integer operations
-----------------------
>>> divmod(mpz(123),'a')
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpq(1,2),'a')
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpfr(1),'a')
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpc(1),'a')
Traceback (most recent call last):
...
TypeError:
>>> ctx=gmpy2.context()
>>> ctx.divmod('a',456)
Traceback (most recent call last):
...
TypeError:
>>> ctx.divmod(a,mpc(456))
Traceback (most recent call last):
...
TypeError:
>>> ctx.divmod(mpc(1,2),mpc(3,4))
Traceback (most recent call last):
...
TypeError:
>>> ctx.divmod(mpfr(2),mpfr(1))
(mpfr('2.0'), mpfr('0.0'))
>>> ctx.divmod(mpq(3,2),mpq(3,7))
(mpz(3), mpq(3,14))
>>> ctx.divmod(1,2,3)
Traceback (most recent call last):
...
TypeError:
>>> ctx.divmod(456, 0)
Traceback (most recent call last):
...
ZeroDivisionError:
>>> ctx.divmod(a,b)
(mpz(0), mpz(123))
>>> ctx.divmod(123,456)
(mpz(0), mpz(123))
>>> divmod(mpz(1), mpc(1,2))
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpq(1,2), mpc(1,2))
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpfr(1), mpc(1,2))
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpc(1,2), mpc(1,2))
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpfr(1.2), mpfr(0.7))
(mpfr('1.0'), mpfr('0.5'))
>>> ctx=gmpy2.ieee(64)
>>> gmpy2.set_context(ctx)
>>> divmod(mpz(123),'a')
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpq(1,2),'a')
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpfr(1),'a')
Traceback (most recent call last):
...
TypeError:
>>> divmod(mpc(1),'a')
Traceback (most recent call last):
...
TypeError:
>>> ctx=gmpy2.context()
>>> ctx.divmod('a',456)
Traceback (most recent call last):
...
TypeError:
>>> ctx.divmod(a,mpc(456))
Traceback (most recent call last):
...
TypeError:
>>> ctx.divmod(mpc(1,2),mpc(3,4))
Traceback (most recent call last):
...
TypeError:
>>> ctx.divmod(456, 0)
Traceback (most recent call last):
...
ZeroDivisionError:
>>> divmod(mpfr(1.2), mpfr(0.7))
(mpfr('1.0'), mpfr('0.5'))
>>> ctx.clear_flags()
>>> ctx.divzero
False
>>> divmod(mpfr(1.2), mpfr(0))
(mpfr('nan'), mpfr('nan'))
>>>
>>> gmpy2.set_context(gmpy2.context())
gmpy2-2.1.0b3/test/test_gmpy2_floordiv.txt 0000664 0001750 0001750 00000011145 13452502175 020376 0 ustar case case 0000000 0000000 Test gmpy2's floordiv
=====================
>>> import gmpy2
>>> ctx = gmpy2.get_context()
>>> from gmpy2 import mpz, xmpz, mpq, mpfr, mpc
>>> from fractions import Fraction
>>> a, b = mpz(45), mpz(6)
>>> r, r2 = mpfr(45), mpfr(3.1)
>>> q, q2 = mpq(118,18), mpq(3,2)
>>> pyq, pyq2 = Fraction(118,18), Fraction(3,2)
>>> c, c2 = mpc(51, 65), mpc(4, 6)
Tests integer floordiv
----------------------
>>> ctx.floor_div(a, 6)
mpz(7)
>>> ctx.floor_div(a, b)
mpz(7)
>>> ctx.floor_div(a, 0)
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> ctx.floor_div(a, mpz(0))
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> ctx.floor_div(45, b)
mpz(7)
>>> ctx.floor_div(45, 0)
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> ctx.floor_div(45, mpz(0))
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> ctx.floor_div()
Traceback (most recent call last):
File "", line 1, in
TypeError: floor_div() requires 2 arguments
>>> gmpy2.floor_div(4,5,6)
Traceback (most recent call last):
File "", line 1, in
TypeError: floor_div() requires 2 arguments
>>> a // b
mpz(7)
>>> a // 0
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> a // mpz(0)
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> ctx.floor_div(a, q2)
mpz(30)
>>> ctx.floor_div(a, r2)
mpfr('14.0')
>>> ctx.floor_div(a, c)
Traceback (most recent call last):
File "", line 1, in
TypeError: can't take floor of complex number
>>> a // b
mpz(7)
>>> a // q
mpz(6)
>>> a // r2
mpfr('14.0')
>>> a // c2
Traceback (most recent call last):
File "", line 1, in
TypeError: can't take floor of complex number
>>> a // 'not'
Traceback (most recent call last):
File "", line 1, in
TypeError: unsupported operand type(s) for //: 'mpz' and 'str'
>>> 1
1
Rational floor_div
------------------
>>> ctx.floor_div(q, q2)
mpz(4)
>>> ctx.floor_div(q, pyq2)
mpz(4)
>>> ctx.floor_div(q, pyq)
mpz(1)
>>> ctx.floor_div(pyq, q2)
mpz(4)
>>> ctx.floor_div(pyq, pyq2)
mpz(4)
>>> ctx.floor_div(pyq, q)
mpz(1)
>>> ctx.floor_div(q, mpq(0,1))
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> ctx.floor_div(q, Fraction(0))
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> ctx.floor_div(pyq, mpq(0,1))
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> ctx.floor_div(pyq, Fraction(0))
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division or modulo by zero
>>> q // b
mpz(1)
>>> q // q2
mpz(4)
>>> q // r2
mpfr('2.0')
>>> q // c2
Traceback (most recent call last):
File "", line 1, in
TypeError: can't take floor of complex number
>>> q // 'not'
Traceback (most recent call last):
File "", line 1, in
TypeError: unsupported operand type(s) for //: 'mpq' and 'str'
>>> 1
1
Real floor_div
--------------
>>> ctx.floor_div(r, r2)
mpfr('14.0')
>>> ctx.floor_div(r, r2)
mpfr('14.0')
>>> ctx.floor_div(r, 3.1)
mpfr('14.0')
>>> ctx.floor_div(r, 4)
mpfr('11.0')
>>> ctx.floor_div(r, b)
mpfr('7.0')
>>> ctx.floor_div(r, q2)
mpfr('30.0')
>>> ctx.floor_div(r, pyq2)
mpfr('30.0')
>>> ctx.floor_div(r, 0)
mpfr('inf')
>>> ctx.floor_div(r, mpz(0))
mpfr('inf')
>>> ctx.floor_div(45.0, r2)
mpfr('14.0')
>>> ctx.floor_div(45.0, r2)
mpfr('14.0')
>>> ctx.floor_div(45.0, 3.1)
mpfr('14.0')
>>> ctx.floor_div(45.0, 4)
mpfr('11.0')
>>> ctx.floor_div(45.0, b)
mpfr('7.0')
>>> ctx.floor_div(45.0, q2)
mpfr('30.0')
>>> ctx.floor_div(45.0, pyq2)
mpfr('30.0')
>>> ctx.floor_div(45.0, 0)
mpfr('inf')
>>> ctx.floor_div(45.0, mpz(0))
mpfr('inf')
>>> ctx.floor_div(45, r2)
mpfr('14.0')
>>> ctx.floor_div(r, 'not')
Traceback (most recent call last):
File "", line 1, in
TypeError: floor_div() argument type not supported
>>> r // b
mpfr('7.0')
>>> r // q2
mpfr('30.0')
>>> r // r2
mpfr('14.0')
>>> r // c2
Traceback (most recent call last):
File "", line 1, in
TypeError: can't take floor of complex number
>>> r // 'not'
Traceback (most recent call last):
File "", line 1, in
TypeError: unsupported operand type(s) for //: 'mpfr' and 'str'
>>> 1
1
gmpy2-2.1.0b3/test/test_gmpy2_format.txt 0000664 0001750 0001750 00000017320 13452503000 020027 0 ustar case case 0000000 0000000 Tests for gmpy2_format.c
========================
>>> from gmpy2 import mpz, xmpz, mpq, mpfr, mpc
>>> import gmpy2
>>> z1, z2 = mpz(-3), mpz(5)
>>> r, r1, r2 = mpfr(5.6), mpfr(-3), mpfr(5)
>>> q = mpq(2/3)
Tests mpz format
----------------
>>> z1.__format__('<5')
'-3 '
>>> z2.__format__('>+5')
' +5'
>>> z1.__format__('5+')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> z2.__format__('>-4')
' 5'
>>> z1.__format__('<-4')
'-3 '
>>> z1.__format__('>4-')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> z1.__format__('<4 ')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> z1.__format__('#x')
'-0x3'
>>> z1.__format__('#o')
'-0o3'
>>> z1.__format__('>5#')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> z1.__format__('~')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> 1
1
Tests mpfr format
-----------------
>>> r1.__format__('<30')
'-3.000000 '
>>> r2.__format__('>+20')
' +5.000000'
>>> r2.__format__('>-15')
' 5.000000'
>>> r1.__format__('>-15')
' -3.000000'
>>> r.__format__('U')
'5.600000'
>>> r.__format__('U-')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> r.__format__('Z')
'5.599999'
>>> r.__format__('Z+')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> r.__format__('+Z')
'+5.599999'
>>> r.__format__('Z ')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> r.__format__('.10f')
'5.6000000000'
>>> r.__format__('.10f.')
'5.6000000000'
>>> r.__format__('Z.')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> r.__format__('->')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> r.__format__('YZ')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> 1
1
Tests mpc format
----------------
>>> c = mpc(mpq(1/3), 5)
>>> c.__format__()
Traceback (most recent call last):
File "", line 1, in
TypeError: function takes exactly 1 argument (0 given)
>>> c.__format__('>20')
' 0.333333+5.000000j'
>>> c.__format__('<20')
'0.333333+5.000000j '
>>> c.__format__('^20')
' 0.333333+5.000000j '
>>> c.__format__('<20', 'xx')
Traceback (most recent call last):
File "", line 1, in
TypeError: function takes exactly 1 argument (2 given)
>>> c.__format__('<<20')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> c.__format__('>+20')
' +0.333333+5.000000j'
>>> c.__format__('+^20')
Traceback (most recent call last):
File "", line 1, in
ValueError: Invalid conversion specification
>>> c.__format__('.10f')
'0.3333333333+5.0000000000j'
>>> c.__format__('Z.10f')
Traceback (most recent call last):
File "